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 Gupta/**
198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood * Bluetooth Headset Client StateMachine
20aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                      (Disconnected)
21aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           | ^  ^
22aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                   CONNECT | |  | DISCONNECTED
23aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           V |  |
24aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                   (Connecting) |
25aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           |    |
26aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                 CONNECTED |    | DISCONNECT
27aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           V    |
28aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                        (Connected)
29aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           |    ^
30aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *             CONNECT_AUDIO |    | DISCONNECT_AUDIO
31aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                           V    |
32aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta *                         (AudioOn)
33aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta */
34aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
35aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptapackage com.android.bluetooth.hfpclient;
36aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
37aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothAdapter;
38aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothDevice;
398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClient;
408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodimport android.bluetooth.BluetoothHeadsetClientCall;
41aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothProfile;
42aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.bluetooth.BluetoothUuid;
43aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Bundle;
44aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.Message;
45aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.os.ParcelUuid;
46aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.util.Log;
47aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.util.Pair;
48aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Context;
49aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.content.Intent;
50aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.media.AudioManager;
51aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.media.Ringtone;
52aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.media.RingtoneManager;
53aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport android.net.Uri;
54a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwalimport android.telecom.TelecomManager;
55aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
56aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.Utils;
57aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.btservice.AdapterService;
58aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport com.android.bluetooth.btservice.ProfileService;
59a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwalimport com.android.bluetooth.hfpclient.connserv.HfpClientConnectionService;
60a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwalimport com.android.internal.util.IState;
61a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwalimport com.android.internal.util.State;
62a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwalimport com.android.internal.util.StateMachine;
63aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
64aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.ArrayList;
65aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.Arrays;
66aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.Hashtable;
67aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.Iterator;
68aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.LinkedList;
69aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.List;
70aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.Queue;
71aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Guptaimport java.util.Set;
72aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Leeimport com.android.bluetooth.R;
7422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
758d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwoodfinal class HeadsetClientStateMachine extends StateMachine {
768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private static final String TAG = "HeadsetClientStateMachine";
77aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private static final boolean DBG = false;
78aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
79aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int NO_ACTION = 0;
80aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
81aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // external actions
82aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int CONNECT = 1;
83aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int DISCONNECT = 2;
84aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int CONNECT_AUDIO = 3;
85aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int DISCONNECT_AUDIO = 4;
86aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int VOICE_RECOGNITION_START = 5;
87aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int VOICE_RECOGNITION_STOP = 6;
88aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int SET_MIC_VOLUME = 7;
89aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int SET_SPEAKER_VOLUME = 8;
90aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int REDIAL = 9;
91aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int DIAL_NUMBER = 10;
92aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int DIAL_MEMORY = 11;
93aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int ACCEPT_CALL = 12;
94aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int REJECT_CALL = 13;
95aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int HOLD_CALL = 14;
96aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int TERMINATE_CALL = 15;
97aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int ENTER_PRIVATE_MODE = 16;
98aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int SEND_DTMF = 17;
99aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int EXPLICIT_CALL_TRANSFER = 18;
100aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int LAST_VTAG_NUMBER = 19;
101d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens    static final int DISABLE_NREC = 20;
102aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
103aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // internal actions
104aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int QUERY_CURRENT_CALLS = 50;
105aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int QUERY_OPERATOR_NAME = 51;
106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int SUBSCRIBER_INFO = 52;
107aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // special action to handle terminating specific call from multiparty call
108aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static final int TERMINATE_SPECIFIC_CALL = 53;
109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
110d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    static final int MAX_HFP_SCO_VOICE_CALL_VOLUME = 15; // HFP 1.5 spec.
111d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    static final int MIN_HFP_SCO_VOICE_CALL_VOLUME = 1; // HFP 1.5 spec.
112d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
113aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private static final int STACK_EVENT = 100;
114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
115aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final Disconnected mDisconnected;
116aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final Connecting mConnecting;
117aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final Connected mConnected;
118aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final AudioOn mAudioOn;
119aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private final HeadsetClientService mService;
121aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private Hashtable<Integer, BluetoothHeadsetClientCall> mCalls;
1238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private Hashtable<Integer, BluetoothHeadsetClientCall> mCallsUpdate;
124aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean mQueryCallsSupported;
125aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
126aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorNetworkState;
127aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorNetworkType;
128aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorNetworkSignal;
129aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorBatteryLevel;
130aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorCall;
132aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorCallSetup;
133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mIndicatorCallHeld;
134aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean mVgsFromStack = false;
135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean mVgmFromStack = false;
136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
137aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private String mOperatorName;
138aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private String mSubscriberInfo;
139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mVoiceRecognitionActive;
141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mInBandRingtone;
142aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
143d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    private int mMaxAmVcVol;
144d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    private int mMinAmVcVol;
145d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
146aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // queue of send actions (pair action, action_data)
147aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private Queue<Pair<Integer, Object>> mQueuedActions;
148aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
149aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // last executed command, before action is complete e.g. waiting for some
150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // indicator
151aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private Pair<Integer, Object> mPendingAction;
152aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final AudioManager mAudioManager;
154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mAudioState;
15522bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    // Indicates whether audio can be routed to the device.
15622bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    private boolean mAudioRouteAllowed;
157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean mAudioWbs;
158aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final BluetoothAdapter mAdapter;
159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean mNativeAvailable;
160a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwal    private TelecomManager mTelecomManager;
161aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // currently connected device
163aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private BluetoothDevice mCurrentDevice = null;
164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
165aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // general peer features and call handling features
166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mPeerFeatures;
167aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int mChldFeatures;
168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    static {
170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        classInitNative();
171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
172aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
173838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    public void dump(StringBuilder sb) {
174838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mCurrentDevice: " + mCurrentDevice);
175838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mAudioOn: " + mAudioOn);
176838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mAudioState: " + mAudioState);
177838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mAudioWbs: " + mAudioWbs);
178838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorNetworkState: " + mIndicatorNetworkState);
179838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorNetworkType: " + mIndicatorNetworkType);
180838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorNetworkSignal: " + mIndicatorNetworkSignal);
181838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorBatteryLevel: " + mIndicatorBatteryLevel);
182838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorCall: " + mIndicatorCall);
183838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorCallSetup: " + mIndicatorCallSetup);
184838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mIndicatorCallHeld: " + mIndicatorCallHeld);
185838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mVgsFromStack: " + mVgsFromStack);
186838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mVgmFromStack: " + mVgmFromStack);
187838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mOperatorName: " + mOperatorName);
188838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mSubscriberInfo: " + mSubscriberInfo);
189838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mVoiceRecognitionActive: " + mVoiceRecognitionActive);
190838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mInBandRingtone: " + mInBandRingtone);
1917618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati
192838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mCalls:");
1937618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati        if (mCalls != null) {
1947618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati            for (BluetoothHeadsetClientCall call : mCalls.values()) {
1957618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati                ProfileService.println(sb, "  " + call);
1967618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati            }
197838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
1987618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati
199838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        ProfileService.println(sb, "mCallsUpdate:");
2007618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati        if (mCallsUpdate != null) {
2017618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati            for (BluetoothHeadsetClientCall call : mCallsUpdate.values()) {
2027618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati                ProfileService.println(sb, "  " + call);
2037618faa5df18324c581ade91f75454e2e3d8ad49Sharvil Nanavati            }
204838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood        }
205838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood    }
206838949d46a4cc054985a8cfd682004f8dd6d3bbbMike Lockwood
207aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void clearPendingAction() {
208aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mPendingAction = new Pair<Integer, Object>(NO_ACTION, 0);
209aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
210aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
211aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void addQueuedAction(int action) {
212aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        addQueuedAction(action, 0);
213aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
215aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void addQueuedAction(int action, Object data) {
216aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueuedActions.add(new Pair<Integer, Object>(action, data));
217aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
219aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void addQueuedAction(int action, int data) {
220aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueuedActions.add(new Pair<Integer, Object>(action, data));
221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
223aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void addCall(int state, String number) {
224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "addToCalls state:" + state + " number:" + number);
225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        boolean outgoing = state == BluetoothHeadsetClientCall.CALL_STATE_DIALING ||
2278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood               state == BluetoothHeadsetClientCall.CALL_STATE_ALERTING;
228aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
229aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // new call always takes lowest possible id, starting with 1
230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Integer id = 1;
231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        while (mCalls.containsKey(id)) {
232aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            id++;
233aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
234aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2350301badedb14c68fe1c0e46efc14eb24411e333cMike Lockwood        BluetoothHeadsetClientCall c = new BluetoothHeadsetClientCall(mCurrentDevice, id, state,
2360301badedb14c68fe1c0e46efc14eb24411e333cMike Lockwood                number, false, outgoing);
237aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mCalls.put(id, c);
238aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendCallChangedIntent(c);
240aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
241aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
242aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void removeCalls(int... states) {
243aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "removeFromCalls states:" + Arrays.toString(states));
244aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Iterator<Hashtable.Entry<Integer, BluetoothHeadsetClientCall>> it;
246aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
247aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        it = mCalls.entrySet().iterator();
248aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        while (it.hasNext()) {
2498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            BluetoothHeadsetClientCall c = it.next().getValue();
250aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
251aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            for (int s : states) {
252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c.getState() == s) {
253aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    it.remove();
2548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
255aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
256aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
257aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
259aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void changeCallsState(int old_state, int new_state) {
262aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "changeStateFromCalls old:" + old_state + " new: " + new_state);
263aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        for (BluetoothHeadsetClientCall c : mCalls.values()) {
265aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c.getState() == old_state) {
266aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                setCallState(c, new_state);
267aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
268aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
269aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
270aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private BluetoothHeadsetClientCall getCall(int... states) {
272aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "getFromCallsWithStates states:" + Arrays.toString(states));
2738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        for (BluetoothHeadsetClientCall c : mCalls.values()) {
274aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            for (int s : states) {
275aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c.getState() == s) {
276aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return c;
277aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
278aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
279aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
280aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
281aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return null;
282aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
283aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
284aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private int callsInState(int state) {
285aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int i = 0;
2868d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        for (BluetoothHeadsetClientCall c : mCalls.values()) {
287aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c.getState() == state) {
288aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                i++;
289aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
290aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
291aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
292aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return i;
293aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
294aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
295aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateCallsMultiParty() {
2968d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        boolean multi = callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) > 1;
297aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        for (BluetoothHeadsetClientCall c : mCalls.values()) {
2998d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (c.getState() == BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) {
300aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c.isMultiParty() == multi) {
301aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    continue;
302aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
303aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
304aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                c.setMultiParty(multi);
305aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                sendCallChangedIntent(c);
306aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            } else {
307aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c.isMultiParty()) {
308aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    c.setMultiParty(false);
309aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    sendCallChangedIntent(c);
310aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
311aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
312aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
313aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
314aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
3158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private void setCallState(BluetoothHeadsetClientCall c, int state) {
316aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (state == c.getState()) {
317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
318aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
319aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        c.setState(state);
320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendCallChangedIntent(c);
321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
322aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
3238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private void sendCallChangedIntent(BluetoothHeadsetClientCall c) {
324a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwal        Log.d(TAG, "sendCallChangedIntent " + c);
3258d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CALL_CHANGED);
32606c566ebd3462ec18624f1db9f49f81c2eec0cefLianchao Song        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
3278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        intent.putExtra(BluetoothHeadsetClient.EXTRA_CALL, c);
328aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
329aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
330aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
331aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean waitForIndicators(int call, int callsetup, int callheld) {
332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // all indicators initial values received
333aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mIndicatorCall != -1 && mIndicatorCallSetup != -1 &&
334aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                mIndicatorCallHeld != -1) {
335aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
336aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
337aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
338aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (call != -1) {
339aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCall = call;
340aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else if (callsetup != -1) {
341aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCallSetup = callsetup;
342aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else if (callheld != -1) {
343aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCallHeld = callheld;
344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
345aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
346aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // still waiting for some indicators
347aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mIndicatorCall == -1 || mIndicatorCallSetup == -1 ||
348aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                mIndicatorCallHeld == -1) {
349aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
351aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
352aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // for start always query calls to define if it is supported
353aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueryCallsSupported = queryCallsStart();
354aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
355aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported) {
356aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
357aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
359aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // no support for querying calls
360aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
361aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (mIndicatorCallSetup) {
3628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_INCOMING:
3638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING, "");
364aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
3658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_OUTGOING:
3668d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING, "");
367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
3688d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_ALERTING:
3698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_ALERTING, "");
370aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
3718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_NONE:
372aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
373aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
374aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
376aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (mIndicatorCall) {
3778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALL_CALLS_IN_PROGRESS:
3788d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE, "");
379aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
3808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALL_NO_CALLS_IN_PROGRESS:
381aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
382aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
383aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (mIndicatorCallHeld) {
3868d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_HOLD_AND_ACTIVE:
3878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_HOLD:
3888d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_HELD, "");
389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
3908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_NONE:
391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
392aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return true;
396aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
397aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateCallIndicator(int call) {
399aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "updateCallIndicator " + call);
400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
401aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (waitForIndicators(call, -1, -1)) {
402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported) {
406aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendMessage(QUERY_CURRENT_CALLS);
407aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
408aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
4108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = null;
411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (call) {
4138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALL_NO_CALLS_IN_PROGRESS:
4148d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE,
4158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        BluetoothHeadsetClientCall.CALL_STATE_HELD,
4168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD);
417aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
418aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
4198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALL_CALLS_IN_PROGRESS:
4208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (mIndicatorCall == HeadsetClientHalConstants.CALL_CALLS_IN_PROGRESS) {
421aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // WP7.8 is sending call=1 before setup=0 when rejecting
422aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // waiting call
4238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (mIndicatorCallSetup != HeadsetClientHalConstants.CALLSETUP_NONE) {
4248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        c = getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING);
425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if (c != null) {
4268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
427aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mCalls.remove(c.getId());
428aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
429aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
430aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
431aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
432aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
433aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
434aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // if there is only waiting call it is changed to incoming so
435aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // don't
436aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // handle it here
4378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (mIndicatorCallSetup != HeadsetClientHalConstants.CALLSETUP_NONE) {
4388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    c = getCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING,
4398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            BluetoothHeadsetClientCall.CALL_STATE_ALERTING,
4408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (c != null) {
4428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
443aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
445aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
446aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                updateCallsMultiParty();
447aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
448aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
450aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
451aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
452aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCall = call;
453aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
454aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
455aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateCallSetupIndicator(int callsetup) {
456aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "updateCallSetupIndicator " + callsetup + " " + mPendingAction.first);
457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (waitForIndicators(-1, callsetup, -1)) {
459aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
460aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
461aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
462aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported) {
463aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendMessage(QUERY_CURRENT_CALLS);
464aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
467aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (callsetup) {
4688d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_NONE:
469aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                switch (mPendingAction.first) {
470aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case ACCEPT_CALL:
471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        switch ((Integer) mPendingAction.second) {
4728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_ATA:
4738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_DIALING,
4748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ALERTING);
475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
476aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
4778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_1:
4788d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
4798d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_WAITING,
4808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
4838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_2:
484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                // no specific order for callsetup=0 and
485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                // callheld=1
486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                if (mIndicatorCallHeld ==
4878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        HeadsetClientHalConstants.CALLHELD_HOLD_AND_ACTIVE) {
488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    clearPendingAction();
489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                }
490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
4918d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_3:
492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                if (mIndicatorCallHeld ==
4938d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        HeadsetClientHalConstants.CALLHELD_NONE) {
494aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    clearPendingAction();
495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                }
496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            default:
498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                Log.e(TAG, "Unexpected callsetup=0 while in action ACCEPT_CALL");
499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REJECT_CALL:
503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        switch ((Integer) mPendingAction.second) {
5048d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHUP:
5058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
507aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
5088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_0:
5098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_WAITING);
510aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
512aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            default:
513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                Log.e(TAG, "Unexpected callsetup=0 while in action REJECT_CALL");
514aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_NUMBER:
518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_MEMORY:
519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REDIAL:
520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case NO_ACTION:
521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case TERMINATE_CALL:
5228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        removeCalls(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
5238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClientCall.CALL_STATE_DIALING,
5248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClientCall.CALL_STATE_WAITING,
5258d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClientCall.CALL_STATE_ALERTING);
526aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        clearPendingAction();
527aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
528aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    default:
529aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Unexpected callsetup=0 while in action " +
530aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mPendingAction.first);
531aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
5348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_ALERTING:
5358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                BluetoothHeadsetClientCall c =
5368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        getCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING);
537aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c == null) {
538aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mPendingAction.first == DIAL_NUMBER) {
5398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        addCall(BluetoothHeadsetClientCall.CALL_STATE_ALERTING,
540aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                (String) mPendingAction.second);
541aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
5428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        addCall(BluetoothHeadsetClientCall.CALL_STATE_ALERTING, "");
543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
544aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
5458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_ALERTING);
546aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                switch (mPendingAction.first) {
549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_NUMBER:
550aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_MEMORY:
551aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REDIAL:
552aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        clearPendingAction();
553aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
554aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    default:
555aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
5588d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_OUTGOING:
559aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mPendingAction.first == DIAL_NUMBER) {
5608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    addCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING,
561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            (String) mPendingAction.second);
562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
5638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    addCall(BluetoothHeadsetClientCall.CALL_STATE_DIALING, "");
564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
5668d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLSETUP_INCOMING:
5678d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING) == null)
568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                {
569aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // will get number in clip if known
5708d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    addCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING, "");
571aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
572aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
573aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
574aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
575aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
576aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
577aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        updateCallsMultiParty();
578aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
579aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCallSetup = callsetup;
580aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateCallHeldIndicator(int callheld) {
583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "updateCallHeld " + callheld);
584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (waitForIndicators(-1, -1, callheld)) {
586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
587aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
588aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
589aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported) {
590aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendMessage(QUERY_CURRENT_CALLS);
591aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
592aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
593aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
594aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (callheld) {
5958d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_NONE:
596aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                switch (mPendingAction.first) {
597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REJECT_CALL:
5988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        removeCalls(BluetoothHeadsetClientCall.CALL_STATE_HELD);
599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        clearPendingAction();
600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case ACCEPT_CALL:
602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        switch ((Integer) mPendingAction.second) {
6038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_1:
6048d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
6058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_HELD,
6068d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
607aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
6098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_3:
6108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_HELD,
6118d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
612aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            default:
615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case NO_ACTION:
6198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        if (mIndicatorCall == HeadsetClientHalConstants.CALL_CALLS_IN_PROGRESS &&
6208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                mIndicatorCallHeld == HeadsetClientHalConstants.CALLHELD_HOLD) {
6218d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_HELD,
6228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
623aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
6268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        removeCalls(BluetoothHeadsetClientCall.CALL_STATE_HELD);
627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    default:
629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Unexpected callheld=0 while in action " + mPendingAction.first);
630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
6338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_HOLD_AND_ACTIVE:
634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                switch (mPendingAction.first) {
635aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case ACCEPT_CALL:
636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if ((Integer) mPendingAction.second ==
6378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                HeadsetClientHalConstants.CALL_ACTION_CHLD_2) {
6388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            BluetoothHeadsetClientCall c =
6398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING);
640aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (c != null) { // accept
6418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE,
6428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_HELD);
6438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            } else { // swap
6458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                for (BluetoothHeadsetClientCall cc : mCalls.values()) {
646aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    if (cc.getState() ==
6478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) {
648aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        setCallState(cc,
6498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                BluetoothHeadsetClientCall.CALL_STATE_HELD);
650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    } else if (cc.getState() ==
6518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            BluetoothHeadsetClientCall.CALL_STATE_HELD) {
652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        setCallState(cc,
6538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
655aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                }
656aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
657aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            clearPendingAction();
658aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
659aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
660aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case NO_ACTION:
6618d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        BluetoothHeadsetClientCall c =
6628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING);
663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if (c != null) { // accept
6648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE,
6658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    BluetoothHeadsetClientCall.CALL_STATE_HELD);
6668d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
668aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
669aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
670aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // swap
6718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        for (BluetoothHeadsetClientCall cc : mCalls.values()) {
6728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            if (cc.getState() == BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) {
6738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                setCallState(cc, BluetoothHeadsetClientCall.CALL_STATE_HELD);
6748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            } else if (cc.getState() == BluetoothHeadsetClientCall.CALL_STATE_HELD) {
6758d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                setCallState(cc, BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
676aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
677aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
678aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
679aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case ENTER_PRIVATE_MODE:
6808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        for (BluetoothHeadsetClientCall cc : mCalls.values()) {
6818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            if (cc != (BluetoothHeadsetClientCall) mPendingAction.second) {
6828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                setCallState(cc, BluetoothHeadsetClientCall.CALL_STATE_HELD);
683aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        clearPendingAction();
686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
687aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    default:
688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Unexpected callheld=0 while in action " + mPendingAction.first);
689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
690aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
6928d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.CALLHELD_HOLD:
693aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                switch (mPendingAction.first) {
694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_NUMBER:
695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case DIAL_MEMORY:
696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REDIAL:
6978d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE,
6988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClientCall.CALL_STATE_HELD);
699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
700aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case REJECT_CALL:
701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        switch ((Integer) mPendingAction.second) {
7028d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_1:
7038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
7048d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_HELD,
7058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
706aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
7088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            case HeadsetClientHalConstants.CALL_ACTION_CHLD_3:
7098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                changeCallsState(BluetoothHeadsetClientCall.CALL_STATE_HELD,
7108d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
711aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
713aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            default:
714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
716aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case TERMINATE_CALL:
718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    case NO_ACTION:
7198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        removeCalls(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    default:
722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Unexpected callheld=0 while in action " + mPendingAction.first);
723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
726aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
728aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
729aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        updateCallsMultiParty();
731aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCallHeld = callheld;
733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateRespAndHold(int resp_and_hold) {
736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "updatRespAndHold " + resp_and_hold);
737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported) {
739aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendMessage(QUERY_CURRENT_CALLS);
740aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
742aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
7438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = null;
744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
745aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (resp_and_hold) {
7468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.RESP_AND_HOLD_HELD:
747aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // might be active if it was resp-and-hold before SLC created
7488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
7498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
750aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c != null) {
751aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    setCallState(c,
7528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD);
753aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
7548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    addCall(BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD, "");
755aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
756aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
7578d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.RESP_AND_HOLD_ACCEPT:
7588d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                c = getCall(BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD);
759aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (c != null) {
7608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
761aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
762aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mPendingAction.first == ACCEPT_CALL &&
763aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        (Integer) mPendingAction.second ==
7648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        HeadsetClientHalConstants.CALL_ACTION_BTRH_1) {
765aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    clearPendingAction();
766aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
767aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
7688d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case HeadsetClientHalConstants.RESP_AND_HOLD_REJECT:
7698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                removeCalls(BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD);
770aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
771aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
772aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
773aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
774aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
775aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
776aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void updateClip(String number) {
7778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
778aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
779aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (c == null) {
780aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // MeeGo sends CLCC indicating waiting call followed by CLIP when call state changes
781aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // from waiting to incoming in 3WC scenarios. Handle this call state transfer here.
7828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            BluetoothHeadsetClientCall cw = getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING);
783aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if(cw != null) {
7848d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                setCallState(cw, BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
785aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
786aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            else {
7878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                addCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING, number);
788aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
789aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
790aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            c.setNumber(number);
791aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendCallChangedIntent(c);
792aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
793aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
794aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
795aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void addCallWaiting(String number) {
7968d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING) == null) {
7978d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            addCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING, number);
798aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
799aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
800aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
801aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // use ECS
802aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean queryCallsStart() {
803aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "queryCallsStart");
804aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
805aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // not supported
806aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mQueryCallsSupported == false) {
807aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return false;
808aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
809aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
810aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        clearPendingAction();
811aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
812aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // already started
813aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCallsUpdate != null) {
814aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
815aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
816aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
817aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (queryCurrentCallsNative()) {
8188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mCallsUpdate = new Hashtable<Integer, BluetoothHeadsetClientCall>();
819aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(QUERY_CURRENT_CALLS, 0);
820aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
821aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
822aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
823aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.i(TAG, "updateCallsStart queryCurrentCallsNative failed");
824aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueryCallsSupported = false;
825aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mCallsUpdate = null;
826aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
827aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
828aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
829aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void queryCallsDone() {
830aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "queryCallsDone");
8318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Iterator<Hashtable.Entry<Integer, BluetoothHeadsetClientCall>> it;
832aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
833aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // check if any call was removed
834aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        it = mCalls.entrySet().iterator();
835aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        while (it.hasNext()) {
8368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            Hashtable.Entry<Integer, BluetoothHeadsetClientCall> entry = it.next();
837aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
838aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mCallsUpdate.containsKey(entry.getKey())) {
839aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                continue;
840aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
841aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
842aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "updateCallsDone call removed id:" + entry.getValue().getId());
8438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            BluetoothHeadsetClientCall c = entry.getValue();
844aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
8458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            setCallState(c, BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
846aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
847aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
848aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        /* check if any calls changed or new call is present */
849aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        it = mCallsUpdate.entrySet().iterator();
850aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        while (it.hasNext()) {
8518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            Hashtable.Entry<Integer, BluetoothHeadsetClientCall> entry = it.next();
852aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
853aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mCalls.containsKey(entry.getKey())) {
854aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // avoid losing number if was not present in clcc
855aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (entry.getValue().getNumber().equals("")) {
856aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    entry.getValue().setNumber(mCalls.get(entry.getKey()).getNumber());
857aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
858aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
859aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mCalls.get(entry.getKey()).equals(entry.getValue())) {
860aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    continue;
861aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
862aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
863aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.d(TAG, "updateCallsDone call changed id:" + entry.getValue().getId());
864aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                sendCallChangedIntent(entry.getValue());
865aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            } else {
866aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.d(TAG, "updateCallsDone new call id:" + entry.getValue().getId());
867aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                sendCallChangedIntent(entry.getValue());
868aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
869aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
870aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
871aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mCalls = mCallsUpdate;
872aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mCallsUpdate = null;
873aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
874aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (loopQueryCalls()) {
875aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "queryCallsDone ambigious calls, starting call query loop");
876aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            sendMessageDelayed(QUERY_CURRENT_CALLS, 1523);
877aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
878aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
879aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
880aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void queryCallsUpdate(int id, int state, String number, boolean multiParty,
881aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            boolean outgoing) {
882aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "queryCallsUpdate: " + id);
883aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
884aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // should not happen
885aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCallsUpdate == null) {
886aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
887aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
888aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
8890301badedb14c68fe1c0e46efc14eb24411e333cMike Lockwood        mCallsUpdate.put(id, new BluetoothHeadsetClientCall(mCurrentDevice, id, state, number,
8900301badedb14c68fe1c0e46efc14eb24411e333cMike Lockwood                multiParty, outgoing));
891aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
892aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
893aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // helper function for determining if query calls should be looped
894aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private boolean loopQueryCalls() {
8958d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) > 1) {
896aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
897aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
898aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
899aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // Workaround for Windows Phone 7.8 not sending callsetup=0 after
900aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // rejecting incoming call in 3WC use case (when no active calls present).
901aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // Fixes both, AG and HF rejecting the call.
9028d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
9038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (c != null && mIndicatorCallSetup == HeadsetClientHalConstants.CALLSETUP_NONE)
904aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return true;
905aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
906aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return false;
907aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
908aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
909aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void acceptCall(int flag, boolean retry) {
910aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int action;
911aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
912aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "acceptCall: (" + flag + ")");
913aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
9148d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
9158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                BluetoothHeadsetClientCall.CALL_STATE_WAITING);
916aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (c == null) {
9178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            c = getCall(BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
9188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    BluetoothHeadsetClientCall.CALL_STATE_HELD);
919aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
920aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c == null) {
921aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
922aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
923aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
924aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
925aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (c.getState()) {
9268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_INCOMING:
9278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
928aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return;
929aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
930aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
931aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // Some NOKIA phones with Windows Phone 7.8 and MeeGo requires CHLD=1
932aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // for accepting incoming call if it is the only call present after
933aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // second active remote has disconnected (3WC scenario - call state
934aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // changes from waiting to incoming). On the other hand some Android
935aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // phones and iPhone requires ATA. Try to handle those gently by
936aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // first issuing ATA. Failing means that AG is probably one of those
937aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // phones that requires CHLD=1. Handle this case when we are retrying.
938aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // Accepting incoming calls when there is held one and
939aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // no active should also be handled by ATA.
9408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                action = HeadsetClientHalConstants.CALL_ACTION_ATA;
941aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
942aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mCalls.size() == 1 && retry) {
9438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
944aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
945aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
9468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_WAITING:
9478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) == 0) {
948aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // if no active calls present only plain accept is allowed
9498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
950aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        return;
951aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
952aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
953aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // Some phones (WP7) require ATA instead of CHLD=2
954aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // to accept waiting call if no active calls are present.
955aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (retry) {
9568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        action = HeadsetClientHalConstants.CALL_ACTION_ATA;
957aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
9588d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
959aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
960aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
961aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
962aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
963aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                // if active calls are present action must be selected
9648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
9658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
9668d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_TERMINATE) {
9678d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
968aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
969aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return;
970aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
971aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
9728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_HELD:
9738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
9748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
9758d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (flag == BluetoothHeadsetClient.CALL_ACCEPT_TERMINATE) {
9768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1;
9778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                } else if (getCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) != null) {
9788d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_3;
979aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
9808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
981aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
982aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
9838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
9848d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (flag != BluetoothHeadsetClient.CALL_ACCEPT_NONE) {
985aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return;
986aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
9878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                action = HeadsetClientHalConstants.CALL_ACTION_BTRH_1;
988aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
9898d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_ALERTING:
9908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
9918d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_DIALING:
992aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
993aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
994aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
995aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
9963ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        if (flag == BluetoothHeadsetClient.CALL_ACCEPT_HOLD) {
9973ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom            // HFP is disabled when a call is put on hold to ensure correct audio routing for
9983ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom            // cellular calls accepted while an HFP call is in progress. Reenable HFP when the HFP
9993ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom            // call is put off hold.
10003ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom            Log.d(TAG,"hfp_enable=true");
10013ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom            mAudioManager.setParameters("hfp_enable=true");
10023ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        }
10033ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom
1004aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (handleCallActionNative(action, 0)) {
1005aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(ACCEPT_CALL, action);
1006aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1007aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.e(TAG, "ERROR: Couldn't accept a call, action:" + action);
1008aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1009aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1010aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1011aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void rejectCall() {
1012aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int action;
1013aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1014aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "rejectCall");
1015aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c =
10178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING,
10188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                BluetoothHeadsetClientCall.CALL_STATE_WAITING,
10198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD,
10208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                BluetoothHeadsetClientCall.CALL_STATE_HELD);
1021aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (c == null) {
1022aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
1023aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1024aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1025aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        switch (c.getState()) {
10268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_INCOMING:
10278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                action = HeadsetClientHalConstants.CALL_ACTION_CHUP;
1028aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
10298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_WAITING:
10308d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_HELD:
10318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                action = HeadsetClientHalConstants.CALL_ACTION_CHLD_0;
1032aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
10338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_HELD_BY_RESPONSE_AND_HOLD:
10348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                action = HeadsetClientHalConstants.CALL_ACTION_BTRH_2;
1035aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                break;
10368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
10378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_DIALING:
10388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            case BluetoothHeadsetClientCall.CALL_STATE_ALERTING:
1039aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            default:
1040aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
1041aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1042aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1043aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (handleCallActionNative(action, 0)) {
1044aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(REJECT_CALL, action);
1045aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1046aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.e(TAG, "ERROR: Couldn't reject a call, action:" + action);
1047aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1048aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1049aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1050aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void holdCall() {
1051aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int action;
1052aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1053aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "holdCall");
1054aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10558d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING);
1056aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (c != null) {
10578d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            action = HeadsetClientHalConstants.CALL_ACTION_BTRH_0;
1058aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
10598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            c = getCall(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE);
1060aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c == null) {
1061aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
1062aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1063aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            action = HeadsetClientHalConstants.CALL_ACTION_CHLD_2;
1065aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1066aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10673ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        // Set HFP enable to false in case the call is being held to accept a cellular call. This
10683ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        // allows the cellular call's audio to be correctly routed.
10693ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        Log.d(TAG,"hfp_enable=false");
10703ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom        mAudioManager.setParameters("hfp_enable=false");
10713ee63fdfb7fa5896bff7e172be60c763919c9f63Christine Hallstrom
1072aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (handleCallActionNative(action, 0)) {
1073aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(HOLD_CALL, action);
1074aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1075aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.e(TAG, "ERROR: Couldn't hold a call, action:" + action);
1076aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1077aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1078aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1079aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void terminateCall(int idx) {
1080aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "terminateCall: " + idx);
1081aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1082aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (idx == 0) {
10838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            int action = HeadsetClientHalConstants.CALL_ACTION_CHUP;
1084aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10858d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            BluetoothHeadsetClientCall c = getCall(
10868d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    BluetoothHeadsetClientCall.CALL_STATE_DIALING,
10878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    BluetoothHeadsetClientCall.CALL_STATE_ALERTING);
1088aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c != null) {
1089aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (handleCallActionNative(action, 0)) {
1090aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    addQueuedAction(TERMINATE_CALL, action);
1091aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
1092aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "ERROR: Couldn't terminate outgoing call");
1093aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
1094aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1095aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
10968d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) > 0) {
1097aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (handleCallActionNative(action, 0)) {
1098aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    addQueuedAction(TERMINATE_CALL, action);
1099aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
1100aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "ERROR: Couldn't terminate active calls");
1101aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
1102aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1103aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1104aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            int action;
11058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            BluetoothHeadsetClientCall c = mCalls.get(idx);
1106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1107aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (c == null) {
1108aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
1109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1110aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1111aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (c.getState()) {
11128d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case BluetoothHeadsetClientCall.CALL_STATE_ACTIVE:
11138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHLD_1x;
1114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
11158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case BluetoothHeadsetClientCall.CALL_STATE_DIALING:
11168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case BluetoothHeadsetClientCall.CALL_STATE_ALERTING:
11178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    action = HeadsetClientHalConstants.CALL_ACTION_CHUP;
1118aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1119aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
1120aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return;
1121aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1122aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1123aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (handleCallActionNative(action, idx)) {
11248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                if (action == HeadsetClientHalConstants.CALL_ACTION_CHLD_1x) {
1125aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    addQueuedAction(TERMINATE_SPECIFIC_CALL, c);
1126aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                } else {
1127aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    addQueuedAction(TERMINATE_CALL, action);
1128aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
1129aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            } else {
1130aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.e(TAG, "ERROR: Couldn't terminate a call, action:" + action + " id:" + idx);
1131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1132aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1134aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void enterPrivateMode(int idx) {
1136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "enterPrivateMode: " + idx);
1137aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
11388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        BluetoothHeadsetClientCall c = mCalls.get(idx);
1139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (c == null) {
1141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
1142aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1143aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
11448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (c.getState() != BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) {
1145aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
1146aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1147aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1148aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!c.isMultiParty()) {
1149aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
1150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1151aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
11528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (handleCallActionNative(HeadsetClientHalConstants.CALL_ACTION_CHLD_2x, idx)) {
1153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(ENTER_PRIVATE_MODE, c);
1154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1155aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.e(TAG, "ERROR: Couldn't enter private " + " id:" + idx);
1156aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1158aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void explicitCallTransfer() {
1160aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "explicitCallTransfer");
1161aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // can't transfer call if there is not enough call parties
1163aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCalls.size() < 2) {
1164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return;
1165aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
11678d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (handleCallActionNative(HeadsetClientHalConstants.CALL_ACTION_CHLD_4, -1)) {
1168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            addQueuedAction(EXPLICIT_CALL_TRANSFER);
1169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        } else {
1170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.e(TAG, "ERROR: Couldn't transfer call");
1171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1172aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1173aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1174aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgFeatures()
1175aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    {
1176aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Bundle b = new Bundle();
11778d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_3WAY) ==
11788d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.PEER_FEAT_3WAY) {
11798d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_3WAY_CALLING, true);
1180aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
11818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_VREC) ==
11828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.PEER_FEAT_VREC) {
11838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_VOICE_RECOGNITION, true);
1184aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
11858d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_VTAG) ==
11868d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.PEER_FEAT_VTAG) {
11878d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT, true);
1188aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
11898d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_REJECT) ==
11908d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.PEER_FEAT_REJECT) {
11918d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_REJECT_CALL, true);
1192aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
11938d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_ECC) ==
11948d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.PEER_FEAT_ECC) {
11958d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ECC, true);
1196aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1197aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1198aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // add individual CHLD support extras
11998d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC) ==
12008d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC) {
12018d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL, true);
1202aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
12038d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_REL) ==
12048d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.CHLD_FEAT_REL) {
12058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL, true);
1206aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
12078d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_REL_ACC) ==
12088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.CHLD_FEAT_REL_ACC) {
12098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT, true);
1210aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
12118d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_MERGE) ==
12128d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.CHLD_FEAT_MERGE) {
12138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE, true);
1214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
12158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH) ==
12168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH) {
12178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            b.putBoolean(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE_AND_DETACH, true);
1218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1219aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1220aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return b;
1221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
12238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    private HeadsetClientStateMachine(HeadsetClientService context) {
1224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        super(TAG);
1225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mService = context;
1226aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1227aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mAdapter = BluetoothAdapter.getDefaultAdapter();
1228aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
12298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
1230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mAudioWbs = false;
1231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
123222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        mAudioRouteAllowed = context.getResources().getBoolean(
123322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                R.bool.headset_client_initial_audio_route_allowed);
123422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
1235a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwal        mTelecomManager = (TelecomManager) context.getSystemService(context.TELECOM_SERVICE);
1236a9ad98ec1222093baecd70b32611c3a74ba7f2d8Sanket Agarwal
12378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mIndicatorNetworkState = HeadsetClientHalConstants.NETWORK_STATE_NOT_AVAILABLE;
12388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mIndicatorNetworkType = HeadsetClientHalConstants.SERVICE_TYPE_HOME;
1239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorNetworkSignal = 0;
1240aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorBatteryLevel = 0;
1241aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1242aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // all will be set on connected
1243aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCall = -1;
1244aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCallSetup = -1;
1245aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mIndicatorCallHeld = -1;
1246aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1247d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        mMaxAmVcVol = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
1248d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        mMinAmVcVol = mAudioManager.getStreamMinVolume(AudioManager.STREAM_VOICE_CALL);
1249d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
1250aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mOperatorName = null;
1251aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mSubscriberInfo = null;
1252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
12538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mVoiceRecognitionActive = HeadsetClientHalConstants.VR_STATE_STOPPED;
12548d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mInBandRingtone = HeadsetClientHalConstants.IN_BAND_RING_NOT_PROVIDED;
1255aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1256aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueuedActions = new LinkedList<Pair<Integer, Object>>();
1257aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        clearPendingAction();
1258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
12598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mCalls = new Hashtable<Integer, BluetoothHeadsetClientCall>();
1260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mCallsUpdate = null;
1261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mQueryCallsSupported = true;
1262aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1263aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        initializeNative();
1264aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mNativeAvailable = true;
1265aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1266aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mDisconnected = new Disconnected();
1267aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mConnecting = new Connecting();
1268aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mConnected = new Connected();
1269aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mAudioOn = new AudioOn();
1270aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1271aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        addState(mDisconnected);
1272aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        addState(mConnecting);
1273aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        addState(mConnected);
1274aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        addState(mAudioOn, mConnected);
1275aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1276aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        setInitialState(mDisconnected);
1277aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1278aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
12798d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    static HeadsetClientStateMachine make(HeadsetClientService context) {
1280aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "make");
12818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        HeadsetClientStateMachine hfcsm = new HeadsetClientStateMachine(context);
1282aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        hfcsm.start();
1283aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return hfcsm;
1284aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1285aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1286aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public void doQuit() {
1287aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        quitNow();
1288aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1289aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1290aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public void cleanup() {
1291aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mNativeAvailable) {
1292aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            cleanupNative();
1293aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mNativeAvailable = false;
1294aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1295aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1296aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1297d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    private int hfToAmVol(int hfVol) {
1298d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int amRange = mMaxAmVcVol - mMinAmVcVol;
1299d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME;
1300d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int amOffset =
1301d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal            (amRange * (hfVol - MIN_HFP_SCO_VOICE_CALL_VOLUME)) / hfRange;
1302d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int amVol = mMinAmVcVol + amOffset;
1303d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        Log.d(TAG, "HF -> AM " + hfVol + " " + amVol);
1304d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        return amVol;
1305d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    }
1306d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
1307d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    private int amToHfVol(int amVol) {
1308d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int amRange = mMaxAmVcVol - mMinAmVcVol;
1309d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int hfRange = MAX_HFP_SCO_VOICE_CALL_VOLUME - MIN_HFP_SCO_VOICE_CALL_VOLUME;
1310d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int hfOffset = (hfRange * (amVol - mMinAmVcVol)) / amRange;
1311d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        int hfVol = MIN_HFP_SCO_VOICE_CALL_VOLUME + hfOffset;
1312d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        Log.d(TAG, "AM -> HF " + amVol + " " + hfVol);
1313d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal        return hfVol;
1314d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal    }
1315d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
1316aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private class Disconnected extends State {
1317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1318aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void enter() {
1319aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Enter Disconnected: " + getCurrentMessage().what);
1320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // cleanup
13228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mIndicatorNetworkState = HeadsetClientHalConstants.NETWORK_STATE_NOT_AVAILABLE;
13238d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mIndicatorNetworkType = HeadsetClientHalConstants.SERVICE_TYPE_HOME;
1324aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorNetworkSignal = 0;
1325aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorBatteryLevel = 0;
1326aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1327aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mAudioWbs = false;
1328aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1329aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // will be set on connect
1330aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCall = -1;
1331aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCallSetup = -1;
1332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mIndicatorCallHeld = -1;
1333aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1334aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mOperatorName = null;
1335aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mSubscriberInfo = null;
1336aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1337aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mQueuedActions = new LinkedList<Pair<Integer, Object>>();
1338aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            clearPendingAction();
1339aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
13408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mVoiceRecognitionActive = HeadsetClientHalConstants.VR_STATE_STOPPED;
13418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mInBandRingtone = HeadsetClientHalConstants.IN_BAND_RING_NOT_PROVIDED;
1342aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
13438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            mCalls = new Hashtable<Integer, BluetoothHeadsetClientCall>();
1344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mCallsUpdate = null;
1345aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mQueryCallsSupported = true;
1346aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1347aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mPeerFeatures = 0;
1348aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mChldFeatures = 0;
1349aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            removeMessages(QUERY_CURRENT_CALLS);
1351aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1352aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1353aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1354aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public synchronized boolean processMessage(Message message) {
1355aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Disconnected process message: " + message.what);
1356aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1357aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (mCurrentDevice != null) {
1358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.e(TAG, "ERROR: current device not null in Disconnected");
1359aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return NOT_HANDLED;
1360aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1361aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1362aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (message.what) {
1363aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case CONNECT:
1364aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    BluetoothDevice device = (BluetoothDevice) message.obj;
1365aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1366aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
1367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            BluetoothProfile.STATE_DISCONNECTED);
1368aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1369aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!connectNative(getByteAddress(device))) {
1370aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
1371aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_CONNECTING);
1372aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1373aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1374aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mCurrentDevice = device;
1376aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    transitionTo(mConnecting);
1377aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1378aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT:
1379aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // ignore
1380aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1381aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case STACK_EVENT:
1382aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    StackEvent event = (StackEvent) message.obj;
1383aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (DBG) {
1384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG, "Stack event type: " + event.type);
1385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1386aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    switch (event.type) {
1387aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CONNECTION_STATE_CHANGED:
1388aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Disconnected: Connection " + event.device
1389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + " state changed:" + event.valueInt);
1390aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processConnectionEvent(event.valueInt, event.device);
1391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1392aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        default:
1393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.e(TAG, "Disconnected: Unexpected stack event: " + event.type);
1394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1396aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1397aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
1398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
1399aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return HANDLED;
1401aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in Disconnected state
1404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processConnectionEvent(int state, BluetoothDevice device)
1405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        {
1406aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
14078d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED:
1408aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.w(TAG, "HFPClient Connecting from Disconnected state");
1409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (okToConnect(device)) {
1410aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.i(TAG, "Incoming AG accepted");
1411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
1412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED);
1413aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mCurrentDevice = device;
1414aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        transitionTo(mConnecting);
1415aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1416aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.i(TAG, "Incoming AG rejected. priority=" + mService.getPriority(device)
1417aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                +
1418aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                " bondState=" + device.getBondState());
1419aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // reject the connection and stay in Disconnected state
1420aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // itself
1421aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        disconnectNative(getByteAddress(device));
1422aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // the other profile connection should be initiated
1423aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        AdapterService adapterService = AdapterService.getAdapterService();
1424aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if (adapterService != null) {
1425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            adapterService.connectOtherProfile(device,
1426aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    AdapterService.PROFILE_CONN_REJECTED);
1427aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
1428aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1429aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
14308d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_CONNECTING:
14318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED:
14328d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTING:
1433aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
1434aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.i(TAG, "ignoring state: " + state);
1435aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1436aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1437aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1438aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1439aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1440aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void exit() {
1441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Exit Disconnected: " + getCurrentMessage().what);
1442aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1443aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1445aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private class Connecting extends State {
1446aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1447aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void enter() {
1448aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Enter Connecting: " + getCurrentMessage().what);
1449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1450aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1451aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1452aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public synchronized boolean processMessage(Message message) {
1453aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Connecting process message: " + message.what);
1454aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1455aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            boolean retValue = HANDLED;
1456aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (message.what) {
1457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case CONNECT:
1458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case CONNECT_AUDIO:
1459aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT:
1460aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    deferMessage(message);
1461aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1462aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case STACK_EVENT:
1463aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    StackEvent event = (StackEvent) message.obj;
1464aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (DBG) {
1465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG, "Connecting: event type: " + event.type);
1466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1467aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    switch (event.type) {
1468aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CONNECTION_STATE_CHANGED:
1469aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connecting: Connection " + event.device + " state changed:"
1470aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + event.valueInt);
1471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processConnectionEvent(event.valueInt, event.valueInt2,
1472aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt3, event.device);
1473aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1474aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_AUDIO_STATE_CHANGED:
1475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_VR_STATE_CHANGED:
1476aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_NETWORK_STATE:
1477aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_ROAMING_STATE:
1478aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_NETWORK_SIGNAL:
1479aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_BATTERY_LEVEL:
1480aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALL:
1481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALLSETUP:
1482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALLHELD:
1483aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_RESP_AND_HOLD:
1484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CLIP:
1485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALL_WAITING:
1486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_VOLUME_CHANGED:
1487aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_IN_BAND_RING:
1488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            deferMessage(message);
1489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CMD_RESULT:
1491aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_SUBSCRIBER_INFO:
1492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CURRENT_CALLS:
1493aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_OPERATOR_NAME:
1494aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        default:
1495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.e(TAG, "Connecting: ignoring stack event: " + event.type);
1496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
1500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
1501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return retValue;
1503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1504aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1505aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in Connecting state
1506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processConnectionEvent(int state, int peer_feat, int chld_feat, BluetoothDevice device) {
1507aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
15088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED:
1509aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    broadcastConnectionState(mCurrentDevice, BluetoothProfile.STATE_DISCONNECTED,
1510aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            BluetoothProfile.STATE_CONNECTING);
1511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mCurrentDevice = null;
1512aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    transitionTo(mDisconnected);
1513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
15148d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_SLC_CONNECTED:
1515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.w(TAG, "HFPClient Connected from Connecting state");
1516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mPeerFeatures = peer_feat;
1518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mChldFeatures = chld_feat;
1519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    broadcastConnectionState(mCurrentDevice, BluetoothProfile.STATE_CONNECTED,
1521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            BluetoothProfile.STATE_CONNECTING);
1522aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // Send AT+NREC to remote if supported by audio
1523d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                    if (HeadsetClientHalConstants.HANDSFREECLIENT_NREC_SUPPORTED &&
1524d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                            ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_ECNR) ==
1525d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                    HeadsetClientHalConstants.PEER_FEAT_ECNR)) {
1526d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                        if (sendATCmdNative(HeadsetClientHalConstants.HANDSFREECLIENT_AT_CMD_NREC,
1527d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                            1 , 0, null)) {
1528d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                            addQueuedAction(DISABLE_NREC);
1529d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                        } else {
1530d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                            Log.e(TAG, "Failed to send NREC");
1531d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                        }
1532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    transitionTo(mConnected);
1534aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1535d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    int amVol = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
1536d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    sendMessage(
1537d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                            obtainMessage(HeadsetClientStateMachine.SET_SPEAKER_VOLUME, amVol, 0));
15383076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // Mic is either in ON state (full volume) or OFF state. There is no way in
15393076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // Android to change the MIC volume.
15408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    sendMessage(obtainMessage(HeadsetClientStateMachine.SET_MIC_VOLUME,
1541aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mAudioManager.isMicrophoneMute() ? 0 : 15, 0));
1542aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // query subscriber info
15448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    sendMessage(HeadsetClientStateMachine.SUBSCRIBER_INFO);
1545aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
15468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_CONNECTED:
1547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!mCurrentDevice.equals(device)) {
1548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.w(TAG, "incoming connection event, device: " + device);
1549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1550aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(mCurrentDevice,
1551aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED,
1552aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_CONNECTING);
1553aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
1554aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED);
1555aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mCurrentDevice = device;
1557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1558aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
15598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_CONNECTING:
1560aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    /* outgoing connecting started */
1561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG, "outgoing connection started, ignore");
1562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
15638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTING:
1564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
1565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "Incorrect state: " + state);
1566aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1567aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1569aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1570aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1571aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void exit() {
1572aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Exit Connecting: " + getCurrentMessage().what);
1573aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1574aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
1575aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1576aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private class Connected extends State {
1577aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1578aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void enter() {
1579aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Enter Connected: " + getCurrentMessage().what);
1580aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mAudioWbs = false;
1582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
1583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
1585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public synchronized boolean processMessage(Message message) {
1586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Connected process message: " + message.what);
1587aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
1588aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mCurrentDevice == null) {
1589aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG, "ERROR: mCurrentDevice is null in Connected");
1590aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
1591aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
1592aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
1593aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1594aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (message.what) {
1595aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case CONNECT:
1596aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    BluetoothDevice device = (BluetoothDevice) message.obj;
1597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mCurrentDevice.equals(device)) {
1598aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // already connected to this device, do nothing
1599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!disconnectNative(getByteAddress(mCurrentDevice))) {
1603aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // if succeed this will be handled from disconnected
1604aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // state
1605aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(device, BluetoothProfile.STATE_CONNECTING,
1606aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED);
1607aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(device, BluetoothProfile.STATE_DISCONNECTED,
1608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_CONNECTING);
1609aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1610aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1611aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1612aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // will be handled when entered disconnected
1613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    deferMessage(message);
1614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT:
1616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    BluetoothDevice dev = (BluetoothDevice) message.obj;
1617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!mCurrentDevice.equals(dev)) {
1618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1619aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1620aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    broadcastConnectionState(dev, BluetoothProfile.STATE_DISCONNECTING,
1621aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            BluetoothProfile.STATE_CONNECTED);
1622aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!disconnectNative(getByteAddress(dev))) {
1623aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        // disconnecting failed
1624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(dev, BluetoothProfile.STATE_CONNECTED,
1625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED);
1626aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case CONNECT_AUDIO:
1630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // TODO: handle audio connection failure
1631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!connectAudioNative(getByteAddress(mCurrentDevice))) {
1632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Couldn't connect Audio.");
1633aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1635aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT_AUDIO:
1636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // TODO: handle audio disconnection failure
1637aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!disconnectAudioNative(getByteAddress(mCurrentDevice))) {
1638aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Couldn't connect Audio.");
1639aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1640aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1641aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case VOICE_RECOGNITION_START:
16428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (mVoiceRecognitionActive == HeadsetClientHalConstants.VR_STATE_STOPPED) {
1643aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if (startVoiceRecognitionNative()) {
1644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            addQueuedAction(VOICE_RECOGNITION_START);
1645aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        } else {
1646aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.e(TAG, "ERROR: Couldn't start voice recognition");
1647aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
1648aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1649aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case VOICE_RECOGNITION_STOP:
16518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (mVoiceRecognitionActive == HeadsetClientHalConstants.VR_STATE_STARTED) {
1652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        if (stopVoiceRecognitionNative()) {
1653aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            addQueuedAction(VOICE_RECOGNITION_STOP);
1654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        } else {
1655aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.e(TAG, "ERROR: Couldn't stop voice recognition");
1656aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        }
1657aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1658aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
16593076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                // Called only for Mute/Un-mute - Mic volume change is not allowed.
1660aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case SET_MIC_VOLUME:
1661aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mVgmFromStack) {
1662aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mVgmFromStack = false;
1663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1664aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
16658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (setVolumeNative(HeadsetClientHalConstants.VOLUME_TYPE_MIC, message.arg1)) {
1666aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(SET_MIC_VOLUME);
1667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1668aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1669aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case SET_SPEAKER_VOLUME:
1670d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    // This message should always contain the volume in AudioManager max normalized.
1671d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    int amVol = message.arg1;
1672d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    int hfVol = amToHfVol(amVol);
1673d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    Log.d(TAG,"HF volume is set to " + hfVol);
1674d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    mAudioManager.setParameters("hfp_volume=" + hfVol);
1675aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mVgsFromStack) {
1676aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mVgsFromStack = false;
1677aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
1678aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1679d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    if (setVolumeNative(HeadsetClientHalConstants.VOLUME_TYPE_SPK, hfVol)) {
1680aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(SET_SPEAKER_VOLUME);
1681aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1682aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1683aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case REDIAL:
1684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (dialNative(null)) {
1685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(REDIAL);
1686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1687aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Cannot redial");
1688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1690aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DIAL_NUMBER:
1691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (dialNative((String) message.obj)) {
1692aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(DIAL_NUMBER, message.obj);
1693aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Cannot dial with a given number:" + (String) message.obj);
1695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1697aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DIAL_MEMORY:
1698aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (dialMemoryNative(message.arg1)) {
1699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(DIAL_MEMORY);
1700aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Cannot dial with a given location:" + message.arg1);
1702aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1703aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1704aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case ACCEPT_CALL:
1705aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    acceptCall(message.arg1, false);
1706aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case REJECT_CALL:
1708aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    rejectCall();
1709aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1710aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case HOLD_CALL:
1711aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    holdCall();
1712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1713aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case TERMINATE_CALL:
1714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    terminateCall(message.arg1);
1715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1716aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case ENTER_PRIVATE_MODE:
1717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    enterPrivateMode(message.arg1);
1718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1719aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case EXPLICIT_CALL_TRANSFER:
1720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    explicitCallTransfer();
1721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case SEND_DTMF:
1723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (sendDtmfNative((byte) message.arg1)) {
1724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(SEND_DTMF);
1725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1726aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Couldn't send DTMF");
1727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1728aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1729aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case SUBSCRIBER_INFO:
1730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (retrieveSubscriberInfoNative()) {
1731aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(SUBSCRIBER_INFO);
1732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Couldn't retrieve subscriber info");
1734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case LAST_VTAG_NUMBER:
1737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (requestLastVoiceTagNumberNative()) {
1738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        addQueuedAction(LAST_VTAG_NUMBER);
1739aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
1740aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "ERROR: Couldn't get last VTAG number");
1741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1742aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1743aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case QUERY_CURRENT_CALLS:
1744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    queryCallsStart();
1745aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
1746aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case STACK_EVENT:
1747aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Intent intent = null;
1748aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    StackEvent event = (StackEvent) message.obj;
1749aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (DBG) {
1750aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG, "Connected: event type: " + event.type);
1751aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
1752aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1753aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    switch (event.type) {
1754aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CONNECTION_STATE_CHANGED:
1755aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Connection state changed: " + event.device
1756aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + ": " + event.valueInt);
1757aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processConnectionEvent(event.valueInt, event.device);
1758aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1759aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_AUDIO_STATE_CHANGED:
1760aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Audio state changed: " + event.device + ": "
1761aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + event.valueInt);
1762aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processAudioEvent(event.valueInt, event.device);
1763aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1764aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_NETWORK_STATE:
1765aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Network state: " + event.valueInt);
1766aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1767aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mIndicatorNetworkState = event.valueInt;
1768aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
17698d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
17708d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_STATUS,
1771aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt);
1772aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1773aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (mIndicatorNetworkState ==
17748d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    HeadsetClientHalConstants.NETWORK_STATE_NOT_AVAILABLE) {
1775aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mOperatorName = null;
17768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                intent.putExtra(BluetoothHeadsetClient.EXTRA_OPERATOR_NAME,
1777aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mOperatorName);
1778aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1779aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1780aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1781aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1782aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1783aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (mIndicatorNetworkState ==
17848d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    HeadsetClientHalConstants.NETWORK_STATE_AVAILABLE) {
1785aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                if (queryCurrentOperatorNameNative()) {
1786aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    addQueuedAction(QUERY_OPERATOR_NAME);
1787aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                } else {
1788aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    Log.e(TAG, "ERROR: Couldn't querry operator name");
1789aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                }
1790aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1791aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1792aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_ROAMING_STATE:
1793aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Roaming state: " + event.valueInt);
1794aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1795aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mIndicatorNetworkType = event.valueInt;
1796aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
17978d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
17988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_ROAMING,
1799aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt);
1800aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1801aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1802aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1803aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_NETWORK_SIGNAL:
1804aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Signal level: " + event.valueInt);
1805aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1806aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mIndicatorNetworkSignal = event.valueInt;
1807aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
18088d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
18098d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_NETWORK_SIGNAL_STRENGTH,
1810aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt);
1811aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1812aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1813aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1814aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_BATTERY_LEVEL:
1815aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Battery level: " + event.valueInt);
1816aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1817aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mIndicatorBatteryLevel = event.valueInt;
1818aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
18198d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
18208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL,
1821aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt);
1822aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1823aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1824aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1825aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_OPERATOR_NAME:
1826aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Operator name: " + event.valueString);
1827aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1828aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mOperatorName = event.valueString;
1829aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
18308d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
18318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_OPERATOR_NAME,
1832aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueString);
1833aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1834aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1835aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1836aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_VR_STATE_CHANGED:
1837aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: Voice recognition state: " + event.valueInt);
1838aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1839aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (mVoiceRecognitionActive != event.valueInt) {
1840aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mVoiceRecognitionActive = event.valueInt;
1841aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
18428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
18438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                intent.putExtra(BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION,
1844aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mVoiceRecognitionActive);
1845aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1846aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1847aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1848aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1849aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALL:
1850aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            updateCallIndicator(event.valueInt);
1851aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1852aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALLSETUP:
1853aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            updateCallSetupIndicator(event.valueInt);
1854aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1855aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALLHELD:
1856aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            updateCallHeldIndicator(event.valueInt);
1857aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1858aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_RESP_AND_HOLD:
1859aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            updateRespAndHold(event.valueInt);
1860aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1861aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CLIP:
1862aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            updateClip(event.valueString);
1863aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1864aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CALL_WAITING:
1865aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            addCallWaiting(event.valueString);
1866aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1867aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_IN_BAND_RING:
1868aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (mInBandRingtone != event.valueInt) {
1869aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mInBandRingtone = event.valueInt;
18708d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
18718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                intent.putExtra(BluetoothHeadsetClient.EXTRA_IN_BAND_RING,
1872aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mInBandRingtone);
1873aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1874aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1875aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1876aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1877aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CURRENT_CALLS:
1878aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            queryCallsUpdate(
1879aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt,
1880aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt3,
1881aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueString,
1882aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt4 ==
18838d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            HeadsetClientHalConstants.CALL_MPTY_TYPE_MULTI,
1884aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueInt2 ==
18858d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            HeadsetClientHalConstants.CALL_DIRECTION_OUTGOING);
1886aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1887aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_VOLUME_CHANGED:
18888d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            if (event.valueInt == HeadsetClientHalConstants.VOLUME_TYPE_SPK) {
1889d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                                Log.d(TAG, "AM volume set to " +
1890d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                                      hfToAmVol(event.valueInt2));
18913076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                                mAudioManager.setStreamVolume(
18923076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                                    AudioManager.STREAM_VOICE_CALL,
1893d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                                    hfToAmVol(event.valueInt2),
18943076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                                    AudioManager.FLAG_SHOW_UI);
1895aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mVgsFromStack = true;
18963076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                            } else if (event.valueInt ==
18973076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                                HeadsetClientHalConstants.VOLUME_TYPE_MIC) {
1898aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mAudioManager.setMicrophoneMute(event.valueInt2 == 0);
18993076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal
1900aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                mVgmFromStack = true;
1901aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1902aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
1903aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CMD_RESULT:
1904aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Pair<Integer, Object> queuedAction = mQueuedActions.poll();
1905aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1906aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            // should not happen but...
1907aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            if (queuedAction == null || queuedAction.first == NO_ACTION) {
1908aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                clearPendingAction();
1909aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                break;
1910aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
1911aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1912aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "Connected: command result: " + event.valueInt
1913aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + " queuedAction: " + queuedAction.first);
1914aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
1915aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            switch (queuedAction.first) {
1916aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case VOICE_RECOGNITION_STOP:
1917aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case VOICE_RECOGNITION_START:
19188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    if (event.valueInt == HeadsetClientHalConstants.CMD_COMPLETE_OK) {
1919aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        if (queuedAction.first == VOICE_RECOGNITION_STOP) {
1920aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                            mVoiceRecognitionActive =
19218d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                    HeadsetClientHalConstants.VR_STATE_STOPPED;
1922aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        } else {
1923aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                            mVoiceRecognitionActive =
19248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                    HeadsetClientHalConstants.VR_STATE_STARTED;
1925aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        }
1926aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
19278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
1928aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    intent.putExtra(
19298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION,
1930aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                            mVoiceRecognitionActive);
1931aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
1932aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
1933aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1934aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case QUERY_CURRENT_CALLS:
1935aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    queryCallsDone();
1936aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1937aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case ACCEPT_CALL:
19388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    if (event.valueInt == BluetoothHeadsetClient.ACTION_RESULT_OK) {
1939aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mPendingAction = queuedAction;
1940aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    } else {
19418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        if (callsInState(BluetoothHeadsetClientCall.CALL_STATE_ACTIVE) == 0) {
19428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            if(getCall(BluetoothHeadsetClientCall.CALL_STATE_INCOMING) != null &&
19438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                (Integer) mPendingAction.second == HeadsetClientHalConstants.CALL_ACTION_ATA) {
19448d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                acceptCall(BluetoothHeadsetClient.CALL_ACCEPT_NONE, true);
1945aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                                break;
19468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                            } else if(getCall(BluetoothHeadsetClientCall.CALL_STATE_WAITING) != null &&
19478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                     (Integer) mPendingAction.second == HeadsetClientHalConstants.CALL_ACTION_CHLD_2) {
19488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                acceptCall(BluetoothHeadsetClient.CALL_ACCEPT_NONE, true);
1949aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                                break;
1950aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                            }
1951aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        }
1952aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        sendActionResultIntent(event);
1953aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
1954aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1955aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case REJECT_CALL:
1956aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case HOLD_CALL:
1957aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case TERMINATE_CALL:
1958aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case ENTER_PRIVATE_MODE:
1959aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case DIAL_NUMBER:
1960aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case DIAL_MEMORY:
1961aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case REDIAL:
19628d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    if (event.valueInt == BluetoothHeadsetClient.ACTION_RESULT_OK) {
1963aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mPendingAction = queuedAction;
1964aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    } else {
1965aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        sendActionResultIntent(event);
1966aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
1967aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1968aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case TERMINATE_SPECIFIC_CALL:
1969aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    // if terminating specific succeed no other
1970aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    // event is send
19718d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    if (event.valueInt == BluetoothHeadsetClient.ACTION_RESULT_OK) {
19728d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                        BluetoothHeadsetClientCall c =
19738d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                (BluetoothHeadsetClientCall) queuedAction.second;
1974aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        setCallState(c,
19758d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                                BluetoothHeadsetClientCall.CALL_STATE_TERMINATED);
1976aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        mCalls.remove(c.getId());
1977aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    } else {
1978aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        sendActionResultIntent(event);
1979aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
1980aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1981aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case LAST_VTAG_NUMBER:
19828d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                    if (event.valueInt != BluetoothHeadsetClient.ACTION_RESULT_OK) {
1983aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                        sendActionResultIntent(event);
1984aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    }
1985d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                    break;
1986d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                case DISABLE_NREC:
1987d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                    if (event.valueInt != HeadsetClientHalConstants.CMD_COMPLETE_OK) {
1988d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                        Log.w(TAG, "Failed to disable AG's EC and NR");
1989d1fadc3b23a03cbf028bfbdca9fd64640d7a05bdDavid Stevens                                    }
1990aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1991aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case SET_MIC_VOLUME:
1992aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case SET_SPEAKER_VOLUME:
1993aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case SUBSCRIBER_INFO:
1994aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                case QUERY_OPERATOR_NAME:
1995aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1996aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                default:
1997aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    sendActionResultIntent(event);
1998aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    break;
1999aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            }
2000aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2001aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2002aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_SUBSCRIBER_INFO:
2003aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            /* TODO should we handle type as well? */
2004aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mSubscriberInfo = event.valueString;
20058d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_AG_EVENT);
20068d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_SUBSCRIBER_INFO,
2007aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    mSubscriberInfo);
2008aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
2009aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
2010aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2011aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_LAST_VOICE_TAG_NUMBER:
20128d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent = new Intent(BluetoothHeadsetClient.ACTION_LAST_VTAG);
20138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            intent.putExtra(BluetoothHeadsetClient.EXTRA_NUMBER,
2014aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    event.valueString);
2015aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
2016aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
2017aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2018aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_RING_INDICATION:
20193076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                            // Ringing is not handled at this indication and rather should be
20203076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                            // implemented (by the client of this service). Use the
20213076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                            // CALL_STATE_INCOMING (and similar) handle ringing.
2022aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2023aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        default:
2024aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.e(TAG, "Unknown stack event: " + event.type);
2025aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2026aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2027aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2028aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2029aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2030aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
2031aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2032aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return HANDLED;
2033aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2034aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2035aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void sendActionResultIntent(StackEvent event) {
20368d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            Intent intent = new Intent(BluetoothHeadsetClient.ACTION_RESULT);
20378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            intent.putExtra(BluetoothHeadsetClient.EXTRA_RESULT_CODE, event.valueInt);
20388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if (event.valueInt == BluetoothHeadsetClient.ACTION_RESULT_ERROR_CME) {
20398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_CME_CODE, event.valueInt2);
2040aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2041aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            intent.putExtra(BluetoothDevice.EXTRA_DEVICE, event.device);
2042aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
2043aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2044aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2045aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in Connected state
2046aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processConnectionEvent(int state, BluetoothDevice device) {
2047aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
20488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED:
2049aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG, "Connected disconnects.");
2050aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // AG disconnects
2051aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mCurrentDevice.equals(device)) {
2052aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(mCurrentDevice,
2053aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED,
2054aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_CONNECTED);
2055aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mCurrentDevice = null;
2056aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        transitionTo(mDisconnected);
2057aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
2058aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Disconnected from unknown device: " + device);
2059aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2060aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2061aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2062aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "Connection State Device: " + device + " bad state: " + state);
2063aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2064aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2065aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2066aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2067aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in Connected state
2068aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processAudioEvent(int state, BluetoothDevice device) {
2069aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // message from old device
2070aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (!mCurrentDevice.equals(device)) {
2071aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.e(TAG, "Audio changed on disconnected device: " + device);
2072aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
2073aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2074aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2075aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
20768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.AUDIO_STATE_CONNECTED_MSBC:
2077aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mAudioWbs = true;
2078aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    // fall through
20798d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.AUDIO_STATE_CONNECTED:
208022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                    if (!mAudioRouteAllowed) {
208122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                        sendMessage(HeadsetClientStateMachine.DISCONNECT_AUDIO);
208222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                        break;
208322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee                    }
208422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
20853076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // Audio state is split in two parts, the audio focus is maintained by the
20863076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // entity exercising this service (typically the Telecom stack) and audio
20873076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // routing is handled by the bluetooth stack itself. The only reason to do so is
20883076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // because Bluetooth SCO connection from the HF role is not entirely supported
20893076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // for routing and volume purposes.
20903076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // NOTE: All calls here are routed via the setParameters which changes the
20913076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                    // routing at the Audio HAL level.
20928d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTED;
209337604004520846495a5dba50d7c3afef05a9ecf9Sharvil Nanavati
209437604004520846495a5dba50d7c3afef05a9ecf9Sharvil Nanavati                    // We need to set the volume after switching into HFP mode as some Audio HALs
209537604004520846495a5dba50d7c3afef05a9ecf9Sharvil Nanavati                    // reset the volume to a known-default on mode switch.
2096d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    final int amVol =
20973076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                            mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
2098d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    final int hfVol = amToHfVol(amVol);
2099d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal
2100aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG,"hfp_enable=true");
2101aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG,"mAudioWbs is " + mAudioWbs);
2102aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mAudioWbs) {
2103aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG,"Setting sampling rate as 16000");
2104aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mAudioManager.setParameters("hfp_set_sampling_rate=16000");
2105aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2106aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    else {
2107aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG,"Setting sampling rate as 8000");
2108aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mAudioManager.setParameters("hfp_set_sampling_rate=8000");
2109aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2110d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    Log.d(TAG, "hf_volume " + hfVol);
2111aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    mAudioManager.setParameters("hfp_enable=true");
2112d38ba29ff12eea818f2fd502ee9d5a4f1bfb278eSanket Agarwal                    mAudioManager.setParameters("hfp_volume=" + hfVol);
2113aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    transitionTo(mAudioOn);
2114aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
21158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.AUDIO_STATE_CONNECTING:
21168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    mAudioState = BluetoothHeadsetClient.STATE_AUDIO_CONNECTING;
21178d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    broadcastAudioState(device, BluetoothHeadsetClient.STATE_AUDIO_CONNECTING,
21188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                            BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED);
2119aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
21208d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED:
21218d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (mAudioState == BluetoothHeadsetClient.STATE_AUDIO_CONNECTING) {
21228d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
2123aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastAudioState(device,
21248d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED,
21258d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_CONNECTING);
2126aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2127aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2128aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2129aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "Audio State Device: " + device + " bad state: " + state);
2130aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2131aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2132aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2133aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2134aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
2135aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void exit() {
2136aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Exit Connected: " + getCurrentMessage().what);
2137aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2138aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2139aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2140aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private class AudioOn extends State {
2141aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
2142aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void enter() {
2143aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Enter AudioOn: " + getCurrentMessage().what);
2144a27628d5cb96981b65daec4db798d06ba9d98ce2Sharvil Nanavati            broadcastAudioState(mCurrentDevice, BluetoothHeadsetClient.STATE_AUDIO_CONNECTED,
2145a27628d5cb96981b65daec4db798d06ba9d98ce2Sharvil Nanavati                BluetoothHeadsetClient.STATE_AUDIO_CONNECTING);
2146aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2147aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2148aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
2149aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public synchronized boolean processMessage(Message message) {
2150aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "AudioOn process message: " + message.what);
2151aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (DBG) {
2152aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (mCurrentDevice == null) {
2153aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.d(TAG, "ERROR: mCurrentDevice is null in Connected");
2154aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
2155aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
2156aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2157aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2158aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (message.what) {
2159aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT:
2160aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    BluetoothDevice device = (BluetoothDevice) message.obj;
2161aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (!mCurrentDevice.equals(device)) {
2162aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        break;
2163aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2164aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    deferMessage(message);
2165aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    /*
2166aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     * fall through - disconnect audio first then expect
2167aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     * deferred DISCONNECT message in Connected state
2168aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     */
2169aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case DISCONNECT_AUDIO:
2170aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    /*
2171aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     * just disconnect audio and wait for
2172aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     * EVENT_TYPE_AUDIO_STATE_CHANGED, that triggers State
2173aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     * Machines state changing
2174aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                     */
2175aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (disconnectAudioNative(getByteAddress(mCurrentDevice))) {
21768d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
2177aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG,"hfp_enable=false");
2178aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mAudioManager.setParameters("hfp_enable=false");
2179aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastAudioState(mCurrentDevice,
21808d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED,
21818d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_CONNECTED);
2182aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2183aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2184aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                case STACK_EVENT:
2185aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    StackEvent event = (StackEvent) message.obj;
2186aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (DBG) {
2187aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG, "AudioOn: event type: " + event.type);
2188aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2189aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    switch (event.type) {
2190aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_CONNECTION_STATE_CHANGED:
2191aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "AudioOn connection state changed" + event.device + ": "
2192aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + event.valueInt);
2193aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processConnectionEvent(event.valueInt, event.device);
2194aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2195aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        case EVENT_TYPE_AUDIO_STATE_CHANGED:
2196aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            Log.d(TAG, "AudioOn audio state changed" + event.device + ": "
2197aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                    + event.valueInt);
2198aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            processAudioEvent(event.valueInt, event.device);
2199aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            break;
2200aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        default:
2201aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                            return NOT_HANDLED;
2202aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2203aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2204aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2205aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    return NOT_HANDLED;
2206aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2207aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return HANDLED;
2208aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2209aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2210aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in AudioOn state. Can AG disconnect RFCOMM prior to SCO? Handle this
2211aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processConnectionEvent(int state, BluetoothDevice device) {
2212aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
22138d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.CONNECTION_STATE_DISCONNECTED:
2214aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (mCurrentDevice.equals(device)) {
22158d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        processAudioEvent(HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED,
2216aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                device);
2217aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastConnectionState(mCurrentDevice,
2218aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_DISCONNECTED,
2219aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                                BluetoothProfile.STATE_CONNECTED);
2220aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mCurrentDevice = null;
2221aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        transitionTo(mDisconnected);
2222aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    } else {
2223aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.e(TAG, "Disconnected from unknown device: " + device);
2224aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2225aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2226aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2227aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "Connection State Device: " + device + " bad state: " + state);
2228aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2229aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2230aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2231aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2232aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // in AudioOn state
2233aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private void processAudioEvent(int state, BluetoothDevice device) {
2234aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (!mCurrentDevice.equals(device)) {
2235aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                Log.e(TAG, "Audio changed on disconnected device: " + device);
2236aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                return;
2237aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2238aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2239aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            switch (state) {
22408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                case HeadsetClientHalConstants.AUDIO_STATE_DISCONNECTED:
22418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    if (mAudioState != BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED) {
22428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                        mAudioState = BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
22433076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                        // Audio focus may still be held by the entity controlling the actual call
22443076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                        // (such as Telecom) and hence this will still keep the call around, there
22453076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                        // is not much we can do here since dropping the call without user consent
22463076d2acccf5c3db0db19b622f062e259be39f3aSanket Agarwal                        // even if the audio connection snapped may not be a good idea.
2247aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        Log.d(TAG,"hfp_enable=false");
2248aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        mAudioManager.setParameters("hfp_enable=false");
2249aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        broadcastAudioState(device,
22508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED,
22518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                                BluetoothHeadsetClient.STATE_AUDIO_CONNECTED);
2252aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2253aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2254aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    transitionTo(mConnected);
2255aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2256aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                default:
2257aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    Log.e(TAG, "Audio State Device: " + device + " bad state: " + state);
2258aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    break;
2259aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2260aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2261aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2262aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
2263aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public void exit() {
2264aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            Log.d(TAG, "Exit AudioOn: " + getCurrentMessage().what);
2265aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2266aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2267aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2268aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    /**
2269aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     * @hide
2270aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     */
2271aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public synchronized int getConnectionState(BluetoothDevice device) {
2272aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCurrentDevice == null) {
2273aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return BluetoothProfile.STATE_DISCONNECTED;
2274aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2275aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2276aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (!mCurrentDevice.equals(device)) {
2277aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return BluetoothProfile.STATE_DISCONNECTED;
2278aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2279aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2280aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        IState currentState = getCurrentState();
2281aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (currentState == mConnecting) {
2282aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return BluetoothProfile.STATE_CONNECTING;
2283aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2284aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2285aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (currentState == mConnected || currentState == mAudioOn) {
2286aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return BluetoothProfile.STATE_CONNECTED;
2287aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2288aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2289aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.e(TAG, "Bad currentState: " + currentState);
2290aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return BluetoothProfile.STATE_DISCONNECTED;
2291aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2292aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2293aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void broadcastAudioState(BluetoothDevice device, int newState, int prevState) {
22948d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Intent intent = new Intent(BluetoothHeadsetClient.ACTION_AUDIO_STATE_CHANGED);
2295aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
2296aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
2297aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
22988d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        if (newState == BluetoothHeadsetClient.STATE_AUDIO_CONNECTED) {
22998d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            intent.putExtra(BluetoothHeadsetClient.EXTRA_AUDIO_WBS, mAudioWbs);
2300aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2301aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2302aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
2303aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
2304aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "Audio state " + device + ": " + prevState + "->" + newState);
2305aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2306aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2307aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // This method does not check for error condition (newState == prevState)
2308aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void broadcastConnectionState(BluetoothDevice device, int newState, int prevState) {
2309aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "Connection state " + device + ": " + prevState + "->" + newState);
2310aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        /*
2311aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta         * Notifying the connection state change of the profile before sending
2312aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta         * the intent for connection state change, as it was causing a race
2313aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta         * condition, with the UI not being updated with the correct connection
2314aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta         * state.
2315aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta         */
23168d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        mService.notifyProfileConnectionStateChanged(device, BluetoothProfile.HEADSET_CLIENT,
2317aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                newState, prevState);
23188d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        Intent intent = new Intent(BluetoothHeadsetClient.ACTION_CONNECTION_STATE_CHANGED);
2319aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState);
2320aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothProfile.EXTRA_STATE, newState);
2321aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device);
2322aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2323aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // add feature extras when connected
2324aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (newState == BluetoothProfile.STATE_CONNECTED) {
23258d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_3WAY) ==
23268d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.PEER_FEAT_3WAY) {
23278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_3WAY_CALLING, true);
2328aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23298d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_VREC) ==
23308d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.PEER_FEAT_VREC) {
23318d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_VOICE_RECOGNITION, true);
2332aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23338d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_VTAG) ==
23348d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.PEER_FEAT_VTAG) {
23358d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ATTACH_NUMBER_TO_VT, true);
2336aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23378d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_REJECT) ==
23388d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.PEER_FEAT_REJECT) {
23398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_REJECT_CALL, true);
2340aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23418d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mPeerFeatures & HeadsetClientHalConstants.PEER_FEAT_ECC) ==
23428d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.PEER_FEAT_ECC) {
23438d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ECC, true);
2344aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2345aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2346aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // add individual CHLD support extras
23478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC) ==
23488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.CHLD_FEAT_HOLD_ACC) {
23498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_ACCEPT_HELD_OR_WAITING_CALL, true);
2350aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_REL) ==
23528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.CHLD_FEAT_REL) {
23538d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_HELD_OR_WAITING_CALL, true);
2354aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23558d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_REL_ACC) ==
23568d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.CHLD_FEAT_REL_ACC) {
23578d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_RELEASE_AND_ACCEPT, true);
2358aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23598d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_MERGE) ==
23608d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.CHLD_FEAT_MERGE) {
23618d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE, true);
2362aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
23638d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            if ((mChldFeatures & HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH) ==
23648d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                    HeadsetClientHalConstants.CHLD_FEAT_MERGE_DETACH) {
23658d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood                intent.putExtra(BluetoothHeadsetClient.EXTRA_AG_FEATURE_MERGE_AND_DETACH, true);
2366aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2367aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2368aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        mService.sendBroadcast(intent, ProfileService.BLUETOOTH_PERM);
2369aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2370aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2371aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean isConnected() {
2372aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        IState currentState = getCurrentState();
2373aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return (currentState == mConnected || currentState == mAudioOn);
2374aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2375aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2376aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
2377aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        List<BluetoothDevice> deviceList = new ArrayList<BluetoothDevice>();
2378aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Set<BluetoothDevice> bondedDevices = mAdapter.getBondedDevices();
2379aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int connectionState;
2380aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        synchronized (this) {
2381aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            for (BluetoothDevice device : bondedDevices) {
2382aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                ParcelUuid[] featureUuids = device.getUuids();
2383aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                if (!BluetoothUuid.isUuidPresent(featureUuids, BluetoothUuid.Handsfree_AG)) {
2384aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    continue;
2385aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
2386aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                connectionState = getConnectionState(device);
2387aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                for (int state : states) {
2388aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    if (connectionState == state) {
2389aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                        deviceList.add(device);
2390aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                    }
2391aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                }
2392aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2393aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2394aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return deviceList;
2395aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2396aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2397aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean okToConnect(BluetoothDevice device) {
2398aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int priority = mService.getPriority(device);
2399aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        boolean ret = false;
2400aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // check priority and accept or reject the connection. if priority is
2401aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // undefined
2402aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // it is likely that our SDP has not completed and peer is initiating
2403aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // the
2404aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        // connection. Allow this connection, provided the device is bonded
2405aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if ((BluetoothProfile.PRIORITY_OFF < priority) ||
2406aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                ((BluetoothProfile.PRIORITY_UNDEFINED == priority) &&
2407aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                (device.getBondState() != BluetoothDevice.BOND_NONE))) {
2408aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            ret = true;
2409aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2410aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return ret;
2411aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2412aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2413aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    boolean isAudioOn() {
2414aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return (getCurrentState() == mAudioOn);
2415aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2416aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
241722bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public void setAudioRouteAllowed(boolean allowed) {
241822bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        mAudioRouteAllowed = allowed;
241922bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
242022bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
242122bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    public boolean getAudioRouteAllowed() {
242222bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee        return mAudioRouteAllowed;
242322bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee    }
242422bb39444356637fbcabd4acf04f2fdb9e3da177Bryce Lee
2425aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    synchronized int getAudioState(BluetoothDevice device) {
2426aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCurrentDevice == null || !mCurrentDevice.equals(device)) {
24278d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood            return BluetoothHeadsetClient.STATE_AUDIO_DISCONNECTED;
2428aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2429aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mAudioState;
2430aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2431aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2432aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    /**
2433aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     * @hide
2434aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta     */
2435aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    List<BluetoothDevice> getConnectedDevices() {
2436aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
2437aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        synchronized (this) {
2438aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            if (isConnected()) {
2439aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta                devices.add(mCurrentDevice);
2440aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            }
2441aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2442aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return devices;
2443aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2444aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2445aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private BluetoothDevice getDevice(byte[] address) {
2446aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return mAdapter.getRemoteDevice(Utils.getAddressStringFromByte(address));
2447aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2448aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2449aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onConnectionStateChanged(int state, int peer_feat, int chld_feat, byte[] address) {
2450aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CONNECTION_STATE_CHANGED);
2451aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = state;
2452aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt2 = peer_feat;
2453aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt3 = chld_feat;
2454aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.device = getDevice(address);
2455aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2456aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2457aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2458aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2459aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onAudioStateChanged(int state, byte[] address) {
2460aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_AUDIO_STATE_CHANGED);
2461aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = state;
2462aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.device = getDevice(address);
2463aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2464aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2465aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2466aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2467aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onVrStateChanged(int state) {
2468aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_VR_STATE_CHANGED);
2469aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = state;
2470aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2471aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2472aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2473aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2474aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onNetworkState(int state) {
2475aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_NETWORK_STATE);
2476aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = state;
2477aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2478aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2479aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2480aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2481aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onNetworkRoaming(int state) {
2482aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_ROAMING_STATE);
2483aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = state;
2484aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2485aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2486aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2487aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2488aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onNetworkSignal(int signal) {
2489aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_NETWORK_SIGNAL);
2490aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = signal;
2491aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2492aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2493aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2494aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2495aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onBatteryLevel(int level) {
2496aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_BATTERY_LEVEL);
2497aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = level;
2498aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2499aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2500aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2501aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2502aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCurrentOperator(String name) {
2503aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_OPERATOR_NAME);
2504aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = name;
2505aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2506aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2507aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2508aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2509aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCall(int call) {
2510aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CALL);
2511aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = call;
2512aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2513aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2514aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2515aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2516aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCallSetup(int callsetup) {
2517aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CALLSETUP);
2518aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = callsetup;
2519aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2520aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2521aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2522aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2523aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCallHeld(int callheld) {
2524aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CALLHELD);
2525aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = callheld;
2526aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2527aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2528aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2529aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2530aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onRespAndHold(int resp_and_hold) {
2531aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_RESP_AND_HOLD);
2532aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = resp_and_hold;
2533aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2534aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2535aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2536aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2537aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onClip(String number) {
2538aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CLIP);
2539aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = number;
2540aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2541aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2542aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2543aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2544aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCallWaiting(String number) {
2545aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CALL_WAITING);
2546aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = number;
2547aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2548aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2549aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2550aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2551aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCurrentCalls(int index, int dir, int state, int mparty, String number) {
2552aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CURRENT_CALLS);
2553aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = index;
2554aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt2 = dir;
2555aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt3 = state;
2556aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt4 = mparty;
2557aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = number;
2558aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming " + event);
2559aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2560aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2561aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2562aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onVolumeChange(int type, int volume) {
2563aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_VOLUME_CHANGED);
2564aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = type;
2565aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt2 = volume;
2566aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2567aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2568aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2569aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2570aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onCmdResult(int type, int cme) {
2571aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_CMD_RESULT);
2572aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = type;
2573aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt2 = cme;
2574aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2575aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2576aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2577aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2578aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onSubscriberInfo(String number, int type) {
2579aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_SUBSCRIBER_INFO);
2580aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = type;
2581aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = number;
2582aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2583aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2584aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2585aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2586aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onInBandRing(int in_band) {
2587aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_IN_BAND_RING);
2588aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueInt = in_band;
2589aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2590aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2591aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2592aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2593aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onLastVoiceTagNumber(String number) {
2594aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_LAST_VOICE_TAG_NUMBER);
2595aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        event.valueString = number;
2596aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2597aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2598aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2599aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private void onRingIndication() {
2600aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        StackEvent event = new StackEvent(EVENT_TYPE_RING_INDICATION);
2601aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Log.d(TAG, "incoming" + event);
2602aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        sendMessage(STACK_EVENT, event);
2603aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2604aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2605aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private String getCurrentDeviceName() {
2606aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        String defaultName = "<unknown>";
2607aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (mCurrentDevice == null) {
2608aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return defaultName;
2609aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2610aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        String deviceName = mCurrentDevice.getName();
2611aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        if (deviceName == null) {
2612aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return defaultName;
2613aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2614aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return deviceName;
2615aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2616aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2617aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private byte[] getByteAddress(BluetoothDevice device) {
2618aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return Utils.getBytesFromAddress(device.getAddress());
2619aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2620aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2621aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // Event types for STACK_EVENT message
2622aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_NONE = 0;
2623aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CONNECTION_STATE_CHANGED = 1;
2624aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_AUDIO_STATE_CHANGED = 2;
2625aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_VR_STATE_CHANGED = 3;
2626aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_NETWORK_STATE = 4;
2627aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_ROAMING_STATE = 5;
2628aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_NETWORK_SIGNAL = 6;
2629aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_BATTERY_LEVEL = 7;
2630aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_OPERATOR_NAME = 8;
2631aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CALL = 9;
2632aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CALLSETUP = 10;
2633aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CALLHELD = 11;
2634aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CLIP = 12;
2635aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CALL_WAITING = 13;
2636aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CURRENT_CALLS = 14;
2637aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_VOLUME_CHANGED = 15;
2638aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_CMD_RESULT = 16;
2639aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_SUBSCRIBER_INFO = 17;
2640aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_RESP_AND_HOLD = 18;
2641aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_IN_BAND_RING = 19;
2642aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_LAST_VOICE_TAG_NUMBER = 20;
2643aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    final private static int EVENT_TYPE_RING_INDICATION= 21;
2644aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2645aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    // for debugging only
2646aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private final String EVENT_TYPE_NAMES[] =
2647aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    {
2648aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_NONE",
2649aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CONNECTION_STATE_CHANGED",
2650aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_AUDIO_STATE_CHANGED",
2651aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_VR_STATE_CHANGED",
2652aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_NETWORK_STATE",
2653aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_ROAMING_STATE",
2654aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_NETWORK_SIGNAL",
2655aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_BATTERY_LEVEL",
2656aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_OPERATOR_NAME",
2657aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CALL",
2658aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CALLSETUP",
2659aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CALLHELD",
2660aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CLIP",
2661aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CALL_WAITING",
2662aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CURRENT_CALLS",
2663aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_VOLUME_CHANGED",
2664aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_CMD_RESULT",
2665aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_SUBSCRIBER_INFO",
2666aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_RESP_AND_HOLD",
2667aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_IN_BAND_RING",
2668aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_LAST_VOICE_TAG_NUMBER",
2669aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            "EVENT_TYPE_RING_INDICATION",
2670aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    };
2671aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2672aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private class StackEvent {
2673aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int type = EVENT_TYPE_NONE;
2674aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int valueInt = 0;
2675aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int valueInt2 = 0;
2676aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int valueInt3 = 0;
2677aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        int valueInt4 = 0;
2678aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        String valueString = null;
2679aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        BluetoothDevice device = null;
2680aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2681aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        private StackEvent(int type) {
2682aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            this.type = type;
2683aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2684aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2685aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        @Override
2686aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        public String toString() {
2687aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            // event dump
2688aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            StringBuilder result = new StringBuilder();
2689aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append("StackEvent {type:" + EVENT_TYPE_NAMES[type]);
2690aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", value1:" + valueInt);
2691aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", value2:" + valueInt2);
2692aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", value3:" + valueInt3);
2693aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", value4:" + valueInt4);
2694aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", string: \"" + valueString + "\"");
2695aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            result.append(", device:" + device + "}");
2696aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            return result.toString();
2697aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        }
2698aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2699aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2700aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native static void classInitNative();
2701aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2702aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native void initializeNative();
2703aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2704aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native void cleanupNative();
2705aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2706aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean connectNative(byte[] address);
2707aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2708aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean disconnectNative(byte[] address);
2709aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2710aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean connectAudioNative(byte[] address);
2711aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2712aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean disconnectAudioNative(byte[] address);
2713aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2714aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean startVoiceRecognitionNative();
2715aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2716aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean stopVoiceRecognitionNative();
2717aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2718aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean setVolumeNative(int volumeType, int volume);
2719aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2720aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean dialNative(String number);
2721aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2722aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean dialMemoryNative(int location);
2723aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2724aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean handleCallActionNative(int action, int index);
2725aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2726aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean queryCurrentCallsNative();
2727aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2728aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean queryCurrentOperatorNameNative();
2729aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2730aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean retrieveSubscriberInfoNative();
2731aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2732aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean sendDtmfNative(byte code);
2733aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2734aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean requestLastVoiceTagNumberNative();
2735aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2736aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    private native boolean sendATCmdNative(int ATCmd, int val1,
2737aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta            int val2, String arg);
2738aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
27398d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood    public List<BluetoothHeadsetClientCall> getCurrentCalls() {
27408d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        return new ArrayList<BluetoothHeadsetClientCall>(mCalls.values());
2741aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2742aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta
2743aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    public Bundle getCurrentAgEvents() {
2744aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        Bundle b = new Bundle();
27458d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_NETWORK_STATUS, mIndicatorNetworkState);
27468d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_NETWORK_SIGNAL_STRENGTH, mIndicatorNetworkSignal);
27478d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_NETWORK_ROAMING, mIndicatorNetworkType);
27488d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_BATTERY_LEVEL, mIndicatorBatteryLevel);
27498d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putString(BluetoothHeadsetClient.EXTRA_OPERATOR_NAME, mOperatorName);
27508d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_VOICE_RECOGNITION, mVoiceRecognitionActive);
27518d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putInt(BluetoothHeadsetClient.EXTRA_IN_BAND_RING, mInBandRingtone);
27528d536f3db19e8ea7426e98e470dc15d10ecbae87Mike Lockwood        b.putString(BluetoothHeadsetClient.EXTRA_SUBSCRIBER_INFO, mSubscriberInfo);
2753aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta        return b;
2754aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta    }
2755aebc726105204f8a7b977eb3556c14b5ba18a5caHemant Gupta}
2756