BluetoothHandsfree.java revision c39c3c9ada26aa8fab1373ad94c9b0d9e8875caa
1b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/* 2b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 4b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * you may not use this file except in compliance with the License. 6b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * You may obtain a copy of the License at 7b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 8b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 10b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * See the License for the specific language governing permissions and 14b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * limitations under the License. 15b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 16b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 17b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpackage com.android.phone; 18b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 19b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.AtCommandHandler; 20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.AtCommandResult; 21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.AtParser; 22f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lanimport android.bluetooth.BluetoothA2dp; 231498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinekimport android.bluetooth.BluetoothAssignedNumbers; 24db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pellyimport android.bluetooth.BluetoothAdapter; 25b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 264079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.HeadsetBase; 28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.ScoSocket; 29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.ActivityNotFoundException; 30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.BroadcastReceiver; 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Intent; 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.IntentFilter; 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.AudioManager; 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri; 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult; 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Bundle; 38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager.WakeLock; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.SystemProperties; 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.ServiceState; 45404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.telephony.SignalStrength; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Call; 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Connection; 50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Phone; 51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.TelephonyIntents; 528058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wangimport com.android.internal.telephony.CallManager; 53b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.LinkedList; 55f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Bluetooth headset manager for the Phone app. 58b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @hide 59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 60b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class BluetoothHandsfree { 61b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String TAG = "BT HS/HF"; 628eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 1) 638eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan && (SystemProperties.getInt("ro.debuggable", 0) == 1); 648eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan private static final boolean VDBG = (PhoneApp.DBG_LEVEL >= 2); // even more logging 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_UNKNOWN = 0; 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HEADSET = 1; 68b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HANDSFREE = 2; 69b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 704079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private final Context mContext; 718058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang private final CallManager mCM; 72f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private final BluetoothA2dp mA2dp; 73f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 74f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private BluetoothDevice mA2dpDevice; 75f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private int mA2dpState; 76f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ServiceState mServiceState; 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private HeadsetBase mHeadset; // null when not connected 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mHeadsetType; 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mAudioPossible; 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mIncomingSco; 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mOutgoingSco; 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mConnectedSco; 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AudioManager mAudioManager; 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private PowerManager mPowerManager; 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 88f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private boolean mPendingSco; // waiting for a2dp sink to suspend before establishing SCO 89ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent private boolean mA2dpSuspended; 90b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mUserWantsAudio; 91b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartCallWakeLock; // held while waiting for the intent to start call 92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartVoiceRecognitionWakeLock; // held while waiting for voice recognition 93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 94b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT command state 95c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private static final int GSM_MAX_CONNECTIONS = 6; // Max connections allowed by GSM 96c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private static final int CDMA_MAX_CONNECTIONS = 2; // Max connections allowed by CDMA 97b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 98b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long mBgndEarliestConnectionTime = 0; 99b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mClip = false; // Calling Line Information Presentation 100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIndicatorsEnabled = false; 101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mCmee = false; // Extended Error reporting 102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long[] mClccTimestamps; // Timestamps associated with each clcc index 103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean[] mClccUsed; // Is this clcc index in use 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForCallStart; 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForVoiceRecognition; 1060966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // do not connect audio until service connection is established 1070966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for 3-way supported devices, this is after AT+CHLD 1080966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for non-3-way supported devices, this is after AT+CMER (see spec) 1090966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly private boolean mServiceConnectionEstablished; 110db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly 1111dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private final BluetoothPhoneState mBluetoothPhoneState; // for CIND and CIEV updates 112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BluetoothAtPhonebook mPhonebook; 1131dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private Phone.State mPhoneState = Phone.State.IDLE; 114487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState mCdmaThreeWayCallState = 115487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.IDLE; 116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private DebugThread mDebugThread; 118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mScoGain = Integer.MIN_VALUE; 119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static Intent sVoiceCommandIntent; 121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Audio parameters 123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NREC = "bt_headset_nrec"; 124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NAME = "bt_headset_name"; 125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRemoteBrsf = 0; 127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mLocalBrsf = 0; 128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 129c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CDMA specific flag used in context with BT devices having display capabilities 130c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // to show which Caller is active. This state might not be always true as in CDMA 131c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // networks if a caller drops off no update is provided to the Phone. 132c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // This flag is just used as a toggle to provide a update to the BT device to specify 133c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // which caller is active. 134c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private boolean mCdmaIsSecondCallActive = false; 135c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Constants from Bluetooth Specification Hands-Free profile version 1.5 */ 1376967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_THREE_WAY_CALLING = 1 << 0; 1386967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_EC_NR = 1 << 1; 1396967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_RECOG = 1 << 2; 1406967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_IN_BAND_RING = 1 << 3; 1416967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_TAG_NUMBE = 1 << 4; 1426967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_REJECT_CALL = 1 << 5; 1436967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_STATUS = 1 << 6; 1446967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_CONTROL = 1 << 7; 1456967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_ERR_RESULT_CODES = 1 << 8; 1466967e2d953bc077c99c4831946201f3d333b833fNick Pelly 1476967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_EC_NR = 1 << 0; 1486967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CW_THREE_WAY_CALLING = 1 << 1; 1496967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CLIP = 1 << 2; 1506967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_VOICE_REG_ACT = 1 << 3; 1516967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_REMOTE_VOL_CONTROL = 1 << 4; 1526967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_STATUS = 1 << 5; 1536967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_CONTROL = 1 << 6; 154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static String typeToString(int type) { 156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (type) { 157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_UNKNOWN: 158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "unknown"; 159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HEADSET: 160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "headset"; 161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HANDSFREE: 162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "handsfree"; 163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1678058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang public BluetoothHandsfree(Context context, CallManager cm) { 1688058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM = cm; 169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext = context; 170cec56587c1d3c90014848d7adfe817bef9c325eaNick Pelly BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 171db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly boolean bluetoothCapable = (adapter != null); 172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; // nothing connected yet 173f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dp = new BluetoothA2dp(mContext); 174f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState = BluetoothA2dp.STATE_DISCONNECTED; 175f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpDevice = null; 176ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":StartCall"); 181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.setReferenceCounted(false); 182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":VoiceRecognition"); 184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.setReferenceCounted(false); 185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf = BRSF_AG_THREE_WAY_CALLING | 187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_EC_NR | 188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_REJECT_CALL | 189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_ENHANCED_CALL_STATUS; 1904b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project 191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sVoiceCommandIntent == null) { 192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND); 193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1956967e2d953bc077c99c4831946201f3d333b833fNick Pelly if (mContext.getPackageManager().resolveActivity(sVoiceCommandIntent, 0) != null && 196b8dbab241df3aa3487c1bdb488fd4e0b694d2d9aEric Laurent BluetoothHeadset.isBluetoothVoiceDialingEnabled(mContext)) { 197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf |= BRSF_AG_VOICE_RECOG; 198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2001dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState = new BluetoothPhoneState(); 201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook = new BluetoothAtPhonebook(mContext, this); 203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 204c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(false); 205f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh 206f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh if (bluetoothCapable) { 207f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh resetAtState(); 208f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh } 209f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh 210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothEnabled() { 213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Bluez has a bug where it will always accept and then orphan 214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * incoming SCO connections, regardless of whether we have a listening 215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * SCO socket. So the best thing to do is always run a listening socket 216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * while bluetooth is on so that at least we can diconnect it 217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * immediately when we don't want it. 218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco == null) { 220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = createScoSocket(); 221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.accept(); 222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothDisabled() { 226a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent audioOff(); 227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco != null) { 228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.close(); 229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = null; 230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isHeadsetConnected() { 234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset == null) { 235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return mHeadset.isConnected(); 238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 240f6adf1a33b12c9900b3ce9c15130642ce515ae91Jaikumar Ganesh /* package */ synchronized void connectHeadset(HeadsetBase headset, int headsetType) { 241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = headset; 242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadsetType = headsetType; 243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadsetType == TYPE_HEADSET) { 244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHeadsetAtParser(); 245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHandsfreeAtParser(); 247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2481498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 2491498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek // Headset vendor-specific commands 2501498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek registerAllVendorSpecificCommands(); 2511498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project headset.startEventThread(); 253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project configAudioParameters(); 254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (inDebug()) { 256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project startDebug(); 257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isIncallAudio()) { 260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 261179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi } else if ( mCM.getFirstActiveRingingCall().isRinging()) { 262179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi // need to update HS with RING when single ringing call exist 263179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi mBluetoothPhoneState.ring(); 264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* returns true if there is some kind of in-call audio we may wish to route 268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth to */ 269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isIncallAudio() { 2708058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call.State state = mCM.getActiveFgCallState(); 271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (state == Call.State.ACTIVE || state == Call.State.ALERTING); 273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 275819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh /* package */ synchronized void disconnectHeadset() { 276819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh // Close off the SCO sockets 277819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh audioOff(); 278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; 279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stopDebug(); 280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project resetAtState(); 281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 283bfc44512504ebc93c101ddb394719840f2d25072Jaikumar Ganesh /* package */ synchronized void resetAtState() { 284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = false; 285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 2860966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = false; 287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 288c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mClccTimestamps = new long[GSM_MAX_CONNECTIONS]; 289c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mClccUsed = new boolean[GSM_MAX_CONNECTIONS]; 290c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = 0; 294f5945125c4e044b860f89a370fe376b97bd91d37Jaikumar Ganesh mPhonebook.resetAtState(); 295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void configAudioParameters() { 298db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly String name = mHeadset.getRemoteDevice().getName(); 299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (name == null) { 300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project name = "<unknown>"; 301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 302aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NAME+"="+name+";"+HEADSET_NREC+"=on"); 303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Represents the data that we send in a +CIND or +CIEV command to the HF 307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class BluetoothPhoneState { 309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no service 310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: service 311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mService; 312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no active call 314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: active call (where active means audio is routed - not held call) 315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCall; 316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not in call setup 318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: incoming call setup 319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: outgoing call setup 320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3: remote party being alerted in an outgoing call setup 321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallsetup; 322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no calls held 324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: held call and active call 325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: held call only 326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallheld; 327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength of AG: 0-5 329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mSignal; 330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength in CSQ rssi scale 332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRssi; // for CSQ 333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: roaming not active (home) 335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: roaming active 336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRoam; 337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // battery charge of AG: 0-5 339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mBattchg; 340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not registered 342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: registered, home network 343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 5: registered, roaming 344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mStat; // for CREG 345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String mRingingNumber; // Context for in-progress RING's 347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRingingType; 348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIgnoreRing = false; 3491ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh private boolean mStopRing = false; 350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SERVICE_STATE_CHANGED = 1; 352487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private static final int PRECISE_CALL_STATE_CHANGED = 2; 353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int RING = 3; 354a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman private static final int PHONE_CDMA_CALL_WAITING = 4; 355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Handler mStateChangeHandler = new Handler() { 357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void handleMessage(Message msg) { 359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(msg.what) { 360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RING: 361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = ring(); 362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result != null) { 363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SERVICE_STATE_CHANGED: 367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateServiceState(sendUpdate(), state); 369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 370487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh case PRECISE_CALL_STATE_CHANGED: 371a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman case PHONE_CDMA_CALL_WAITING: 372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection connection = null; 373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (((AsyncResult) msg.obj).result instanceof Connection) { 374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connection = (Connection) ((AsyncResult) msg.obj).result; 375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 376487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh handlePreciseCallStateChange(sendUpdate(), connection); 377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private BluetoothPhoneState() { 383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // init members 3848058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang // TODO May consider to repalce the default phone's state and signal 3858058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang // by CallManagter's state and signal 3868058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang updateServiceState(false, mCM.getDefaultPhone().getServiceState()); 387487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh handlePreciseCallStateChange(false, null); 388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = 5; // There is currently no API to get battery level 389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // on demand, so set to 5 and wait for an update 3908058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mSignal = asuToSignal(mCM.getDefaultPhone().getSignalStrength()); 391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // register for updates 393f8453f9e061b237d83d006e07009402fa7680583John Wang // Use the service state of default phone as BT service state to 394f8453f9e061b237d83d006e07009402fa7680583John Wang // avoid situation such as no cell or wifi connection but still 395f8453f9e061b237d83d006e07009402fa7680583John Wang // reporting in service (since SipPhone always reports in service). 396f8453f9e061b237d83d006e07009402fa7680583John Wang mCM.getDefaultPhone().registerForServiceStateChanged(mStateChangeHandler, 397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SERVICE_STATE_CHANGED, null); 3988058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.registerForPreciseCallStateChanged(mStateChangeHandler, 399487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh PRECISE_CALL_STATE_CHANGED, null); 4008058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.registerForCallWaiting(mStateChangeHandler, 4018058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PHONE_CDMA_CALL_WAITING, null); 4028058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang 403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project filter.addAction(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); 405f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED); 406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.registerReceiver(mStateReceiver, filter); 407b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 409a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville private void updateBtPhoneStateAfterRadioTechnologyChange() { 4108eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if(VDBG) Log.d(TAG, "updateBtPhoneStateAfterRadioTechnologyChange..."); 411a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 412a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Unregister all events from the old obsolete phone 413f8453f9e061b237d83d006e07009402fa7680583John Wang mCM.getDefaultPhone().unregisterForServiceStateChanged(mStateChangeHandler); 4148058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.unregisterForPreciseCallStateChanged(mStateChangeHandler); 4158058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.unregisterForCallWaiting(mStateChangeHandler); 416a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 417a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Register all events new to the new active phone 418f8453f9e061b237d83d006e07009402fa7680583John Wang mCM.getDefaultPhone().registerForServiceStateChanged(mStateChangeHandler, 41919dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh SERVICE_STATE_CHANGED, null); 4208058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.registerForPreciseCallStateChanged(mStateChangeHandler, 421487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh PRECISE_CALL_STATE_CHANGED, null); 4228058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mCM.registerForCallWaiting(mStateChangeHandler, 4238058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PHONE_CDMA_CALL_WAITING, null); 424a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 425a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 426b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendUpdate() { 4270280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mIndicatorsEnabled 4280280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS && mServiceConnectionEstablished; 429b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 430b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 431b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendClipUpdate() { 4320280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mClip && 4330280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS mServiceConnectionEstablished; 4340280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS } 4350280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS 4360280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS private boolean sendRingUpdate() { 4370280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS if (isHeadsetConnected() && !mIgnoreRing && !mStopRing && 4380280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS mCM.getFirstActiveRingingCall().isRinging()) { 4390280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS if (mHeadsetType == TYPE_HANDSFREE) { 4400280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS return mServiceConnectionEstablished ? true : false; 4410280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS } 4420280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS return true; 4430280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS } 4440280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS return false; 445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4471ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh private void stopRing() { 4481ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mStopRing = true; 4491ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh } 4501ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh 451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,31] ASU signal strength to the [0,5] expected by 452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth devices. Scale is similar to status bar policy 453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 45434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh private int gsmAsuToSignal(SignalStrength signalStrength) { 45534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int asu = signalStrength.getGsmSignalStrength(); 456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (asu >= 16) return 5; 457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 8) return 4; 458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 4) return 3; 459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 2) return 2; 460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 1) return 1; 461b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else return 0; 462b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 463b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 46434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh /** 46534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * Convert the cdma / evdo db levels to appropriate icon level. 46634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * The scale is similar to the one used in status bar policy. 46734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * 46834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * @param signalStrength 46934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * @return the icon level 470404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville */ 47134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh private int cdmaDbmEcioToSignal(SignalStrength signalStrength) { 47234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelDbm = 0; 47334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEcio = 0; 47434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaIconLevel = 0; 47534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoIconLevel = 0; 47634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaDbm = signalStrength.getCdmaDbm(); 47734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaEcio = signalStrength.getCdmaEcio(); 47834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 47934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (cdmaDbm >= -75) levelDbm = 4; 48034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -85) levelDbm = 3; 48134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -95) levelDbm = 2; 48234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -100) levelDbm = 1; 48334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelDbm = 0; 48434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 48534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // Ec/Io are in dB*10 48634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (cdmaEcio >= -90) levelEcio = 4; 48734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -110) levelEcio = 3; 48834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -130) levelEcio = 2; 48934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -150) levelEcio = 1; 49034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEcio = 0; 49134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 49234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio; 49334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 49413df4bba7e39d516317d005b4b917b1f1c6baf8dJaikumar Ganesh if (mServiceState != null && 495b1164d370e8d83a8a4f3cbdc73dffc087254cabdJaikumar Ganesh (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0 || 496b1164d370e8d83a8a4f3cbdc73dffc087254cabdJaikumar Ganesh mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) { 49734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoEcio = signalStrength.getEvdoEcio(); 49834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoSnr = signalStrength.getEvdoSnr(); 49934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEvdoEcio = 0; 50034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEvdoSnr = 0; 50134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 50234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // Ec/Io are in dB*10 50334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (evdoEcio >= -650) levelEvdoEcio = 4; 50434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -750) levelEvdoEcio = 3; 50534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -900) levelEvdoEcio = 2; 50634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -1050) levelEvdoEcio = 1; 50734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEvdoEcio = 0; 50834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 50934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (evdoSnr > 7) levelEvdoSnr = 4; 51034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 5) levelEvdoSnr = 3; 51134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 3) levelEvdoSnr = 2; 51234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 1) levelEvdoSnr = 1; 51334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEvdoSnr = 0; 51434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 51534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr; 51634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh } 51734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // TODO(): There is a bug open regarding what should be sent. 51834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return (cdmaIconLevel > evdoIconLevel) ? cdmaIconLevel : evdoIconLevel; 51934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 520404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 521404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 522404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 523404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville private int asuToSignal(SignalStrength signalStrength) { 52434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (signalStrength.isGsm()) { 52534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return gsmAsuToSignal(signalStrength); 526404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 52734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return cdmaDbmEcioToSignal(signalStrength); 528404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 529404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 530404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 531404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,5] signal strength to a rssi signal strength for CSQ 533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * which is [0,31]. Despite the same scale, this is not the same value 534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * as ASU. 535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int signalToRssi(int signal) { 537b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // using C4A suggested values 538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (signal) { 539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 0: return 0; 540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 1: return 4; 541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 2: return 8; 542b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 3: return 13; 543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 4: return 19; 544b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 5: return 31; 545b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return 0; 547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 548b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() { 551b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void onReceive(Context context, Intent intent) { 553b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { 554b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateBatteryState(intent); 555f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else if (intent.getAction().equals( 556f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED)) { 557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateSignalState(intent); 558f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else if (intent.getAction().equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) { 559f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan int state = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, 560f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothA2dp.STATE_DISCONNECTED); 561f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan int oldState = intent.getIntExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, 562f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothA2dp.STATE_DISCONNECTED); 563f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothDevice device = 564f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 565105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh 566105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh // We are only concerned about Connected sinks to suspend and resume 567105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh // them. We can safely ignore SINK_STATE_CHANGE for other devices. 568105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh if (mA2dpDevice != null && !device.equals(mA2dpDevice)) return; 569105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh 570f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan synchronized (BluetoothHandsfree.this) { 571f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState = state; 572105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh if (state == BluetoothA2dp.STATE_DISCONNECTED) { 573105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh mA2dpDevice = null; 574105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh } else { 575105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh mA2dpDevice = device; 576105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh } 577ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (oldState == BluetoothA2dp.STATE_PLAYING && 578ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpState == BluetoothA2dp.STATE_CONNECTED) { 579ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 580ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mPendingSco) { 581ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mHandler.removeMessages(MESSAGE_CHECK_PENDING_SCO); 582ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (DBG) log("A2DP suspended, completing SCO"); 583ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mOutgoingSco = createScoSocket(); 584ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (!mOutgoingSco.connect( 585f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getAddress(), 586f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getName())) { 587ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mOutgoingSco = null; 588ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent } 589ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = false; 590f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 591f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 592f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 593f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateBatteryState(Intent intent) { 599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = intent.getIntExtra("level", -1); 600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int scale = intent.getIntExtra("scale", -1); 601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel == -1 || scale == -1) { 602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; // ignore 603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 604b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project batteryLevel = batteryLevel * 5 / scale; 605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mBattchg != batteryLevel) { 606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = batteryLevel; 607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 7," + mBattchg); 609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateSignalState(Intent intent) { 614404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // NOTE this function is called by the BroadcastReceiver mStateReceiver after intent 615404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // ACTION_SIGNAL_STRENGTH_CHANGED and by the DebugThread mDebugThread 616d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh if (mHeadset == null) { 617d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh return; 618d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh } 619d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh 620404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = SignalStrength.newFromBundle(intent.getExtras()); 621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signal; 622404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 623404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signalStrength != null) { 624404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signal = asuToSignal(signalStrength); 625404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mRssi = signalToRssi(signal); // no unsolicited CSQ 626404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signal != mSignal) { 627404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mSignal = signal; 628404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (sendUpdate()) { 629404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville sendURC("+CIEV: 5," + mSignal); 630404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 632404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 633404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Log.e(TAG, "Signal Strength null"); 634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateServiceState(boolean sendUpdate, ServiceState state) { 638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int service = state.getState() == ServiceState.STATE_IN_SERVICE ? 1 : 0; 639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int roam = state.getRoaming() ? 1 : 0; 640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int stat; 641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 64213df4bba7e39d516317d005b4b917b1f1c6baf8dJaikumar Ganesh mServiceState = state; 643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service == 0) { 644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = 0; 645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = (roam == 1) ? 5 : 1; 647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service != mService) { 650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mService = service; 651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 1," + mService); 653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (roam != mRoam) { 656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRoam = roam; 657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 658b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 6," + mRoam); 659b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (stat != mStat) { 662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStat = stat; 663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(toCregString()); 665b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 666b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 669b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 670b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 671487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private synchronized void handlePreciseCallStateChange(boolean sendUpdate, 672487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh Connection connection) { 673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int call = 0; 674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callsetup = 0; 675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callheld = 0; 676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int prevCallsetup = mCallsetup; 677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 6788058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call foregroundCall = mCM.getActiveFgCall(); 6798058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call backgroundCall = mCM.getFirstActiveBgCall(); 6808058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call ringingCall = mCM.getFirstActiveRingingCall(); 681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 6828eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("updatePhoneState()"); 683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 684487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // This function will get called when the Precise Call State 685487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // {@link Call.State} changes. Hence, we might get this update 686487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // even if the {@link Phone.state} is same as before. 687487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Check for the same. 688487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 6898058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Phone.State newState = mCM.getState(); 6901dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh if (newState != mPhoneState) { 6911dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mPhoneState = newState; 6921dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh switch (mPhoneState) { 6931dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh case IDLE: 6941dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mUserWantsAudio = true; // out of call - reset state 6951dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh audioOff(); 6961dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh break; 6971dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh default: 6981dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh callStarted(); 6991dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh } 700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 7028058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang switch(foregroundCall.getState()) { 703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 2; 709a41427328932deb7cbadf586a1ec58e0ba26a932Jaikumar Ganesh mAudioPossible = true; 7103904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // We also need to send a Call started indication 7113904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // for cases where the 2nd MO was initiated was 7123904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // from a *BT hands free* and is waiting for a 7133904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // +BLND: OK response 7143904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // There is a special case handling of the same case 7153904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // for CDMA below 7168058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (mCM.getFgPhone().getPhoneType() == Phone.PHONE_TYPE_GSM) { 7173904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh callStarted(); 7183904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh } 719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 3; 722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Open the SCO channel for the outgoing call. 723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 72681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 72781a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 72881a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 72981a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 73081a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 73181a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 73281a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = false; 735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 7378058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang switch(ringingCall.getState()) { 738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 1; 741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 74281a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 74381a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 74481a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 74581a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 74681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 74781a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 74881a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 7518058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang switch(backgroundCall.getState()) { 752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 1; 755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 2; 758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 76081a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 76181a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 76281a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 76381a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 76481a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 76581a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 76681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCall != call) { 770b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 771b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This means that a call has transitioned from NOT ACTIVE to ACTIVE. 772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Switch on audio. 773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 774b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 775b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCall = call; 776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 2," + mCall); 778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallsetup != callsetup) { 781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = callsetup; 782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 7834b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // If mCall = 0, send CIEV 7844b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 0, send CIEV 7854b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 1, send CIEV after CCWA, 7864b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way supported. 7874b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 2 / 3 -> send CIEV, 7884b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way is supported 7894b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project if (mCall != 1 || mCallsetup == 0 || 7904b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project mCallsetup != 1 && (mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 3," + mCallsetup); 792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 7968058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (mCM.getDefaultPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) { 797c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneApp app = PhoneApp.getInstance(); 79860877272381161201c6969dea501e683705d6e32w if (app.cdmaPhoneCallState != null) { 799487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState currCdmaThreeWayCallState = 80060877272381161201c6969dea501e683705d6e32w app.cdmaPhoneCallState.getCurrentCallState(); 801487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState prevCdmaThreeWayCallState = 802ed1d155825eb32990fde95eef9d89a7260e4c3f1w app.cdmaPhoneCallState.getPreviousCallState(); 803ed1d155825eb32990fde95eef9d89a7260e4c3f1w 804487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = getCdmaCallHeldStatus(currCdmaThreeWayCallState, 805487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh prevCdmaThreeWayCallState); 806487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 807487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (mCdmaThreeWayCallState != currCdmaThreeWayCallState) { 808487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // In CDMA, the network does not provide any feedback 809487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // to the phone when the 2nd MO call goes through the 810487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // stages of DIALING > ALERTING -> ACTIVE we fake the 811487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // sequence 812487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((currCdmaThreeWayCallState == 813487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 814487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh && app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) { 815487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mAudioPossible = true; 816487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (sendUpdate) { 817487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 818487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,2"); 819487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,3"); 820487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,0"); 821487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 82260877272381161201c6969dea501e683705d6e32w } 823487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // We also need to send a Call started indication 824487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // for cases where the 2nd MO was initiated was 825487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // from a *BT hands free* and is waiting for a 826487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // +BLND: OK response 827487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callStarted(); 828c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 829c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 830487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // In CDMA, the network does not provide any feedback to 831487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // the phone when a user merges a 3way call or swaps 832487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // between two calls we need to send a CIEV response 833487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // indicating that a call state got changed which should 834487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // trigger a CLCC update request from the BT client. 835487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (currCdmaThreeWayCallState == 836487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 837487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mAudioPossible = true; 838487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (sendUpdate) { 839487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 840487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 2,1"); 841487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,0"); 842487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 84360877272381161201c6969dea501e683705d6e32w } 844c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 845c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 846487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mCdmaThreeWayCallState = currCdmaThreeWayCallState; 847c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 848c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 849c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean callsSwitched = 8518058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang (callheld == 1 && ! (backgroundCall.getEarliestConnectTime() == 852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBgndEarliestConnectionTime)); 853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 8548058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang mBgndEarliestConnectionTime = backgroundCall.getEarliestConnectTime(); 855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallheld != callheld || callsSwitched) { 857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld = callheld; 858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 4," + mCallheld); 860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (callsetup == 1 && callsetup != prevCallsetup) { 864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // new incoming call 865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = null; 866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = 128; 867b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // find incoming phone number and type 868b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 8698058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang connection = ringingCall.getEarliestConnection(); 870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 871b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Could not get a handle on Connection object for new " + 872b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "incoming call"); 873b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection != null) { 876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = connection.getAddress(); 877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = ""; 883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((call != 0 || callheld != 0) && sendUpdate) { 885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // call waiting 886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CCWA: \"" + number + "\"," + type); 8884b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project result.addResponse("+CIEV: 3," + callsetup); 889b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 891b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // regular new incoming call 892b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingNumber = number; 893b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingType = type; 894b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = false; 8951ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mStopRing = false; 896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 897a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly if ((mLocalBrsf & BRSF_AG_IN_BAND_RING) != 0x0) { 898a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly audioOn(); 899a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly } 900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResult(ring()); 901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 904b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 906487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private int getCdmaCallHeldStatus(CdmaPhoneCallState.PhoneCallState currState, 907487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState prevState) { 908487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh int callheld; 909487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Update the Call held information 910487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (currState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 911487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (prevState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 912487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 0; //0: no calls held, as now *both* the caller are active 913487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else { 914487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 1; //1: held call and active call, as on answering a 915487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Call Waiting, one of the caller *is* put on hold 916487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 917487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else if (currState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 918487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 1; //1: held call and active call, as on make a 3 Way Call 919487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // the first caller *is* put on hold 920487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else { 921487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 0; //0: no calls held as this is a SINGLE_ACTIVE call 922487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 923487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh return callheld; 924487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 925487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 926487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult ring() { 9280280bd6306692055f42ed0b7408dcc089a235c37SRINIVAS if (sendRingUpdate()) { 929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("RING"); 931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendClipUpdate()) { 932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CLIP: \"" + mRingingNumber + "\"," + mRingingType); 933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = mStateChangeHandler.obtainMessage(RING); 936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStateChangeHandler.sendMessageDelayed(msg, 3000); 937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized String toCregString() { 943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new String("+CREG: 1," + mStat); 944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCindResult() { 947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 948d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh mSignal = asuToSignal(mCM.getDefaultPhone().getSignalStrength()); 949d16be9780f29c031e3d854fde5b92f05392836e3Jaikumar Ganesh 950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CIND: " + mService + "," + mCall + "," + mCallsetup + "," + 951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld + "," + mSignal + "," + mRoam + "," + mBattchg; 952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCsqResult() { 957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CSQ: " + mRssi + ",99"; 959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult getCindTestResult() { 965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CIND: (\"service\",(0-1))," + "(\"call\",(0-1))," + 966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"callsetup\",(0-3)),(\"callheld\",(0-2)),(\"signal\",(0-5))," + 967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"roam\",(0-1)),(\"battchg\",(0-5))"); 968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void ignoreRing() { 971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = 0; 972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = true; 973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 3," + mCallsetup); 975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_ACCEPTED = 1; 981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CONNECTED = 2; 982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CLOSED = 3; 983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_CALL_STARTED = 4; 984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_VOICE_RECOGNITION_STARTED = 5; 985f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private static final int MESSAGE_CHECK_PENDING_SCO = 6; 986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final Handler mHandler = new Handler() { 988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 9897757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh public void handleMessage(Message msg) { 9907757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh synchronized (BluetoothHandsfree.this) { 9917757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh switch (msg.what) { 9927757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_ACCEPTED: 9937757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 9947757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (isHeadsetConnected() && (mAudioPossible || allowAudioAnytime()) && 9957757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco == null) { 9967757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.i(TAG, "Routing audio for incoming SCO connection"); 9977757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco = (ScoSocket)msg.obj; 9987757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mAudioManager.setBluetoothScoOn(true); 999db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED, 1000db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly mHeadset.getRemoteDevice()); 10017757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else { 10027757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.i(TAG, "Rejecting incoming SCO connection"); 10037757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh ((ScoSocket)msg.obj).close(); 10047757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10057757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } // else error trying to accept, try again 10067757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mIncomingSco = createScoSocket(); 10077757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mIncomingSco.accept(); 10087757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10097757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_CONNECTED: 10107757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (msg.arg1 == ScoSocket.STATE_CONNECTED && isHeadsetConnected() && 1011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco == null) { 10128eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Routing audio for outgoing SCO conection"); 1013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = (ScoSocket)msg.obj; 1014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(true); 1015db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED, 1016db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly mHeadset.getRemoteDevice()); 10177757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 10188eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Rejecting new connected outgoing SCO socket"); 1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((ScoSocket)msg.obj).close(); 10207757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mOutgoingSco.close(); 1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 10237757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10247757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_CLOSED: 10257757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mConnectedSco == (ScoSocket)msg.obj) { 1026819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mConnectedSco.close(); 10277757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco = null; 10287757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mAudioManager.setBluetoothScoOn(false); 1029db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED, 1030819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mHeadset.getRemoteDevice()); 10317757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else if (mOutgoingSco == (ScoSocket)msg.obj) { 1032819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mOutgoingSco.close(); 10337757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mOutgoingSco = null; 1034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 10357757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10367757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case CHECK_CALL_STARTED: 10377757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mWaitingForCallStart) { 10387757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mWaitingForCallStart = false; 10397757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.e(TAG, "Timeout waiting for call to start"); 10407757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh sendURC("ERROR"); 10417757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mStartCallWakeLock.isHeld()) { 10427757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mStartCallWakeLock.release(); 10437757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10447757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10457757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10467757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case CHECK_VOICE_RECOGNITION_STARTED: 10477757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mWaitingForVoiceRecognition) { 10487757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mWaitingForVoiceRecognition = false; 10497757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.e(TAG, "Timeout waiting for voice recognition to start"); 10507757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh sendURC("ERROR"); 10517757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10527757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 1053f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan case MESSAGE_CHECK_PENDING_SCO: 1054f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (mPendingSco && isA2dpMultiProfile()) { 1055f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Log.w(TAG, "Timeout suspending A2DP for SCO (mA2dpState = " + 1056f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState + "). Starting SCO anyway"); 1057f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mOutgoingSco = createScoSocket(); 1058819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh if (!(isHeadsetConnected() && 1059819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mOutgoingSco.connect(mHeadset.getRemoteDevice().getAddress(), 1060819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mHeadset.getRemoteDevice().getName()))) { 1061f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mOutgoingSco = null; 1062f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1063f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mPendingSco = false; 1064f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1065f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan break; 1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket createScoSocket() { 1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new ScoSocket(mPowerManager, mHandler, SCO_ACCEPTED, SCO_CONNECTED, SCO_CLOSED); 1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1075db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly private void broadcastAudioStateIntent(int state, BluetoothDevice device) { 10764079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project if (VDBG) log("broadcastAudioStateIntent(" + state + ")"); 107718e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 107818e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly intent.putExtra(BluetoothHeadset.EXTRA_AUDIO_STATE, state); 107918e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 10804079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH); 10814079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project } 10824079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project 10831498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek /* 10841498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * Put the AT command, company ID, arguments, and device in an Intent and broadcast it. 10851498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek */ 10861498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private void broadcastVendorSpecificEventIntent(String command, 10871498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek int companyId, 10881498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek Object[] arguments, 10891498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek BluetoothDevice device) { 10901498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek if (VDBG) log("broadcastVendorSpecificEventIntent(" + command + ")"); 10911498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek Intent intent = 10921498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek new Intent(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT); 10931498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD, command); 10941498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID, 10951498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek companyId); 10961498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 10971498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek // assert: all elements of args are Serializable 10981498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek intent.putExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS, arguments); 10991498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 11001498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH); 11011498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 11021498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 1103a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville void updateBtHandsfreeAfterRadioTechnologyChange() { 11041498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek if (VDBG) Log.d(TAG, "updateBtHandsfreeAfterRadioTechnologyChange..."); 1105a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 11061dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBtPhoneStateAfterRadioTechnologyChange(); 1107a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 1108a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to establish SCO (audio) connection to bluetooth 1110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 1111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns false if the user has requested audio off, or if there 1112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * is some other immediate problem that will prevent BT audio. 1113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean audioOn() { 1115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (VDBG) log("audioOn()"); 1116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isHeadsetConnected()) { 1117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): headset is not connected!"); 1118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 11200966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (mHeadsetType == TYPE_HANDSFREE && !mServiceConnectionEstablished) { 11210966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (DBG) log("audioOn(): service connection not yet established!"); 11220966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return false; 11230966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): audio is already connected"); 1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mUserWantsAudio) { 1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): user requested no audio, ignoring"); 1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 1136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): outgoing SCO already in progress"); 1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1139f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1140f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (mPendingSco) { 1141f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (DBG) log("audioOn(): SCO already pending"); 1142f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan return true; 1143f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1144f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1145ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 1146ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = false; 1147f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (isA2dpMultiProfile() && mA2dpState == BluetoothA2dp.STATE_PLAYING) { 1148f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (DBG) log("suspending A2DP stream for SCO"); 1149ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = mA2dp.suspendSink(mA2dpDevice); 1150ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 1151ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = true; 1152f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Message msg = mHandler.obtainMessage(MESSAGE_CHECK_PENDING_SCO); 1153f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mHandler.sendMessageDelayed(msg, 2000); 1154f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else { 1155f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Log.w(TAG, "Could not suspend A2DP stream for SCO, going ahead with SCO"); 1156337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly } 1157337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly } 1158337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly 1159337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly if (!mPendingSco) { 1160337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly mOutgoingSco = createScoSocket(); 1161f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen if (!mOutgoingSco.connect(mHeadset.getRemoteDevice().getAddress(), 1162f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getName())) { 1163337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly mOutgoingSco = null; 1164f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio on. 1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will establish SCO (BT audio), even if the user requested it off 1172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * previously on this call. 1173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOn() { 1175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 1176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio off. 1179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will prevent us from establishing BT audio again during this call 1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if audioOn() is called. 1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOff() { 1183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = false; 1184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to disconnect SCO (audio) connection to bluetooth 1188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 1189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void audioOff() { 1191819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh if (VDBG) log("audioOff(): mPendingSco: " + mPendingSco + 1192819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mConnectedSco: " + mConnectedSco + 1193819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mOutgoingSco: " + mOutgoingSco + 1194819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mA2dpState: " + mA2dpState + 1195819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mA2dpSuspended: " + mA2dpSuspended + 1196819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mIncomingSco:" + mIncomingSco); 1197ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent 1198ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 1199a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent if (isA2dpMultiProfile()) { 1200a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent if (DBG) log("resuming A2DP stream after disconnecting SCO"); 1201a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent mA2dp.resumeSink(mA2dpDevice); 1202a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent } 1203ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 1204ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent } 1205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1206310e6fb854504637a4cefd123d8dd387660cf811Nick Pelly mPendingSco = false; 1207310e6fb854504637a4cefd123d8dd387660cf811Nick Pelly 1208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 1209c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly BluetoothDevice device = null; 1210c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly if (mHeadset != null) { 1211c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly device = mHeadset.getRemoteDevice(); 1212c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly } 1213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco.close(); 1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = null; 12151b69b5d702539a74d1511d7467737eddc24b7744Nick Pelly mAudioManager.setBluetoothScoOn(false); 12161b69b5d702539a74d1511d7467737eddc24b7744Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED, device); 1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco.close(); 1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1222819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh 1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ boolean isAudioOn() { 1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (mConnectedSco != null); 1227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1229f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private boolean isA2dpMultiProfile() { 1230f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan return mA2dp != null && mHeadset != null && mA2dpDevice != null && 1231f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpDevice.equals(mHeadset.getRemoteDevice()); 1232f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1233f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void ignoreRing() { 12351dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.ignoreRing(); 1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void sendURC(String urc) { 1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isHeadsetConnected()) { 1240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset.sendURC(urc); 1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** helper to redial last dialled number */ 1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult redial() { 1246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = mPhonebook.getLastDialledNumber(); 1247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 1248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // spec seems to suggest sending ERROR if we dont have a 1249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // number to redial 12508eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Bluetooth redial requested (+BLDN), but no previous " + 1251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "outgoing calls found. Ignoring"); 1252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 1255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", number, null)); 1256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 1258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // We do not immediately respond OK, wait until we get a phone state 1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update. If we return OK now and the handsfree immeidately requests 1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // our phone state it will say we are not in call yet which confuses 1262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // some devices 1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Build the +CLCC result 1268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * The complexity arises from the fact that we need to maintain the same 1269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CLCC index even as a call moves between states. */ 1270c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private synchronized AtCommandResult gsmGetClccResult() { 1271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Collect all known connections 1272c9d9ed30aa547b79b81adc13a4d148a003b6ee62w Connection[] clccConnections = new Connection[GSM_MAX_CONNECTIONS]; // indexed by CLCC index 1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> newConnections = new LinkedList<Connection>(); 1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> connections = new LinkedList<Connection>(); 1275a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 12768058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call foregroundCall = mCM.getActiveFgCall(); 12778058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call backgroundCall = mCM.getFirstActiveBgCall(); 12788058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call ringingCall = mCM.getFirstActiveRingingCall(); 12798058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang 12808058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (ringingCall.getState().isAlive()) { 12818058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang connections.addAll(ringingCall.getConnections()); 1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 12838058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (foregroundCall.getState().isAlive()) { 12848058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang connections.addAll(foregroundCall.getConnections()); 1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 12868058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (backgroundCall.getState().isAlive()) { 12878058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang connections.addAll(backgroundCall.getConnections()); 1288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mark connections that we already known about 1291c9d9ed30aa547b79b81adc13a4d148a003b6ee62w boolean clccUsed[] = new boolean[GSM_MAX_CONNECTIONS]; 1292c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccUsed[i] = mClccUsed[i]; 1294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 1295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection c : connections) { 1297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean found = false; 1298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = c.getCreateTime(); 1299c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 1300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccUsed[i] && timestamp == mClccTimestamps[i]) { 1301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 1302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project found = true; 1303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = c; 1304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!found) { 1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.add(c); 1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find a CLCC index for new connections 1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!newConnections.isEmpty()) { 1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find lowest empty index 1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int i = 0; 1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (mClccUsed[i]) i++; 1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find earliest connection 1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long earliestTimestamp = newConnections.get(0).getCreateTime(); 1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection earliestConnection = newConnections.get(0); 1320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int j = 0; j < newConnections.size(); j++) { 1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = newConnections.get(j).getCreateTime(); 1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (timestamp < earliestTimestamp) { 1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestTimestamp = timestamp; 1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestConnection = newConnections.get(j); 1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update 1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccTimestamps[i] = earliestTimestamp; 1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = earliestConnection; 1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.remove(earliestConnection); 1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Build CLCC 1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < clccConnections.length; i++) { 1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mClccUsed[i]) { 1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String clccEntry = connectionToClccEntry(i, clccConnections[i]); 1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccEntry != null) { 1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(clccEntry); 1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Convert a Connection object into a single +CLCC result */ 1350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String connectionToClccEntry(int index, Connection c) { 1351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int state; 1352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c.getState()) { 1353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 1354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 0; 1355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 1357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 1; 1358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 1360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 2; 1361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 1363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 3; 1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 4; 1367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 1369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 5; 1370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; // bad state 1373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int mpty = 0; 1376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call call = c.getCall(); 1377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call != null) { 1378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mpty = call.isMultiparty() ? 1 : 0; 1379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int direction = c.isIncoming() ? 1 : 0; 1382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = -1; 1385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 1387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String result = "+CLCC: " + (index + 1) + "," + direction + "," + state + ",0," + mpty; 1390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result += ",\"" + number + "\"," + type; 1392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1395c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1396c9d9ed30aa547b79b81adc13a4d148a003b6ee62w /** Build the +CLCC result for CDMA 1397c9d9ed30aa547b79b81adc13a4d148a003b6ee62w * The complexity arises from the fact that we need to maintain the same 1398c9d9ed30aa547b79b81adc13a4d148a003b6ee62w * CLCC index even as a call moves between states. */ 1399c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private synchronized AtCommandResult cdmaGetClccResult() { 1400c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // In CDMA at one time a user can have only two live/active connections 1401c9d9ed30aa547b79b81adc13a4d148a003b6ee62w Connection[] clccConnections = new Connection[CDMA_MAX_CONNECTIONS];// indexed by CLCC index 14028058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call foregroundCall = mCM.getActiveFgCall(); 14038058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call ringingCall = mCM.getFirstActiveRingingCall(); 1404c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 14058058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call.State ringingCallState = ringingCall.getState(); 1406c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the Ringing Call state is INCOMING, that means this is the very first call 1407c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // hence there should not be any Foreground Call 1408c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (ringingCallState == Call.State.INCOMING) { 14098eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] for INCOMING state"); 14108058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[0] = ringingCall.getLatestConnection(); 14118058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang } else if (foregroundCall.getState().isAlive()) { 1412c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Getting Foreground Call connection based on Call state 14138058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (ringingCall.isRinging()) { 14148eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] & [1] for CALL WAITING state"); 14158058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[0] = foregroundCall.getEarliestConnection(); 14168058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[1] = ringingCall.getLatestConnection(); 1417c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 14188058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (foregroundCall.getConnections().size() <= 1) { 1419c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Single call scenario 14208eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] with ForgroundCall latest connection"); 14218058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[0] = foregroundCall.getLatestConnection(); 1422c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1423c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Multiple Call scenario. This would be true for both 1424c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CONF_CALL and THRWAY_ACTIVE state 14258eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] & [1] with ForgroundCall connections"); 14268058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[0] = foregroundCall.getEarliestConnection(); 14278058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang clccConnections[1] = foregroundCall.getLatestConnection(); 1428c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1429c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1430c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1431c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1432c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Update the mCdmaIsSecondCallActive flag based on the Phone call state 1433c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1434c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE) { 1435c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(false); 1436c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1437c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 1438c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1439c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1440c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1441c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Build CLCC 1442c9d9ed30aa547b79b81adc13a4d148a003b6ee62w AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 1443c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; (i < clccConnections.length) && (clccConnections[i] != null); i++) { 1444c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String clccEntry = cdmaConnectionToClccEntry(i, clccConnections[i]); 1445c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (clccEntry != null) { 1446c9d9ed30aa547b79b81adc13a4d148a003b6ee62w result.addResponse(clccEntry); 1447c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1448c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1449c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1450c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return result; 1451c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1452c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1453c9d9ed30aa547b79b81adc13a4d148a003b6ee62w /** Convert a Connection object into a single +CLCC result for CDMA phones */ 1454c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private String cdmaConnectionToClccEntry(int index, Connection c) { 1455c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int state; 1456c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneApp app = PhoneApp.getInstance(); 1457c9d9ed30aa547b79b81adc13a4d148a003b6ee62w CdmaPhoneCallState.PhoneCallState currCdmaCallState = 1458c9d9ed30aa547b79b81adc13a4d148a003b6ee62w app.cdmaPhoneCallState.getCurrentCallState(); 1459c9d9ed30aa547b79b81adc13a4d148a003b6ee62w CdmaPhoneCallState.PhoneCallState prevCdmaCallState = 1460c9d9ed30aa547b79b81adc13a4d148a003b6ee62w app.cdmaPhoneCallState.getPreviousCallState(); 1461c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1462c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if ((prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 1463c9d9ed30aa547b79b81adc13a4d148a003b6ee62w && (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL)) { 1464c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the current state is reached after merging two calls 1465c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // we set the state of all the connections as ACTIVE 1466c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 0; 1467c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1468c9d9ed30aa547b79b81adc13a4d148a003b6ee62w switch (c.getState()) { 1469c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case ACTIVE: 1470c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // For CDMA since both the connections are set as active by FW after accepting 1471c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // a Call waiting or making a 3 way call, we need to set the state specifically 1472c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // to ACTIVE/HOLDING based on the mCdmaIsSecondCallActive flag. This way the 1473c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CLCC result will allow BT devices to enable the swap or merge options 1474c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (index == 0) { // For the 1st active connection 1475c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = mCdmaIsSecondCallActive ? 1 : 0; 1476c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { // for the 2nd active connection 1477c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = mCdmaIsSecondCallActive ? 0 : 1; 1478c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1479c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1480c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case HOLDING: 1481c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 1; 1482c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1483c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case DIALING: 1484c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 2; 1485c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1486c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case ALERTING: 1487c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 3; 1488c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1489c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case INCOMING: 1490c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 4; 1491c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1492c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case WAITING: 1493c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 5; 1494c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1495c9d9ed30aa547b79b81adc13a4d148a003b6ee62w default: 1496c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return null; // bad state 1497c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1498c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1499c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1500c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int mpty = 0; 15013eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu if (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 1502c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi if (prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 1503c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // If the current state is reached after merging two calls 1504c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // we set the multiparty call true. 1505c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi mpty = 1; 1506c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi } else { 1507c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // CALL_CONF state is not from merging two calls, but from 1508c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // accepting the second call. In this case first will be on 1509c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // hold in most cases but in some cases its already merged. 1510c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // However, we will follow the common case and the test case 1511c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi // as per Bluetooth SIG PTS 1512c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi mpty = 0; 1513c39c3c9ada26aa8fab1373ad94c9b0d9e8875caaSrinivas Krovvidi } 15143eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu } else { 15153eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu mpty = 0; 1516c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1517c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1518c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int direction = c.isIncoming() ? 1 : 0; 1519c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1520c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String number = c.getAddress(); 1521c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int type = -1; 1522c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (number != null) { 1523c9d9ed30aa547b79b81adc13a4d148a003b6ee62w type = PhoneNumberUtils.toaFromString(number); 1524c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1525c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1526c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String result = "+CLCC: " + (index + 1) + "," + direction + "," + state + ",0," + mpty; 1527c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (number != null) { 1528c9d9ed30aa547b79b81adc13a4d148a003b6ee62w result += ",\"" + number + "\"," + type; 1529c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1530c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return result; 1531c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1532c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 15331498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek /* 15341498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * Register a vendor-specific command. 15351498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * @param commandName the name of the command. For example, if the expected 15361498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * incoming command is <code>AT+FOO=bar,baz</code>, the value of this should be 15371498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * <code>"+FOO"</code>. 15381498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * @param companyId the Bluetooth SIG Company Identifier 15391498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * @param parser the AtParser on which to register the command 15401498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek */ 15411498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private void registerVendorSpecificCommand(String commandName, 15421498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek int companyId, 15431498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek AtParser parser) { 15441498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek parser.register(commandName, 15451498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek new VendorSpecificCommandHandler(commandName, companyId)); 15461498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 15471498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 15481498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek /* 15491498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * Register all vendor-specific commands here. 15501498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek */ 15511498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private void registerAllVendorSpecificCommands() { 15521498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek AtParser parser = mHeadset.getAtParser(); 15531498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 15541498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek // Plantronics-specific headset events go here 15551498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek registerVendorSpecificCommand("+XEVENT", 15561498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek BluetoothAssignedNumbers.PLANTRONICS, 15571498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek parser); 15581498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 15591498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 1560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Headset profile 1562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHeadsetAtParser() { 15648eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Registering Headset AT commands"); 1565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 15661498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek // Headsets usually only have one button, which is meant to cause the 1567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HS to send us AT+CKPD=200 or AT+CKPD. 1568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CKPD", new AtCommandHandler() { 1569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult headsetButtonPress() { 15708058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (mCM.getFirstActiveRingingCall().isRinging()) { 1571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer the call 15721ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mBluetoothPhoneState.stopRing(); 15731ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh sendURC("OK"); 15748058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.answerCall(mCM.getFirstActiveRingingCall()); 1575a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly // If in-band ring tone is supported, SCO connection will already 1576a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly // be up and the following call will just return. 1577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 15781ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 15798058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang } else if (mCM.hasActiveFgCall()) { 1580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isAudioOn()) { 1581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Transfer audio from AG to HS 1582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1583b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset.getDirection() == HeadsetBase.DIRECTION_INCOMING && 1585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (System.currentTimeMillis() - mHeadset.getConnectTimestamp()) < 5000) { 1586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset made a recent ACL connection to us - and 1587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // made a mandatory AT+CKPD request to connect 1588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // audio which races with our automatic audio 1589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // setup. ignore 1590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang up the call 1592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 15938343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangup(PhoneApp.getInstance().mCM); 1594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 15961ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.OK); 1597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No current call - redial last number 1599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1604b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Handsfree profile 1615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHandsfreeAtParser() { 16178eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Registering Handsfree AT commands"); 1618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 16198058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang final Phone phone = mCM.getDefaultPhone(); 1620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer 1622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('A', new AtCommandHandler() { 1623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 16251ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh sendURC("OK"); 16261ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mBluetoothPhoneState.stopRing(); 16278058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.answerCall(mCM.getFirstActiveRingingCall()); 16281ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('D', new AtCommandHandler() { 1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length() > 0) { 1635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(0) == '>') { 1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Yuck - memory dialling requested. 1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Just dial last number for now 1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.startsWith(">9999")) { // for PTS test 1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Remove trailing ';' 1644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(args.length() - 1) == ';') { 1645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args = args.substring(0, args.length() - 1); 1646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 1648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", args, null)); 1649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 1651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 1653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 1654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1658b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1659b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang-up command 1661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHUP", new AtCommandHandler() { 1662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1664586668fe6a1259083fbbc67de8ecac850c1475f1Jaikumar Ganesh sendURC("OK"); 16658058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (mCM.hasActiveFgCall()) { 16668058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.hangupActiveCall(mCM.getActiveFgCall()); 16678058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang } else if (mCM.hasActiveRingingCall()) { 16688058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall()); 16698058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang } else if (mCM.hasActiveBgCall()) { 16708058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.hangupHoldingCall(mCM.getFirstActiveBgCall()); 1671b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1672586668fe6a1259083fbbc67de8ecac850c1475f1Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 1673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Retrieve Supported Features command 1677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BRSF", new AtCommandHandler() { 1678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult sendBRSF() { 1679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+BRSF: " + mLocalBrsf); 1680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+BRSF=<handsfree supported features bitmap> 1684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is telling us which features it supports. We 1685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // send the features we support 1686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 1 && (args[0] instanceof Integer)) { 1687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = (Integer) args[0]; 1688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1689b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "HF didn't sent BRSF assuming 0"); 1690b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1691b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1693b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1702b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting notification on/off 1706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CCWA", new AtCommandHandler() { 1707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Seems to be out of spec, but lets return nicely 1710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting is always on 1715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: 1"); 1716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1718b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CCWA=<n> 1720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is trying to enable/disable call waiting. We 1721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cannot disable in the current implementation. 1722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request for range of supported CCWA paramters 1727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: (\"n\",(1))"); 1728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Event Reporting enable/disable command 1732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Of the full 3GPP syntax paramters (mode, keyp, disp, ind, bfr) we 1733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only support paramter ind (disable/enable evert reporting using 1734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // +CDEV) 1735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMER", new AtCommandHandler() { 1736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+CMER: 3,0,0," + (mIndicatorsEnabled ? "1" : "0")); 1740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length < 4) { 1744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This is a syntax error 1745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3) && args[1].equals(0) && 1747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args[2].equals(0)) { 17480966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly boolean valid = false; 1749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[3].equals(0)) { 1750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 17510966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 1752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[3].equals(1)) { 1753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = true; 17540966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 17550966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 17560966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (valid) { 17570966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) == 0x0) { 17580966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 17590966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly sendURC("OK"); // send immediately, then initiate audio 17600966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 17610966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 1762179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi } else if (mCM.getFirstActiveRingingCall().isRinging()) { 1763179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi // need to update HS with RING cmd when single 1764179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi // ringing call exist 1765179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi mBluetoothPhoneState.ring(); 17660966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 17670966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // only send OK once 17680966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 17690966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } else { 17700966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.OK); 17710966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 1772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 17740966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 1775b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMER: (3),(0),(0),(0-1)"); 1779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Error Reporting enable/disable 1783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMEE", new AtCommandHandler() { 1784b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1786b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // out of spec, assume they want to enable 1787b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = true; 1788b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: " + (mCmee ? "1" : "0")); 1793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1796b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CMEE=<n> 1797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 0) { 1798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // <n> ommitted - default to 0 1799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 1800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!(args[0] instanceof Integer)) { 1802b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Syntax error 1803b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = ((Integer)args[0] == 1); 1806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Probably not required but spec, but no harm done 1812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: (0-1)"); 1813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Last Dialled Number 1817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BLDN", new AtCommandHandler() { 1818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Indicator Update command 1825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIND", new AtCommandHandler() { 1826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 18281dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCindResult(); 1829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 18321dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.getCindTestResult(); 1833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query Signal Quality (legacy) 1837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CSQ", new AtCommandHandler() { 1838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 18401dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCsqResult(); 1841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query network registration state 1845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CREG", new AtCommandHandler() { 1846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 18481dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return new AtCommandResult(mBluetoothPhoneState.toCregString()); 1849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Send DTMF. I don't know if we are also expected to play the DTMF tone 1853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // locally, right now we don't 1854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VTS", new AtCommandHandler() { 1855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project char c; 1859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0] instanceof Integer) { 1860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((Integer) args[0]).toString().charAt(0); 1861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((String) args[0]).charAt(0); 1863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isValidDtmf(c)) { 18658058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang phone.sendDtmf(c); 1866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1867b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1868b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1869b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1871b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isValidDtmf(char c) { 1872b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c) { 1873b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '#': 1874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '*': 1875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (Character.digit(c, 14) != -1) { 1878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; // 0-9 and A-D 1879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // List calls 1886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLCC", new AtCommandHandler() { 1887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1888b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 18898058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang int phoneType = phone.getPhoneType(); 189079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1891c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return cdmaGetClccResult(); 189279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 1893c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return gsmGetClccResult(); 189479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 189579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1896c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call Hold and Multiparty Handling command 1901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHLD", new AtCommandHandler() { 1902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 19048058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang int phoneType = phone.getPhoneType(); 19058058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call ringingCall = mCM.getFirstActiveRingingCall(); 19068058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang Call backgroundCall = mCM.getFirstActiveBgCall(); 19078058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang 1908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 1910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean result; 19118058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (ringingCall.isRinging()) { 19128058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang result = PhoneUtils.hangupRingingCall(ringingCall); 1913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 19148058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang result = PhoneUtils.hangupHoldingCall(backgroundCall); 1915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result) { 1917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 192279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 19238058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (ringingCall.isRinging()) { 1924c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If there is Call waiting then answer the call and 1925c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // put the first call on hold. 19268eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:1 Callwaiting Answer call"); 19278058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.answerCall(ringingCall); 1928a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang PhoneUtils.setMute(false); 1929c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Setting the second callers state flag to TRUE (i.e. active) 1930c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1931c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1932c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If there is no Call waiting then just hangup 1933c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // the active call. In CDMA this mean that the complete 1934c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // call session would be ended 19358eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:1 Hangup Call"); 19368343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangup(PhoneApp.getInstance().mCM); 1937c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 193979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 1940a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // Hangup active call, answer held call 19418343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (PhoneUtils.answerAndEndActive( 19428058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneApp.getInstance().mCM, ringingCall)) { 1943a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman return new AtCommandResult(AtCommandResult.OK); 1944a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } else { 1945a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman return new AtCommandResult(AtCommandResult.ERROR); 1946a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 194779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 194879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(2)) { 195179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1952a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // For CDMA, the way we switch to a new incoming call is by 1953a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // calling PhoneUtils.answerCall(). switchAndHoldActive() won't 1954a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // properly update the call state within telephony. 1955c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the Phone state is already in CONF_CALL then we simply send 1956c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // a flash cmd by calling switchHoldingAndActive() 19578058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (ringingCall.isRinging()) { 19588eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:2 Callwaiting Answer call"); 19598058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.answerCall(ringingCall); 1960a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang PhoneUtils.setMute(false); 1961c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Setting the second callers state flag to TRUE (i.e. active) 1962c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1963c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else if (PhoneApp.getInstance().cdmaPhoneCallState 1964c9d9ed30aa547b79b81adc13a4d148a003b6ee62w .getCurrentCallState() 1965c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 19668eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:2 Swap Calls"); 19678058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.switchHoldingAndActive(backgroundCall); 1968c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Toggle the second callers active state flag 1969c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSwapSecondCallState(); 1970c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 197179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 19728058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang PhoneUtils.switchHoldingAndActive(backgroundCall); 197379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 197479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1975a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 1976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3)) { 197879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1979c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // For CDMA, we need to check if the call is in THRWAY_ACTIVE state 1980c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1981c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 19828eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:3 Merge Calls"); 1983b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan PhoneUtils.mergeCalls(); 1984c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 198579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 19868058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang if (mCM.hasActiveFgCall() && mCM.hasActiveBgCall()) { 1987b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan PhoneUtils.mergeCalls(); 1988c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 198979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 199079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1998b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 19990966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 2000d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("+CHLD: (0,1,2,3)"); 2001d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("OK"); // send reply first, then connect audio 20020966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 20030966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 2004179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi } else if (mCM.getFirstActiveRingingCall().isRinging()) { 2005179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi // need to update HS with RING when single ringing call exist 2006179bbc0b646d7af4cb6662927c7a3e7a36332dedSrinivas Krovvidi mBluetoothPhoneState.ring(); 20070966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 20080966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // already replied 20090966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 2010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get Network operator name 2014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+COPS", new AtCommandHandler() { 2015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 20178058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang String operatorName = phone.getServiceState().getOperatorAlphaLong(); 2018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName != null) { 2019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName.length() > 16) { 2020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project operatorName = operatorName.substring(0, 16); 2021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 2023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+COPS: 0,0,\"" + operatorName + "\""); 2024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 20265b58955238953dd3c689b1d1342cb9d79ec3e9deJesper Hansson "+COPS: 0"); 2027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree only supports AT+COPS=3,0 2032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 2 || !(args[0] instanceof Integer) 2033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project || !(args[1] instanceof Integer)) { 2034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // syntax error 2035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if ((Integer)args[0] != 3 || (Integer)args[1] != 0) { 2037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 2038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 2044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Out of spec, but lets be friendly 2045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+COPS: (3),(0)"); 2046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile PIN 2050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CPIN is not in the handsfree spec (although it is in 3GPP) 2051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPIN", new AtCommandHandler() { 2052b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 2054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPIN: READY"); 2055b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2056b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2057b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Response and Hold 2059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Only supported on PDC (Japan) and CDMA networks. 2060b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BTRH", new AtCommandHandler() { 2061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2062b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 2063b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Replying with just OK indicates no response and hold 2064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // features in use now 2065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Neeed PDC or CDMA 2070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request International Mobile Subscriber Identity (IMSI) 2075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Not in bluetooth handset spec 2076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIMI", new AtCommandHandler() { 2077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CIMI 20808058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang String imsi = phone.getSubscriberId(); 2081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (imsi == null || imsi.length() == 0) { 2082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.SIM_FAILURE); 2083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(imsi); 2085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Calling Line Identification Presentation 2090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLIP", new AtCommandHandler() { 2091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 2093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Currently assumes the network is provisioned for CLIP 2094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: " + (mClip ? "1" : "0") + ",1"); 2095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CLIP=<n> 2099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && (args[0].equals(0) || args[0].equals(1))) { 2100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = args[0].equals(1); 2101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 2108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: (0-1)"); 2109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGSN - Returns the device IMEI number. 2113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGSN", new AtCommandHandler() { 2114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get the IMEI of the device. 21178058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang // phone will not be NULL at this point. 21188058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang return new AtCommandResult("+CGSN: " + phone.getDeviceId()); 2119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMM - Query Model Information 2123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMM", new AtCommandHandler() { 2124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 2127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String model = SystemProperties.get("ro.product.model"); 2128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (model != null) { 2129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMM: " + model); 2130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMI - Query Manufacturer Information 2137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMI", new AtCommandHandler() { 2138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 2141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String manuf = SystemProperties.get("ro.product.manufacturer"); 2142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (manuf != null) { 2143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMI: " + manuf); 2144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Noise Reduction and Echo Cancellation control 2151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+NREC", new AtCommandHandler() { 2152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 2155aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NREC+"=off"); 2156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 2158aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NREC+"=on"); 2159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Voice recognition (dialing) 2166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BVRA", new AtCommandHandler() { 2167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2169b8dbab241df3aa3487c1bdb488fd4e0b694d2d9aEric Laurent if (!BluetoothHeadset.isBluetoothVoiceDialingEnabled(mContext)) { 21706967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult(AtCommandResult.ERROR); 21716967e2d953bc077c99c4831946201f3d333b833fNick Pelly } 2172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && args[0].equals(1)) { 2173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project synchronized (BluetoothHandsfree.this) { 2174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mWaitingForVoiceRecognition) { 2175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 2176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(sVoiceCommandIntent); 2177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (ActivityNotFoundException e) { 2178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectVoiceRecognition(); 2181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing yet 2184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args.length >= 1 && args[0].equals(0)) { 2185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 21926967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult("+BVRA: (0-1)"); 2193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Retrieve Subscriber Number 2197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CNUM", new AtCommandHandler() { 2198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 22008058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang String number = phone.getLine1Number(); 2201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 2202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CNUM: ,\"" + number + "\"," + 2205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneNumberUtils.toaFromString(number) + ",,4"); 2206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Microphone Gain 2210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGM", new AtCommandHandler() { 2211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGM=<gain> in range [0,15] 2214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset/Handsfree is reporting its current gain setting 2215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Speaker Gain 2220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGS", new AtCommandHandler() { 2221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGS=<gain> in range [0,15] 2224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 1 || !(args[0] instanceof Integer)) { 2225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = (Integer) args[0]; 2228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int flag = mAudioManager.isBluetoothScoOn() ? AudioManager.FLAG_SHOW_UI:0; 2229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, mScoGain, flag); 2231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Phone activity status 2236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPAS", new AtCommandHandler() { 2237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int status = 0; 22408058bbc4c7d0d56e133bd2fb9dfc559004e4d61aJohn Wang switch (mCM.getState()) { 2241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case IDLE: 2242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 0; 2243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RINGING: 2245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 3; 2246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case OFFHOOK: 2248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 4; 2249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPAS: " + status); 2252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 22541498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 2255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook.register(parser); 2256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void sendScoGainUpdate(int gain) { 2259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mScoGain != gain && (mRemoteBrsf & BRSF_HF_REMOTE_VOL_CONTROL) != 0x0) { 2260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+VGS:" + gain); 2261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = gain; 2262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult reportCmeError(int error) { 2266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCmee) { 2267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 2268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CME ERROR: " + error); 2269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 2270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_CALL_TIMEOUT = 10000; // ms 2276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectCallStart() { 2278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = true; 2279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_CALL_STARTED); 2280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_CALL_TIMEOUT); 2281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartCallWakeLock.isHeld()) { 2282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.acquire(START_CALL_TIMEOUT); 2283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void callStarted() { 2287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForCallStart) { 2288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = false; 2289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 2290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartCallWakeLock.isHeld()) { 2291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.release(); 2292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_VOICE_RECOGNITION_TIMEOUT = 5000; // ms 2297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectVoiceRecognition() { 2299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = true; 2300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_VOICE_RECOGNITION_STARTED); 2301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_VOICE_RECOGNITION_TIMEOUT); 2302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartVoiceRecognitionWakeLock.isHeld()) { 2303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.acquire(START_VOICE_RECOGNITION_TIMEOUT); 2304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean startVoiceRecognition() { 2308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForVoiceRecognition) { 2309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HF initiated 2310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = false; 2311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 2312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AG initiated 2314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 1"); 2315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean ret = audioOn(); 2317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartVoiceRecognitionWakeLock.isHeld()) { 2318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.release(); 2319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return ret; 2321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean stopVoiceRecognition() { 2324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 0"); 2325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 2327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 23291498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek /* 23301498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek * This class broadcasts vendor-specific commands + arguments to interested receivers. 23311498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek */ 23321498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private class VendorSpecificCommandHandler extends AtCommandHandler { 23331498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 23341498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private String mCommandName; 23351498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 23361498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private int mCompanyId; 23371498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 23381498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek private VendorSpecificCommandHandler(String commandName, int companyId) { 23391498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek mCommandName = commandName; 23401498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek mCompanyId = companyId; 23411498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 23421498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 23431498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek @Override 23441498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek public AtCommandResult handleSetCommand(Object[] arguments) { 23451498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek broadcastVendorSpecificEventIntent(mCommandName, 23461498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek mCompanyId, 23471498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek arguments, 23481498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek mHeadset.getRemoteDevice()); 23491498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek return new AtCommandResult(AtCommandResult.OK); 23501498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 23511498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek } 23521498a77b9d76318817fe5a1e3a961070ead26fadHerb Jellinek 2353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean inDebug() { 2354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return DBG && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE, false); 2355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean allowAudioAnytime() { 2358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return inDebug() && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE_AUDIO_ANYTIME, 2359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project false); 2360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void startDebug() { 2363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG && mDebugThread == null) { 2364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = new DebugThread(); 2365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.start(); 2366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void stopDebug() { 2370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mDebugThread != null) { 2371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.interrupt(); 2372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = null; 2373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug thread to read debug properties - runs when debug.bt.hfp is true 2377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * at the time a bluetooth handsfree device is connected. Debug properties 2378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * are polled and mock updates sent every 1 second */ 2379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class DebugThread extends Thread { 2380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Turns on/off handsfree profile debugging mode */ 2381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE = "debug.bt.hfp"; 2382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock battery level change - use 0 to 5 */ 2384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_BATTERY = "debug.bt.hfp.battery"; 2385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock no cellular service when false */ 2387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SERVICE = "debug.bt.hfp.service"; 2388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock cellular roaming when true */ 2390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_ROAM = "debug.bt.hfp.roam"; 2391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** false to true transition will force an audio (SCO) connection to 2393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * be established. true to false will force audio to be disconnected 2394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO = "debug.bt.hfp.audio"; 2396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** true allows incoming SCO connection out of call. 2398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO_ANYTIME = "debug.bt.hfp.audio_anytime"; 2400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock signal strength change in ASU - use 0 to 31 */ 2402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SIGNAL = "debug.bt.hfp.signal"; 2403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+CLCC: print +CLCC result */ 2405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_CLCC = "debug.bt.hfp.clcc"; 2406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2407b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+BSIR - Send In Band Ringtones Unsolicited AT command. 2408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 0 => AT+BSIR = 0 sent by the AG 2409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 1 => AT+BSIR = 0 sent by the AG 2410b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Other values are ignored. 2411b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_UNSOL_INBAND_RINGTONE = 2414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "debug.bt.unsol.inband"; 2415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2417b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void run() { 2418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldService = true; 2419b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldRoam = false; 2420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldAudio = false; 2421b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2422b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!isInterrupted() && inDebug()) { 2423b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = SystemProperties.getInt(DEBUG_HANDSFREE_BATTERY, -1); 2424b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel >= 0 && batteryLevel <= 5) { 2425b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 2426b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("level", batteryLevel); 2427b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("scale", 5); 24281dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBatteryState(intent); 2429b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2430b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2431b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean serviceStateChanged = false; 2432b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_SERVICE, true) != oldService) { 2433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldService = !oldService; 2434b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 2435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2436b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_ROAM, false) != oldRoam) { 2437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldRoam = !oldRoam; 2438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 2439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (serviceStateChanged) { 2441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Bundle b = new Bundle(); 2442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putInt("state", oldService ? 0 : 1); 2443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putBoolean("roaming", oldRoam); 24441dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateServiceState(true, ServiceState.newFromBundle(b)); 2445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_AUDIO, false) != oldAudio) { 2448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldAudio = !oldAudio; 2449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (oldAudio) { 2450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 2451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signalLevel = SystemProperties.getInt(DEBUG_HANDSFREE_SIGNAL, -1); 2457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (signalLevel >= 0 && signalLevel <= 31) { 2458404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = new SignalStrength(signalLevel, -1, -1, -1, 2459404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville -1, -1, -1, true); 2460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 2461404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Bundle data = new Bundle(); 2462404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signalStrength.fillInNotifierBundle(data); 2463404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville intent.putExtras(data); 24641dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateSignalState(intent); 2465b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_CLCC, false)) { 2468c9d9ed30aa547b79b81adc13a4d148a003b6ee62w log(gsmGetClccResult().toString()); 2469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 2471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sleep(1000); // 1 second 2472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (InterruptedException e) { 2473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int inBandRing = 2477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SystemProperties.getInt(DEBUG_UNSOL_INBAND_RINGTONE, -1); 2478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (inBandRing == 0 || inBandRing == 1) { 2479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = 2480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new AtCommandResult(AtCommandResult.UNSOLICITED); 2481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+BSIR: " + inBandRing); 2482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 2483b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2487b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2488c9d9ed30aa547b79b81adc13a4d148a003b6ee62w public void cdmaSwapSecondCallState() { 24898eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("cdmaSetSecondCallState: Toggling mCdmaIsSecondCallActive"); 2490c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mCdmaIsSecondCallActive = !mCdmaIsSecondCallActive; 2491c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 2492c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 2493c9d9ed30aa547b79b81adc13a4d148a003b6ee62w public void cdmaSetSecondCallState(boolean state) { 24948eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("cdmaSetSecondCallState: Setting mCdmaIsSecondCallActive to " + state); 2495c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mCdmaIsSecondCallActive = state; 2496c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 2497c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 2498b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 2499b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.d(TAG, msg); 2500b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2501b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 2502