• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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