HeadsetClientService.java revision a8fc504fed7dcb5dc074980b9d4cfa7a56445424
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;
35a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwalimport com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService;
36aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.Utils;
37aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.ArrayList;
38aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.List;
39aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
40a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
41aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta/**
428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood * Provides Bluetooth Headset Client (HF Role) profile, as a service in the
43aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Bluetooth application.
44aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
45aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * @hide
46aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodpublic class HeadsetClientService extends ProfileService {
48aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private static final boolean DBG = false;
498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static final String TAG = "HeadsetClientService";
50aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private HeadsetClientStateMachine mStateMachine;
528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static HeadsetClientService sHeadsetClientService;
53aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
54a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal    public static String HFP_CLIENT_STOP_TAG = "hfp_client_stop_tag";
55a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
56aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
57aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected String getName() {
58aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return TAG;
59aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
60aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
61aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
62aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public IProfileServiceBinder initBinder() {
638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        return new BluetoothHeadsetClientBinder(this);
64aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
65aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
66aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
67aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean start() {
688d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine = HeadsetClientStateMachine.make(this);
69aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
70aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
71aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
72aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            registerReceiver(mBroadcastReceiver, filter);
73aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
74aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to register broadcat receiver", e);
75aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        setHeadsetClientService(this);
77a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
78a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // Start the HfpClientConnectionService to create connection with telecom when HFP
79a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // connection is available.
80a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        Intent startIntent = new Intent(this, HfpClientConnectionService.class);
81a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        startService(startIntent);
82a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
83aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
84aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
85aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
86aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
87aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean stop() {
88aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
89aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            unregisterReceiver(mBroadcastReceiver);
90aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
91aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to unregister broadcast receiver", e);
92aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
93aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.doQuit();
94a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
95a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // Stop the HfpClientConnectionService.
96a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        Intent stopIntent = new Intent(this, HfpClientConnectionService.class);
97a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        stopIntent.putExtra(HFP_CLIENT_STOP_TAG, true);
98a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        startService(stopIntent);
99a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
100aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
101aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
102aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
103aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
104aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean cleanup() {
105aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine != null) {
106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mStateMachine.cleanup();
107aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        clearHeadsetClientService();
109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
110aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
111aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
112aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
113aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void onReceive(Context context, Intent intent) {
115aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            String action = intent.getAction();
116aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1173076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // We handle the volume changes for Voice calls here since HFP audio volume control does
1183076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // not go through audio manager (audio mixer). We check if the voice call volume has
1193076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // changed and subsequently change the SCO volume see
1203076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // ({@link HeadsetClientStateMachine#SET_SPEAKER_VOLUME} in
1213076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // {@link HeadsetClientStateMachine} for details.
122aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
1233076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                Log.d(TAG, "Volume changed for stream: " +
1243076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    intent.getExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE));
125aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
1263076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                if (streamType == AudioManager.STREAM_VOICE_CALL) {
127aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamValue = intent
128aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
129aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamPrevValue = intent.getIntExtra(
130aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
132aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (streamValue != -1 && streamValue != streamPrevValue) {
133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mStateMachine.sendMessage(mStateMachine.obtainMessage(
1348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0));
135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
137aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
138aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    /**
142aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     * Handlers for incoming service calls
143aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     */
1448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
145aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            implements IProfileServiceBinder {
1468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService mService;
147aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public BluetoothHeadsetClientBinder(HeadsetClientService svc) {
149aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = svc;
150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
151aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
152aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean cleanup() {
154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = null;
155aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
156aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1588d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService getService() {
159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (!Utils.checkCaller()) {
1608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.w(TAG, "HeadsetClient call not allowed for non-active user");
161aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
163aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mService != null && mService.isAvailable()) {
165aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return mService;
166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
167aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connect(BluetoothDevice device) {
1728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
173aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
174aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
175aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
176aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connect(device);
177aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
178aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
179aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
180aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnect(BluetoothDevice device) {
1818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
182aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
183aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
184aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
185aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnect(device);
186aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
187aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
188aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
189aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getConnectedDevices() {
1908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
191aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
192aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
193aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
194aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectedDevices();
195aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
196aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
197aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
198aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
1998d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
200aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
201aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
202aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
203aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getDevicesMatchingConnectionStates(states);
204aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
205aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
206aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
207aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getConnectionState(BluetoothDevice device) {
2088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
209aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
210aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.STATE_DISCONNECTED;
211aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
212aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectionState(device);
213aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
215aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
216aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean setPriority(BluetoothDevice device, int priority) {
2178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
219aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
220aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.setPriority(device, priority);
222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
223aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getPriority(BluetoothDevice device) {
2268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
227aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
228aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.PRIORITY_UNDEFINED;
229aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getPriority(device);
231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
232aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
233aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
234aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean startVoiceRecognition(BluetoothDevice device) {
2358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
236aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
237aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
238aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.startVoiceRecognition(device);
240aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
241aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
242aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
243aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean stopVoiceRecognition(BluetoothDevice device) {
2448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
245aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
246aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
247aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
248aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.stopVoiceRecognition(device);
249aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
250aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
251aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptIncomingConnect(BluetoothDevice device) {
2538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
254aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
255aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
256aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
257aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptIncomingConnect(device);
258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
259aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectIncomingConnect(BluetoothDevice device) {
2628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
263aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
264aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
265aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
266aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectIncomingConnect(device);
267aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
268aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
269aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
270aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getAudioState(BluetoothDevice device) {
2718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
272aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
2738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
274aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
275aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getAudioState(device);
276aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
277aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
278aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
27922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public void setAudioRouteAllowed(boolean allowed) {
28022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
28122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
28222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                service.setAudioRouteAllowed(allowed);
28322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
28422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
28522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
28622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
28722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public boolean getAudioRouteAllowed() {
28822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
28922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
29022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                return service.getAudioRouteAllowed();
29122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
29222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
29322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            return false;
29422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
29522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
29622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
297aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connectAudio() {
2988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
299aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
300aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
301aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
302aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connectAudio();
303aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
304aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
305aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
306aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnectAudio() {
3078d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
308aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
309aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
310aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
311aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnectAudio();
312aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
313aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
314aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
315aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptCall(BluetoothDevice device, int flag) {
3168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
318aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
319aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptCall(device, flag);
321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
322aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
323aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
324aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectCall(BluetoothDevice device) {
3258d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
326aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
327aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
328aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
329aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectCall(device);
330aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
331aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
333aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean holdCall(BluetoothDevice device) {
3348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
335aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
336aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
337aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
338aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.holdCall(device);
339aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
340aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
341aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
342aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean terminateCall(BluetoothDevice device, int index) {
3438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
345aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
346aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
347aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.terminateCall(device, index);
348aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
349aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
351aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean explicitCallTransfer(BluetoothDevice device) {
3528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
353aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
354aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
355aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
356aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.explicitCallTransfer(device);
357aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
359aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
360aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean enterPrivateMode(BluetoothDevice device, int index) {
3618d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
362aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
363aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
364aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
365aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.enterPrivateMode(device, index);
366aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
368aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
369aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean redial(BluetoothDevice device) {
3708d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
371aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
372aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
373aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
374aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.redial(device);
375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
376aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
377aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
378aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean dial(BluetoothDevice device, String number) {
3798d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
380aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
381aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
382aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
383aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.dial(device, number);
384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
386aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
387aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean dialMemory(BluetoothDevice device, int location) {
3888d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
390aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
392aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.dialMemory(device, location);
393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
3968d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
3978d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
399aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
401aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentCalls(device);
402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean sendDTMF(BluetoothDevice device, byte code) {
4068d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
407aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
408aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
410aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.sendDTMF(device, code);
411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
413aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
414aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean getLastVoiceTagNumber(BluetoothDevice device) {
4158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
416aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
417aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
418aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
419aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getLastVoiceTagNumber(device);
420aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
421aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
422aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
423aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgEvents(BluetoothDevice device) {
4248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
426aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
427aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
428aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgEvents(device);
429aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
430aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
431aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
432aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgFeatures(BluetoothDevice device) {
4338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
434aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
435aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
436aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
437aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgFeatures(device);
438aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
439aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
440aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // API methods
4428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public static synchronized HeadsetClientService getHeadsetClientService() {
4438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (sHeadsetClientService != null && sHeadsetClientService.isAvailable()) {
444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): returning " + sHeadsetClientService);
446aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            return sHeadsetClientService;
448aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
4508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (sHeadsetClientService == null) {
4518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is NULL");
4528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            } else if (!(sHeadsetClientService.isAvailable())) {
4538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is not available");
454aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
455aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
456aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return null;
457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void setHeadsetClientService(HeadsetClientService instance) {
460aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (instance != null && instance.isAvailable()) {
461aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "setHeadsetClientService(): set to: " + sHeadsetClientService);
463aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            sHeadsetClientService = instance;
465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4678d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (sHeadsetClientService == null) {
4688d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service not available");
4698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (!sHeadsetClientService.isAvailable()) {
4708d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service is cleaning up");
471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
472aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
473aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
474aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void clearHeadsetClientService() {
4778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        sHeadsetClientService = null;
478aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
479aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
480aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean connect(BluetoothDevice device) {
481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
483aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
487aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState == BluetoothProfile.STATE_CONNECTING) {
491aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
493aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4948d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device);
495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnect(BluetoothDevice device) {
499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
504aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
505aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
5078d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, device);
508aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
509aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
510aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public List<BluetoothDevice> getConnectedDevices() {
512aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectedDevices();
514aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getDevicesMatchingConnectionStates(states);
519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getConnectionState(BluetoothDevice device) {
522aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
523aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectionState(device);
524aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
525aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
5268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    // TODO Should new setting for HeadsetClient priority be created?
527aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean setPriority(BluetoothDevice device, int priority) {
528aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
529aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
530aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Settings.Global.putInt(getContentResolver(),
531aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                priority);
533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
534aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Saved priority " + device + " = " + priority);
535aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
536aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
537aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
538aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
539aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public int getPriority(BluetoothDevice device) {
540aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
541aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
542aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int priority = Settings.Global.getInt(getContentResolver(),
543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
544aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                BluetoothProfile.PRIORITY_UNDEFINED);
545aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return priority;
546aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean startVoiceRecognition(BluetoothDevice device) {
549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
550aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
551aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
552aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
553aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
554aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5558d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START);
556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
558aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
559aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean stopVoiceRecognition(BluetoothDevice device) {
560aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // It seem that we really need to check the AudioOn state.
562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // But since we allow startVoiceRecognition in STATE_CONNECTED and
563aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // STATE_CONNECTING state, we do these 2 in this method
564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
566aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
567aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_STOP);
570aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
571aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
572aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
573aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptIncomingConnect(BluetoothDevice device) {
574aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
575aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
576aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
577aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
578aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectIncomingConnect(BluetoothDevice device) {
579aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
580aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getAudioState(BluetoothDevice device) {
584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getAudioState(device);
585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
58722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public void setAudioRouteAllowed(boolean allowed) {
58822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        mStateMachine.setAudioRouteAllowed(allowed);
58922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
59022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
59122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public boolean getAudioRouteAllowed() {
59222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        return mStateMachine.getAudioRouteAllowed();
59322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
59422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
595aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean connectAudio() {
596aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isConnected()) {
598aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine.isAudioOn()) {
601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO);
604aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
605aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
606aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
607aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnectAudio() {
608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
609aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isAudioOn()) {
610aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
611aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6128d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO);
613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean holdCall(BluetoothDevice device) {
617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
619aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
620aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
621aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
622aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.HOLD_CALL);
624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
626aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptCall(BluetoothDevice device, int flag) {
629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
633aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL);
636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = flag;
637aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
638aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
639aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
640aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
641aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectCall(BluetoothDevice device) {
642aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
643aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
645aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
646aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
647aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
648aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REJECT_CALL);
650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
651aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
653aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean terminateCall(BluetoothDevice device, int index) {
655aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
656aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
657aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
658aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
659aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
660aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
661aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL);
663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = index;
664aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
665aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
666aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
668aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean enterPrivateMode(BluetoothDevice device, int index) {
669aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
670aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
671aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
672aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
673aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
674aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
675aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ENTER_PRIVATE_MODE);
677aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = index;
678aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
679aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
680aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
681aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
682aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean redial(BluetoothDevice device) {
683aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
687aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REDIAL);
691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
692aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
693aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean dial(BluetoothDevice device, String number) {
696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
697aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
698aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
700aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
702aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER);
704aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.obj = number;
705aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
706aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
708aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
709aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean dialMemory(BluetoothDevice device, int location) {
710aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
711aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
713aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_MEMORY);
717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = location;
718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
719aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean sendDTMF(BluetoothDevice device, byte code) {
723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
726aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
728aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_DTMF);
730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = code;
731aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean getLastVoiceTagNumber(BluetoothDevice device) {
736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
739aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
740aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.LAST_VTAG_NUMBER);
743aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
745aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
746aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
748aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
749aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
750aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
751aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
752aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
753aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentCalls();
754aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
755aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
756aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean explicitCallTransfer(BluetoothDevice device) {
757aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
758aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
759aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
760aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
761aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
762aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
763aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Message msg = mStateMachine
7648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                .obtainMessage(HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER);
765aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
766aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
767aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
768aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
769aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgEvents(BluetoothDevice device) {
770aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
771aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
772aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
773aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
774aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
775aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgEvents();
776aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
777aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
778aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgFeatures(BluetoothDevice device) {
779aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
780aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
781aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
782aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
783aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
784aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgFeatures();
785aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
786838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood
787838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    @Override
788838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    public void dump(StringBuilder sb) {
789838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        super.dump(sb);
790838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        if (mStateMachine != null) {
791838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood            mStateMachine.dump(sb);
792838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
793838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    }
794aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta}
795