HeadsetClientService.java revision 2a32ce991573191acde4d5d2f875658ada301874
1aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta/*
2aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Copyright (c) 2014 The Android Open Source Project
3aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
4aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Licensed under the Apache License, Version 2.0 (the "License");
5aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * you may not use this file except in compliance with the License.
6aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * You may obtain a copy of the License at
7aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
8aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *      http://www.apache.org/licenses/LICENSE-2.0
9aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
10aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Unless required by applicable law or agreed to in writing, software
11aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * distributed under the License is distributed on an "AS IS" BASIS,
12aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * See the License for the specific language governing permissions and
14aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * limitations under the License.
15aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
16aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
17aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptapackage com.android.bluetooth.hfpclient;
18aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
19aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothDevice;
20aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothProfile;
218d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClient;
228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClientCall;
238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.IBluetoothHeadsetClient;
24aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.BroadcastReceiver;
25aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Context;
26aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Intent;
27aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.IntentFilter;
28aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.media.AudioManager;
29aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Bundle;
30aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Message;
31aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.provider.Settings;
32aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.util.Log;
33eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen
34aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.btservice.ProfileService;
35a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwalimport com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService;
36aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.Utils;
37eb7b90f5b93db1230a5b64caa3d8d05a642e33a6Marie Janssen
38aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.ArrayList;
39aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.List;
40ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwalimport java.util.UUID;
41a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
42aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta/**
438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood * Provides Bluetooth Headset Client (HF Role) profile, as a service in the
44aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * Bluetooth application.
45aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *
46aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta * @hide
47aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodpublic class HeadsetClientService extends ProfileService {
49aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private static final boolean DBG = false;
508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static final String TAG = "HeadsetClientService";
51aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private HeadsetClientStateMachine mStateMachine;
538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static HeadsetClientService sHeadsetClientService;
54aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
55a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal    public static String HFP_CLIENT_STOP_TAG = "hfp_client_stop_tag";
56a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
57aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
58aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected String getName() {
59aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return TAG;
60aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
61aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
62aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
63aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public IProfileServiceBinder initBinder() {
648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        return new BluetoothHeadsetClientBinder(this);
65aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
66aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
67aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
68aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean start() {
698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine = HeadsetClientStateMachine.make(this);
70aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION);
71aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        filter.addAction(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY);
72aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
73aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            registerReceiver(mBroadcastReceiver, filter);
74aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
75aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to register broadcat receiver", e);
76aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        setHeadsetClientService(this);
78a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
79a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // Start the HfpClientConnectionService to create connection with telecom when HFP
80a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // connection is available.
81a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        Intent startIntent = new Intent(this, HfpClientConnectionService.class);
82a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        startService(startIntent);
83a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
84aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
85aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
86aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
87aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
88aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean stop() {
89aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        try {
90aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            unregisterReceiver(mBroadcastReceiver);
91aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } catch (Exception e) {
92aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.w(TAG, "Unable to unregister broadcast receiver", e);
93aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
94562547733c2dd517f3bdd30f29bfe43732fe9a13Chenjie Luo
95bebc4dd9edb40710d9588b4a2010eef227756a8eLianchao Song        if (mStateMachine != null) {
96bebc4dd9edb40710d9588b4a2010eef227756a8eLianchao Song            mStateMachine.doQuit();
97bebc4dd9edb40710d9588b4a2010eef227756a8eLianchao Song        }
98a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal
99a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        // Stop the HfpClientConnectionService.
100a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        Intent stopIntent = new Intent(this, HfpClientConnectionService.class);
101a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        stopIntent.putExtra(HFP_CLIENT_STOP_TAG, true);
102a8fc504fed7dcb5dc074980b9d4cfa7a56445424Sanket Agarwal        startService(stopIntent);
103aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
104aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
105aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    @Override
107aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    protected boolean cleanup() {
108aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine != null) {
109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mStateMachine.cleanup();
110aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1118d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        clearHeadsetClientService();
112aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
113aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
115aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
116aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
117aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void onReceive(Context context, Intent intent) {
118aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            String action = intent.getAction();
119aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1203076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // We handle the volume changes for Voice calls here since HFP audio volume control does
1213076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // not go through audio manager (audio mixer). We check if the voice call volume has
1223076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // changed and subsequently change the SCO volume see
1233076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // ({@link HeadsetClientStateMachine#SET_SPEAKER_VOLUME} in
1243076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal            // {@link HeadsetClientStateMachine} for details.
125aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
1263076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                Log.d(TAG, "Volume changed for stream: " +
1273076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    intent.getExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE));
128aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
1293076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                if (streamType == AudioManager.STREAM_VOICE_CALL) {
130aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamValue = intent
131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            .getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
132aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    int streamPrevValue = intent.getIntExtra(
133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
134aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (streamValue != -1 && streamValue != streamPrevValue) {
136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mStateMachine.sendMessage(mStateMachine.obtainMessage(
1378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                HeadsetClientStateMachine.SET_SPEAKER_VOLUME, streamValue, 0));
138aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
142aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
143aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
144aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    /**
145aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     * Handlers for incoming service calls
146aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     */
1478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static class BluetoothHeadsetClientBinder extends IBluetoothHeadsetClient.Stub
148aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            implements IProfileServiceBinder {
1498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService mService;
150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public BluetoothHeadsetClientBinder(HeadsetClientService svc) {
152aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = svc;
153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
155aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
156aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean cleanup() {
157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService = null;
158aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
160aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1618d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        private HeadsetClientService getService() {
162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (!Utils.checkCaller()) {
1638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.w(TAG, "HeadsetClient call not allowed for non-active user");
164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
165aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
167aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mService != null && mService.isAvailable()) {
168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return mService;
169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
172aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
173aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
174aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connect(BluetoothDevice device) {
1758d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
176aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
177aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
178aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
179aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connect(device);
180aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
181aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
182aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
183aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnect(BluetoothDevice device) {
1848d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
185aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
186aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
187aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
188aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnect(device);
189aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
190aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
191aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
192aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getConnectedDevices() {
1938d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
194aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
195aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
196aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
197aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectedDevices();
198aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
199aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
200aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
201aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
2028d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
203aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
204aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return new ArrayList<BluetoothDevice>(0);
205aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
206aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getDevicesMatchingConnectionStates(states);
207aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
208aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
209aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
210aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getConnectionState(BluetoothDevice device) {
2118d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
212aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
213aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.STATE_DISCONNECTED;
214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
215aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getConnectionState(device);
216aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
217aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
219aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean setPriority(BluetoothDevice device, int priority) {
2208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
223aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.setPriority(device, priority);
225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
226aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
227aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
228aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getPriority(BluetoothDevice device) {
2298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return BluetoothProfile.PRIORITY_UNDEFINED;
232aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
233aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getPriority(device);
234aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
235aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
236aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
237aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean startVoiceRecognition(BluetoothDevice device) {
2388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
240aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
241aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
242aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.startVoiceRecognition(device);
243aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
244aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
245aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
246aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean stopVoiceRecognition(BluetoothDevice device) {
2478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
248aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
249aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
250aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
251aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.stopVoiceRecognition(device);
252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
253aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
254aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
255aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptIncomingConnect(BluetoothDevice device) {
2568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
257aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
259aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptIncomingConnect(device);
261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
262aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
263aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
264aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectIncomingConnect(BluetoothDevice device) {
2658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
266aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
267aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
268aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
269aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectIncomingConnect(device);
270aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
271aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
272aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
273aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public int getAudioState(BluetoothDevice device) {
2748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
275aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
2768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
277aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
278aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getAudioState(device);
279aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
280aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
281aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
28222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public void setAudioRouteAllowed(boolean allowed) {
28322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
28422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
28522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                service.setAudioRouteAllowed(allowed);
28622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
28722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
28822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
28922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
29022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        public boolean getAudioRouteAllowed() {
29122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            HeadsetClientService service = getService();
29222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            if (service != null) {
29322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                return service.getAudioRouteAllowed();
29422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            }
29522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
29622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee            return false;
29722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        }
29822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
29922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        @Override
300aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean connectAudio() {
3018d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
302aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
303aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
304aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
305aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.connectAudio();
306aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
307aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
308aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
309aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean disconnectAudio() {
3108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
311aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
312aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
313aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
314aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.disconnectAudio();
315aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
316aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
318aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean acceptCall(BluetoothDevice device, int flag) {
3198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
322aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
323aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.acceptCall(device, flag);
324aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
325aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
326aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
327aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean rejectCall(BluetoothDevice device) {
3288d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
329aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
330aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
331aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.rejectCall(device);
333aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
334aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
335aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
336aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean holdCall(BluetoothDevice device) {
3378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
338aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
339aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
340aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
341aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.holdCall(device);
342aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
343aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
345ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        public boolean terminateCall(BluetoothDevice device, BluetoothHeadsetClientCall call) {
3468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
347aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
3482a32ce991573191acde4d5d2f875658ada301874Sanket Agarwal                Log.w(TAG, "service is null");
349aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
351ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal            return service.terminateCall(device, call.getUUID());
352aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
353aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
354aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
355aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean explicitCallTransfer(BluetoothDevice device) {
3568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
357aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
359aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
360aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.explicitCallTransfer(device);
361aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
362aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
363aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
364aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean enterPrivateMode(BluetoothDevice device, int index) {
3658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
366aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
368aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
369aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.enterPrivateMode(device, index);
370aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
371aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
372aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
373ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        public BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
3748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
376ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal                return null;
377aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
378aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.dial(device, number);
379aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
380aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
381aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
3828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
3838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
386aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
387aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentCalls(device);
388aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
390aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean sendDTMF(BluetoothDevice device, byte code) {
3928d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
396aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.sendDTMF(device, code);
397aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
399aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public boolean getLastVoiceTagNumber(BluetoothDevice device) {
4018d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return false;
404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getLastVoiceTagNumber(device);
406aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
407aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
408aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgEvents(BluetoothDevice device) {
4108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
413aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
414aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgEvents(device);
415aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
416aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
417aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
418aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public Bundle getCurrentAgFeatures(BluetoothDevice device) {
4198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            HeadsetClientService service = getService();
420aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (service == null) {
421aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return null;
422aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
423aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return service.getCurrentAgFeatures(device);
424aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
426aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
427aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // API methods
4288d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public static synchronized HeadsetClientService getHeadsetClientService() {
4298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (sHeadsetClientService != null && sHeadsetClientService.isAvailable()) {
430aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): returning " + sHeadsetClientService);
432aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            return sHeadsetClientService;
434aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
435aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
4368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (sHeadsetClientService == null) {
4378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is NULL");
4388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            } else if (!(sHeadsetClientService.isAvailable())) {
4398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "getHeadsetClientService(): service is not available");
440aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
442aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return null;
443aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void setHeadsetClientService(HeadsetClientService instance) {
446aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (instance != null && instance.isAvailable()) {
447aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                Log.d(TAG, "setHeadsetClientService(): set to: " + sHeadsetClientService);
449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
4508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            sHeadsetClientService = instance;
451aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
452aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
4538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (sHeadsetClientService == null) {
4548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service not available");
4558d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (!sHeadsetClientService.isAvailable()) {
4568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    Log.d(TAG, "setHeadsetClientService(): service is cleaning up");
457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
459aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
460aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
461aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static synchronized void clearHeadsetClientService() {
4638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        sHeadsetClientService = null;
464aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean connect(BluetoothDevice device) {
467aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
468aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
469aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
470aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (getPriority(device) == BluetoothProfile.PRIORITY_OFF) {
471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
472aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
473aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
474aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState == BluetoothProfile.STATE_CONNECTED ||
476aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState == BluetoothProfile.STATE_CONNECTING) {
477aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
478aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
479aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT, device);
481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
483aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnect(BluetoothDevice device) {
485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH ADMIN permission");
487aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
491aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4938d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT, device);
494aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public List<BluetoothDevice> getConnectedDevices() {
498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectedDevices();
500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
504aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getDevicesMatchingConnectionStates(states);
505aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
507aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getConnectionState(BluetoothDevice device) {
508aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
509aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getConnectionState(device);
510aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
5128d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    // TODO Should new setting for HeadsetClient priority be created?
513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean setPriority(BluetoothDevice device, int priority) {
514aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Settings.Global.putInt(getContentResolver(),
517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                priority);
519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (DBG) {
520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Saved priority " + device + " = " + priority);
521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
522aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
523aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
524aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
525aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public int getPriority(BluetoothDevice device) {
526aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
527aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                "Need BLUETOOTH_ADMIN permission");
528aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int priority = Settings.Global.getInt(getContentResolver(),
529aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Settings.Global.getBluetoothHeadsetPriorityKey(device.getAddress()),
530aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                BluetoothProfile.PRIORITY_UNDEFINED);
531aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return priority;
532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
534aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean startVoiceRecognition(BluetoothDevice device) {
535aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
536aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
537aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
538aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
539aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
540aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.VOICE_RECOGNITION_START);
542aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
544aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
545aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean stopVoiceRecognition(BluetoothDevice device) {
546aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // It seem that we really need to check the AudioOn state.
548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // But since we allow startVoiceRecognition in STATE_CONNECTED and
549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // STATE_CONNECTING state, we do these 2 in this method
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_STOP);
556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
558aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
559aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptIncomingConnect(BluetoothDevice device) {
560aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
563aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectIncomingConnect(BluetoothDevice device) {
565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // TODO(BT) remove it if stack does access control
566aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
567aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
569aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    int getAudioState(BluetoothDevice device) {
570aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getAudioState(device);
571aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
572aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
57322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public void setAudioRouteAllowed(boolean allowed) {
57422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        mStateMachine.setAudioRouteAllowed(allowed);
57522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
57622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
57722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public boolean getAudioRouteAllowed() {
57822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        return mStateMachine.getAudioRouteAllowed();
57922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
58022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean connectAudio() {
582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isConnected()) {
584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mStateMachine.isAudioOn()) {
587aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
588aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5898d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.CONNECT_AUDIO);
590aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
591aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
592aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
593aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean disconnectAudio() {
594aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM, "Need BLUETOOTH_ADMIN permission");
595aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mStateMachine.isAudioOn()) {
596aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
5988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mStateMachine.sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO);
599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean holdCall(BluetoothDevice device) {
603aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
604aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
605aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
606aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
607aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.HOLD_CALL);
610aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
611aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
612aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean acceptCall(BluetoothDevice device, int flag) {
615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
619aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
620aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6218d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.ACCEPT_CALL);
622aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = flag;
623aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
626aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean rejectCall(BluetoothDevice device) {
628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
633aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.REJECT_CALL);
636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
637aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
638aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
639aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
640ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal    boolean terminateCall(BluetoothDevice device, UUID uuid) {
641aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
642aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
643aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
645aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
646aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
647aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.TERMINATE_CALL);
649ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        msg.obj = uuid;
650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
651aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
653aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean enterPrivateMode(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.ENTER_PRIVATE_MODE);
663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = index;
664aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
665aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
666aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
668ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal    BluetoothHeadsetClientCall dial(BluetoothDevice device, String number) {
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) {
673ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal            return null;
674aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
675aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
676ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        BluetoothHeadsetClientCall call = new BluetoothHeadsetClientCall(
677ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal            device, HeadsetClientStateMachine.HF_ORIGINATED_CALL_ID,
678ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal            BluetoothHeadsetClientCall.CALL_STATE_DIALING, number, false  /* multiparty */,
679ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal            true  /* outgoing */);
6808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.DIAL_NUMBER);
681ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        msg.obj = call;
682aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
683ca6e7c65b87c52f5e81b273d7ad979a81b52f991Sanket Agarwal        return call;
684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean sendDTMF(BluetoothDevice device, byte code) {
687aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
690aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
692aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
6938d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.SEND_DTMF);
694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        msg.arg1 = code;
695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
697aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
698aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean getLastVoiceTagNumber(BluetoothDevice device) {
700aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
702aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
703aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
704aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
705aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
7068d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Message msg = mStateMachine.obtainMessage(HeadsetClientStateMachine.LAST_VTAG_NUMBER);
707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
708aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
709aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
710aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7118d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public List<BluetoothHeadsetClientCall> getCurrentCalls(BluetoothDevice device) {
712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
713aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
716aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentCalls();
718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
719aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public boolean explicitCallTransfer(BluetoothDevice device) {
721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED &&
724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState != BluetoothProfile.STATE_CONNECTING) {
725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
726aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Message msg = mStateMachine
7288d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                .obtainMessage(HeadsetClientStateMachine.EXPLICIT_CALL_TRANSFER);
729aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mStateMachine.sendMessage(msg);
730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
731aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgEvents(BluetoothDevice device) {
734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
739aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgEvents();
740aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
742aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgFeatures(BluetoothDevice device) {
743aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState = mStateMachine.getConnectionState(device);
745aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (connectionState != BluetoothProfile.STATE_CONNECTED) {
746aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return null;
747aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
748aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mStateMachine.getCurrentAgFeatures();
749aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
750838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood
751838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    @Override
752838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    public void dump(StringBuilder sb) {
753838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        super.dump(sb);
754838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        if (mStateMachine != null) {
755838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood            mStateMachine.dump(sb);
756838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
757838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    }
758aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta}
759