HeadsetClientService.java revision 3076d2acccf5c3db0db19b622f062e259be39f3a
1aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta/*
2aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Copyright (c) 2014 The Android Open Source Project
3aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Copyright (C) 2012 The Android Open Source Project
4aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
5aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Licensed under the Apache License, Version 2.0 (the "License");
6aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * you may not use this file except in compliance with the License.
7aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * You may obtain a copy of the License at
8aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
9aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *      http://www.apache.org/licenses/LICENSE-2.0
10aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
11aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Unless required by applicable law or agreed to in writing, software
12aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * distributed under the License is distributed on an "AS IS" BASIS,
13aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * See the License for the specific language governing permissions and
15aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * limitations under the License.
16aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
17aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
18aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptapackage com.android.bluetooth.hfpclient;
19aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
20aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothDevice;
21aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothProfile;
228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClient;
238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClientCall;
248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.IBluetoothHeadsetClient;
25aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.BroadcastReceiver;
26aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Context;
27aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Intent;
28aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.IntentFilter;
29aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.media.AudioManager;
30aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Bundle;
31aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Message;
32aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.provider.Settings;
33aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.util.Log;
34aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.btservice.ProfileService;
35aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.Utils;
36aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.ArrayList;
37aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.List;
38aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
39aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta/**
408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood * Provides Bluetooth Headset Client (HF Role) profile, as a service in the
41aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Bluetooth application.
42aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
43aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * @hide
44aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodpublic class HeadsetClientService extends ProfileService {
46aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private static final boolean DBG = false;
478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static final String TAG = "HeadsetClientService";
48aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private HeadsetClientStateMachine mStateMachine;
508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static HeadsetClientService sHeadsetClientService;
51aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
52aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
53aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected String getName() {
54aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return TAG;
55aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
56aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
57aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
58aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public IProfileServiceBinder initBinder() {
598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        return new BluetoothHeadsetClientBinder(this);
60aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
61aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
62aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
63aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean start() {
648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine = HeadsetClientStateMachine.make(this);
65aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
66aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
67aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
68aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            registerReceiver(mBroadcastReceiver, filter);
69aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
70aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to register broadcat receiver", e);
71aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        setHeadsetClientService(this);
73aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
74aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
75aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
76aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
77aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean stop() {
78aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
79aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            unregisterReceiver(mBroadcastReceiver);
80aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
81aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to unregister broadcast receiver", e);
82aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
83aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.doQuit();
84aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
85aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
86aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
87aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
88aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean cleanup() {
89aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine != null) {
90aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mStateMachine.cleanup();
91aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
928d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        clearHeadsetClientService();
93aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
94aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
95aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
96aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
97aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
98aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void onReceive(Context context, Intent intent) {
99aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            String action = intent.getAction();
100aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1013076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // We handle the volume changes for Voice calls here since HFP audio volume control does
1023076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // not go through audio manager (audio mixer). We check if the voice call volume has
1033076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // changed and subsequently change the SCO volume see
1043076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // ({@link HeadsetClientStateMachine#SET_SPEAKER_VOLUME} in
1053076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // {@link HeadsetClientStateMachine} for details.
106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
1073076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                Log.d(TAG, "Volume changed for stream: " +
1083076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    intent.getExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE));
109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
1103076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                if (streamType == AudioManager.STREAM_VOICE_CALL) {
111aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamValue = intent
112aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
113aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamPrevValue = intent.getIntExtra(
114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
115aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
116aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (streamValue != -1 && streamValue != streamPrevValue) {
117aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mStateMachine.sendMessage(mStateMachine.obtainMessage(
1188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0));
119aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
120aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
121aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
122aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
123aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
124aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
125aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    /**
126aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     * Handlers for incoming service calls
127aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     */
1288d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
129aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            implements IProfileServiceBinder {
1308d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService mService;
131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1328d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public BluetoothHeadsetClientBinder(HeadsetClientService svc) {
133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = svc;
134aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
137aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean cleanup() {
138aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = null;
139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService getService() {
143aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (!Utils.checkCaller()) {
1448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.w(TAG, "HeadsetClient call not allowed for non-active user");
145aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
146aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
147aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
148aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mService != null && mService.isAvailable()) {
149aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return mService;
150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
151aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
152aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
155aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connect(BluetoothDevice device) {
1568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
158aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
160aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connect(device);
161aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
163aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnect(BluetoothDevice device) {
1658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
167aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnect(device);
170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
172aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
173aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getConnectedDevices() {
1748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
175aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
176aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
177aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
178aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectedDevices();
179aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
180aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
181aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
182aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
184aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
185aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
186aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
187aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getDevicesMatchingConnectionStates(states);
188aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
189aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
190aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
191aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getConnectionState(BluetoothDevice device) {
1928d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
193aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
194aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.STATE_DISCONNECTED;
195aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
196aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectionState(device);
197aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
198aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
199aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
200aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean setPriority(BluetoothDevice device, int priority) {
2018d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
202aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
203aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
204aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
205aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.setPriority(device, priority);
206aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
207aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
208aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
209aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getPriority(BluetoothDevice device) {
2108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
211aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
212aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.PRIORITY_UNDEFINED;
213aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getPriority(device);
215aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
216aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
217aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean startVoiceRecognition(BluetoothDevice device) {
2198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
220aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
223aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.startVoiceRecognition(device);
224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
226aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
227aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean stopVoiceRecognition(BluetoothDevice device) {
2288d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
229aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
232aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.stopVoiceRecognition(device);
233aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
234aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
235aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
236aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptIncomingConnect(BluetoothDevice device) {
2378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
238aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
240aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
241aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptIncomingConnect(device);
242aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
243aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
244aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
245aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectIncomingConnect(BluetoothDevice device) {
2468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
247aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
248aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
249aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
250aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectIncomingConnect(device);
251aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
253aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
254aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getAudioState(BluetoothDevice device) {
2558d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
256aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
2578d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
259aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getAudioState(device);
260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
262aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
26322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public void setAudioRouteAllowed(boolean allowed) {
26422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
26522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
26622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                service.setAudioRouteAllowed(allowed);
26722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
26822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
26922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
27022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
27122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public boolean getAudioRouteAllowed() {
27222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
27322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
27422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                return service.getAudioRouteAllowed();
27522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
27622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
27722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            return false;
27822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
27922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
28022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
281aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connectAudio() {
2828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
283aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
284aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
285aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
286aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connectAudio();
287aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
288aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
289aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
290aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnectAudio() {
2918d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
292aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
293aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
294aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
295aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnectAudio();
296aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
297aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
298aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
299aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptCall(BluetoothDevice device, int flag) {
3008d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
301aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
302aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
303aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
304aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptCall(device, flag);
305aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
306aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
307aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
308aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectCall(BluetoothDevice device) {
3098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
310aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
311aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
312aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
313aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectCall(device);
314aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
315aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
316aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean holdCall(BluetoothDevice device) {
3188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
319aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
322aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.holdCall(device);
323aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
324aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
325aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
326aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean terminateCall(BluetoothDevice device, int index) {
3278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
328aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
329aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
330aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
331aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.terminateCall(device, index);
332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
333aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
334aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
335aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean explicitCallTransfer(BluetoothDevice device) {
3368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
337aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
338aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
339aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
340aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.explicitCallTransfer(device);
341aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
342aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
343aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean enterPrivateMode(BluetoothDevice device, int index) {
3458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
346aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
347aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
348aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
349aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.enterPrivateMode(device, index);
350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
351aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
352aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
353aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean redial(BluetoothDevice device) {
3548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
355aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
356aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
357aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.redial(device);
359aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
360aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
361aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
362aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean dial(BluetoothDevice device, String number) {
3638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
364aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
365aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
366aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.dial(device, number);
368aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
369aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
370aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
371aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean dialMemory(BluetoothDevice device, int location) {
3728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
373aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
374aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
376aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.dialMemory(device, location);
377aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
378aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
379aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
3808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
3818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
382aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
383aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentCalls(device);
386aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
387aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
388aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean sendDTMF(BluetoothDevice device, byte code) {
3908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
392aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.sendDTMF(device, code);
395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
396aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
397aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean getLastVoiceTagNumber(BluetoothDevice device) {
3998d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
401aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getLastVoiceTagNumber(device);
404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
406aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
407aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgEvents(BluetoothDevice device) {
4088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
410aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgEvents(device);
413aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
414aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
415aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
416aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgFeatures(BluetoothDevice device) {
4178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
418aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
419aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
420aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
421aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgFeatures(device);
422aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
423aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
424aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // API methods
4268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public static synchronized HeadsetClientService getHeadsetClientService() {
4278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (sHeadsetClientService != null && sHeadsetClientService.isAvailable()) {
428aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): returning " + sHeadsetClientService);
430aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            return sHeadsetClientService;
432aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
433aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
4348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (sHeadsetClientService == null) {
4358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is NULL");
4368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            } else if (!(sHeadsetClientService.isAvailable())) {
4378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is not available");
438aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
439aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
440aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return null;
441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
442aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void setHeadsetClientService(HeadsetClientService instance) {
444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (instance != null && instance.isAvailable()) {
445aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "setHeadsetClientService(): set to: " + sHeadsetClientService);
447aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            sHeadsetClientService = instance;
449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
450aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (sHeadsetClientService == null) {
4528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service not available");
4538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (!sHeadsetClientService.isAvailable()) {
4548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service is cleaning up");
455aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
456aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
459aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void clearHeadsetClientService() {
4618d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        sHeadsetClientService = null;
462aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
463aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
464aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean connect(BluetoothDevice device) {
465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
467aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
468aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
469aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
470aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
472aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
473aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
474aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState == BluetoothProfile.STATE_CONNECTING) {
475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
476aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
477aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4788d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device);
479aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
480aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnect(BluetoothDevice device) {
483aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
487aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4918d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, device);
492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
493aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
494aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public List<BluetoothDevice> getConnectedDevices() {
496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectedDevices();
498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getDevicesMatchingConnectionStates(states);
503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
504aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
505aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getConnectionState(BluetoothDevice device) {
506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
507aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectionState(device);
508aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
509aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
5108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    // TODO Should new setting for HeadsetClient priority be created?
511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean setPriority(BluetoothDevice device, int priority) {
512aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
514aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Settings.Global.putInt(getContentResolver(),
515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                priority);
517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Saved priority " + device + " = " + priority);
519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
522aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
523aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public int getPriority(BluetoothDevice device) {
524aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
525aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
526aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int priority = Settings.Global.getInt(getContentResolver(),
527aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
528aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                BluetoothProfile.PRIORITY_UNDEFINED);
529aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return priority;
530aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
531aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean startVoiceRecognition(BluetoothDevice device) {
533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
534aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
535aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
536aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
537aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
538aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START);
540aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
541aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
542aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean stopVoiceRecognition(BluetoothDevice device) {
544aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
545aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // It seem that we really need to check the AudioOn state.
546aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // But since we allow startVoiceRecognition in STATE_CONNECTED and
547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // STATE_CONNECTING state, we do these 2 in this method
548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
550aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
551aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
552aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_STOP);
554aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
555aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptIncomingConnect(BluetoothDevice device) {
558aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
559aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
560aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectIncomingConnect(BluetoothDevice device) {
563aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
566aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
567aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getAudioState(BluetoothDevice device) {
568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getAudioState(device);
569aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
570aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
57122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public void setAudioRouteAllowed(boolean allowed) {
57222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        mStateMachine.setAudioRouteAllowed(allowed);
57322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
57422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
57522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public boolean getAudioRouteAllowed() {
57622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        return mStateMachine.getAudioRouteAllowed();
57722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
57822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
579aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean connectAudio() {
580aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isConnected()) {
582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine.isAudioOn()) {
585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO);
588aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
589aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
590aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
591aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnectAudio() {
592aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
593aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isAudioOn()) {
594aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
595aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5968d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO);
597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
598aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean holdCall(BluetoothDevice device) {
601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
603aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
604aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
605aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
606aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6078d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.HOLD_CALL);
608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
609aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
610aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
611aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
612aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptCall(BluetoothDevice device, int flag) {
613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL);
620aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = flag;
621aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
622aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
623aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectCall(BluetoothDevice device) {
626aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REJECT_CALL);
634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
635aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
637aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
638aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean terminateCall(BluetoothDevice device, int index) {
639aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
640aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
641aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
642aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
643aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
645aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL);
647aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = index;
648aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
649aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
651aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean enterPrivateMode(BluetoothDevice device, int index) {
653aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
655aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
656aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
657aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
658aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
659aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ENTER_PRIVATE_MODE);
661aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = index;
662aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
664aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
665aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
666aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean redial(BluetoothDevice device) {
667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
668aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
669aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
670aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
671aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
672aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
673aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REDIAL);
675aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
676aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
677aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
678aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
679aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean dial(BluetoothDevice device, String number) {
680aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
681aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
682aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
683aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER);
688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.obj = number;
689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
690aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
692aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
693aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean dialMemory(BluetoothDevice device, int location) {
694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
697aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
698aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7008d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_MEMORY);
701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = location;
702aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
703aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
704aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
705aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
706aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean sendDTMF(BluetoothDevice device, byte code) {
707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
708aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
709aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
710aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
711aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_DTMF);
714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = code;
715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
716aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
719aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean getLastVoiceTagNumber(BluetoothDevice device) {
720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.LAST_VTAG_NUMBER);
727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
728aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
729aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentCalls();
738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
739aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
740aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean explicitCallTransfer(BluetoothDevice device) {
741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
742aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
743aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
745aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
746aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
747aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Message msg = mStateMachine
7488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                .obtainMessage(HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER);
749aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
750aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
751aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
752aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
753aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgEvents(BluetoothDevice device) {
754aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
755aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
756aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
757aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
758aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
759aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgEvents();
760aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
761aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
762aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgFeatures(BluetoothDevice device) {
763aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
764aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
765aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
766aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
767aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
768aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgFeatures();
769aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
770838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood
771838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    @Override
772838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    public void dump(StringBuilder sb) {
773838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        super.dump(sb);
774838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        if (mStateMachine != null) {
775838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood            mStateMachine.dump(sb);
776838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
777838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    }
778aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta}
779