Merge "Unhide Bluetooth Low Energy public APIs" into jb-mr2-dev

This commit is contained in:
Matthew Xie
2013-03-28 23:04:47 +00:00
committed by Android (Google) Code Review
20 changed files with 1207 additions and 1025 deletions

View File

@ -4613,8 +4613,13 @@ package android.bluetooth {
method public boolean isEnabled();
method public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(java.lang.String, java.util.UUID) throws java.io.IOException;
method public boolean registerCallback(android.bluetooth.BluetoothAdapterCallback);
method public boolean setName(java.lang.String);
method public boolean startDiscovery();
method public boolean startLeScan();
method public boolean startLeScan(java.util.UUID[]);
method public void stopLeScan();
method public boolean unRegisterCallback(android.bluetooth.BluetoothAdapterCallback);
field public static final java.lang.String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED";
field public static final java.lang.String ACTION_DISCOVERY_FINISHED = "android.bluetooth.adapter.action.DISCOVERY_FINISHED";
field public static final java.lang.String ACTION_DISCOVERY_STARTED = "android.bluetooth.adapter.action.DISCOVERY_STARTED";
@ -4645,6 +4650,14 @@ package android.bluetooth {
field public static final int STATE_TURNING_ON = 11; // 0xb
}
public abstract class BluetoothAdapterCallback {
ctor public BluetoothAdapterCallback();
method public void onCallbackRegistration(int);
method public void onLeScan(android.bluetooth.BluetoothDevice, int, byte[]);
field public static final int CALLBACK_REGISTERED = 0; // 0x0
field public static final int CALLBACK_REGISTRATION_FAILURE = 1; // 0x1
}
public class BluetoothAssignedNumbers {
field public static final int ACCEL_SEMICONDUCTOR = 74; // 0x4a
field public static final int ALCATEL = 36; // 0x24
@ -4837,6 +4850,7 @@ package android.bluetooth {
}
public final class BluetoothDevice implements android.os.Parcelable {
method public android.bluetooth.BluetoothGatt connectGattServer(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
method public int describeContents();
@ -4869,6 +4883,159 @@ package android.bluetooth {
field public static final java.lang.String EXTRA_UUID = "android.bluetooth.device.extra.UUID";
}
public final class BluetoothGatt implements android.bluetooth.BluetoothProfile {
method public void abortReliableWrite(android.bluetooth.BluetoothDevice);
method public boolean beginReliableWrite();
method public void disconnect();
method public boolean discoverServices();
method public boolean executeReliableWrite();
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public int getConnectionState(android.bluetooth.BluetoothDevice);
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
method public boolean readCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean readDescriptor(android.bluetooth.BluetoothGattDescriptor);
method public boolean readRemoteRssi();
method public boolean setCharacteristicNotification(android.bluetooth.BluetoothGattCharacteristic, boolean);
method public boolean writeCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean writeDescriptor(android.bluetooth.BluetoothGattDescriptor);
field public static final int GATT_FAILURE = 0; // 0x0
field public static final int GATT_INSUFFICIENT_AUTHENTICATION = 5; // 0x5
field public static final int GATT_INSUFFICIENT_ENCRYPTION = 15; // 0xf
field public static final int GATT_INVALID_ATTRIBUTE_LENGTH = 13; // 0xd
field public static final int GATT_INVALID_OFFSET = 7; // 0x7
field public static final int GATT_READ_NOT_PERMITTED = 2; // 0x2
field public static final int GATT_REQUEST_NOT_SUPPORTED = 6; // 0x6
field public static final int GATT_SUCCESS = 0; // 0x0
field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
}
public abstract class BluetoothGattCallback {
ctor public BluetoothGattCallback();
method public void onCharacteristicChanged(android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicRead(android.bluetooth.BluetoothGattCharacteristic, int);
method public void onCharacteristicWrite(android.bluetooth.BluetoothGattCharacteristic, int);
method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
method public void onDescriptorRead(android.bluetooth.BluetoothGattDescriptor, int);
method public void onDescriptorWrite(android.bluetooth.BluetoothGattDescriptor, int);
method public void onReadRemoteRssi(android.bluetooth.BluetoothDevice, int, int);
method public void onReliableWriteCompleted(android.bluetooth.BluetoothDevice, int);
method public void onServicesDiscovered(android.bluetooth.BluetoothDevice, int);
}
public class BluetoothGattCharacteristic {
ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
method public java.lang.Float getFloatValue(int, int);
method public int getInstanceId();
method public java.lang.Integer getIntValue(int, int);
method public int getPermissions();
method public int getProperties();
method public android.bluetooth.BluetoothGattService getService();
method public java.lang.String getStringValue(int);
method public java.util.UUID getUuid();
method public byte[] getValue();
method public int getWriteType();
method public boolean setValue(byte[]);
method public boolean setValue(int, int, int);
method public boolean setValue(int, int, int, int);
method public boolean setValue(java.lang.String);
method public void setWriteType(int);
field public static final int FORMAT_FLOAT = 52; // 0x34
field public static final int FORMAT_SFLOAT = 50; // 0x32
field public static final int FORMAT_SINT16 = 34; // 0x22
field public static final int FORMAT_SINT32 = 36; // 0x24
field public static final int FORMAT_SINT8 = 33; // 0x21
field public static final int FORMAT_UINT16 = 18; // 0x12
field public static final int FORMAT_UINT32 = 20; // 0x14
field public static final int FORMAT_UINT8 = 17; // 0x11
field public static final int PERMISSION_READ = 1; // 0x1
field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
field public static final int PERMISSION_WRITE = 16; // 0x10
field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
field public static final int PROPERTY_BROADCAST = 1; // 0x1
field public static final int PROPERTY_EXTENDED_PROPS = 128; // 0x80
field public static final int PROPERTY_INDICATE = 32; // 0x20
field public static final int PROPERTY_NOTIFY = 16; // 0x10
field public static final int PROPERTY_READ = 2; // 0x2
field public static final int PROPERTY_SIGNED_WRITE = 64; // 0x40
field public static final int PROPERTY_WRITE = 8; // 0x8
field public static final int PROPERTY_WRITE_NO_RESPONSE = 4; // 0x4
field public static final int WRITE_TYPE_DEFAULT = 2; // 0x2
field public static final int WRITE_TYPE_NO_RESPONSE = 1; // 0x1
field public static final int WRITE_TYPE_SIGNED = 4; // 0x4
field protected java.util.List mDescriptors;
}
public class BluetoothGattDescriptor {
ctor public BluetoothGattDescriptor(java.util.UUID, int);
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
method public int getPermissions();
method public java.util.UUID getUuid();
method public byte[] getValue();
method public boolean setValue(byte[]);
field public static final byte[] DISABLE_NOTIFICATION_VALUE;
field public static final byte[] ENABLE_INDICATION_VALUE;
field public static final byte[] ENABLE_NOTIFICATION_VALUE;
field public static final int PERMISSION_READ = 1; // 0x1
field public static final int PERMISSION_READ_ENCRYPTED = 2; // 0x2
field public static final int PERMISSION_READ_ENCRYPTED_MITM = 4; // 0x4
field public static final int PERMISSION_WRITE = 16; // 0x10
field public static final int PERMISSION_WRITE_ENCRYPTED = 32; // 0x20
field public static final int PERMISSION_WRITE_ENCRYPTED_MITM = 64; // 0x40
field public static final int PERMISSION_WRITE_SIGNED = 128; // 0x80
field public static final int PERMISSION_WRITE_SIGNED_MITM = 256; // 0x100
}
public final class BluetoothGattServer implements android.bluetooth.BluetoothProfile {
method public boolean addService(android.bluetooth.BluetoothGattService);
method public void cancelConnection(android.bluetooth.BluetoothDevice);
method public void clearServices();
method public boolean connect(android.bluetooth.BluetoothDevice, boolean);
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public int getConnectionState(android.bluetooth.BluetoothDevice);
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
method public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
method public boolean removeService(android.bluetooth.BluetoothGattService);
method public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
}
public abstract class BluetoothGattServerCallback {
ctor public BluetoothGattServerCallback();
method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
method public void onDescriptorReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattDescriptor);
method public void onDescriptorWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattDescriptor, boolean, boolean, int, byte[]);
method public void onExecuteWrite(android.bluetooth.BluetoothDevice, int, boolean);
method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
}
public class BluetoothGattService {
ctor public BluetoothGattService(java.util.UUID, int);
method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean addService(android.bluetooth.BluetoothGattService);
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
method public int getInstanceId();
method public int getType();
method public java.util.UUID getUuid();
field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
field protected java.util.List mCharacteristics;
field protected java.util.List mIncludedServices;
}
public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public int getConnectionState(android.bluetooth.BluetoothDevice);
@ -4931,6 +5098,14 @@ package android.bluetooth {
method public void onHealthChannelStateChange(android.bluetooth.BluetoothHealthAppConfiguration, android.bluetooth.BluetoothDevice, int, int, android.os.ParcelFileDescriptor, int);
}
public final class BluetoothManager {
method public android.bluetooth.BluetoothAdapter getAdapter();
method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
method public int getConnectionState(android.bluetooth.BluetoothDevice, int);
method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int, int[]);
method public android.bluetooth.BluetoothGattServer openGattServer(android.content.Context, android.bluetooth.BluetoothGattServerCallback);
}
public abstract interface BluetoothProfile {
method public abstract java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
method public abstract int getConnectionState(android.bluetooth.BluetoothDevice);
@ -4938,6 +5113,8 @@ package android.bluetooth {
field public static final int A2DP = 2; // 0x2
field public static final java.lang.String EXTRA_PREVIOUS_STATE = "android.bluetooth.profile.extra.PREVIOUS_STATE";
field public static final java.lang.String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
field public static final int GATT = 7; // 0x7
field public static final int GATT_SERVER = 8; // 0x8
field public static final int HEADSET = 1; // 0x1
field public static final int HEALTH = 3; // 0x3
field public static final int STATE_CONNECTED = 2; // 0x2
@ -5495,6 +5672,7 @@ package android.content {
field public static final int BIND_IMPORTANT = 64; // 0x40
field public static final int BIND_NOT_FOREGROUND = 4; // 0x4
field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20
field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
@ -6658,6 +6836,7 @@ package android.content.pm {
method public abstract boolean addPermission(android.content.pm.PermissionInfo);
method public abstract boolean addPermissionAsync(android.content.pm.PermissionInfo);
method public abstract deprecated void addPreferredActivity(android.content.IntentFilter, int, android.content.ComponentName[], android.content.ComponentName);
method public android.content.Intent buildPermissionRequestIntent(java.lang.String...);
method public abstract java.lang.String[] canonicalToCurrentPackageNames(java.lang.String[]);
method public abstract int checkPermission(java.lang.String, java.lang.String);
method public abstract int checkSignatures(java.lang.String, java.lang.String);
@ -6717,7 +6896,6 @@ package android.content.pm {
method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract deprecated void removePackageFromPreferred(java.lang.String);
method public abstract void removePermission(java.lang.String);
method public android.content.Intent buildPermissionRequestIntent(java.lang.String...);
method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int);
method public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int);
method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int);
@ -16810,13 +16988,13 @@ package android.os {
method public void setUserRestriction(java.lang.String, boolean);
method public void setUserRestrictions(android.os.Bundle);
method public void setUserRestrictions(android.os.Bundle, android.os.UserHandle);
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_CONFIG_WIFI = "no_config_wifi";
field public static final java.lang.String DISALLOW_INSTALL_APPS = "no_install_apps";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts";
field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location";
field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps";
field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources";
field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth";
field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer";
}

View File

@ -19,7 +19,7 @@ package android.app;
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 @@ class ContextImpl extends Context {
registerService(BLUETOOTH_SERVICE, new ServiceFetcher() {
public Object createService(ContextImpl ctx) {
return BluetoothAdapter.getDefaultAdapter();
return new BluetoothManager(ctx);
}});
registerService(CLIPBOARD_SERVICE, new ServiceFetcher() {

View File

@ -22,7 +22,6 @@ import android.content.Context;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
@ -359,6 +358,8 @@ public final class BluetoothAdapter {
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 @@ public final class BluetoothAdapter {
* 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 @@ public final class BluetoothAdapter {
} 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 @@ public final class BluetoothAdapter {
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
}
};
}

View File

@ -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) {
}
}

View File

@ -18,6 +18,7 @@ package android.bluetooth;
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 @@ public final class BluetoothDevice implements Parcelable {
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;
}
}

View File

@ -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.List;
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 */
@ -110,55 +114,6 @@ public final class BluetoothGatt implements BluetoothProfile {
*/
/*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
*/
@ -171,11 +126,27 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
* @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 final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 final class BluetoothGatt implements BluetoothProfile {
*/
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 final class BluetoothGatt implements BluetoothProfile {
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 final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
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 @@ public final class BluetoothGatt implements BluetoothProfile {
/**
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
/**
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
* 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 @@ public final class BluetoothGatt implements BluetoothProfile {
*
* <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 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
* 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.");
}
}

View File

@ -18,34 +18,10 @@ package android.bluetooth;
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 @@ public abstract class BluetoothGattCallback {
}
/**
* 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 @@ public abstract class BluetoothGattCallback {
* @param status The result of the write operation
*/
public void onCharacteristicWrite(BluetoothGattCharacteristic characteristic,
int status) {
int status) {
}
/**
@ -113,23 +89,21 @@ public abstract class BluetoothGattCallback {
* 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 @@ public abstract class BluetoothGattCallback {
*
* @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) {
}

View File

@ -21,8 +21,7 @@ import java.util.List;
import java.util.UUID;
/**
* Represents a Bluetooth Gatt Characteristic
* @hide
* Represents a Bluetooth GATT Characteristic
*/
public class BluetoothGattCharacteristic {
@ -119,7 +118,7 @@ public class BluetoothGattCharacteristic {
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;
@ -218,6 +217,18 @@ public class BluetoothGattCharacteristic {
*/
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
@ -225,6 +236,12 @@ public class BluetoothGattCharacteristic {
/*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 @@ public class BluetoothGattCharacteristic {
}
/**
* 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;
}
/**
@ -264,9 +286,16 @@ public class BluetoothGattCharacteristic {
return mService;
}
/**
* 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 @@ public class BluetoothGattCharacteristic {
* <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 @@ public class BluetoothGattCharacteristic {
* <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 @@ public class BluetoothGattCharacteristic {
/**
* Returns the permissions for this characteristic.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this characteristic
*/
@ -314,7 +338,6 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
* {@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},
@ -344,9 +362,16 @@ public class BluetoothGattCharacteristic {
mWriteType = writeType;
}
/**
* 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 @@ public class BluetoothGattCharacteristic {
* 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 @@ public class BluetoothGattCharacteristic {
* 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 @@ public class BluetoothGattCharacteristic {
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
* {@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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* Returns the size of a give value type.
* @hide
*/
private int getTypeLen(int formatType) {
return formatType & 0xF;
@ -601,7 +615,6 @@ public class BluetoothGattCharacteristic {
/**
* Convert a signed byte to an unsigned int.
* @hide
*/
private int unsignedByteToInt(byte b) {
return b & 0xFF;
@ -609,7 +622,6 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* 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 @@ public class BluetoothGattCharacteristic {
/**
* Convert an integer into the signed bits of a given length.
* @hide
*/
private int intToSignedBits(int i, int size) {
if (i < 0) {

View File

@ -19,8 +19,7 @@ package android.bluetooth;
import java.util.UUID;
/**
* Represents a Bluetooth Gatt Descriptor
* @hide
* Represents a Bluetooth GATT Descriptor
*/
public class BluetoothGattDescriptor {
@ -105,6 +104,17 @@ public class BluetoothGattDescriptor {
*/
protected byte[] mValue;
/**
* 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.
@ -115,6 +125,11 @@ public class BluetoothGattDescriptor {
*/
/*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;
@ -128,9 +143,16 @@ public class BluetoothGattDescriptor {
return mCharacteristic;
}
/**
* 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 @@ public class BluetoothGattDescriptor {
/**
* Returns the permissions for this descriptor.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return Permissions of this descriptor
*/
@ -152,12 +173,10 @@ public class BluetoothGattDescriptor {
* 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 @@ public class BluetoothGattDescriptor {
* {@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.

View File

@ -38,88 +38,30 @@ import java.util.List;
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 final class BluetoothGattServer implements BluetoothProfile {
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 final class BluetoothGattServer implements BluetoothProfile {
*/
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 @@ public final class BluetoothGattServer implements BluetoothProfile {
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 @@ public final class BluetoothGattServer implements BluetoothProfile {
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
*/
/*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 @@ public final class BluetoothGattServer implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
}
/**
* 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 @@ public final class BluetoothGattServer implements BluetoothProfile {
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.");
}
}

View File

@ -22,30 +22,8 @@ import android.util.Log;
/**
* 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 @@ public abstract class BluetoothGattServerCallback {
* @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 @@ public abstract class BluetoothGattServerCallback {
* @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 @@ public abstract class BluetoothGattServerCallback {
* @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) {
}
/**

View File

@ -22,8 +22,7 @@ import java.util.List;
import java.util.UUID;
/**
* Represents a Bluetooth Gatt Service
* @hide
* Represents a Bluetooth GATT Service
*/
public class BluetoothGattService {
@ -81,9 +80,14 @@ public class BluetoothGattService {
/**
* 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 @@ public class BluetoothGattService {
}
/**
* 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;
}
/**
@ -135,6 +156,15 @@ public class BluetoothGattService {
return null;
}
/**
* 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
@ -143,6 +173,15 @@ public class BluetoothGattService {
return mHandles;
}
/**
* 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 @@ public class BluetoothGattService {
/**
* Returns the UUID of this service
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @return UUID of this service
*/
@ -168,8 +206,6 @@ public class BluetoothGattService {
* (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 @@ public class BluetoothGattService {
/**
* 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 @@ public class BluetoothGattService {
/**
* 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 @@ public class BluetoothGattService {
* 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) {

View File

@ -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;
}
}
}

View File

@ -89,13 +89,11 @@ public interface BluetoothProfile {
/**
* GATT
* @hide
*/
static public final int GATT = 7;
/**
* GATT_SERVER
* @hide
*/
static public final int GATT_SERVER = 8;

View File

@ -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 @@ interface IBluetoothManager
boolean enable();
boolean enableNoAutoConnect();
boolean disable(boolean persist);
IBluetoothGatt getBluetoothGatt();
String getAddress();
String getName();

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -2203,7 +2203,6 @@ public abstract class Context {
* {@link android.bluetooth.BluetoothAdapter} for using Bluetooth.
*
* @see #getSystemService
* @hide
*/
public static final String BLUETOOTH_SERVICE = "bluetooth";

View File

@ -19,6 +19,7 @@ package com.android.server;
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetooth;
import android.bluetooth.IBluetoothGatt;
import android.bluetooth.IBluetoothCallback;
import android.bluetooth.IBluetoothManager;
import android.bluetooth.IBluetoothManagerCallback;
@ -87,6 +88,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
// and Airplane mode will have higher priority.
private static final int BLUETOOTH_ON_AIRPLANE=2;
private static final int SERVICE_IBLUETOOTH = 1;
private static final int SERVICE_IBLUETOOTHGATT = 2;
private final Context mContext;
// Locks are not provided for mName and mAddress.
@ -97,6 +101,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
private final RemoteCallbackList<IBluetoothManagerCallback> mCallbacks;
private final RemoteCallbackList<IBluetoothStateChangeCallback> mStateChangeCallbacks;
private IBluetooth mBluetooth;
private IBluetoothGatt mBluetoothGatt;
private boolean mBinding;
private boolean mUnbinding;
// used inside handler thread
@ -463,6 +468,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
}
public IBluetoothGatt getBluetoothGatt() {
// sync protection
return mBluetoothGatt;
}
private void sendBluetoothStateCallback(boolean isUp) {
int n = mStateChangeCallbacks.beginBroadcast();
if (DBG) Log.d(TAG,"Broadcasting onBluetoothStateChange("+isUp+") to " + n + " receivers.");
@ -575,16 +585,35 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
public void onServiceConnected(ComponentName className, IBinder service) {
if (DBG) Log.d(TAG, "BluetoothServiceConnection: connected to AdapterService");
if (DBG) Log.d(TAG, "BluetoothServiceConnection: " + className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_CONNECTED);
// TBD if (className.getClassName().equals(IBluetooth.class.getName())) {
if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
// } else if (className.getClassName().equals(IBluetoothGatt.class.getName())) {
} else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Log.e(TAG, "Unknown service connected: " + className.getClassName());
return;
}
msg.obj = service;
mHandler.sendMessage(msg);
}
public void onServiceDisconnected(ComponentName className) {
// Called if we unexpected disconnected.
if (DBG) Log.d(TAG, "BluetoothServiceConnection: disconnected from AdapterService");
if (DBG) Log.d(TAG, "BluetoothServiceConnection, disconnected: " +
className.getClassName());
Message msg = mHandler.obtainMessage(MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED);
if (className.getClassName().equals("com.android.bluetooth.btservice.AdapterService")) {
msg.arg1 = SERVICE_IBLUETOOTH;
} else if (className.getClassName().equals("com.android.bluetooth.gatt.GattService")) {
msg.arg1 = SERVICE_IBLUETOOTHGATT;
} else {
Log.e(TAG, "Unknown service disconnected: " + className.getClassName());
return;
}
mHandler.sendMessage(msg);
}
}
@ -746,13 +775,18 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
case MESSAGE_BLUETOOTH_SERVICE_CONNECTED:
{
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED");
//Remove timeout
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
if (DBG) Log.d(TAG,"MESSAGE_BLUETOOTH_SERVICE_CONNECTED: " + msg.arg1);
IBinder service = (IBinder) msg.obj;
synchronized(mConnection) {
if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
break;
} // else must be SERVICE_IBLUETOOTH
//Remove timeout
mHandler.removeMessages(MESSAGE_TIMEOUT_BIND);
mBinding = false;
mBluetooth = IBluetooth.Stub.asInterface(service);
@ -816,11 +850,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
}
case MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED:
{
Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED");
Log.e(TAG, "MESSAGE_BLUETOOTH_SERVICE_DISCONNECTED: " + msg.arg1);
synchronized(mConnection) {
// if service is unbinded already, do nothing and return
if (mBluetooth == null) return;
mBluetooth = null;
if (msg.arg1 == SERVICE_IBLUETOOTH) {
// if service is unbinded already, do nothing and return
if (mBluetooth == null) break;
mBluetooth = null;
} else if (msg.arg1 == SERVICE_IBLUETOOTHGATT) {
mBluetoothGatt = null;
break;
} else {
Log.e(TAG, "Bad msg.arg1: " + msg.arg1);
break;
}
}
if (mEnable) {
@ -1048,10 +1090,19 @@ class BluetoothManagerService extends IBluetoothManager.Stub {
boolean isUp = (newState==BluetoothAdapter.STATE_ON);
sendBluetoothStateCallback(isUp);
//If Bluetooth is off, send service down event to proxy objects, and unbind
if (!isUp && canUnbindBluetoothService()) {
sendBluetoothServiceDownCallback();
unbindAndFinish();
if (isUp) {
// connect to GattService
Intent i = new Intent(IBluetoothGatt.class.getName());
if (!mContext.bindServiceAsUser(i, mConnection, Context.BIND_AUTO_CREATE,
UserHandle.CURRENT)) {
Log.e(TAG, "Fail to bind to: " + IBluetoothGatt.class.getName());
}
} else {
//If Bluetooth is off, send service down event to proxy objects, and unbind
if (!isUp && canUnbindBluetoothService()) {
sendBluetoothServiceDownCallback();
unbindAndFinish();
}
}
}