BluetoothHeadset.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
1/* 2 * Copyright (C) 2008 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 17package android.bluetooth; 18 19import android.content.ComponentName; 20import android.content.Context; 21import android.content.Intent; 22import android.content.ServiceConnection; 23import android.os.RemoteException; 24import android.os.IBinder; 25import android.util.Log; 26 27/** 28 * The Android Bluetooth API is not finalized, and *will* change. Use at your 29 * own risk. 30 * 31 * Public API for controlling the Bluetooth Headset Service. This includes both 32 * Bluetooth Headset and Handsfree (v1.5) profiles. The Headset service will 33 * attempt a handsfree connection first, and fall back to headset. 34 * 35 * BluetoothHeadset is a proxy object for controlling the Bluetooth Headset 36 * Service via IPC. 37 * 38 * Creating a BluetoothHeadset object will create a binding with the 39 * BluetoothHeadset service. Users of this object should call close() when they 40 * are finished with the BluetoothHeadset, so that this proxy object can unbind 41 * from the service. 42 * 43 * This BluetoothHeadset object is not immediately bound to the 44 * BluetoothHeadset service. Use the ServiceListener interface to obtain a 45 * notification when it is bound, this is especially important if you wish to 46 * immediately call methods on BluetootHeadset after construction. 47 * 48 * Android only supports one connected Bluetooth Headset at a time. 49 * 50 * @hide 51 */ 52public class BluetoothHeadset { 53 54 private static final String TAG = "BluetoothHeadset"; 55 private static final boolean DBG = false; 56 57 private IBluetoothHeadset mService; 58 private final Context mContext; 59 private final ServiceListener mServiceListener; 60 private ConnectHeadsetCallback mConnectHeadsetCallback; 61 62 /** There was an error trying to obtain the state */ 63 public static final int STATE_ERROR = -1; 64 /** No headset currently connected */ 65 public static final int STATE_DISCONNECTED = 0; 66 /** Connection attempt in progress */ 67 public static final int STATE_CONNECTING = 1; 68 /** A headset is currently connected */ 69 public static final int STATE_CONNECTED = 2; 70 71 public static final int RESULT_FAILURE = 0; 72 public static final int RESULT_SUCCESS = 1; 73 /** Connection cancelled before completetion. */ 74 public static final int RESULT_CANCELLED = 2; 75 76 /** 77 * An interface for notifying BluetoothHeadset IPC clients when they have 78 * been connected to the BluetoothHeadset service. 79 */ 80 public interface ServiceListener { 81 /** 82 * Called to notify the client when this proxy object has been 83 * connected to the BluetoothHeadset service. Clients must wait for 84 * this callback before making IPC calls on the BluetoothHeadset 85 * service. 86 */ 87 public void onServiceConnected(); 88 89 /** 90 * Called to notify the client that this proxy object has been 91 * disconnected from the BluetoothHeadset service. Clients must not 92 * make IPC calls on the BluetoothHeadset service after this callback. 93 * This callback will currently only occur if the application hosting 94 * the BluetoothHeadset service, but may be called more often in future. 95 */ 96 public void onServiceDisconnected(); 97 } 98 99 /** 100 * Interface for connectHeadset() callback. 101 * This callback can occur in the Binder thread. 102 */ 103 public interface ConnectHeadsetCallback { 104 public void onConnectHeadsetResult(String address, int resultCode); 105 } 106 107 /** 108 * Create a BluetoothHeadset proxy object. 109 */ 110 public BluetoothHeadset(Context context, ServiceListener l) { 111 mContext = context; 112 mServiceListener = l; 113 if (!context.bindService(new Intent(IBluetoothHeadset.class.getName()), mConnection, 0)) { 114 Log.e(TAG, "Could not bind to Bluetooth Headset Service"); 115 } 116 } 117 118 protected void finalize() throws Throwable { 119 try { 120 close(); 121 } finally { 122 super.finalize(); 123 } 124 } 125 126 /** 127 * Close the connection to the backing service. 128 * Other public functions of BluetoothHeadset will return default error 129 * results once close() has been called. Multiple invocations of close() 130 * are ok. 131 */ 132 public synchronized void close() { 133 if (mConnection != null) { 134 mContext.unbindService(mConnection); 135 mConnection = null; 136 } 137 } 138 139 /** 140 * Get the current state of the Bluetooth Headset service. 141 * @return One of the STATE_ return codes, or STATE_ERROR if this proxy 142 * object is currently not connected to the Headset service. 143 */ 144 public int getState() { 145 if (mService != null) { 146 try { 147 return mService.getState(); 148 } catch (RemoteException e) {Log.e(TAG, e.toString());} 149 } else { 150 Log.w(TAG, "Proxy not attached to service"); 151 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 152 } 153 return BluetoothHeadset.STATE_ERROR; 154 } 155 156 /** 157 * Get the Bluetooth address of the current headset. 158 * @return The Bluetooth address, or null if not in connected or connecting 159 * state, or if this proxy object is not connected to the Headset 160 * service. 161 */ 162 public String getHeadsetAddress() { 163 if (mService != null) { 164 try { 165 return mService.getHeadsetAddress(); 166 } catch (RemoteException e) {Log.e(TAG, e.toString());} 167 } else { 168 Log.w(TAG, "Proxy not attached to service"); 169 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 170 } 171 return null; 172 } 173 174 /** 175 * Request to initiate a connection to a headset. 176 * This call does not block. Fails if a headset is already connecting 177 * or connected. 178 * Will connect to the last connected headset if address is null. 179 * onConnectHeadsetResult() of your ConnectHeadsetCallback will be called 180 * on completition. 181 * @param address The Bluetooth Address to connect to, or null to connect 182 * to the last connected headset. 183 * @param callback Callback on result. Not called if false is returned. Can 184 * be null. 185 * to the last connected headset. 186 * @return False if there was a problem initiating the connection 187 * procedure, and your callback will not be used. True if 188 * the connection procedure was initiated, in which case 189 * your callback is guarenteed to be called. 190 */ 191 public boolean connectHeadset(String address, ConnectHeadsetCallback callback) { 192 if (mService != null) { 193 try { 194 if (mService.connectHeadset(address, mHeadsetCallback)) { 195 mConnectHeadsetCallback = callback; 196 return true; 197 } 198 } catch (RemoteException e) {Log.e(TAG, e.toString());} 199 } else { 200 Log.w(TAG, "Proxy not attached to service"); 201 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 202 } 203 return false; 204 } 205 206 /** 207 * Returns true if the specified headset is connected (does not include 208 * connecting). Returns false if not connected, or if this proxy object 209 * if not currently connected to the headset service. 210 */ 211 public boolean isConnected(String address) { 212 if (mService != null) { 213 try { 214 return mService.isConnected(address); 215 } catch (RemoteException e) {Log.e(TAG, e.toString());} 216 } else { 217 Log.w(TAG, "Proxy not attached to service"); 218 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 219 } 220 return false; 221 } 222 223 /** 224 * Disconnects the current headset. Currently this call blocks, it may soon 225 * be made asynchornous. Returns false if this proxy object is 226 * not currently connected to the Headset service. 227 */ 228 public boolean disconnectHeadset() { 229 if (mService != null) { 230 try { 231 mService.disconnectHeadset(); 232 return true; 233 } catch (RemoteException e) {Log.e(TAG, e.toString());} 234 } else { 235 Log.w(TAG, "Proxy not attached to service"); 236 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 237 } 238 return false; 239 } 240 241 /** 242 * Start BT Voice Recognition mode, and set up Bluetooth audio path. 243 * Returns false if there is no headset connected, or if the 244 * connected headset does not support voice recognition, or on 245 * error. 246 */ 247 public boolean startVoiceRecognition() { 248 if (mService != null) { 249 try { 250 return mService.startVoiceRecognition(); 251 } catch (RemoteException e) {Log.e(TAG, e.toString());} 252 } else { 253 Log.w(TAG, "Proxy not attached to service"); 254 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 255 } 256 return false; 257 } 258 259 /** 260 * Stop BT Voice Recognition mode, and shut down Bluetooth audio path. 261 * Returns false if there is no headset connected, or the connected 262 * headset is not in voice recognition mode, or on error. 263 */ 264 public boolean stopVoiceRecognition() { 265 if (mService != null) { 266 try { 267 return mService.stopVoiceRecognition(); 268 } catch (RemoteException e) {Log.e(TAG, e.toString());} 269 } else { 270 Log.w(TAG, "Proxy not attached to service"); 271 if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable())); 272 } 273 return false; 274 } 275 276 private ServiceConnection mConnection = new ServiceConnection() { 277 public void onServiceConnected(ComponentName className, IBinder service) { 278 if (DBG) Log.d(TAG, "Proxy object connected"); 279 mService = IBluetoothHeadset.Stub.asInterface(service); 280 if (mServiceListener != null) { 281 mServiceListener.onServiceConnected(); 282 } 283 } 284 public void onServiceDisconnected(ComponentName className) { 285 if (DBG) Log.d(TAG, "Proxy object disconnected"); 286 mService = null; 287 if (mServiceListener != null) { 288 mServiceListener.onServiceDisconnected(); 289 } 290 } 291 }; 292 293 private IBluetoothHeadsetCallback mHeadsetCallback = new IBluetoothHeadsetCallback.Stub() { 294 public void onConnectHeadsetResult(String address, int resultCode) { 295 if (mConnectHeadsetCallback != null) { 296 mConnectHeadsetCallback.onConnectHeadsetResult(address, resultCode); 297 } 298 } 299 }; 300} 301