1 /* 2 * Copyright (C) 2012 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 com.android.bluetooth.hfp; 18 19 import android.bluetooth.BluetoothDevice; 20 import android.bluetooth.BluetoothHeadset; 21 import android.bluetooth.BluetoothProfile; 22 import android.bluetooth.IBluetoothHeadset; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.media.AudioManager; 28 import android.os.Message; 29 import android.provider.Settings; 30 import android.util.Log; 31 import com.android.bluetooth.btservice.ProfileService; 32 import com.android.bluetooth.Utils; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** 37 * Provides Bluetooth Headset and Handsfree profile, as a service in 38 * the Bluetooth application. 39 * @hide 40 */ 41 public class HeadsetService extends ProfileService { 42 private static final boolean DBG = false; 43 private static final String TAG = "HeadsetService"; 44 private static final String MODIFY_PHONE_STATE = android.Manifest.permission.MODIFY_PHONE_STATE; 45 46 private HeadsetStateMachine mStateMachine; 47 private static HeadsetService sHeadsetService; 48 getName()49 protected String getName() { 50 return TAG; 51 } 52 initBinder()53 public IProfileServiceBinder initBinder() { 54 return new BluetoothHeadsetBinder(this); 55 } 56 start()57 protected boolean start() { 58 mStateMachine = HeadsetStateMachine.make(this); 59 IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 60 filter.addAction(AudioManager.VOLUME_CHANGED_ACTION); 61 filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY); 62 try { 63 registerReceiver(mHeadsetReceiver, filter); 64 } catch (Exception e) { 65 Log.w(TAG, "Unable to register headset receiver", e); 66 } 67 setHeadsetService(this); 68 return true; 69 } 70 stop()71 protected boolean stop() { 72 try { 73 unregisterReceiver(mHeadsetReceiver); 74 } catch (Exception e) { 75 Log.w(TAG, "Unable to unregister headset receiver", e); 76 } 77 if (mStateMachine != null) { 78 mStateMachine.doQuit(); 79 } 80 return true; 81 } 82 cleanup()83 protected boolean cleanup() { 84 if (mStateMachine != null) { 85 mStateMachine.cleanup(); 86 } 87 clearHeadsetService(); 88 return true; 89 } 90 91 private final BroadcastReceiver mHeadsetReceiver = new BroadcastReceiver() { 92 @Override 93 public void onReceive(Context context, Intent intent) { 94 String action = intent.getAction(); 95 if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 96 mStateMachine.sendMessage(HeadsetStateMachine.INTENT_BATTERY_CHANGED, intent); 97 } else if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) { 98 int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); 99 if (streamType == AudioManager.STREAM_BLUETOOTH_SCO) { 100 mStateMachine.sendMessage( 101 HeadsetStateMachine.INTENT_SCO_VOLUME_CHANGED, intent); 102 } 103 } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) { 104 int requestType = intent.getIntExtra(BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, 105 BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS); 106 if (requestType == BluetoothDevice.REQUEST_TYPE_PHONEBOOK_ACCESS) { 107 Log.v(TAG, "Received BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY"); 108 mStateMachine.handleAccessPermissionResult(intent); 109 } 110 } 111 } 112 }; 113 114 /** 115 * Handlers for incoming service calls 116 */ 117 private static class BluetoothHeadsetBinder 118 extends IBluetoothHeadset.Stub implements IProfileServiceBinder { 119 private HeadsetService mService; 120 BluetoothHeadsetBinder(HeadsetService svc)121 public BluetoothHeadsetBinder(HeadsetService svc) { 122 mService = svc; 123 } cleanup()124 public boolean cleanup() { 125 mService = null; 126 return true; 127 } 128 getService()129 private HeadsetService getService() { 130 if (!Utils.checkCallerAllowManagedProfiles(mService)) { 131 Log.w(TAG, "Headset call not allowed for non-active user"); 132 return null; 133 } 134 135 if (mService != null && mService.isAvailable()) { 136 return mService; 137 } 138 return null; 139 } 140 connect(BluetoothDevice device)141 public boolean connect(BluetoothDevice device) { 142 HeadsetService service = getService(); 143 if (service == null) return false; 144 return service.connect(device); 145 } 146 disconnect(BluetoothDevice device)147 public boolean disconnect(BluetoothDevice device) { 148 HeadsetService service = getService(); 149 if (service == null) return false; 150 if (DBG) Log.d(TAG, "disconnect in HeadsetService"); 151 return service.disconnect(device); 152 } 153 getConnectedDevices()154 public List<BluetoothDevice> getConnectedDevices() { 155 HeadsetService service = getService(); 156 if (service == null) return new ArrayList<BluetoothDevice>(0); 157 return service.getConnectedDevices(); 158 } 159 getDevicesMatchingConnectionStates(int[] states)160 public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 161 HeadsetService service = getService(); 162 if (service == null) return new ArrayList<BluetoothDevice>(0); 163 return service.getDevicesMatchingConnectionStates(states); 164 } 165 getConnectionState(BluetoothDevice device)166 public int getConnectionState(BluetoothDevice device) { 167 HeadsetService service = getService(); 168 if (service == null) return BluetoothProfile.STATE_DISCONNECTED; 169 return service.getConnectionState(device); 170 } 171 setPriority(BluetoothDevice device, int priority)172 public boolean setPriority(BluetoothDevice device, int priority) { 173 HeadsetService service = getService(); 174 if (service == null) return false; 175 return service.setPriority(device, priority); 176 } 177 getPriority(BluetoothDevice device)178 public int getPriority(BluetoothDevice device) { 179 HeadsetService service = getService(); 180 if (service == null) return BluetoothProfile.PRIORITY_UNDEFINED; 181 return service.getPriority(device); 182 } 183 startVoiceRecognition(BluetoothDevice device)184 public boolean startVoiceRecognition(BluetoothDevice device) { 185 HeadsetService service = getService(); 186 if (service == null) return false; 187 return service.startVoiceRecognition(device); 188 } 189 stopVoiceRecognition(BluetoothDevice device)190 public boolean stopVoiceRecognition(BluetoothDevice device) { 191 HeadsetService service = getService(); 192 if (service == null) return false; 193 return service.stopVoiceRecognition(device); 194 } 195 isAudioOn()196 public boolean isAudioOn() { 197 HeadsetService service = getService(); 198 if (service == null) return false; 199 return service.isAudioOn(); 200 } 201 isAudioConnected(BluetoothDevice device)202 public boolean isAudioConnected(BluetoothDevice device) { 203 HeadsetService service = getService(); 204 if (service == null) return false; 205 return service.isAudioConnected(device); 206 } 207 getBatteryUsageHint(BluetoothDevice device)208 public int getBatteryUsageHint(BluetoothDevice device) { 209 HeadsetService service = getService(); 210 if (service == null) return 0; 211 return service.getBatteryUsageHint(device); 212 } 213 acceptIncomingConnect(BluetoothDevice device)214 public boolean acceptIncomingConnect(BluetoothDevice device) { 215 HeadsetService service = getService(); 216 if (service == null) return false; 217 return service.acceptIncomingConnect(device); 218 } 219 rejectIncomingConnect(BluetoothDevice device)220 public boolean rejectIncomingConnect(BluetoothDevice device) { 221 HeadsetService service = getService(); 222 if (service == null) return false; 223 return service.rejectIncomingConnect(device); 224 } 225 getAudioState(BluetoothDevice device)226 public int getAudioState(BluetoothDevice device) { 227 HeadsetService service = getService(); 228 if (service == null) return BluetoothHeadset.STATE_AUDIO_DISCONNECTED; 229 return service.getAudioState(device); 230 } 231 connectAudio()232 public boolean connectAudio() { 233 HeadsetService service = getService(); 234 if (service == null) return false; 235 return service.connectAudio(); 236 } 237 disconnectAudio()238 public boolean disconnectAudio() { 239 HeadsetService service = getService(); 240 if (service == null) return false; 241 return service.disconnectAudio(); 242 } 243 setAudioRouteAllowed(boolean allowed)244 public void setAudioRouteAllowed(boolean allowed) { 245 HeadsetService service = getService(); 246 if (service == null) return; 247 service.setAudioRouteAllowed(allowed); 248 } 249 getAudioRouteAllowed()250 public boolean getAudioRouteAllowed() { 251 HeadsetService service = getService(); 252 if (service != null) { 253 return service.getAudioRouteAllowed(); 254 } 255 256 return false; 257 } 258 startScoUsingVirtualVoiceCall(BluetoothDevice device)259 public boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) { 260 HeadsetService service = getService(); 261 if (service == null) return false; 262 return service.startScoUsingVirtualVoiceCall(device); 263 } 264 stopScoUsingVirtualVoiceCall(BluetoothDevice device)265 public boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) { 266 HeadsetService service = getService(); 267 if (service == null) return false; 268 return service.stopScoUsingVirtualVoiceCall(device); 269 } 270 phoneStateChanged( int numActive, int numHeld, int callState, String number, int type)271 public void phoneStateChanged( 272 int numActive, int numHeld, int callState, String number, int type) { 273 HeadsetService service = getService(); 274 if (service == null) return; 275 service.phoneStateChanged(numActive, numHeld, callState, number, type); 276 } 277 clccResponse(int index, int direction, int status, int mode, boolean mpty, String number, int type)278 public void clccResponse(int index, int direction, int status, int mode, boolean mpty, 279 String number, int type) { 280 HeadsetService service = getService(); 281 if (service == null) return; 282 service.clccResponse(index, direction, status, mode, mpty, number, type); 283 } 284 sendVendorSpecificResultCode( BluetoothDevice device, String command, String arg)285 public boolean sendVendorSpecificResultCode( 286 BluetoothDevice device, String command, String arg) { 287 HeadsetService service = getService(); 288 if (service == null) { 289 return false; 290 } 291 return service.sendVendorSpecificResultCode(device, command, arg); 292 } 293 enableWBS()294 public boolean enableWBS() { 295 HeadsetService service = getService(); 296 if (service == null) return false; 297 return service.enableWBS(); 298 } 299 disableWBS()300 public boolean disableWBS() { 301 HeadsetService service = getService(); 302 if (service == null) return false; 303 return service.disableWBS(); 304 } 305 bindResponse(int ind_id, boolean ind_status)306 public void bindResponse(int ind_id, boolean ind_status) { 307 HeadsetService service = getService(); 308 if (service == null) return; 309 service.bindResponse(ind_id, ind_status); 310 } 311 }; 312 313 // API methods getHeadsetService()314 public static synchronized HeadsetService getHeadsetService() { 315 if (sHeadsetService != null && sHeadsetService.isAvailable()) { 316 if (DBG) Log.d(TAG, "getHeadsetService(): returning " + sHeadsetService); 317 return sHeadsetService; 318 } 319 if (DBG) { 320 if (sHeadsetService == null) { 321 Log.d(TAG, "getHeadsetService(): service is NULL"); 322 } else if (!(sHeadsetService.isAvailable())) { 323 Log.d(TAG, "getHeadsetService(): service is not available"); 324 } 325 } 326 return null; 327 } 328 setHeadsetService(HeadsetService instance)329 private static synchronized void setHeadsetService(HeadsetService instance) { 330 if (instance != null && instance.isAvailable()) { 331 if (DBG) Log.d(TAG, "setHeadsetService(): set to: " + sHeadsetService); 332 sHeadsetService = instance; 333 } else { 334 if (DBG) { 335 if (sHeadsetService == null) { 336 Log.d(TAG, "setHeadsetService(): service not available"); 337 } else if (!sHeadsetService.isAvailable()) { 338 Log.d(TAG, "setHeadsetService(): service is cleaning up"); 339 } 340 } 341 } 342 } 343 clearHeadsetService()344 private static synchronized void clearHeadsetService() { 345 sHeadsetService = null; 346 } 347 connect(BluetoothDevice device)348 public boolean connect(BluetoothDevice device) { 349 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 350 351 if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) { 352 return false; 353 } 354 355 int connectionState = mStateMachine.getConnectionState(device); 356 Log.d(TAG, "connectionState = " + connectionState); 357 if (connectionState == BluetoothProfile.STATE_CONNECTED 358 || connectionState == BluetoothProfile.STATE_CONNECTING) { 359 return false; 360 } 361 362 mStateMachine.sendMessage(HeadsetStateMachine.CONNECT, device); 363 return true; 364 } 365 disconnect(BluetoothDevice device)366 boolean disconnect(BluetoothDevice device) { 367 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH ADMIN permission"); 368 int connectionState = mStateMachine.getConnectionState(device); 369 if (connectionState != BluetoothProfile.STATE_CONNECTED 370 && connectionState != BluetoothProfile.STATE_CONNECTING) { 371 return false; 372 } 373 374 mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT, device); 375 return true; 376 } 377 getConnectedDevices()378 public List<BluetoothDevice> getConnectedDevices() { 379 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 380 return mStateMachine.getConnectedDevices(); 381 } 382 getDevicesMatchingConnectionStates(int[] states)383 private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { 384 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 385 return mStateMachine.getDevicesMatchingConnectionStates(states); 386 } 387 getConnectionState(BluetoothDevice device)388 public int getConnectionState(BluetoothDevice device) { 389 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 390 return mStateMachine.getConnectionState(device); 391 } 392 setPriority(BluetoothDevice device, int priority)393 public boolean setPriority(BluetoothDevice device, int priority) { 394 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 395 Settings.Global.putInt(getContentResolver(), 396 Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), priority); 397 if (DBG) Log.d(TAG, "Saved priority " + device + " = " + priority); 398 return true; 399 } 400 getPriority(BluetoothDevice device)401 public int getPriority(BluetoothDevice device) { 402 enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission"); 403 int priority = Settings.Global.getInt(getContentResolver(), 404 Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()), 405 BluetoothProfile.PRIORITY_UNDEFINED); 406 return priority; 407 } 408 startVoiceRecognition(BluetoothDevice device)409 boolean startVoiceRecognition(BluetoothDevice device) { 410 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 411 int connectionState = mStateMachine.getConnectionState(device); 412 if (connectionState != BluetoothProfile.STATE_CONNECTED 413 && connectionState != BluetoothProfile.STATE_CONNECTING) { 414 return false; 415 } 416 mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_START); 417 return true; 418 } 419 stopVoiceRecognition(BluetoothDevice device)420 boolean stopVoiceRecognition(BluetoothDevice device) { 421 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 422 // It seem that we really need to check the AudioOn state. 423 // But since we allow startVoiceRecognition in STATE_CONNECTED and 424 // STATE_CONNECTING state, we do these 2 in this method 425 int connectionState = mStateMachine.getConnectionState(device); 426 if (connectionState != BluetoothProfile.STATE_CONNECTED 427 && connectionState != BluetoothProfile.STATE_CONNECTING) { 428 return false; 429 } 430 mStateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP); 431 // TODO is this return correct when the voice recognition is not on? 432 return true; 433 } 434 isAudioOn()435 boolean isAudioOn() { 436 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 437 return mStateMachine.isAudioOn(); 438 } 439 isAudioConnected(BluetoothDevice device)440 boolean isAudioConnected(BluetoothDevice device) { 441 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 442 return mStateMachine.isAudioConnected(device); 443 } 444 getBatteryUsageHint(BluetoothDevice device)445 int getBatteryUsageHint(BluetoothDevice device) { 446 // TODO(BT) ask for BT stack support? 447 return 0; 448 } 449 acceptIncomingConnect(BluetoothDevice device)450 boolean acceptIncomingConnect(BluetoothDevice device) { 451 // TODO(BT) remove it if stack does access control 452 return false; 453 } 454 rejectIncomingConnect(BluetoothDevice device)455 boolean rejectIncomingConnect(BluetoothDevice device) { 456 // TODO(BT) remove it if stack does access control 457 return false; 458 } 459 getAudioState(BluetoothDevice device)460 int getAudioState(BluetoothDevice device) { 461 return mStateMachine.getAudioState(device); 462 } 463 setAudioRouteAllowed(boolean allowed)464 public void setAudioRouteAllowed(boolean allowed) { 465 mStateMachine.setAudioRouteAllowed(allowed); 466 } 467 getAudioRouteAllowed()468 public boolean getAudioRouteAllowed() { 469 return mStateMachine.getAudioRouteAllowed(); 470 } 471 connectAudio()472 boolean connectAudio() { 473 // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission 474 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 475 if (!mStateMachine.isConnected()) { 476 return false; 477 } 478 if (!mStateMachine.isSlcConnected()) { 479 return false; 480 } 481 if (mStateMachine.isAudioOn()) { 482 return false; 483 } 484 mStateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO); 485 return true; 486 } 487 disconnectAudio()488 boolean disconnectAudio() { 489 // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission 490 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 491 if (!mStateMachine.isAudioOn()) { 492 return false; 493 } 494 mStateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO); 495 return true; 496 } 497 startScoUsingVirtualVoiceCall(BluetoothDevice device)498 boolean startScoUsingVirtualVoiceCall(BluetoothDevice device) { 499 /* Do not ignore request if HSM state is still Disconnected or 500 Pending, it will be processed when transitioned to Connected */ 501 mStateMachine.sendMessage(HeadsetStateMachine.VIRTUAL_CALL_START, device); 502 return true; 503 } 504 stopScoUsingVirtualVoiceCall(BluetoothDevice device)505 boolean stopScoUsingVirtualVoiceCall(BluetoothDevice device) { 506 int connectionState = mStateMachine.getConnectionState(device); 507 if (connectionState != BluetoothProfile.STATE_CONNECTED 508 && connectionState != BluetoothProfile.STATE_CONNECTING) { 509 return false; 510 } 511 mStateMachine.sendMessage(HeadsetStateMachine.VIRTUAL_CALL_STOP, device); 512 return true; 513 } 514 phoneStateChanged( int numActive, int numHeld, int callState, String number, int type)515 private void phoneStateChanged( 516 int numActive, int numHeld, int callState, String number, int type) { 517 enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); 518 Message msg = mStateMachine.obtainMessage(HeadsetStateMachine.CALL_STATE_CHANGED); 519 msg.obj = new HeadsetCallState(numActive, numHeld, callState, number, type); 520 msg.arg1 = 0; // false 521 mStateMachine.sendMessage(msg); 522 } 523 clccResponse( int index, int direction, int status, int mode, boolean mpty, String number, int type)524 private void clccResponse( 525 int index, int direction, int status, int mode, boolean mpty, String number, int type) { 526 enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); 527 mStateMachine.sendMessage(HeadsetStateMachine.SEND_CCLC_RESPONSE, 528 new HeadsetClccResponse(index, direction, status, mode, mpty, number, type)); 529 } 530 sendVendorSpecificResultCode( BluetoothDevice device, String command, String arg)531 private boolean sendVendorSpecificResultCode( 532 BluetoothDevice device, String command, String arg) { 533 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 534 int connectionState = mStateMachine.getConnectionState(device); 535 if (connectionState != BluetoothProfile.STATE_CONNECTED) { 536 return false; 537 } 538 // Currently we support only "+ANDROID". 539 if (!command.equals(BluetoothHeadset.VENDOR_RESULT_CODE_COMMAND_ANDROID)) { 540 Log.w(TAG, "Disallowed unsolicited result code command: " + command); 541 return false; 542 } 543 mStateMachine.sendMessage(HeadsetStateMachine.SEND_VENDOR_SPECIFIC_RESULT_CODE, 544 new HeadsetVendorSpecificResultCode(device, command, arg)); 545 return true; 546 } 547 enableWBS()548 boolean enableWBS() { 549 // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission 550 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 551 if (!mStateMachine.isConnected()) { 552 return false; 553 } 554 if (mStateMachine.isAudioOn()) { 555 return false; 556 } 557 558 for (BluetoothDevice device : getConnectedDevices()) { 559 mStateMachine.sendMessage(HeadsetStateMachine.ENABLE_WBS, device); 560 } 561 562 return true; 563 } 564 disableWBS()565 boolean disableWBS() { 566 // TODO(BT) BLUETOOTH or BLUETOOTH_ADMIN permission 567 enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission"); 568 if (!mStateMachine.isConnected()) { 569 return false; 570 } 571 if (mStateMachine.isAudioOn()) { 572 return false; 573 } 574 for (BluetoothDevice device : getConnectedDevices()) { 575 mStateMachine.sendMessage(HeadsetStateMachine.DISABLE_WBS, device); 576 } 577 return true; 578 } 579 bindResponse(int ind_id, boolean ind_status)580 private boolean bindResponse(int ind_id, boolean ind_status) { 581 for (BluetoothDevice device : getConnectedDevices()) { 582 int connectionState = mStateMachine.getConnectionState(device); 583 if (connectionState != BluetoothProfile.STATE_CONNECTED 584 && connectionState != BluetoothProfile.STATE_CONNECTING) { 585 continue; 586 } 587 if (DBG) Log.d("Bind Response sent for", device.getAddress()); 588 Message msg = mStateMachine.obtainMessage(HeadsetStateMachine.BIND_RESPONSE); 589 msg.obj = device; 590 msg.arg1 = ind_id; 591 msg.arg2 = ind_status ? 1 : 0; 592 mStateMachine.sendMessage(msg); 593 return true; 594 } 595 return false; 596 } 597 598 @Override dump(StringBuilder sb)599 public void dump(StringBuilder sb) { 600 super.dump(sb); 601 if (mStateMachine != null) { 602 mStateMachine.dump(sb); 603 } 604 } 605 } 606