1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.bluetooth; 18 19 import android.Manifest; 20 import android.annotation.RequiresFeature; 21 import android.annotation.RequiresPermission; 22 import android.annotation.SystemService; 23 import android.content.Context; 24 import android.content.pm.PackageManager; 25 import android.os.IBinder; 26 import android.os.RemoteException; 27 import android.os.ServiceManager; 28 import android.util.Log; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * High level manager used to obtain an instance of an {@link BluetoothAdapter} 35 * and to conduct overall Bluetooth Management. 36 * <p> 37 * Use {@link android.content.Context#getSystemService(java.lang.String)} 38 * with {@link Context#BLUETOOTH_SERVICE} to create an {@link BluetoothManager}, 39 * then call {@link #getAdapter} to obtain the {@link BluetoothAdapter}. 40 * </p> 41 * <div class="special reference"> 42 * <h3>Developer Guides</h3> 43 * <p> 44 * For more information about using BLUETOOTH, read the <a href= 45 * "{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> developer 46 * guide. 47 * </p> 48 * </div> 49 * 50 * @see Context#getSystemService 51 * @see BluetoothAdapter#getDefaultAdapter() 52 */ 53 @SystemService(Context.BLUETOOTH_SERVICE) 54 @RequiresFeature(PackageManager.FEATURE_BLUETOOTH) 55 public final class BluetoothManager { 56 private static final String TAG = "BluetoothManager"; 57 private static final boolean DBG = false; 58 59 private final BluetoothAdapter mAdapter; 60 61 /** 62 * @hide 63 */ BluetoothManager(Context context)64 public BluetoothManager(Context context) { 65 if (null == null) { 66 context = context.getApplicationContext(); 67 if (context == null) { 68 throw new IllegalArgumentException( 69 "context not associated with any application (using a mock context?)"); 70 } 71 72 mAdapter = BluetoothAdapter.getDefaultAdapter(); 73 } else { 74 IBinder b = ServiceManager.getService(BluetoothAdapter.BLUETOOTH_MANAGER_SERVICE); 75 if (b != null) { 76 mAdapter = new BluetoothAdapter(IBluetoothManager.Stub.asInterface(b)); 77 } else { 78 Log.e(TAG, "Bluetooth binder is null"); 79 mAdapter = null; 80 } 81 } 82 83 // Context is not initialized in constructor 84 if (mAdapter != null) { 85 mAdapter.setContext(context); 86 } 87 } 88 89 /** 90 * Get the BLUETOOTH Adapter for this device. 91 * 92 * @return the BLUETOOTH Adapter 93 */ getAdapter()94 public BluetoothAdapter getAdapter() { 95 return mAdapter; 96 } 97 98 /** 99 * Get the current connection state of the profile to the remote device. 100 * 101 * <p>This is not specific to any application configuration but represents 102 * the connection state of the local Bluetooth adapter for certain profile. 103 * This can be used by applications like status bar which would just like 104 * to know the state of Bluetooth. 105 * 106 * @param device Remote bluetooth device. 107 * @param profile GATT or GATT_SERVER 108 * @return State of the profile connection. One of {@link BluetoothProfile#STATE_CONNECTED}, 109 * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED}, 110 * {@link BluetoothProfile#STATE_DISCONNECTING} 111 */ 112 @RequiresPermission(Manifest.permission.BLUETOOTH) getConnectionState(BluetoothDevice device, int profile)113 public int getConnectionState(BluetoothDevice device, int profile) { 114 if (DBG) Log.d(TAG, "getConnectionState()"); 115 116 List<BluetoothDevice> connectedDevices = getConnectedDevices(profile); 117 for (BluetoothDevice connectedDevice : connectedDevices) { 118 if (device.equals(connectedDevice)) { 119 return BluetoothProfile.STATE_CONNECTED; 120 } 121 } 122 123 return BluetoothProfile.STATE_DISCONNECTED; 124 } 125 126 /** 127 * Get connected devices for the specified profile. 128 * 129 * <p> Return the set of devices which are in state {@link BluetoothProfile#STATE_CONNECTED} 130 * 131 * <p>This is not specific to any application configuration but represents 132 * the connection state of Bluetooth for this profile. 133 * This can be used by applications like status bar which would just like 134 * to know the state of Bluetooth. 135 * 136 * @param profile GATT or GATT_SERVER 137 * @return List of devices. The list will be empty on error. 138 */ 139 @RequiresPermission(Manifest.permission.BLUETOOTH) getConnectedDevices(int profile)140 public List<BluetoothDevice> getConnectedDevices(int profile) { 141 if (DBG) Log.d(TAG, "getConnectedDevices"); 142 if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) { 143 throw new IllegalArgumentException("Profile not supported: " + profile); 144 } 145 146 List<BluetoothDevice> connectedDevices = new ArrayList<BluetoothDevice>(); 147 148 try { 149 IBluetoothManager managerService = mAdapter.getBluetoothManager(); 150 IBluetoothGatt iGatt = managerService.getBluetoothGatt(); 151 if (iGatt == null) return connectedDevices; 152 153 connectedDevices = iGatt.getDevicesMatchingConnectionStates( 154 new int[]{BluetoothProfile.STATE_CONNECTED}); 155 } catch (RemoteException e) { 156 Log.e(TAG, "", e); 157 } 158 159 return connectedDevices; 160 } 161 162 /** 163 * Get a list of devices that match any of the given connection 164 * states. 165 * 166 * <p> If none of the devices match any of the given states, 167 * an empty list will be returned. 168 * 169 * <p>This is not specific to any application configuration but represents 170 * the connection state of the local Bluetooth adapter for this profile. 171 * This can be used by applications like status bar which would just like 172 * to know the state of the local adapter. 173 * 174 * @param profile GATT or GATT_SERVER 175 * @param states Array of states. States can be one of {@link BluetoothProfile#STATE_CONNECTED}, 176 * {@link BluetoothProfile#STATE_CONNECTING}, {@link BluetoothProfile#STATE_DISCONNECTED}, 177 * {@link BluetoothProfile#STATE_DISCONNECTING}, 178 * @return List of devices. The list will be empty on error. 179 */ 180 @RequiresPermission(Manifest.permission.BLUETOOTH) getDevicesMatchingConnectionStates(int profile, int[] states)181 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int profile, int[] states) { 182 if (DBG) Log.d(TAG, "getDevicesMatchingConnectionStates"); 183 184 if (profile != BluetoothProfile.GATT && profile != BluetoothProfile.GATT_SERVER) { 185 throw new IllegalArgumentException("Profile not supported: " + profile); 186 } 187 188 List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>(); 189 190 try { 191 IBluetoothManager managerService = mAdapter.getBluetoothManager(); 192 IBluetoothGatt iGatt = managerService.getBluetoothGatt(); 193 if (iGatt == null) return devices; 194 devices = iGatt.getDevicesMatchingConnectionStates(states); 195 } catch (RemoteException e) { 196 Log.e(TAG, "", e); 197 } 198 199 return devices; 200 } 201 202 /** 203 * Open a GATT Server 204 * The callback is used to deliver results to Caller, such as connection status as well 205 * as the results of any other GATT server operations. 206 * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer 207 * to conduct GATT server operations. 208 * 209 * @param context App context 210 * @param callback GATT server callback handler that will receive asynchronous callbacks. 211 * @return BluetoothGattServer instance 212 */ openGattServer(Context context, BluetoothGattServerCallback callback)213 public BluetoothGattServer openGattServer(Context context, 214 BluetoothGattServerCallback callback) { 215 216 return (openGattServer(context, callback, BluetoothDevice.TRANSPORT_AUTO)); 217 } 218 219 /** 220 * Open a GATT Server 221 * The callback is used to deliver results to Caller, such as connection status as well 222 * as the results of any other GATT server operations. 223 * The method returns a BluetoothGattServer instance. You can use BluetoothGattServer 224 * to conduct GATT server operations. 225 * 226 * @param context App context 227 * @param callback GATT server callback handler that will receive asynchronous callbacks. 228 * @param transport preferred transport for GATT connections to remote dual-mode devices {@link 229 * BluetoothDevice#TRANSPORT_AUTO} or {@link BluetoothDevice#TRANSPORT_BREDR} or {@link 230 * BluetoothDevice#TRANSPORT_LE} 231 * @return BluetoothGattServer instance 232 * @hide 233 */ openGattServer(Context context, BluetoothGattServerCallback callback, int transport)234 public BluetoothGattServer openGattServer(Context context, 235 BluetoothGattServerCallback callback, int transport) { 236 if (context == null || callback == null) { 237 throw new IllegalArgumentException("null parameter: " + context + " " + callback); 238 } 239 240 // TODO(Bluetooth) check whether platform support BLE 241 // Do the check here or in GattServer? 242 243 try { 244 IBluetoothManager managerService = mAdapter.getBluetoothManager(); 245 IBluetoothGatt iGatt = managerService.getBluetoothGatt(); 246 if (iGatt == null) { 247 Log.e(TAG, "Fail to get GATT Server connection"); 248 return null; 249 } 250 BluetoothGattServer mGattServer = new BluetoothGattServer(iGatt, transport); 251 Boolean regStatus = mGattServer.registerCallback(callback); 252 return regStatus ? mGattServer : null; 253 } catch (RemoteException e) { 254 Log.e(TAG, "", e); 255 return null; 256 } 257 } 258 } 259