Unhide Bluetooth Low Energy public APIs
Updated API headers. Add BluetoothManager to be retrieved by
context.getSystemService(Context.BLUETOOTH_SERVICE).
LE scan functions are placed in BluetoothAdapter
The GATT API are device driven instead of a profile-driver.
bug 8450158
Change-Id: I424a4cedaac3ef8120a05996500008dd210d2553
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 734d435..459e49c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -19,7 +19,7 @@
import com.android.internal.policy.PolicyManager;
import com.android.internal.util.Preconditions;
-import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -319,7 +319,7 @@
registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
- return BluetoothAdapter.getDefaultAdapter();
+ return new BluetoothManager(ctx);
}});
registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index b00bf09..2e9c9e3 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -22,7 +22,6 @@
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;
@@ -359,6 +358,8 @@
private IBluetooth mService;
private Handler mServiceRecordHandler;
+ private BluetoothAdapterCallback mCallback;
+ private int mClientIf;
/**
* Get a handle to the default local Bluetooth adapter.
@@ -1137,7 +1138,8 @@
* Get the profile proxy object associated with the profile.
*
* <p>Profile can be one of {@link BluetoothProfile#HEALTH}, {@link BluetoothProfile#HEADSET},
- * or {@link BluetoothProfile#A2DP}. Clients must implement
+ * {@link BluetoothProfile#A2DP}, {@link BluetoothProfile#GATT}, or
+ * {@link BluetoothProfile#GATT_SERVER}. Clients must implement
* {@link BluetoothProfile.ServiceListener} to get notified of
* the connection status and to get the proxy object.
*
@@ -1166,12 +1168,6 @@
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
- } else if (profile == BluetoothProfile.GATT) {
- BluetoothGatt gatt = new BluetoothGatt(context, listener);
- return true;
- } else if (profile == BluetoothProfile.GATT_SERVER) {
- BluetoothGattServer gattServer = new BluetoothGattServer(context, listener);
- return true;
} else {
return false;
}
@@ -1411,4 +1407,230 @@
mProxyServiceStateCallbacks.remove(cb);
}
}
+
+ /**
+ * Register an callback to receive async results, such as LE scan result.
+ *
+ * <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
+ */
+ 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;
+ }
+ }
+
+ /**
+ * Starts a scan for Bluetooth LE devices.
+ *
+ * <p>Results of the scan are reported using the
+ * {@link BluetoothAdapterCallback#onLeScan} callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @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;
+ }
+
+ /**
+ * Starts a scan for Bluetooth LE devices, looking for devices that
+ * advertise given services.
+ *
+ * <p>Devices which advertise all specified services are reported using the
+ * {@link BluetoothAdapterCallback#onLeScan} callback.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param serviceUuids Array of services to look for
+ * @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;
+
+ 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);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Stops an ongoing Bluetooth LE device scan.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ */
+ 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);
+ }
+ }
+
+ /**
+ * 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);
+ }
+
+ 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);
+
+ try {
+ mCallback.onLeScan(getRemoteDevice(address), rssi, advData);
+ } catch (Exception ex) {
+ Log.w(TAG, "Unhandled exception: " + ex);
+ }
+ }
+
+ public void onGetService(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid) {
+ // no op
+ }
+
+ public void onGetIncludedService(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int inclSrvcType, int inclSrvcInstId,
+ ParcelUuid inclSrvcUuid) {
+ // no op
+ }
+
+ public void onGetCharacteristic(String address, int srvcType,
+ int srvcInstId, ParcelUuid srvcUuid,
+ int charInstId, ParcelUuid charUuid,
+ int charProps) {
+ // no op
+ }
+
+ 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
+ }
+
+ 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 onExecuteWrite(String address, int status) {
+ // no op
+ }
+
+ public void onReadRemoteRssi(String address, int rssi, int status) {
+ // no op
+ }
+ };
+
}
diff --git a/core/java/android/bluetooth/BluetoothAdapterCallback.java b/core/java/android/bluetooth/BluetoothAdapterCallback.java
new file mode 100644
index 0000000..a726bc9
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdapterCallback.java
@@ -0,0 +1,57 @@
+/*
+ * 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) {
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 4cc22b4..83e95ca 100755
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -18,6 +18,7 @@
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -1126,4 +1127,30 @@
return pinBytes;
}
+ /**
+ * Connect to GATT Server hosted by this device. Caller acts as GATT client.
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as any further GATT client operations.
+ * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
+ * GATT client operations.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @param autoConnect Whether to directly connect to the remote device (false)
+ * or to automatically connect as soon as the remote
+ * device becomes available (true).
+ * @throws IllegalArgumentException if callback is null
+ */
+ public BluetoothGatt connectGattServer(Context context, boolean autoConnect,
+ BluetoothGattCallback callback) {
+ // TODO(Bluetooth) check whether platform support BLE
+ // Do the check here or in GattServer?
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ IBluetoothManager managerService = adapter.getBluetoothManager();
+ try {
+ IBluetoothGatt iGatt = managerService.getBluetoothGatt();
+ BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this);
+ gatt.connect(autoConnect, callback);
+ return gatt;
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return null;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 1e12025..f9ce6ea 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -16,8 +16,6 @@
package android.bluetooth;
-
-import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothProfile.ServiceListener;
@@ -39,42 +37,48 @@
import java.util.UUID;
/**
- * Public API for the Bluetooth Gatt Profile.
+ * Public API for the Bluetooth GATT Profile.
*
- * <p>This class provides Bluetooth Gatt functionality to enable communication
+ * <p>This class provides Bluetooth GATT functionality to enable communication
* with Bluetooth Smart or Smart Ready devices.
*
- * <p>BluetoothGatt is a proxy object for controlling the Bluetooth Service
- * via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
- * BluetoothGatt proxy object.
- *
* <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
- * and call {@link #registerApp} to register your application. Gatt capable
- * devices can be discovered using the {@link #startScan} function or the
- * regular Bluetooth device discovery process.
- * @hide
+ * and call {@link BluetoothDevice#connectGattServer} to get a instance of this class.
+ * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
+ * scan process.
*/
public final class BluetoothGatt implements BluetoothProfile {
private static final String TAG = "BluetoothGatt";
private static final boolean DBG = true;
+ private static final boolean VDBG = true;
- private Context mContext;
- private ServiceListener mServiceListener;
- private BluetoothAdapter mAdapter;
+ private final Context mContext;
private IBluetoothGatt mService;
private BluetoothGattCallback mCallback;
private int mClientIf;
private boolean mAuthRetry = false;
+ private BluetoothDevice mDevice;
+ private boolean mAutoConnect;
+ private int mConnState;
+ private final Object mStateLock = new Object();
+
+ private static final int CONN_STATE_IDLE = 0;
+ private static final int CONN_STATE_CONNECTING = 1;
+ private static final int CONN_STATE_CONNECTED = 2;
+ private static final int CONN_STATE_DISCONNECTING = 3;
private List<BluetoothGattService> mServices;
- /** A Gatt operation completed successfully */
+ /** A GATT operation failed */
+ public static final int GATT_FAILURE = 0;
+
+ /** A GATT operation completed successfully */
public static final int GATT_SUCCESS = 0;
- /** Gatt read operation is not permitted */
+ /** GATT read operation is not permitted */
public static final int GATT_READ_NOT_PERMITTED = 0x2;
- /** Gatt write operation is not permitted */
+ /** GATT write operation is not permitted */
public static final int GATT_WRITE_NOT_PERMITTED = 0x3;
/** Insufficient authentication for a given operation */
@@ -111,55 +115,6 @@
/*package*/ static final int AUTHENTICATION_MITM = 2;
/**
- * Bluetooth state change handlers
- */
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (DBG) Log.d(TAG,"Unbinding service...");
- synchronized (mConnection) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- } else {
- synchronized (mConnection) {
- if (mService == null) {
- if (DBG) Log.d(TAG,"Binding service...");
- if (!mContext.bindService(new Intent(IBluetoothGatt.class.getName()),
- mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth GATT Service");
- }
- }
- }
- }
- }
- };
-
- /**
- * Service binder handling
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothGatt.Stub.asInterface(service);
- ServiceListener serviceListener = mServiceListener;
- if (serviceListener != null) {
- serviceListener.onServiceConnected(BluetoothProfile.GATT, BluetoothGatt.this);
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- ServiceListener serviceListener = mServiceListener;
- if (serviceListener != null) {
- serviceListener.onServiceDisconnected(BluetoothProfile.GATT);
- }
- }
- };
-
- /**
* Bluetooth GATT interface callbacks
*/
private final IBluetoothGattCallback mBluetoothGattCallback =
@@ -171,11 +126,27 @@
public void onClientRegistered(int status, int clientIf) {
if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
+ " clientIf=" + clientIf);
+ if (VDBG) {
+ synchronized(mStateLock) {
+ if (mConnState != CONN_STATE_CONNECTING) {
+ Log.e(TAG, "Bad connection state: " + mConnState);
+ }
+ }
+ }
mClientIf = clientIf;
+ if (status != GATT_SUCCESS) {
+ mCallback.onConnectionStateChange(mDevice, GATT_FAILURE,
+ BluetoothProfile.STATE_DISCONNECTED);
+ synchronized(mStateLock) {
+ mConnState = CONN_STATE_IDLE;
+ }
+ return;
+ }
try {
- mCallback.onAppRegistered(status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
+ mService.clientConnect(mClientIf, mDevice.getAddress(),
+ !mAutoConnect); // autoConnect is inverse of "isDirect"
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
}
}
@@ -187,13 +158,24 @@
boolean connected, String address) {
if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
+ " clientIf=" + clientIf + " device=" + address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ int profileState = connected ? BluetoothProfile.STATE_CONNECTED :
+ BluetoothProfile.STATE_DISCONNECTED;
try {
- mCallback.onConnectionStateChange(mAdapter.getRemoteDevice(address), status,
- connected ? BluetoothProfile.STATE_CONNECTED
- : BluetoothProfile.STATE_DISCONNECTED);
+ mCallback.onConnectionStateChange(mDevice, status, profileState);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
+
+ synchronized(mStateLock) {
+ if (connected) {
+ mConnState = CONN_STATE_CONNECTED;
+ } else {
+ mConnState = CONN_STATE_IDLE;
+ }
+ }
}
/**
@@ -201,13 +183,7 @@
* @hide
*/
public void onScanResult(String address, int rssi, byte[] advData) {
- if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-
- try {
- mCallback.onScanResult(mAdapter.getRemoteDevice(address), rssi, advData);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
+ // no op
}
/**
@@ -219,8 +195,10 @@
public void onGetService(String address, int srvcType,
int srvcInstId, ParcelUuid srvcUuid) {
if (DBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- mServices.add(new BluetoothGattService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType));
}
@@ -236,10 +214,12 @@
if (DBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
+ " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device,
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice,
srvcUuid.getUuid(), srvcInstId, srvcType);
- BluetoothGattService includedService = getService(device,
+ BluetoothGattService includedService = getService(mDevice,
inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
if (service != null && includedService != null) {
@@ -260,8 +240,10 @@
if (DBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service != null) {
service.addCharacteristic(new BluetoothGattCharacteristic(
@@ -281,8 +263,10 @@
ParcelUuid descUuid) {
if (DBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -303,9 +287,11 @@
*/
public void onSearchComplete(String address, int status) {
if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onServicesDiscovered(device, status);
+ mCallback.onServicesDiscovered(mDevice, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
@@ -322,6 +308,9 @@
if (DBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
+ " UUID=" + charUuid + " Status=" + status);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|| status == GATT_INSUFFICIENT_ENCRYPTION)
&& mAuthRetry == false) {
@@ -338,8 +327,7 @@
mAuthRetry = false;
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -367,8 +355,10 @@
if (DBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
+ " UUID=" + charUuid + " Status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -411,8 +401,10 @@
byte[] value) {
if (DBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -439,8 +431,10 @@
ParcelUuid descrUuid, byte[] value) {
if (DBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -486,8 +480,10 @@
ParcelUuid descrUuid) {
if (DBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
- BluetoothGattService service = getService(device, srvcUuid.getUuid(),
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
+ BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
srvcInstId, srvcType);
if (service == null) return;
@@ -529,9 +525,11 @@
public void onExecuteWrite(String address, int status) {
if (DBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
+ " status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onReliableWriteCompleted(device, status);
+ mCallback.onReliableWriteCompleted(mDevice, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
@@ -544,43 +542,24 @@
public void onReadRemoteRssi(String address, int rssi, int status) {
if (DBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
" rssi=" + rssi + " status=" + status);
- BluetoothDevice device = mAdapter.getRemoteDevice(address);
+ if (!address.equals(mDevice.getAddress())) {
+ return;
+ }
try {
- mCallback.onReadRemoteRssi(device, rssi, status);
+ mCallback.onReadRemoteRssi(mDevice, rssi, status);
} catch (Exception ex) {
Log.w(TAG, "Unhandled exception: " + ex);
}
}
};
- /**
- * Create a BluetoothGatt proxy object.
- */
- /*package*/ BluetoothGatt(Context context, ServiceListener l) {
+ /*package*/ BluetoothGatt(Context context, IBluetoothGatt iGatt, BluetoothDevice device) {
mContext = context;
- mServiceListener = l;
- mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mService = iGatt;
+ mDevice = device;
mServices = new ArrayList<BluetoothGattService>();
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- } else {
- Log.e(TAG, "Unable to get BluetoothManager interface.");
- throw new RuntimeException("BluetoothManager inactive");
- }
-
- //Bind to the service only if the Bluetooth is ON
- if(mAdapter.isEnabled()){
- if (!context.bindService(new Intent(IBluetoothGatt.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Gatt Service");
- }
- }
+ mConnState = CONN_STATE_IDLE;
}
/**
@@ -590,24 +569,6 @@
if (DBG) Log.d(TAG, "close()");
unregisterApp();
- mServiceListener = null;
-
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
- }
- }
-
- synchronized (mConnection) {
- if (mService != null) {
- mService = null;
- mContext.unbindService(mConnection);
- }
- }
}
/**
@@ -629,18 +590,18 @@
/**
- * Register an application callback to start using Gatt.
+ * Register an application callback to start using GATT.
*
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
+ * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
+ * is used to notify success or failure if the function returns true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param callback Gatt callback handler that will receive asynchronous
- * callbacks.
- * @return true, if application was successfully registered.
+ * @param callback GATT callback handler that will receive asynchronous callbacks.
+ * @return If true, the callback will be called to notify success or failure,
+ * false on immediate error
*/
- public boolean registerApp(BluetoothGattCallback callback) {
+ private boolean registerApp(BluetoothGattCallback callback) {
if (DBG) Log.d(TAG, "registerApp()");
if (mService == null) return false;
@@ -661,7 +622,7 @@
/**
* Unregister the current application and callbacks.
*/
- public void unregisterApp() {
+ private void unregisterApp() {
if (DBG) Log.d(TAG, "unregisterApp() - mClientIf=" + mClientIf);
if (mService == null || mClientIf == 0) return;
@@ -675,77 +636,7 @@
}
/**
- * Starts a scan for Bluetooth LE devices.
- *
- * <p>Results of the scan are reported using the
- * {@link BluetoothGattCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return true, if the scan was started successfully
- */
- public boolean startScan() {
- if (DBG) Log.d(TAG, "startScan()");
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.startScan(mClientIf, false);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a scan for Bluetooth LE devices, looking for devices that
- * advertise given services.
- *
- * <p>Devices which advertise all specified services are reported using the
- * {@link BluetoothGattCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param serviceUuids Array of services to look for
- * @return true, if the scan was started successfully
- */
- public boolean startScan(UUID[] serviceUuids) {
- if (DBG) Log.d(TAG, "startScan() - with UUIDs");
- if (mService == null || mClientIf == 0) return false;
-
- try {
- ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(serviceUuids[i]);
- }
- mService.startScanWithUuids(mClientIf, false, uuids);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Stops an ongoing Bluetooth LE device scan.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- */
- public void stopScan() {
- if (DBG) Log.d(TAG, "stopScan()");
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.stopScan(mClientIf, false);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Initiate a connection to a Bluetooth Gatt capable device.
+ * Initiate a connection to a Bluetooth GATT capable device.
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
@@ -757,7 +648,7 @@
* when the remote device is in range/available. Generally, the first ever
* connection to a device should be direct (autoConnect set to false) and
* subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to false.
+ * autoConnect parameter set to true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -767,18 +658,24 @@
* device becomes available (true).
* @return true, if the connection attempt was initiated successfully
*/
- public boolean connect(BluetoothDevice device, boolean autoConnect) {
- if (DBG) Log.d(TAG, "connect() - device: " + device.getAddress() + ", auto: " + autoConnect);
- if (mService == null || mClientIf == 0) return false;
-
- try {
- mService.clientConnect(mClientIf, device.getAddress(),
- autoConnect ? false : true); // autoConnect is inverse of "isDirect"
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
+ /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
+ if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
+ synchronized(mStateLock) {
+ if (mConnState != CONN_STATE_IDLE) {
+ throw new IllegalStateException("Not idle");
+ }
+ mConnState = CONN_STATE_CONNECTING;
+ }
+ if (!registerApp(callback)) {
+ synchronized(mStateLock) {
+ mConnState = CONN_STATE_IDLE;
+ }
+ Log.e(TAG, "Failed to register callback");
return false;
}
+ // the connection will continue after successful callback registration
+ mAutoConnect = autoConnect;
return true;
}
@@ -787,18 +684,17 @@
* currently in progress.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote device
*/
- public void cancelConnection(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "cancelOpen() - device: " + device.getAddress());
+ public void disconnect() {
+ if (DBG) Log.d(TAG, "cancelOpen() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return;
try {
- mService.clientDisconnect(mClientIf, device.getAddress());
+ mService.clientDisconnect(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
+ // TBD deregister after conneciton is torn down
}
/**
@@ -812,17 +708,16 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device to explore
* @return true, if the remote service discovery has been started
*/
- public boolean discoverServices(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "discoverServices() - device: " + device.getAddress());
+ public boolean discoverServices() {
+ if (DBG) Log.d(TAG, "discoverServices() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
mServices.clear();
try {
- mService.discoverServices(mClientIf, device.getAddress());
+ mService.discoverServices(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -839,16 +734,15 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return List of services on the remote device. Returns an empty list
* if service discovery has not yet been performed.
*/
- public List<BluetoothGattService> getServices(BluetoothDevice device) {
+ public List<BluetoothGattService> getServices() {
List<BluetoothGattService> result =
new ArrayList<BluetoothGattService>();
for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(device)) {
+ if (service.getDevice().equals(mDevice)) {
result.add(service);
}
}
@@ -868,14 +762,13 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @param uuid UUID of the requested service
* @return BluetoothGattService if supported, or null if the requested
* service is not offered by the remote device.
*/
- public BluetoothGattService getService(BluetoothDevice device, UUID uuid) {
+ public BluetoothGattService getService(UUID uuid) {
for (BluetoothGattService service : mServices) {
- if (service.getDevice().equals(device) &&
+ if (service.getDevice().equals(mDevice) &&
service.getUuid().equals(uuid)) {
return service;
}
@@ -923,8 +816,7 @@
}
/**
- * Writes a given characteristic and it's values to the associated remote
- * device.
+ * Writes a given characteristic and its values to the associated remote device.
*
* <p>Once the write operation has been completed, the
* {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
@@ -1061,15 +953,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the reliable write transaction has been initiated
*/
- public boolean beginReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + device.getAddress());
+ public boolean beginReliableWrite() {
+ if (DBG) Log.d(TAG, "beginReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.beginReliableWrite(mClientIf, device.getAddress());
+ mService.beginReliableWrite(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1089,15 +980,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the request to execute the transaction has been sent
*/
- public boolean executeReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + device.getAddress());
+ public boolean executeReliableWrite() {
+ if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.endReliableWrite(mClientIf, device.getAddress(), true);
+ mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1113,15 +1003,13 @@
* operations for a given remote device.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote device
*/
- public void abortReliableWrite(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + device.getAddress());
+ public void abortReliableWrite(BluetoothDevice mDevice) {
+ if (DBG) Log.d(TAG, "abortReliableWrite() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return;
try {
- mService.endReliableWrite(mClientIf, device.getAddress(), false);
+ mService.endReliableWrite(mClientIf, mDevice.getAddress(), false);
} catch (RemoteException e) {
Log.e(TAG,"",e);
}
@@ -1172,12 +1060,12 @@
* remote device.
* @hide
*/
- public boolean refresh(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "refresh() - device: " + device.getAddress());
+ public boolean refresh() {
+ if (DBG) Log.d(TAG, "refresh() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.refreshDevice(mClientIf, device.getAddress());
+ mService.refreshDevice(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1194,15 +1082,14 @@
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device
* @return true, if the RSSI value has been requested successfully
*/
- public boolean readRemoteRssi(BluetoothDevice device) {
- if (DBG) Log.d(TAG, "readRssi() - device: " + device.getAddress());
+ public boolean readRemoteRssi() {
+ if (DBG) Log.d(TAG, "readRssi() - device: " + mDevice.getAddress());
if (mService == null || mClientIf == 0) return false;
try {
- mService.readRemoteRssi(mClientIf, device.getAddress());
+ mService.readRemoteRssi(mClientIf, mDevice.getAddress());
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
@@ -1212,98 +1099,38 @@
}
/**
- * Get the current connection state of the profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+ * @throws UnsupportedOperationException
*/
@Override
public int getConnectionState(BluetoothDevice device) {
- if (DBG) Log.d(TAG,"getConnectionState()");
- if (mService == null) return STATE_DISCONNECTED;
-
- List<BluetoothDevice> connectedDevices = getConnectedDevices();
- for(BluetoothDevice connectedDevice : connectedDevices) {
- if (device.equals(connectedDevice)) {
- return STATE_CONNECTED;
- }
- }
-
- return STATE_DISCONNECTED;
+ throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
/**
- * Get connected devices for the Gatt profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) Log.d(TAG,"getConnectedDevices");
-
- List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
- if (mService == null) return connectedDevices;
-
- try {
- connectedDevices = mService.getDevicesMatchingConnectionStates(
- new int[] { BluetoothProfile.STATE_CONNECTED });
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return connectedDevices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getConnectedDevices instead.");
}
/**
- * Get a list of devices that match any of the given connection
- * states.
+ * Not supported - please use
+ * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
+ * with {@link BluetoothProfile#GATT} as first argument
*
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param states Array of states. States can be one of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
-
- List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
- if (mService == null) return devices;
-
- try {
- devices = mService.getDevicesMatchingConnectionStates(states);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return devices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
}
}
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index afa4539..c9e5fea 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -18,34 +18,10 @@
import android.bluetooth.BluetoothDevice;
-import android.util.Log;
-
/**
* This abstract class is used to implement {@link BluetoothGatt} callbacks.
- * @hide
*/
public abstract class BluetoothGattCallback {
- /**
- * Callback to inform change in registration state of the application.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the application
- * was successfully registered.
- */
- public void onAppRegistered(int status) {
- }
-
- /**
- * Callback reporting an LE device found during a device scan initiated
- * by the {@link BluetoothGatt#startScan} 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 onScanResult(BluetoothDevice device, int rssi, byte[] scanRecord) {
- }
/**
* Callback indicating when a remote device has been connected or disconnected.
@@ -61,8 +37,8 @@
}
/**
- * Callback invoked when the list of remote services, characteristics and
- * descriptors for the remote device have been updated.
+ * Callback invoked when the list of remote services, characteristics and descriptors
+ * for the remote device have been updated, ie new services have been discovered.
*
* @param device Remote device
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
@@ -97,7 +73,7 @@
* @param status The result of the write operation
*/
public void onCharacteristicWrite(BluetoothGattCharacteristic characteristic,
- int status) {
+ int status) {
}
/**
@@ -113,23 +89,21 @@
* Callback reporting the result of a descriptor read operation.
*
* @param descriptor Descriptor that was read from the associated
- * remote device.
+ * remote device.
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
* was completed successfully
*/
- public void onDescriptorRead(BluetoothGattDescriptor descriptor,
- int status) {
+ public void onDescriptorRead(BluetoothGattDescriptor descriptor, int status) {
}
/**
* Callback indicating the result of a descriptor write operation.
*
* @param descriptor Descriptor that was writte to the associated
- * remote device.
+ * remote device.
* @param status The result of the write operation
*/
- public void onDescriptorWrite(BluetoothGattDescriptor descriptor,
- int status) {
+ public void onDescriptorWrite(BluetoothGattDescriptor descriptor, int status) {
}
/**
@@ -150,7 +124,7 @@
*
* @param device Identifies the remote device
* @param rssi The RSSI value for the remote device
- * @param status 0 if the RSSI was read successfully
+ * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
*/
public void onReadRemoteRssi(BluetoothDevice device, int rssi, int status) {
}
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index f44dc5c0..d63d97e 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -21,8 +21,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Characteristic
- * @hide
+ * Represents a Bluetooth GATT Characteristic
*/
public class BluetoothGattCharacteristic {
@@ -119,7 +118,7 @@
public static final int WRITE_TYPE_NO_RESPONSE = 0x01;
/**
- * Write characteristic including and authenticated signature
+ * Write characteristic including authentication signature
*/
public static final int WRITE_TYPE_SIGNED = 0x04;
@@ -219,12 +218,30 @@
protected List<BluetoothGattDescriptor> mDescriptors;
/**
+ * Create a new BluetoothGattCharacteristic.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid The UUID for this characteristic
+ * @param properties Properties of this characteristic
+ * @param permissions Permissions for this characteristic
+ */
+ public BluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
+ initCharacteristic(null, uuid, 0, properties, permissions);
+ }
+
+ /**
* Create a new BluetoothGattCharacteristic
* @hide
*/
/*package*/ BluetoothGattCharacteristic(BluetoothGattService service,
UUID uuid, int instanceId,
int properties, int permissions) {
+ initCharacteristic(service, uuid, instanceId, properties, permissions);
+ }
+
+ private void initCharacteristic(BluetoothGattService service,
+ UUID uuid, int instanceId,
+ int properties, int permissions) {
mUuid = uuid;
mInstance = instanceId;
mProperties = properties;
@@ -249,11 +266,16 @@
}
/**
- * Add a descriptor to this characteristic
- * @hide
+ * Adds a descriptor to this characteristic.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param descriptor Descriptor to be added to this characteristic.
+ * @return true, if the descriptor was added to the characteristic
*/
- /*package*/ void addDescriptor(BluetoothGattDescriptor descriptor) {
+ public boolean addDescriptor(BluetoothGattDescriptor descriptor) {
mDescriptors.add(descriptor);
+ descriptor.setCharacteristic(this);
+ return true;
}
/**
@@ -265,8 +287,15 @@
}
/**
+ * Sets the service associated with this device.
+ * @hide
+ */
+ /*package*/ void setService(BluetoothGattService service) {
+ mService = service;
+ }
+
+ /**
* Returns the UUID of this characteristic
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this characteristic
*/
@@ -280,8 +309,6 @@
* <p>If a remote device offers multiple characteristics with the same UUID,
* the instance ID is used to distuinguish between characteristics.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Instance ID of this characteristic
*/
public int getInstanceId() {
@@ -294,8 +321,6 @@
* <p>The properties contain a bit mask of property flags indicating
* the features of this characteristic.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Properties of this characteristic
*/
public int getProperties() {
@@ -304,7 +329,6 @@
/**
* Returns the permissions for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this characteristic
*/
@@ -314,7 +338,6 @@
/**
* Gets the write type for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Write type for this characteristic
*/
@@ -329,11 +352,6 @@
* {@link BluetoothGatt#writeCharacteristic} function write this
* characteristic.
*
- * <p>The default write type for a characteristic is
- * {@link #WRITE_TYPE_DEFAULT}.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param writeType The write type to for this characteristic. Can be one
* of:
* {@link #WRITE_TYPE_DEFAULT},
@@ -345,8 +363,15 @@
}
/**
+ * Set the desired key size.
+ * @hide
+ */
+ public void setKeySize(int keySize) {
+ mKeySize = keySize;
+ }
+
+ /**
* Returns a list of descriptors for this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Descriptors for this characteristic
*/
@@ -358,9 +383,7 @@
* Returns a descriptor with a given UUID out of the list of
* descriptors for this characteristic.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return Gatt descriptor object or null if no descriptor with the
+ * @return GATT descriptor object or null if no descriptor with the
* given UUID was found.
*/
public BluetoothGattDescriptor getDescriptor(UUID uuid) {
@@ -376,12 +399,10 @@
* Get the stored value for this characteristic.
*
* <p>This function returns the stored value for this characteristic as
- * retrieved by calling {@link BluetoothGatt#readCharacteristic}. To cached
+ * retrieved by calling {@link BluetoothGatt#readCharacteristic}. The cached
* value of the characteristic is updated as a result of a read characteristic
* operation or if a characteristic update notification has been received.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Cached value of the characteristic
*/
public byte[] getValue() {
@@ -397,8 +418,6 @@
* characteristic value at the given offset are interpreted to generate the
* return value.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param formatType The format type used to interpret the characteristic
* value.
* @param offset Offset at which the integer value can be found.
@@ -436,7 +455,6 @@
/**
* Return the stored value of this characteristic.
* <p>See {@link #getValue} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param formatType The format type used to interpret the characteristic
* value.
@@ -462,7 +480,7 @@
/**
* Return the stored value of this characteristic.
* <p>See {@link #getValue} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param offset Offset at which the string value can be found.
* @return Cached value of the characteristic
*/
@@ -481,8 +499,6 @@
* {@link BluetoothGatt#writeCharacteristic} to send the value to the
* remote device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param value New value for this characteristic
* @return true if the locally stored value has been set, false if the
* requested value could not be stored locally.
@@ -495,7 +511,6 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param value New value for this characteristic
* @param formatType Integer format type used to transform the value parameter
@@ -542,7 +557,7 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param mantissa Mantissa for this characteristic
* @param exponent exponent value for this characteristic
* @param formatType Float format type used to transform the value parameter
@@ -582,7 +597,7 @@
/**
* Set the locally stored value of this characteristic.
* <p>See {@link #setValue(byte[])} for details.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param value New value for this characteristic
* @return true if the locally stored value has been set
*/
@@ -593,7 +608,6 @@
/**
* Returns the size of a give value type.
- * @hide
*/
private int getTypeLen(int formatType) {
return formatType & 0xF;
@@ -601,7 +615,6 @@
/**
* Convert a signed byte to an unsigned int.
- * @hide
*/
private int unsignedByteToInt(byte b) {
return b & 0xFF;
@@ -609,7 +622,6 @@
/**
* Convert signed bytes to a 16-bit unsigned int.
- * @hide
*/
private int unsignedBytesToInt(byte b0, byte b1) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8));
@@ -617,7 +629,6 @@
/**
* Convert signed bytes to a 32-bit unsigned int.
- * @hide
*/
private int unsignedBytesToInt(byte b0, byte b1, byte b2, byte b3) {
return (unsignedByteToInt(b0) + (unsignedByteToInt(b1) << 8))
@@ -626,7 +637,6 @@
/**
* Convert signed bytes to a 16-bit short float value.
- * @hide
*/
private float bytesToFloat(byte b0, byte b1) {
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
@@ -637,7 +647,6 @@
/**
* Convert signed bytes to a 32-bit short float value.
- * @hide
*/
private float bytesToFloat(byte b0, byte b1, byte b2, byte b3) {
int mantissa = unsignedToSigned(unsignedByteToInt(b0)
@@ -649,7 +658,6 @@
/**
* Convert an unsigned integer value to a two's-complement encoded
* signed value.
- * @hide
*/
private int unsignedToSigned(int unsigned, int size) {
if ((unsigned & (1 << size-1)) != 0) {
@@ -660,7 +668,6 @@
/**
* Convert an integer into the signed bits of a given length.
- * @hide
*/
private int intToSignedBits(int i, int size) {
if (i < 0) {
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index ba1f28a..6ba2db7 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -19,8 +19,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Descriptor
- * @hide
+ * Represents a Bluetooth GATT Descriptor
*/
public class BluetoothGattDescriptor {
@@ -109,12 +108,28 @@
* Create a new BluetoothGattDescriptor.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
+ * @param uuid The UUID for this descriptor
+ * @param permissions Permissions for this descriptor
+ */
+ public BluetoothGattDescriptor(UUID uuid, int permissions) {
+ initDescriptor(null, uuid, permissions);
+ }
+
+ /**
+ * Create a new BluetoothGattDescriptor.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
* @param characteristic The characteristic this descriptor belongs to
* @param uuid The UUID for this descriptor
* @param permissions Permissions for this descriptor
*/
/*package*/ BluetoothGattDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
int permissions) {
+ initDescriptor(characteristic, uuid, permissions);
+ }
+
+ private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
+ int permissions) {
mCharacteristic = characteristic;
mUuid = uuid;
mPermissions = permissions;
@@ -129,8 +144,15 @@
}
/**
+ * Set the back-reference to the associated characteristic
+ * @hide
+ */
+ /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
+ mCharacteristic = characteristic;
+ }
+
+ /**
* Returns the UUID of this descriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this descriptor
*/
@@ -140,7 +162,6 @@
/**
* Returns the permissions for this descriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this descriptor
*/
@@ -152,12 +173,10 @@
* Returns the stored value for this descriptor
*
* <p>This function returns the stored value for this descriptor as
- * retrieved by calling {@link BluetoothGatt#readDescriptor}. To cached
+ * retrieved by calling {@link BluetoothGatt#readDescriptor}. The cached
* value of the descriptor is updated as a result of a descriptor read
* operation.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Cached value of the descriptor
*/
public byte[] getValue() {
@@ -172,8 +191,6 @@
* {@link BluetoothGatt#writeDescriptor} to send the value to the
* remote device.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @param value New value for this descriptor
* @return true if the locally stored value has been set, false if the
* requested value could not be stored locally.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 6b69377..d1f4b82 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -38,88 +38,30 @@
import java.util.UUID;
/**
- * Public API for the Bluetooth Gatt Profile server role.
+ * Public API for the Bluetooth GATT Profile server role.
*
- * <p>This class provides Bluetooth Gatt server role functionality,
+ * <p>This class provides Bluetooth GATT server role functionality,
* allowing applications to create and advertise Bluetooth Smart services
* and characteristics.
*
* <p>BluetoothGattServer is a proxy object for controlling the Bluetooth Service
* via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get the
* BluetoothGatt proxy object.
- * @hide
*/
public final class BluetoothGattServer implements BluetoothProfile {
private static final String TAG = "BluetoothGattServer";
private static final boolean DBG = true;
- private Context mContext;
- private ServiceListener mServiceListener;
+ private final Context mContext;
private BluetoothAdapter mAdapter;
private IBluetoothGatt mService;
private BluetoothGattServerCallback mCallback;
- private int mServerIf;
+ private Object mServerIfLock = new Object();
+ private int mServerIf;
private List<BluetoothGattService> mServices;
- /**
- * Bluetooth state change handlers
- */
- private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
- new IBluetoothStateChangeCallback.Stub() {
- public void onBluetoothStateChange(boolean up) {
- if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up);
- if (!up) {
- if (DBG) Log.d(TAG,"Unbinding service...");
- synchronized (mConnection) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
- } else {
- synchronized (mConnection) {
- try {
- if (mService == null) {
- if (DBG) Log.d(TAG,"Binding service...");
- if (!mContext.bindService(new
- Intent(IBluetoothGatt.class.getName()),
- mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth GATT Service");
- }
- }
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
- }
- }
- };
-
- /**
- * Service binder handling
- */
- private ServiceConnection mConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (DBG) Log.d(TAG, "Proxy object connected");
- mService = IBluetoothGatt.Stub.asInterface(service);
- ServiceListener serviceListner = mServiceListener;
- if (serviceListner != null) {
- serviceListner.onServiceConnected(BluetoothProfile.GATT_SERVER,
- BluetoothGattServer.this);
- }
- }
- public void onServiceDisconnected(ComponentName className) {
- if (DBG) Log.d(TAG, "Proxy object disconnected");
- mService = null;
- ServiceListener serviceListner = mServiceListener;
- if (serviceListner != null) {
- serviceListner.onServiceDisconnected(BluetoothProfile.GATT_SERVER);
- }
- }
- };
+ private static final int CALLBACK_REG_TIMEOUT = 10000;
/**
* Bluetooth GATT interface callbacks
@@ -133,11 +75,14 @@
public void onServerRegistered(int status, int serverIf) {
if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
+ " serverIf=" + serverIf);
- mServerIf = serverIf;
- try {
- mCallback.onAppRegistered(status);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
+ synchronized(mServerIfLock) {
+ if (mCallback != null) {
+ mServerIf = serverIf;
+ mServerIfLock.notify();
+ } else {
+ // registration timeout
+ Log.e(TAG, "onServerRegistered: mCallback is null");
+ }
}
}
@@ -147,13 +92,7 @@
*/
public void onScanResult(String address, int rssi, byte[] advData) {
if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-
- try {
- mCallback.onScanResult(mAdapter.getRemoteDevice(address),
- rssi, advData);
- } catch (Exception ex) {
- Log.w(TAG, "Unhandled exception: " + ex);
- }
+ // no op
}
/**
@@ -209,8 +148,7 @@
BluetoothGattService service = getService(srvcUuid, srvcInstId, srvcType);
if (service == null) return;
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid);
+ BluetoothGattCharacteristic characteristic = service.getCharacteristic(charUuid);
if (characteristic == null) return;
try {
@@ -340,31 +278,13 @@
/**
* Create a BluetoothGattServer proxy object.
*/
- /*package*/ BluetoothGattServer(Context context, ServiceListener l) {
+ /*package*/ BluetoothGattServer(Context context, IBluetoothGatt iGatt) {
mContext = context;
- mServiceListener = l;
+ mService = iGatt;
mAdapter = BluetoothAdapter.getDefaultAdapter();
+ mCallback = null;
+ mServerIf = 0;
mServices = new ArrayList<BluetoothGattService>();
-
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
- try {
- mgr.registerStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to register BluetoothStateChangeCallback", re);
- }
- } else {
- Log.e(TAG, "Unable to get BluetoothManager interface.");
- throw new RuntimeException("BluetoothManager inactive");
- }
-
- //Bind to the service only if the Bluetooth is ON
- if(mAdapter.isEnabled()){
- if (!context.bindService(new Intent(IBluetoothGatt.class.getName()), mConnection, 0)) {
- Log.e(TAG, "Could not bind to Bluetooth Gatt Service");
- }
- }
}
/**
@@ -372,29 +292,75 @@
*/
/*package*/ void close() {
if (DBG) Log.d(TAG, "close()");
+ unregisterCallback();
+ }
- unregisterApp();
- mServiceListener = null;
+ /**
+ * Register an application callback to start using GattServer.
+ *
+ * <p>This is an asynchronous call. The callback is used to notify
+ * success or failure if the function returns true.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param callback GATT callback handler that will receive asynchronous
+ * callbacks.
+ * @return true, the callback will be called to notify success or failure,
+ * false on immediate error
+ */
+ /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
+ if (DBG) Log.d(TAG, "registerCallback()");
+ if (mService == null) {
+ Log.e(TAG, "GATT service not available");
+ return false;
+ }
+ UUID uuid = UUID.randomUUID();
+ if (DBG) Log.d(TAG, "registerCallback() - UUID=" + uuid);
- IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE);
- if (b != null) {
- IBluetoothManager mgr = IBluetoothManager.Stub.asInterface(b);
+ synchronized(mServerIfLock) {
+ if (mCallback != null) {
+ Log.e(TAG, "App can register callback only once");
+ return false;
+ }
+
+ mCallback = callback;
try {
- mgr.unregisterStateChangeCallback(mBluetoothStateChangeCallback);
- } catch (RemoteException re) {
- Log.e(TAG, "Unable to unregister BluetoothStateChangeCallback", re);
+ mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ mCallback = null;
+ return false;
+ }
+
+ try {
+ mServerIfLock.wait(CALLBACK_REG_TIMEOUT);
+ } catch (InterruptedException e) {
+ Log.e(TAG, "" + e);
+ mCallback = null;
+ }
+
+ if (mServerIf == 0) {
+ mCallback = null;
+ return false;
+ } else {
+ return true;
}
}
+ }
- synchronized (mConnection) {
- if (mService != null) {
- try {
- mService = null;
- mContext.unbindService(mConnection);
- } catch (Exception re) {
- Log.e(TAG,"",re);
- }
- }
+ /**
+ * Unregister the current application and callbacks.
+ */
+ private void unregisterCallback() {
+ if (DBG) Log.d(TAG, "unregisterCallback() - mServerIf=" + mServerIf);
+ if (mService == null || mServerIf == 0) return;
+
+ try {
+ mCallback = null;
+ mService.unregisterServer(mServerIf);
+ mServerIf = 0;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
}
}
@@ -414,123 +380,7 @@
}
/**
- * Register an application callback to start using Gatt.
- *
- * <p>This is an asynchronous call. The callback is used to notify
- * success or failure if the function returns true.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param callback Gatt callback handler that will receive asynchronous
- * callbacks.
- * @return true, if application was successfully registered.
- */
- public boolean registerApp(BluetoothGattServerCallback callback) {
- if (DBG) Log.d(TAG, "registerApp()");
- if (mService == null) return false;
-
- mCallback = callback;
- UUID uuid = UUID.randomUUID();
- if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
-
- try {
- mService.registerServer(new ParcelUuid(uuid), mBluetoothGattServerCallback);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Unregister the current application and callbacks.
- */
- public void unregisterApp() {
- if (DBG) Log.d(TAG, "unregisterApp() - mServerIf=" + mServerIf);
- if (mService == null || mServerIf == 0) return;
-
- try {
- mCallback = null;
- mService.unregisterServer(mServerIf);
- mServerIf = 0;
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Starts a scan for Bluetooth LE devices.
- *
- * <p>Results of the scan are reported using the
- * {@link BluetoothGattServerCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return true, if the scan was started successfully
- */
- public boolean startScan() {
- if (DBG) Log.d(TAG, "startScan()");
- if (mService == null || mServerIf == 0) return false;
-
- try {
- mService.startScan(mServerIf, true);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Starts a scan for Bluetooth LE devices, looking for devices that
- * advertise given services.
- *
- * <p>Devices which advertise all specified services are reported using the
- * {@link BluetoothGattServerCallback#onScanResult} callback.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param serviceUuids Array of services to look for
- * @return true, if the scan was started successfully
- */
- public boolean startScan(UUID[] serviceUuids) {
- if (DBG) Log.d(TAG, "startScan() - with UUIDs");
- if (mService == null || mServerIf == 0) return false;
-
- try {
- ParcelUuid[] uuids = new ParcelUuid[serviceUuids.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(serviceUuids[i]);
- }
- mService.startScanWithUuids(mServerIf, true, uuids);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- return false;
- }
-
- return true;
- }
-
- /**
- * Stops an ongoing Bluetooth LE device scan.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- */
- public void stopScan() {
- if (DBG) Log.d(TAG, "stopScan()");
- if (mService == null || mServerIf == 0) return;
-
- try {
- mService.stopScan(mServerIf, true);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Initiate a connection to a Bluetooth Gatt capable device.
+ * Initiate a connection to a Bluetooth GATT capable device.
*
* <p>The connection may not be established right away, but will be
* completed when the remote device is available. A
@@ -542,11 +392,10 @@
* when the remote device is in range/available. Generally, the first ever
* connection to a device should be direct (autoConnect set to false) and
* subsequent connections to known devices should be invoked with the
- * autoConnect parameter set to false.
+ * autoConnect parameter set to true.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param device Remote device to connect to
* @param autoConnect Whether to directly connect to the remote device (false)
* or to automatically connect as soon as the remote
* device becomes available (true).
@@ -590,7 +439,7 @@
* Send a response to a read or write request to a remote device.
*
* <p>This function must be invoked in when a remote read/write request
- * is received by one of these callback methots:
+ * is received by one of these callback methods:
*
* <ul>
* <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
@@ -662,17 +511,17 @@
}
/**
- * Add a service to the list of services to be advertised.
+ * Add a service to the list of services to be hosted.
*
* <p>Once a service has been addded to the the list, the service and it's
- * included characteristics will be advertised by the local device.
+ * included characteristics will be provided by the local device.
*
- * <p>If the local device is already advertising services when this function
+ * <p>If the local device has already exposed services when this function
* is called, a service update notification will be sent to all clients.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param service Service to be added to the list of services advertised
+ * @param service Service to be added to the list of services provided
* by this device.
* @return true, if the service has been added successfully
*/
@@ -721,11 +570,11 @@
}
/**
- * Removes a service from the list of services to be advertised.
+ * Removes a service from the list of services to be provided.
*
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
- * @param service Service to beremoved.
+ * @param service Service to be removed.
* @return true, if the service has been removed
*/
public boolean removeService(BluetoothGattService service) {
@@ -749,7 +598,7 @@
}
/**
- * Remove all services from the list of advertised services.
+ * Remove all services from the list of provided services.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*/
public void clearServices() {
@@ -765,7 +614,7 @@
}
/**
- * Returns a list of GATT services offered bu this device.
+ * Returns a list of GATT services offered by this device.
*
* <p>An application must call {@link #addService} to add a serice to the
* list of services offered by this device.
@@ -802,99 +651,40 @@
return null;
}
+
/**
- * Get the current connection state of the profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param device Remote bluetooth device.
- * @return State of the profile connection. One of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING}
+ * @throws UnsupportedOperationException
*/
@Override
public int getConnectionState(BluetoothDevice device) {
- if (DBG) Log.d(TAG,"getConnectionState()");
- if (mService == null) return STATE_DISCONNECTED;
-
- List<BluetoothDevice> connectedDevices = getConnectedDevices();
- for(BluetoothDevice connectedDevice : connectedDevices) {
- if (device.equals(connectedDevice)) {
- return STATE_CONNECTED;
- }
- }
-
- return STATE_DISCONNECTED;
+ throw new UnsupportedOperationException("Use BluetoothManager#getConnectionState instead.");
}
/**
- * Get connected devices for the Gatt profile.
+ * Not supported - please use {@link BluetoothManager#getConnectedDevices(int)}
+ * with {@link BluetoothProfile#GATT} as argument
*
- * <p> Return the set of devices which are in state {@link #STATE_CONNECTED}
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getConnectedDevices() {
- if (DBG) Log.d(TAG,"getConnectedDevices");
-
- List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
- if (mService == null) return connectedDevices;
-
- try {
- connectedDevices = mService.getDevicesMatchingConnectionStates(
- new int[] { BluetoothProfile.STATE_CONNECTED });
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return connectedDevices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getConnectedDevices instead.");
}
/**
- * Get a list of devices that match any of the given connection
- * states.
+ * Not supported - please use
+ * {@link BluetoothManager#getDevicesMatchingConnectionStates(int, int[])}
+ * with {@link BluetoothProfile#GATT} as first argument
*
- * <p> If none of the devices match any of the given states,
- * an empty list will be returned.
- *
- * <p>This is not specific to any application configuration but represents
- * the connection state of the local Bluetooth adapter for this profile.
- * This can be used by applications like status bar which would just like
- * to know the state of the local adapter.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param states Array of states. States can be one of
- * {@link #STATE_CONNECTED}, {@link #STATE_CONNECTING},
- * {@link #STATE_DISCONNECTED}, {@link #STATE_DISCONNECTING},
- * @return List of devices. The list will be empty on error.
+ * @throws UnsupportedOperationException
*/
@Override
public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
- if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
-
- List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
- if (mService == null) return devices;
-
- try {
- devices = mService.getDevicesMatchingConnectionStates(states);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
-
- return devices;
+ throw new UnsupportedOperationException
+ ("Use BluetoothManager#getDevicesMatchingConnectionStates instead.");
}
}
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 4f608ff..f9f1d97 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -22,30 +22,8 @@
/**
* This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- * @hide
*/
public abstract class BluetoothGattServerCallback {
- /**
- * Callback to inform change in registration state of the application.
- *
- * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the application
- * was successfully registered.
- */
- public void onAppRegistered(int status) {
- }
-
- /**
- * Callback reporting an LE device found during a device scan initiated
- * by the {@link BluetoothGattServer#startScan} 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 onScanResult(BluetoothDevice device, int rssi, byte[] scanRecord) {
- }
/**
* Callback indicating when a remote device has been connected or disconnected.
@@ -101,9 +79,9 @@
* @param value The value the client wants to assign to the characteristic
*/
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattCharacteristic characteristic,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
+ BluetoothGattCharacteristic characteristic,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
}
/**
@@ -118,7 +96,7 @@
* @param descriptor Descriptor to be read
*/
public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
- int offset, BluetoothGattDescriptor descriptor) {
+ int offset, BluetoothGattDescriptor descriptor) {
}
/**
@@ -137,9 +115,9 @@
* @param value The value the client wants to assign to the descriptor
*/
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
- BluetoothGattDescriptor descriptor,
- boolean preparedWrite, boolean responseNeeded,
- int offset, byte[] value) {
+ BluetoothGattDescriptor descriptor,
+ boolean preparedWrite, boolean responseNeeded,
+ int offset, byte[] value) {
}
/**
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 6a3ce66e..c3b3cfe 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -22,8 +22,7 @@
import java.util.UUID;
/**
- * Represents a Bluetooth Gatt Service
- * @hide
+ * Represents a Bluetooth GATT Service
*/
public class BluetoothGattService {
@@ -81,9 +80,14 @@
/**
* Create a new BluetoothGattService.
- * @hide
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param uuid The UUID for this service
+ * @param serviceType The type of this service,
+ * {@link BluetoothGattService#SERVICE_TYPE_PRIMARY} or
+ * {@link BluetoothGattService#SERVICE_TYPE_SECONDARY}
*/
- /*package*/ BluetoothGattService(UUID uuid, int serviceType) {
+ public BluetoothGattService(UUID uuid, int serviceType) {
mDevice = null;
mUuid = uuid;
mInstanceId = 0;
@@ -115,11 +119,28 @@
}
/**
- * Add a characteristic to this service.
- * @hide
+ * Add an included service to this service.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param service The service to be added
+ * @return true, if the included service was added to the service
*/
- /*package*/ void addCharacteristic(BluetoothGattCharacteristic characteristic) {
+ public boolean addService(BluetoothGattService service) {
+ mIncludedServices.add(service);
+ return true;
+ }
+
+ /**
+ * Add a characteristic to this service.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param characteristic The characteristics to be added
+ * @return true, if the characteristic was added to the service
+ */
+ public boolean addCharacteristic(BluetoothGattCharacteristic characteristic) {
mCharacteristics.add(characteristic);
+ characteristic.setService(this);
+ return true;
}
/**
@@ -136,6 +157,15 @@
}
/**
+ * Force the instance ID.
+ * This is needed for conformance testing only.
+ * @hide
+ */
+ public void setInstanceId(int instanceId) {
+ mInstanceId = instanceId;
+ }
+
+ /**
* Get the handle count override (conformance testing.
* @hide
*/
@@ -144,6 +174,15 @@
}
/**
+ * Force the number of handles to reserve for this service.
+ * This is needed for conformance testing only.
+ * @hide
+ */
+ public void setHandles(int handles) {
+ mHandles = handles;
+ }
+
+ /**
* Add an included service to the internal map.
* @hide
*/
@@ -153,7 +192,6 @@
/**
* Returns the UUID of this service
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this service
*/
@@ -168,8 +206,6 @@
* (ex. multiple battery services for different batteries), the instance
* ID is used to distuinguish services.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
* @return Instance ID of this service
*/
public int getInstanceId() {
@@ -178,15 +214,13 @@
/**
* Get the type of this service (primary/secondary)
- * @hide
*/
public int getType() {
return mServiceType;
}
/**
- * Get the list of included Gatt services for this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ * Get the list of included GATT services for this service.
*
* @return List of included services or empty list if no included services
* were discovered.
@@ -197,7 +231,6 @@
/**
* Returns a list of characteristics included in this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Characteristics included in this service
*/
@@ -217,9 +250,7 @@
* UUID, the first instance of a characteristic with the given UUID
* is returned.
*
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @return Gatt characteristic object or null if no characteristic with the
+ * @return GATT characteristic object or null if no characteristic with the
* given UUID was found.
*/
public BluetoothGattCharacteristic getCharacteristic(UUID uuid) {
diff --git a/core/java/android/bluetooth/BluetoothManager.java b/core/java/android/bluetooth/BluetoothManager.java
new file mode 100644
index 0000000..19083b5
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothManager.java
@@ -0,0 +1,219 @@
+/*
+ * 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.content.Context;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * High level manager used to obtain an instance of an {@link BluetoothAdapter}
+ * and to conduct overall Bluetooth Management.
+ * <p>
+ * Use {@link android.content.Context#getSystemService(java.lang.String)}
+ * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager},
+ * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}.
+ * <p>
+ * Alternately, you can just call the static helper
+ * {@link BluetoothAdapter#getDefaultAdapter()}.
+ *
+ * <div class="special reference">
+ * <h3>Developer Guides</h3>
+ * <p>For more information about using BLUETOOTH, read the
+ * <a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer guide.</p>
+ * </div>
+ *
+ * @see Context#getSystemService
+ * @see BluetoothAdapter#getDefaultAdapter()
+ */
+public final class BluetoothManager {
+ private static final String TAG = "BluetoothManager";
+ private static final boolean DBG = true;
+ private static final boolean VDBG = true;
+
+ private final BluetoothAdapter mAdapter;
+
+ /**
+ * @hide
+ */
+ public BluetoothManager(Context context) {
+ context = context.getApplicationContext();
+ if (context == null) {
+ throw new IllegalArgumentException(
+ "context not associated with any application (using a mock context?)");
+ }
+ // Legacy api - getDefaultAdapter does not take in the context
+ mAdapter = BluetoothAdapter.getDefaultAdapter();
+ }
+
+ /**
+ * Get the default BLUETOOTH Adapter for this device.
+ *
+ * @return the default BLUETOOTH Adapter
+ */
+ public BluetoothAdapter getAdapter() {
+ return mAdapter;
+ }
+
+ /**
+ * Get the current connection state of the profile to the remote device.
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of the local Bluetooth adapter for certain profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of Bluetooth.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param device Remote bluetooth device.
+ * @param profile GATT or GATT_SERVER
+ * @return State of the profile connection. One of
+ * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING},
+ * {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_DISCONNECTING}
+ */
+ public int getConnectionState(BluetoothDevice device, int profile) {
+ if (DBG) Log.d(TAG,"getConnectionState()");
+
+ List<BluetoothDevice> connectedDevices = getConnectedDevices(profile);
+ for(BluetoothDevice connectedDevice : connectedDevices) {
+ if (device.equals(connectedDevice)) {
+ return BluetoothProfile.STATE_CONNECTED;
+ }
+ }
+
+ return BluetoothProfile.STATE_DISCONNECTED;
+ }
+
+ /**
+ * Get connected devices for the specified profile.
+ *
+ * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED}
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of Bluetooth for this profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of Bluetooth.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param profile GATT or GATT_SERVER
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getConnectedDevices(int profile) {
+ if (DBG) Log.d(TAG,"getConnectedDevices");
+ if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
+ throw new IllegalArgumentException("Profile not supported: " + profile);
+ }
+
+ List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>();
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) return connectedDevices;
+
+ connectedDevices = iGatt.getDevicesMatchingConnectionStates(
+ new int[] { BluetoothProfile.STATE_CONNECTED });
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+
+ return connectedDevices;
+ }
+
+ /**
+ *
+ * Get a list of devices that match any of the given connection
+ * states.
+ *
+ * <p> If none of the devices match any of the given states,
+ * an empty list will be returned.
+ *
+ * <p>This is not specific to any application configuration but represents
+ * the connection state of the local Bluetooth adapter for this profile.
+ * This can be used by applications like status bar which would just like
+ * to know the state of the local adapter.
+ *
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+ *
+ * @param profile GATT or GATT_SERVER
+ * @param states Array of states. States can be one of
+ * {@link BluetoothProfile#STATE_CONNECTED}, {@link BluetoothProfile#STATE_CONNECTING},
+ * {@link BluetoothProfile#STATE_DISCONNECTED},
+ * {@link BluetoothProfile#STATE_DISCONNECTING},
+ * @return List of devices. The list will be empty on error.
+ */
+ public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) {
+ if (DBG) Log.d(TAG,"getDevicesMatchingConnectionStates");
+
+ if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) {
+ throw new IllegalArgumentException("Profile not supported: " + profile);
+ }
+
+ List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) return devices;
+ devices = iGatt.getDevicesMatchingConnectionStates(states);
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ }
+
+ return devices;
+ }
+
+ /**
+ * Open a GATT Server
+ * The callback is used to deliver results to Caller, such as connection status as well
+ * as the results of any other GATT server operations.
+ * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer
+ * to conduct GATT server operations.
+ * @param context App context
+ * @param callback GATT server callback handler that will receive asynchronous callbacks.
+ * @return BluetoothGattServer instance
+ */
+ public BluetoothGattServer openGattServer(Context context,
+ BluetoothGattServerCallback callback) {
+ if (context == null || callback == null) {
+ throw new IllegalArgumentException("null parameter: " + context + " " + callback);
+ }
+
+ // TODO(Bluetooth) check whether platform support BLE
+ // Do the check here or in GattServer?
+
+ try {
+ IBluetoothManager managerService = mAdapter.getBluetoothManager();
+ IBluetoothGatt iGatt = (IBluetoothGatt) managerService.getBluetoothGatt();
+ if (iGatt == null) {
+ Log.e(TAG, "Fail to get GATT Server connection");
+ return null;
+ }
+ BluetoothGattServer mGattServer = new BluetoothGattServer(context, iGatt);
+ Boolean regStatus = mGattServer.registerCallback(callback);
+ return regStatus? mGattServer : null;
+ } catch (RemoteException e) {
+ Log.e(TAG,"",e);
+ return null;
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 9ee202a..43079f4 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -89,13 +89,11 @@
/**
* GATT
- * @hide
*/
static public final int GATT = 7;
/**
* GATT_SERVER
- * @hide
*/
static public final int GATT_SERVER = 8;
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
index ed8777c..493d2f8 100755
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -17,6 +17,7 @@
package android.bluetooth;
import android.bluetooth.IBluetooth;
+import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothManagerCallback;
import android.bluetooth.IBluetoothStateChangeCallback;
@@ -35,6 +36,7 @@
boolean enable();
boolean enableNoAutoConnect();
boolean disable(boolean persist);
+ IBluetoothGatt getBluetoothGatt();
String getAddress();
String getName();
diff --git a/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java b/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java
deleted file mode 100644
index c05abb2..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattCharacteristic.java
+++ /dev/null
@@ -1,67 +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 java.util.ArrayList;
-import java.util.IllegalFormatConversionException;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Mutable variant of a Bluetooth Gatt Characteristic
- * @hide
- */
-public class MutableBluetoothGattCharacteristic extends BluetoothGattCharacteristic {
-
- /**
- * Create a new MutableBluetoothGattCharacteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this characteristic
- * @param properties Properties of this characteristic
- * @param permissions Permissions for this characteristic
- */
- public MutableBluetoothGattCharacteristic(UUID uuid, int properties, int permissions) {
- super(null, uuid, 0, properties, permissions);
- }
-
- /**
- * Adds a descriptor to this characteristic.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param descriptor Descriptor to be added to this characteristic.
- */
- public void addDescriptor(MutableBluetoothGattDescriptor descriptor) {
- mDescriptors.add(descriptor);
- descriptor.setCharacteristic(this);
- }
-
- /**
- * Set the desired key size.
- * @hide
- */
- public void setKeySize(int keySize) {
- mKeySize = keySize;
- }
-
- /**
- * Sets the service associated with this device.
- * @hide
- */
- /*package*/ void setService(BluetoothGattService service) {
- mService = service;
- }
-}
diff --git a/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java b/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java
deleted file mode 100644
index e455392..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattDescriptor.java
+++ /dev/null
@@ -1,45 +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 java.util.UUID;
-
-/**
- * Mutable variant of a Bluetooth Gatt Descriptor
- * @hide
- */
-public class MutableBluetoothGattDescriptor extends BluetoothGattDescriptor {
-
- /**
- * Create a new BluetoothGattDescriptor.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this descriptor
- * @param permissions Permissions for this descriptor
- */
- public MutableBluetoothGattDescriptor(UUID uuid, int permissions) {
- super(null, uuid, permissions);
- }
-
- /**
- * Set the back-reference to the associated characteristic
- * @hide
- */
- /*package*/ void setCharacteristic(BluetoothGattCharacteristic characteristic) {
- mCharacteristic = characteristic;
- }
-}
diff --git a/core/java/android/bluetooth/MutableBluetoothGattService.java b/core/java/android/bluetooth/MutableBluetoothGattService.java
deleted file mode 100644
index 927f5ab..0000000
--- a/core/java/android/bluetooth/MutableBluetoothGattService.java
+++ /dev/null
@@ -1,83 +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;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.UUID;
-
-/**
- * Represents a Bluetooth Gatt Service
- * @hide
- */
-public class MutableBluetoothGattService extends BluetoothGattService {
-
- /**
- * Create a new MutableBluetoothGattService.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param uuid The UUID for this service
- * @param serviceType The type of this service (primary/secondary)
- */
- public MutableBluetoothGattService(UUID uuid, int serviceType) {
- super(uuid, serviceType);
- }
-
- /**
- * Add an included service to this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param service The service to be added
- * @return true, if the included service was added to the service
- */
- public boolean addService(BluetoothGattService service) {
- mIncludedServices.add(service);
- return true;
- }
-
- /**
- * Add a characteristic to this service.
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param characteristic The characteristics to be added
- * @return true, if the characteristic was added to the service
- */
- public boolean addCharacteristic(MutableBluetoothGattCharacteristic characteristic) {
- mCharacteristics.add(characteristic);
- characteristic.setService(this);
- return true;
- }
-
- /**
- * Force the instance ID.
- * This is needed for conformance testing only.
- * @hide
- */
- public void setInstanceId(int instanceId) {
- mInstanceId = instanceId;
- }
-
- /**
- * Force the number of handles to reserve for this service.
- * This is needed for conformance testing only.
- * @hide
- */
- public void setHandles(int handles) {
- mHandles = handles;
- }
-}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 7dd76cd..ef9b0bf 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2203,7 +2203,6 @@
* {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
*
* @see #getSystemService
- * @hide
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";