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