BluetoothHandsfree.java revision b045b9344f339170d134cf814357361d96c349cf
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; 23db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pellyimport android.bluetooth.BluetoothAdapter; 24b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 254079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.HeadsetBase; 27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.ScoSocket; 28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.ActivityNotFoundException; 29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.BroadcastReceiver; 30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Intent; 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.IntentFilter; 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.AudioManager; 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri; 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult; 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Bundle; 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message; 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager.WakeLock; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.SystemProperties; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.ServiceState; 44404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.telephony.SignalStrength; 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Call; 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Connection; 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Phone; 50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.TelephonyIntents; 51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 52b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.LinkedList; 53f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 55b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Bluetooth headset manager for the Phone app. 56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @hide 57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 58b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class BluetoothHandsfree { 59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String TAG = "BT HS/HF"; 608eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 1) 618eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan && (SystemProperties.getInt("ro.debuggable", 0) == 1); 628eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan private static final boolean VDBG = (PhoneApp.DBG_LEVEL >= 2); // even more logging 63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_UNKNOWN = 0; 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HEADSET = 1; 66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HANDSFREE = 2; 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 684079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private final Context mContext; 694079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private final Phone mPhone; 70f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private final BluetoothA2dp mA2dp; 71f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 72f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private BluetoothDevice mA2dpDevice; 73f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private int mA2dpState; 74f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 75b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ServiceState mServiceState; 76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private HeadsetBase mHeadset; // null when not connected 77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mHeadsetType; 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mAudioPossible; 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mIncomingSco; 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mOutgoingSco; 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mConnectedSco; 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mForegroundCall; 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mBackgroundCall; 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mRingingCall; 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AudioManager mAudioManager; 88b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private PowerManager mPowerManager; 89b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 90f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private boolean mPendingSco; // waiting for a2dp sink to suspend before establishing SCO 91ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent private boolean mA2dpSuspended; 92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mUserWantsAudio; 93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartCallWakeLock; // held while waiting for the intent to start call 94b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartVoiceRecognitionWakeLock; // held while waiting for voice recognition 95b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 96b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT command state 97c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private static final int GSM_MAX_CONNECTIONS = 6; // Max connections allowed by GSM 98c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private static final int CDMA_MAX_CONNECTIONS = 2; // Max connections allowed by CDMA 99b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long mBgndEarliestConnectionTime = 0; 101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mClip = false; // Calling Line Information Presentation 102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIndicatorsEnabled = false; 103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mCmee = false; // Extended Error reporting 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long[] mClccTimestamps; // Timestamps associated with each clcc index 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean[] mClccUsed; // Is this clcc index in use 106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForCallStart; 107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForVoiceRecognition; 1080966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // do not connect audio until service connection is established 1090966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for 3-way supported devices, this is after AT+CHLD 1100966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for non-3-way supported devices, this is after AT+CMER (see spec) 1110966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly private boolean mServiceConnectionEstablished; 112db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly 1131dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private final BluetoothPhoneState mBluetoothPhoneState; // for CIND and CIEV updates 114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BluetoothAtPhonebook mPhonebook; 1151dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private Phone.State mPhoneState = Phone.State.IDLE; 116487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState mCdmaThreeWayCallState = 117487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.IDLE; 118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private DebugThread mDebugThread; 120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mScoGain = Integer.MIN_VALUE; 121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static Intent sVoiceCommandIntent; 123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Audio parameters 125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NREC = "bt_headset_nrec"; 126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NAME = "bt_headset_name"; 127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRemoteBrsf = 0; 129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mLocalBrsf = 0; 130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 131c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CDMA specific flag used in context with BT devices having display capabilities 132c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // to show which Caller is active. This state might not be always true as in CDMA 133c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // networks if a caller drops off no update is provided to the Phone. 134c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // This flag is just used as a toggle to provide a update to the BT device to specify 135c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // which caller is active. 136c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private boolean mCdmaIsSecondCallActive = false; 137c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Constants from Bluetooth Specification Hands-Free profile version 1.5 */ 1396967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_THREE_WAY_CALLING = 1 << 0; 1406967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_EC_NR = 1 << 1; 1416967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_RECOG = 1 << 2; 1426967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_IN_BAND_RING = 1 << 3; 1436967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_TAG_NUMBE = 1 << 4; 1446967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_REJECT_CALL = 1 << 5; 1456967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_STATUS = 1 << 6; 1466967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_CONTROL = 1 << 7; 1476967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_ERR_RESULT_CODES = 1 << 8; 1486967e2d953bc077c99c4831946201f3d333b833fNick Pelly 1496967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_EC_NR = 1 << 0; 1506967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CW_THREE_WAY_CALLING = 1 << 1; 1516967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CLIP = 1 << 2; 1526967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_VOICE_REG_ACT = 1 << 3; 1536967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_REMOTE_VOL_CONTROL = 1 << 4; 1546967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_STATUS = 1 << 5; 1556967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_CONTROL = 1 << 6; 156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static String typeToString(int type) { 158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (type) { 159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_UNKNOWN: 160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "unknown"; 161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HEADSET: 162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "headset"; 163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HANDSFREE: 164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "handsfree"; 165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public BluetoothHandsfree(Context context, Phone phone) { 170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone = phone; 171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext = context; 172cec56587c1d3c90014848d7adfe817bef9c325eaNick Pelly BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 173db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly boolean bluetoothCapable = (adapter != null); 174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; // nothing connected yet 175f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dp = new BluetoothA2dp(mContext); 176f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState = BluetoothA2dp.STATE_DISCONNECTED; 177f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpDevice = null; 178ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":StartCall"); 183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.setReferenceCounted(false); 184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":VoiceRecognition"); 186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.setReferenceCounted(false); 187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf = BRSF_AG_THREE_WAY_CALLING | 189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_EC_NR | 190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_REJECT_CALL | 191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_ENHANCED_CALL_STATUS; 1924b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project 193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sVoiceCommandIntent == null) { 194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND); 195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1976967e2d953bc077c99c4831946201f3d333b833fNick Pelly if (mContext.getPackageManager().resolveActivity(sVoiceCommandIntent, 0) != null && 198b8dbab241df3aa3487c1bdb488fd4e0b694d2d9aEric Laurent BluetoothHeadset.isBluetoothVoiceDialingEnabled(mContext)) { 199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf |= BRSF_AG_VOICE_RECOG; 200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (bluetoothCapable) { 203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project resetAtState(); 204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingCall = mPhone.getRingingCall(); 207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mForegroundCall = mPhone.getForegroundCall(); 208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBackgroundCall = mPhone.getBackgroundCall(); 2091dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState = new BluetoothPhoneState(); 210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook = new BluetoothAtPhonebook(mContext, this); 212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 213c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(false); 214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothEnabled() { 217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Bluez has a bug where it will always accept and then orphan 218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * incoming SCO connections, regardless of whether we have a listening 219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * SCO socket. So the best thing to do is always run a listening socket 220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * while bluetooth is on so that at least we can diconnect it 221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * immediately when we don't want it. 222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco == null) { 224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = createScoSocket(); 225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.accept(); 226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothDisabled() { 230a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent audioOff(); 231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco != null) { 232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.close(); 233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = null; 234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isHeadsetConnected() { 238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset == null) { 239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return mHeadset.isConnected(); 242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 244f6adf1a33b12c9900b3ce9c15130642ce515ae91Jaikumar Ganesh /* package */ synchronized void connectHeadset(HeadsetBase headset, int headsetType) { 245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = headset; 246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadsetType = headsetType; 247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadsetType == TYPE_HEADSET) { 248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHeadsetAtParser(); 249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHandsfreeAtParser(); 251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 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(); 261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* returns true if there is some kind of in-call audio we may wish to route 265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth to */ 266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isIncallAudio() { 267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call.State state = mForegroundCall.getState(); 268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (state == Call.State.ACTIVE || state == Call.State.ALERTING); 270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 272819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh /* package */ synchronized void disconnectHeadset() { 273819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh // Close off the SCO sockets 274819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh audioOff(); 275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; 276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stopDebug(); 277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project resetAtState(); 278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 280bfc44512504ebc93c101ddb394719840f2d25072Jaikumar Ganesh /* package */ synchronized void resetAtState() { 281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = false; 282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 2830966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = false; 284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 285c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mClccTimestamps = new long[GSM_MAX_CONNECTIONS]; 286c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mClccUsed = new boolean[GSM_MAX_CONNECTIONS]; 287c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = 0; 291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void configAudioParameters() { 294db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly String name = mHeadset.getRemoteDevice().getName(); 295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (name == null) { 296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project name = "<unknown>"; 297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 298aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NAME+"="+name+";"+HEADSET_NREC+"=on"); 299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Represents the data that we send in a +CIND or +CIEV command to the HF 303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class BluetoothPhoneState { 305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no service 306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: service 307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mService; 308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no active call 310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: active call (where active means audio is routed - not held call) 311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCall; 312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not in call setup 314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: incoming call setup 315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: outgoing call setup 316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3: remote party being alerted in an outgoing call setup 317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallsetup; 318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no calls held 320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: held call and active call 321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: held call only 322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallheld; 323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength of AG: 0-5 325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mSignal; 326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength in CSQ rssi scale 328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRssi; // for CSQ 329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: roaming not active (home) 331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: roaming active 332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRoam; 333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // battery charge of AG: 0-5 335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mBattchg; 336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not registered 338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: registered, home network 339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 5: registered, roaming 340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mStat; // for CREG 341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String mRingingNumber; // Context for in-progress RING's 343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRingingType; 344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIgnoreRing = false; 3451ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh private boolean mStopRing = false; 346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SERVICE_STATE_CHANGED = 1; 348487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private static final int PRECISE_CALL_STATE_CHANGED = 2; 349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int RING = 3; 350a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman private static final int PHONE_CDMA_CALL_WAITING = 4; 351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Handler mStateChangeHandler = new Handler() { 353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void handleMessage(Message msg) { 355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(msg.what) { 356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RING: 357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = ring(); 358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result != null) { 359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SERVICE_STATE_CHANGED: 363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateServiceState(sendUpdate(), state); 365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 366487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh case PRECISE_CALL_STATE_CHANGED: 367a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman case PHONE_CDMA_CALL_WAITING: 368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection connection = null; 369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (((AsyncResult) msg.obj).result instanceof Connection) { 370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connection = (Connection) ((AsyncResult) msg.obj).result; 371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 372487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh handlePreciseCallStateChange(sendUpdate(), connection); 373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private BluetoothPhoneState() { 379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // init members 380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateServiceState(false, mPhone.getServiceState()); 381487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh handlePreciseCallStateChange(false, null); 382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = 5; // There is currently no API to get battery level 383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // on demand, so set to 5 and wait for an update 384404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mSignal = asuToSignal(mPhone.getSignalStrength()); 385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // register for updates 387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone.registerForServiceStateChanged(mStateChangeHandler, 388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SERVICE_STATE_CHANGED, null); 38919dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh mPhone.registerForPreciseCallStateChanged(mStateChangeHandler, 390487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh PRECISE_CALL_STATE_CHANGED, null); 39179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 392a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman mPhone.registerForCallWaiting(mStateChangeHandler, 393a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman PHONE_CDMA_CALL_WAITING, null); 394a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project filter.addAction(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); 397f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan filter.addAction(BluetoothA2dp.ACTION_SINK_STATE_CHANGED); 398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.registerReceiver(mStateReceiver, filter); 399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 401a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville private void updateBtPhoneStateAfterRadioTechnologyChange() { 4028eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if(VDBG) Log.d(TAG, "updateBtPhoneStateAfterRadioTechnologyChange..."); 403a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 404a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Unregister all events from the old obsolete phone 405a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mPhone.unregisterForServiceStateChanged(mStateChangeHandler); 40619dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh mPhone.unregisterForPreciseCallStateChanged(mStateChangeHandler); 407a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman mPhone.unregisterForCallWaiting(mStateChangeHandler); 408a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 409a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Register all events new to the new active phone 41019dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh mPhone.registerForServiceStateChanged(mStateChangeHandler, 41119dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh SERVICE_STATE_CHANGED, null); 41219dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh mPhone.registerForPreciseCallStateChanged(mStateChangeHandler, 413487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh PRECISE_CALL_STATE_CHANGED, null); 41479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 415a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman mPhone.registerForCallWaiting(mStateChangeHandler, 416a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman PHONE_CDMA_CALL_WAITING, null); 417a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 418a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 419a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendUpdate() { 421b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mIndicatorsEnabled; 422b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 423b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 424b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendClipUpdate() { 425b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mClip; 426b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 427b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4281ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh private void stopRing() { 4291ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mStopRing = true; 4301ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh } 4311ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh 432b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,31] ASU signal strength to the [0,5] expected by 433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth devices. Scale is similar to status bar policy 434b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 43534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh private int gsmAsuToSignal(SignalStrength signalStrength) { 43634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int asu = signalStrength.getGsmSignalStrength(); 437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (asu >= 16) return 5; 438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 8) return 4; 439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 4) return 3; 440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 2) return 2; 441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 1) return 1; 442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else return 0; 443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 44534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh /** 44634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * Convert the cdma / evdo db levels to appropriate icon level. 44734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * The scale is similar to the one used in status bar policy. 44834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * 44934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * @param signalStrength 45034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh * @return the icon level 451404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville */ 45234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh private int cdmaDbmEcioToSignal(SignalStrength signalStrength) { 45334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelDbm = 0; 45434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEcio = 0; 45534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaIconLevel = 0; 45634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoIconLevel = 0; 45734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaDbm = signalStrength.getCdmaDbm(); 45834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int cdmaEcio = signalStrength.getCdmaEcio(); 45934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 46034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (cdmaDbm >= -75) levelDbm = 4; 46134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -85) levelDbm = 3; 46234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -95) levelDbm = 2; 46334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaDbm >= -100) levelDbm = 1; 46434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelDbm = 0; 46534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 46634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // Ec/Io are in dB*10 46734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (cdmaEcio >= -90) levelEcio = 4; 46834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -110) levelEcio = 3; 46934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -130) levelEcio = 2; 47034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (cdmaEcio >= -150) levelEcio = 1; 47134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEcio = 0; 47234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 47334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh cdmaIconLevel = (levelDbm < levelEcio) ? levelDbm : levelEcio; 47434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 47513df4bba7e39d516317d005b4b917b1f1c6baf8dJaikumar Ganesh if (mServiceState != null && 476b1164d370e8d83a8a4f3cbdc73dffc087254cabdJaikumar Ganesh (mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_0 || 477b1164d370e8d83a8a4f3cbdc73dffc087254cabdJaikumar Ganesh mServiceState.getRadioTechnology() == ServiceState.RADIO_TECHNOLOGY_EVDO_A)) { 47834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoEcio = signalStrength.getEvdoEcio(); 47934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int evdoSnr = signalStrength.getEvdoSnr(); 48034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEvdoEcio = 0; 48134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh int levelEvdoSnr = 0; 48234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 48334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // Ec/Io are in dB*10 48434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (evdoEcio >= -650) levelEvdoEcio = 4; 48534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -750) levelEvdoEcio = 3; 48634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -900) levelEvdoEcio = 2; 48734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoEcio >= -1050) levelEvdoEcio = 1; 48834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEvdoEcio = 0; 48934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 49034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (evdoSnr > 7) levelEvdoSnr = 4; 49134b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 5) levelEvdoSnr = 3; 49234b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 3) levelEvdoSnr = 2; 49334b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else if (evdoSnr > 1) levelEvdoSnr = 1; 49434b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh else levelEvdoSnr = 0; 49534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 49634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh evdoIconLevel = (levelEvdoEcio < levelEvdoSnr) ? levelEvdoEcio : levelEvdoSnr; 49734b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh } 49834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh // TODO(): There is a bug open regarding what should be sent. 49934b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return (cdmaIconLevel > evdoIconLevel) ? cdmaIconLevel : evdoIconLevel; 50034b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh 501404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 502404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 503404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 504404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville private int asuToSignal(SignalStrength signalStrength) { 50534b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh if (signalStrength.isGsm()) { 50634b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return gsmAsuToSignal(signalStrength); 507404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 50834b9266fbd8c9c4d52e8faf708e02037a7ddcc4cJaikumar Ganesh return cdmaDbmEcioToSignal(signalStrength); 509404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 510404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 511404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 512404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,5] signal strength to a rssi signal strength for CSQ 514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * which is [0,31]. Despite the same scale, this is not the same value 515b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * as ASU. 516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int signalToRssi(int signal) { 518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // using C4A suggested values 519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (signal) { 520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 0: return 0; 521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 1: return 4; 522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 2: return 8; 523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 3: return 13; 524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 4: return 19; 525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 5: return 31; 526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return 0; 528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 529b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 530b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() { 532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void onReceive(Context context, Intent intent) { 534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { 535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateBatteryState(intent); 536f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else if (intent.getAction().equals( 537f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED)) { 538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateSignalState(intent); 539f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else if (intent.getAction().equals(BluetoothA2dp.ACTION_SINK_STATE_CHANGED)) { 540f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan int state = intent.getIntExtra(BluetoothA2dp.EXTRA_SINK_STATE, 541f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothA2dp.STATE_DISCONNECTED); 542f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan int oldState = intent.getIntExtra(BluetoothA2dp.EXTRA_PREVIOUS_SINK_STATE, 543f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothA2dp.STATE_DISCONNECTED); 544f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan BluetoothDevice device = 545f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 546105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh 547105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh // We are only concerned about Connected sinks to suspend and resume 548105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh // them. We can safely ignore SINK_STATE_CHANGE for other devices. 549105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh if (mA2dpDevice != null && !device.equals(mA2dpDevice)) return; 550105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh 551f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan synchronized (BluetoothHandsfree.this) { 552f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState = state; 553105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh if (state == BluetoothA2dp.STATE_DISCONNECTED) { 554105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh mA2dpDevice = null; 555105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh } else { 556105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh mA2dpDevice = device; 557105bb2145aba70c03b43bfab906c1b0551387309Jaikumar Ganesh } 558ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (oldState == BluetoothA2dp.STATE_PLAYING && 559ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpState == BluetoothA2dp.STATE_CONNECTED) { 560ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 561ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mPendingSco) { 562ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mHandler.removeMessages(MESSAGE_CHECK_PENDING_SCO); 563ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (DBG) log("A2DP suspended, completing SCO"); 564ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mOutgoingSco = createScoSocket(); 565ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (!mOutgoingSco.connect( 566f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getAddress(), 567f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getName())) { 568ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mOutgoingSco = null; 569ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent } 570ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = false; 571f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 572f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 573f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 574f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateBatteryState(Intent intent) { 580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = intent.getIntExtra("level", -1); 581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int scale = intent.getIntExtra("scale", -1); 582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel == -1 || scale == -1) { 583b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; // ignore 584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project batteryLevel = batteryLevel * 5 / scale; 586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mBattchg != batteryLevel) { 587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = batteryLevel; 588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 7," + mBattchg); 590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateSignalState(Intent intent) { 595404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // NOTE this function is called by the BroadcastReceiver mStateReceiver after intent 596404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // ACTION_SIGNAL_STRENGTH_CHANGED and by the DebugThread mDebugThread 597404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = SignalStrength.newFromBundle(intent.getExtras()); 598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signal; 599404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 600404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signalStrength != null) { 601404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signal = asuToSignal(signalStrength); 602404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mRssi = signalToRssi(signal); // no unsolicited CSQ 603404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signal != mSignal) { 604404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mSignal = signal; 605404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (sendUpdate()) { 606404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville sendURC("+CIEV: 5," + mSignal); 607404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 609404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 610404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Log.e(TAG, "Signal Strength null"); 611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateServiceState(boolean sendUpdate, ServiceState state) { 615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int service = state.getState() == ServiceState.STATE_IN_SERVICE ? 1 : 0; 616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int roam = state.getRoaming() ? 1 : 0; 617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int stat; 618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 61913df4bba7e39d516317d005b4b917b1f1c6baf8dJaikumar Ganesh mServiceState = state; 620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service == 0) { 621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = 0; 622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = (roam == 1) ? 5 : 1; 624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service != mService) { 627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mService = service; 628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 1," + mService); 630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (roam != mRoam) { 633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRoam = roam; 634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 6," + mRoam); 636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (stat != mStat) { 639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStat = stat; 640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(toCregString()); 642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 648487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private synchronized void handlePreciseCallStateChange(boolean sendUpdate, 649487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh Connection connection) { 650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int call = 0; 651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callsetup = 0; 652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callheld = 0; 653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int prevCallsetup = mCallsetup; 654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 6568eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("updatePhoneState()"); 657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 658487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // This function will get called when the Precise Call State 659487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // {@link Call.State} changes. Hence, we might get this update 660487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // even if the {@link Phone.state} is same as before. 661487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Check for the same. 662487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 6631dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh Phone.State newState = mPhone.getState(); 6641dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh if (newState != mPhoneState) { 6651dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mPhoneState = newState; 6661dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh switch (mPhoneState) { 6671dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh case IDLE: 6681dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mUserWantsAudio = true; // out of call - reset state 6691dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh audioOff(); 6701dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh break; 6711dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh default: 6721dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh callStarted(); 6731dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh } 674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mForegroundCall.getState()) { 677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 2; 683a41427328932deb7cbadf586a1ec58e0ba26a932Jaikumar Ganesh mAudioPossible = true; 6843904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // We also need to send a Call started indication 6853904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // for cases where the 2nd MO was initiated was 6863904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // from a *BT hands free* and is waiting for a 6873904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // +BLND: OK response 6883904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // There is a special case handling of the same case 6893904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh // for CDMA below 6903904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh if (mPhone.getPhoneType() == Phone.PHONE_TYPE_GSM) { 6913904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh callStarted(); 6923904e979ce9a501acbe6d8739393767a495388e8Jaikumar Ganesh } 693b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 3; 696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Open the SCO channel for the outgoing call. 697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 70081a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 70181a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 70281a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 70381a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 70481a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 70581a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 70681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = false; 709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mRingingCall.getState()) { 712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 1; 715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 71681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 71781a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 71881a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 71981a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 72081a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 72181a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 72281a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mBackgroundCall.getState()) { 726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 1; 729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 2; 732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 73481a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh case DISCONNECTING: 73581a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // This is a transient state, we don't want to send 73681a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh // any AT commands during this state. 73781a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh call = mCall; 73881a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callsetup = mCallsetup; 73981a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh callheld = mCallheld; 74081a26f368128024620b0dc7b0eb32debf3fe3419Jaikumar Ganesh break; 741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCall != call) { 744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This means that a call has transitioned from NOT ACTIVE to ACTIVE. 746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Switch on audio. 747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 748b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCall = call; 750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 2," + mCall); 752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallsetup != callsetup) { 755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = callsetup; 756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 7574b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // If mCall = 0, send CIEV 7584b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 0, send CIEV 7594b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 1, send CIEV after CCWA, 7604b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way supported. 7614b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 2 / 3 -> send CIEV, 7624b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way is supported 7634b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project if (mCall != 1 || mCallsetup == 0 || 7644b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project mCallsetup != 1 && (mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 3," + mCallsetup); 766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 77079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (mPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 771c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneApp app = PhoneApp.getInstance(); 77260877272381161201c6969dea501e683705d6e32w if (app.cdmaPhoneCallState != null) { 773487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState currCdmaThreeWayCallState = 77460877272381161201c6969dea501e683705d6e32w app.cdmaPhoneCallState.getCurrentCallState(); 775487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState prevCdmaThreeWayCallState = 776ed1d155825eb32990fde95eef9d89a7260e4c3f1w app.cdmaPhoneCallState.getPreviousCallState(); 777ed1d155825eb32990fde95eef9d89a7260e4c3f1w 778487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = getCdmaCallHeldStatus(currCdmaThreeWayCallState, 779487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh prevCdmaThreeWayCallState); 780487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 781487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (mCdmaThreeWayCallState != currCdmaThreeWayCallState) { 782487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // In CDMA, the network does not provide any feedback 783487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // to the phone when the 2nd MO call goes through the 784487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // stages of DIALING > ALERTING -> ACTIVE we fake the 785487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // sequence 786487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((currCdmaThreeWayCallState == 787487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 788487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh && app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()) { 789487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mAudioPossible = true; 790487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (sendUpdate) { 791487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 792487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,2"); 793487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,3"); 794487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,0"); 795487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 79660877272381161201c6969dea501e683705d6e32w } 797487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // We also need to send a Call started indication 798487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // for cases where the 2nd MO was initiated was 799487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // from a *BT hands free* and is waiting for a 800487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // +BLND: OK response 801487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callStarted(); 802c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 803c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 804487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // In CDMA, the network does not provide any feedback to 805487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // the phone when a user merges a 3way call or swaps 806487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // between two calls we need to send a CIEV response 807487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // indicating that a call state got changed which should 808487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // trigger a CLCC update request from the BT client. 809487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (currCdmaThreeWayCallState == 810487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 811487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mAudioPossible = true; 812487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (sendUpdate) { 813487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 814487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 2,1"); 815487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh result.addResponse("+CIEV: 3,0"); 816487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 81760877272381161201c6969dea501e683705d6e32w } 818c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 819c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 820487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh mCdmaThreeWayCallState = currCdmaThreeWayCallState; 821c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 822c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 823c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean callsSwitched = 825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (callheld == 1 && ! (mBackgroundCall.getEarliestConnectTime() == 826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBgndEarliestConnectionTime)); 827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 828b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBgndEarliestConnectionTime = mBackgroundCall.getEarliestConnectTime(); 829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallheld != callheld || callsSwitched) { 831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld = callheld; 832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 4," + mCallheld); 834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (callsetup == 1 && callsetup != prevCallsetup) { 838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // new incoming call 839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = null; 840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = 128; 841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // find incoming phone number and type 842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connection = mRingingCall.getEarliestConnection(); 844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Could not get a handle on Connection object for new " + 846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "incoming call"); 847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 848b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection != null) { 850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = connection.getAddress(); 851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = ""; 857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((call != 0 || callheld != 0) && sendUpdate) { 859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // call waiting 860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CCWA: \"" + number + "\"," + type); 8624b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project result.addResponse("+CIEV: 3," + callsetup); 863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // regular new incoming call 866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingNumber = number; 867b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingType = type; 868b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = false; 8691ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mStopRing = false; 870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 871a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly if ((mLocalBrsf & BRSF_AG_IN_BAND_RING) != 0x0) { 872a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly audioOn(); 873a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly } 874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResult(ring()); 875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 880487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh private int getCdmaCallHeldStatus(CdmaPhoneCallState.PhoneCallState currState, 881487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState prevState) { 882487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh int callheld; 883487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Update the Call held information 884487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (currState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 885487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh if (prevState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 886487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 0; //0: no calls held, as now *both* the caller are active 887487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else { 888487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 1; //1: held call and active call, as on answering a 889487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // Call Waiting, one of the caller *is* put on hold 890487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 891487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else if (currState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 892487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 1; //1: held call and active call, as on make a 3 Way Call 893487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh // the first caller *is* put on hold 894487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } else { 895487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh callheld = 0; //0: no calls held as this is a SINGLE_ACTIVE call 896487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 897487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh return callheld; 898487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh } 899487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 900487f0e7aa6b2db7212e76713199d4812a61c4625Jaikumar Ganesh 901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult ring() { 9021ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh if (!mIgnoreRing && !mStopRing && mRingingCall.isRinging()) { 903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 904b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("RING"); 905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendClipUpdate()) { 906b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CLIP: \"" + mRingingNumber + "\"," + mRingingType); 907b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = mStateChangeHandler.obtainMessage(RING); 910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStateChangeHandler.sendMessageDelayed(msg, 3000); 911b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized String toCregString() { 917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new String("+CREG: 1," + mStat); 918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCindResult() { 921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 922b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CIND: " + mService + "," + mCall + "," + mCallsetup + "," + 923b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld + "," + mSignal + "," + mRoam + "," + mBattchg; 924b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 925b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 926b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 928b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCsqResult() { 929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CSQ: " + mRssi + ",99"; 931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult getCindTestResult() { 937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CIND: (\"service\",(0-1))," + "(\"call\",(0-1))," + 938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"callsetup\",(0-3)),(\"callheld\",(0-2)),(\"signal\",(0-5))," + 939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"roam\",(0-1)),(\"battchg\",(0-5))"); 940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void ignoreRing() { 943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = 0; 944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = true; 945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 3," + mCallsetup); 947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_ACCEPTED = 1; 953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CONNECTED = 2; 954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CLOSED = 3; 955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_CALL_STARTED = 4; 956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_VOICE_RECOGNITION_STARTED = 5; 957f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private static final int MESSAGE_CHECK_PENDING_SCO = 6; 958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final Handler mHandler = new Handler() { 960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 9617757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh public void handleMessage(Message msg) { 9627757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh synchronized (BluetoothHandsfree.this) { 9637757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh switch (msg.what) { 9647757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_ACCEPTED: 9657757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 9667757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (isHeadsetConnected() && (mAudioPossible || allowAudioAnytime()) && 9677757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco == null) { 9687757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.i(TAG, "Routing audio for incoming SCO connection"); 9697757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco = (ScoSocket)msg.obj; 9707757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mAudioManager.setBluetoothScoOn(true); 971db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED, 972db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly mHeadset.getRemoteDevice()); 9737757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else { 9747757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.i(TAG, "Rejecting incoming SCO connection"); 9757757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh ((ScoSocket)msg.obj).close(); 9767757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 9777757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } // else error trying to accept, try again 9787757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mIncomingSco = createScoSocket(); 9797757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mIncomingSco.accept(); 9807757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 9817757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_CONNECTED: 9827757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (msg.arg1 == ScoSocket.STATE_CONNECTED && isHeadsetConnected() && 983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco == null) { 9848eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Routing audio for outgoing SCO conection"); 985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = (ScoSocket)msg.obj; 986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(true); 987db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED, 988db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly mHeadset.getRemoteDevice()); 9897757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 9908eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Rejecting new connected outgoing SCO socket"); 991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((ScoSocket)msg.obj).close(); 9927757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mOutgoingSco.close(); 993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 9957757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 9967757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case SCO_CLOSED: 9977757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mConnectedSco == (ScoSocket)msg.obj) { 998819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mConnectedSco.close(); 9997757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mConnectedSco = null; 10007757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mAudioManager.setBluetoothScoOn(false); 1001db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED, 1002819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mHeadset.getRemoteDevice()); 10037757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } else if (mOutgoingSco == (ScoSocket)msg.obj) { 1004819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mOutgoingSco.close(); 10057757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mOutgoingSco = null; 1006b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 10077757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10087757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case CHECK_CALL_STARTED: 10097757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mWaitingForCallStart) { 10107757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mWaitingForCallStart = false; 10117757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.e(TAG, "Timeout waiting for call to start"); 10127757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh sendURC("ERROR"); 10137757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mStartCallWakeLock.isHeld()) { 10147757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mStartCallWakeLock.release(); 10157757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10167757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10177757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 10187757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh case CHECK_VOICE_RECOGNITION_STARTED: 10197757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh if (mWaitingForVoiceRecognition) { 10207757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh mWaitingForVoiceRecognition = false; 10217757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh Log.e(TAG, "Timeout waiting for voice recognition to start"); 10227757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh sendURC("ERROR"); 10237757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh } 10247757ebca8f27cd580bc85b6afe66ca43122b8c39Jaikumar Ganesh break; 1025f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan case MESSAGE_CHECK_PENDING_SCO: 1026f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (mPendingSco && isA2dpMultiProfile()) { 1027f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Log.w(TAG, "Timeout suspending A2DP for SCO (mA2dpState = " + 1028f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpState + "). Starting SCO anyway"); 1029f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mOutgoingSco = createScoSocket(); 1030819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh if (!(isHeadsetConnected() && 1031819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mOutgoingSco.connect(mHeadset.getRemoteDevice().getAddress(), 1032819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh mHeadset.getRemoteDevice().getName()))) { 1033f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mOutgoingSco = null; 1034f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1035f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mPendingSco = false; 1036f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1037f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan break; 1038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket createScoSocket() { 1044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new ScoSocket(mPowerManager, mHandler, SCO_ACCEPTED, SCO_CONNECTED, SCO_CLOSED); 1045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1047db065e9834bcad9b0cb16c272b4b272dee8bdf62Nick Pelly private void broadcastAudioStateIntent(int state, BluetoothDevice device) { 10484079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project if (VDBG) log("broadcastAudioStateIntent(" + state + ")"); 104918e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly Intent intent = new Intent(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); 105018e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly intent.putExtra(BluetoothHeadset.EXTRA_AUDIO_STATE, state); 105118e0a07cc700234f5a02fe10eee9b3ea10db58b3Nick Pelly intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); 10524079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH); 10534079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project } 10544079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project 1055a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville void updateBtHandsfreeAfterRadioTechnologyChange() { 10568eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if(VDBG) Log.d(TAG, "updateBtHandsfreeAfterRadioTechnologyChange..."); 1057a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1058a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Get the Call references from the new active phone again 1059a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mRingingCall = mPhone.getRingingCall(); 1060a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mForegroundCall = mPhone.getForegroundCall(); 1061a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mBackgroundCall = mPhone.getBackgroundCall(); 1062a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 10631dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBtPhoneStateAfterRadioTechnologyChange(); 1064a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 1065a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to establish SCO (audio) connection to bluetooth 1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns false if the user has requested audio off, or if there 1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * is some other immediate problem that will prevent BT audio. 1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean audioOn() { 1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (VDBG) log("audioOn()"); 1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isHeadsetConnected()) { 1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): headset is not connected!"); 1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 10770966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (mHeadsetType == TYPE_HANDSFREE && !mServiceConnectionEstablished) { 10780966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (DBG) log("audioOn(): service connection not yet established!"); 10790966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return false; 10800966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 1081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 1083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): audio is already connected"); 1084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mUserWantsAudio) { 1088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): user requested no audio, ignoring"); 1089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 1093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): outgoing SCO already in progress"); 1094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1096f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1097f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (mPendingSco) { 1098f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (DBG) log("audioOn(): SCO already pending"); 1099f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan return true; 1100f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1101f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1102ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 1103ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = false; 1104f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (isA2dpMultiProfile() && mA2dpState == BluetoothA2dp.STATE_PLAYING) { 1105f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan if (DBG) log("suspending A2DP stream for SCO"); 1106ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = mA2dp.suspendSink(mA2dpDevice); 1107ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 1108ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mPendingSco = true; 1109f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Message msg = mHandler.obtainMessage(MESSAGE_CHECK_PENDING_SCO); 1110f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mHandler.sendMessageDelayed(msg, 2000); 1111f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } else { 1112f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan Log.w(TAG, "Could not suspend A2DP stream for SCO, going ahead with SCO"); 1113337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly } 1114337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly } 1115337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly 1116337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly if (!mPendingSco) { 1117337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly mOutgoingSco = createScoSocket(); 1118f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen if (!mOutgoingSco.connect(mHeadset.getRemoteDevice().getAddress(), 1119f0316a1fb5c00585d0fe4b500723557afabec70bEric Olsen mHeadset.getRemoteDevice().getName())) { 1120337c7eb41d344b39efcf740cdc579257152a1c58Nick Pelly mOutgoingSco = null; 1121f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio on. 1128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will establish SCO (BT audio), even if the user requested it off 1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * previously on this call. 1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOn() { 1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio off. 1136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will prevent us from establishing BT audio again during this call 1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if audioOn() is called. 1138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOff() { 1140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = false; 1141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to disconnect SCO (audio) connection to bluetooth 1145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 1146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void audioOff() { 1148819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh if (VDBG) log("audioOff(): mPendingSco: " + mPendingSco + 1149819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mConnectedSco: " + mConnectedSco + 1150819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mOutgoingSco: " + mOutgoingSco + 1151819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mA2dpState: " + mA2dpState + 1152819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mA2dpSuspended: " + mA2dpSuspended + 1153819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh ", mIncomingSco:" + mIncomingSco); 1154ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent 1155ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent if (mA2dpSuspended) { 1156a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent if (isA2dpMultiProfile()) { 1157a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent if (DBG) log("resuming A2DP stream after disconnecting SCO"); 1158a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent mA2dp.resumeSink(mA2dpDevice); 1159a1478a9074b126d13124c99b7543b2518b3de3b7Eric Laurent } 1160ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent mA2dpSuspended = false; 1161ab377a6e67c195c230db42e98d597bf4deba14bdEric Laurent } 1162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1163310e6fb854504637a4cefd123d8dd387660cf811Nick Pelly mPendingSco = false; 1164310e6fb854504637a4cefd123d8dd387660cf811Nick Pelly 1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 1166c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly BluetoothDevice device = null; 1167c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly if (mHeadset != null) { 1168c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly device = mHeadset.getRemoteDevice(); 1169c335ba22b8d739eddaed89b78fad4520abf36b19Nick Pelly } 1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco.close(); 1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = null; 11721b69b5d702539a74d1511d7467737eddc24b7744Nick Pelly mAudioManager.setBluetoothScoOn(false); 11731b69b5d702539a74d1511d7467737eddc24b7744Nick Pelly broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED, device); 1174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 1176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco.close(); 1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1179819fc69ac472a8d77be8e5dd79a21434c6de8a37Jaikumar Ganesh 1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ boolean isAudioOn() { 1183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (mConnectedSco != null); 1184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1186f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan private boolean isA2dpMultiProfile() { 1187f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan return mA2dp != null && mHeadset != null && mA2dpDevice != null && 1188f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan mA2dpDevice.equals(mHeadset.getRemoteDevice()); 1189f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan } 1190f9f946bc1e3ba287f0fa8f47a662e42f20892526Zhu Lan 1191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void ignoreRing() { 11921dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.ignoreRing(); 1193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void sendURC(String urc) { 1196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isHeadsetConnected()) { 1197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset.sendURC(urc); 1198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** helper to redial last dialled number */ 1202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult redial() { 1203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = mPhonebook.getLastDialledNumber(); 1204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 1205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // spec seems to suggest sending ERROR if we dont have a 1206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // number to redial 12078eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Bluetooth redial requested (+BLDN), but no previous " + 1208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "outgoing calls found. Ignoring"); 1209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 1212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", number, null)); 1213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 1215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // We do not immediately respond OK, wait until we get a phone state 1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update. If we return OK now and the handsfree immeidately requests 1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // our phone state it will say we are not in call yet which confuses 1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // some devices 1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Build the +CLCC result 1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * The complexity arises from the fact that we need to maintain the same 1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CLCC index even as a call moves between states. */ 1227c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private synchronized AtCommandResult gsmGetClccResult() { 1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Collect all known connections 1229c9d9ed30aa547b79b81adc13a4d148a003b6ee62w Connection[] clccConnections = new Connection[GSM_MAX_CONNECTIONS]; // indexed by CLCC index 1230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> newConnections = new LinkedList<Connection>(); 1231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> connections = new LinkedList<Connection>(); 1232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.getState().isAlive()) { 1233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mRingingCall.getConnections()); 1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mForegroundCall.getState().isAlive()) { 1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mForegroundCall.getConnections()); 1237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mBackgroundCall.getState().isAlive()) { 1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mBackgroundCall.getConnections()); 1240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mark connections that we already known about 1243c9d9ed30aa547b79b81adc13a4d148a003b6ee62w boolean clccUsed[] = new boolean[GSM_MAX_CONNECTIONS]; 1244c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccUsed[i] = mClccUsed[i]; 1246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 1247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection c : connections) { 1249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean found = false; 1250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = c.getCreateTime(); 1251c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; i < GSM_MAX_CONNECTIONS; i++) { 1252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccUsed[i] && timestamp == mClccTimestamps[i]) { 1253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 1254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project found = true; 1255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = c; 1256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!found) { 1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.add(c); 1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find a CLCC index for new connections 1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!newConnections.isEmpty()) { 1266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find lowest empty index 1267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int i = 0; 1268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (mClccUsed[i]) i++; 1269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find earliest connection 1270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long earliestTimestamp = newConnections.get(0).getCreateTime(); 1271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection earliestConnection = newConnections.get(0); 1272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int j = 0; j < newConnections.size(); j++) { 1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = newConnections.get(j).getCreateTime(); 1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (timestamp < earliestTimestamp) { 1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestTimestamp = timestamp; 1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestConnection = newConnections.get(j); 1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update 1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccTimestamps[i] = earliestTimestamp; 1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = earliestConnection; 1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.remove(earliestConnection); 1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Build CLCC 1288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < clccConnections.length; i++) { 1290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mClccUsed[i]) { 1291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String clccEntry = connectionToClccEntry(i, clccConnections[i]); 1292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccEntry != null) { 1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(clccEntry); 1294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Convert a Connection object into a single +CLCC result */ 1302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String connectionToClccEntry(int index, Connection c) { 1303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int state; 1304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c.getState()) { 1305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 1306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 0; 1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 1; 1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 2; 1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 3; 1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 4; 1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 5; 1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; // bad state 1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int mpty = 0; 1328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call call = c.getCall(); 1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call != null) { 1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mpty = call.isMultiparty() ? 1 : 0; 1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int direction = c.isIncoming() ? 1 : 0; 1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = -1; 1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String result = "+CLCC: " + (index + 1) + "," + direction + "," + state + ",0," + mpty; 1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result += ",\"" + number + "\"," + type; 1344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1347c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1348c9d9ed30aa547b79b81adc13a4d148a003b6ee62w /** Build the +CLCC result for CDMA 1349c9d9ed30aa547b79b81adc13a4d148a003b6ee62w * The complexity arises from the fact that we need to maintain the same 1350c9d9ed30aa547b79b81adc13a4d148a003b6ee62w * CLCC index even as a call moves between states. */ 1351c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private synchronized AtCommandResult cdmaGetClccResult() { 1352c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // In CDMA at one time a user can have only two live/active connections 1353c9d9ed30aa547b79b81adc13a4d148a003b6ee62w Connection[] clccConnections = new Connection[CDMA_MAX_CONNECTIONS];// indexed by CLCC index 1354c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1355c9d9ed30aa547b79b81adc13a4d148a003b6ee62w Call.State ringingCallState = mRingingCall.getState(); 1356c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the Ringing Call state is INCOMING, that means this is the very first call 1357c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // hence there should not be any Foreground Call 1358c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (ringingCallState == Call.State.INCOMING) { 13598eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] for INCOMING state"); 1360c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[0] = mRingingCall.getLatestConnection(); 1361c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else if (mForegroundCall.getState().isAlive()) { 1362c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Getting Foreground Call connection based on Call state 1363c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (mRingingCall.isRinging()) { 13648eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] & [1] for CALL WAITING state"); 1365c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[0] = mForegroundCall.getEarliestConnection(); 1366c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[1] = mRingingCall.getLatestConnection(); 1367c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1368c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (mForegroundCall.getConnections().size() <= 1) { 1369c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Single call scenario 13708eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] with ForgroundCall latest connection"); 1371c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[0] = mForegroundCall.getLatestConnection(); 1372c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1373c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Multiple Call scenario. This would be true for both 1374c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CONF_CALL and THRWAY_ACTIVE state 13758eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Filling clccConnections[0] & [1] with ForgroundCall connections"); 1376c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[0] = mForegroundCall.getEarliestConnection(); 1377c9d9ed30aa547b79b81adc13a4d148a003b6ee62w clccConnections[1] = mForegroundCall.getLatestConnection(); 1378c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1379c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1380c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1381c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1382c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Update the mCdmaIsSecondCallActive flag based on the Phone call state 1383c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1384c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE) { 1385c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(false); 1386c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1387c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 1388c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1389c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1390c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1391c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Build CLCC 1392c9d9ed30aa547b79b81adc13a4d148a003b6ee62w AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 1393c9d9ed30aa547b79b81adc13a4d148a003b6ee62w for (int i = 0; (i < clccConnections.length) && (clccConnections[i] != null); i++) { 1394c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String clccEntry = cdmaConnectionToClccEntry(i, clccConnections[i]); 1395c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (clccEntry != null) { 1396c9d9ed30aa547b79b81adc13a4d148a003b6ee62w result.addResponse(clccEntry); 1397c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1398c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1399c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1400c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return result; 1401c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1402c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1403c9d9ed30aa547b79b81adc13a4d148a003b6ee62w /** Convert a Connection object into a single +CLCC result for CDMA phones */ 1404c9d9ed30aa547b79b81adc13a4d148a003b6ee62w private String cdmaConnectionToClccEntry(int index, Connection c) { 1405c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int state; 1406c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneApp app = PhoneApp.getInstance(); 1407c9d9ed30aa547b79b81adc13a4d148a003b6ee62w CdmaPhoneCallState.PhoneCallState currCdmaCallState = 1408c9d9ed30aa547b79b81adc13a4d148a003b6ee62w app.cdmaPhoneCallState.getCurrentCallState(); 1409c9d9ed30aa547b79b81adc13a4d148a003b6ee62w CdmaPhoneCallState.PhoneCallState prevCdmaCallState = 1410c9d9ed30aa547b79b81adc13a4d148a003b6ee62w app.cdmaPhoneCallState.getPreviousCallState(); 1411c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1412c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if ((prevCdmaCallState == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 1413c9d9ed30aa547b79b81adc13a4d148a003b6ee62w && (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL)) { 1414c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the current state is reached after merging two calls 1415c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // we set the state of all the connections as ACTIVE 1416c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 0; 1417c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1418c9d9ed30aa547b79b81adc13a4d148a003b6ee62w switch (c.getState()) { 1419c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case ACTIVE: 1420c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // For CDMA since both the connections are set as active by FW after accepting 1421c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // a Call waiting or making a 3 way call, we need to set the state specifically 1422c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // to ACTIVE/HOLDING based on the mCdmaIsSecondCallActive flag. This way the 1423c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // CLCC result will allow BT devices to enable the swap or merge options 1424c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (index == 0) { // For the 1st active connection 1425c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = mCdmaIsSecondCallActive ? 1 : 0; 1426c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { // for the 2nd active connection 1427c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = mCdmaIsSecondCallActive ? 0 : 1; 1428c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1429c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1430c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case HOLDING: 1431c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 1; 1432c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1433c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case DIALING: 1434c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 2; 1435c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1436c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case ALERTING: 1437c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 3; 1438c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1439c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case INCOMING: 1440c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 4; 1441c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1442c9d9ed30aa547b79b81adc13a4d148a003b6ee62w case WAITING: 1443c9d9ed30aa547b79b81adc13a4d148a003b6ee62w state = 5; 1444c9d9ed30aa547b79b81adc13a4d148a003b6ee62w break; 1445c9d9ed30aa547b79b81adc13a4d148a003b6ee62w default: 1446c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return null; // bad state 1447c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1448c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1449c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1450c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int mpty = 0; 14513eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu if (currCdmaCallState == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 1452c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mpty = 1; 14533eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu } else { 14543eb2a4ae98eb737004d40f7ce03a8d83883fb079Kuanting Zhu mpty = 0; 1455c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1456c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1457c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int direction = c.isIncoming() ? 1 : 0; 1458c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1459c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String number = c.getAddress(); 1460c9d9ed30aa547b79b81adc13a4d148a003b6ee62w int type = -1; 1461c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (number != null) { 1462c9d9ed30aa547b79b81adc13a4d148a003b6ee62w type = PhoneNumberUtils.toaFromString(number); 1463c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1464c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1465c9d9ed30aa547b79b81adc13a4d148a003b6ee62w String result = "+CLCC: " + (index + 1) + "," + direction + "," + state + ",0," + mpty; 1466c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (number != null) { 1467c9d9ed30aa547b79b81adc13a4d148a003b6ee62w result += ",\"" + number + "\"," + type; 1468c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1469c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return result; 1470c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1471c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 1472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Headset profile 1474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHeadsetAtParser() { 14768eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Registering Headset AT commands"); 1477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 1478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset's usually only have one button, which is meant to cause the 1479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HS to send us AT+CKPD=200 or AT+CKPD. 1480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CKPD", new AtCommandHandler() { 1481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult headsetButtonPress() { 1482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.isRinging()) { 1483b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer the call 14841ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mBluetoothPhoneState.stopRing(); 14851ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh sendURC("OK"); 14868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.answerCall(mPhone.getRingingCall()); 1487a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly // If in-band ring tone is supported, SCO connection will already 1488a23972e3605fb235897250fd4edc2b70be13e00dNick Pelly // be up and the following call will just return. 1489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 14901ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 1491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (mForegroundCall.getState().isAlive()) { 1492b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isAudioOn()) { 1493b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Transfer audio from AG to HS 1494b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1495b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1496b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset.getDirection() == HeadsetBase.DIRECTION_INCOMING && 1497b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (System.currentTimeMillis() - mHeadset.getConnectTimestamp()) < 5000) { 1498b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset made a recent ACL connection to us - and 1499b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // made a mandatory AT+CKPD request to connect 1500b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // audio which races with our automatic audio 1501b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // setup. ignore 1502b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1503b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang up the call 1504b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 15058343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangup(PhoneApp.getInstance().mCM); 1506b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1507b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 15081ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.OK); 1509b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1510b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No current call - redial last number 1511b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1512b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1515b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Handsfree profile 1527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHandsfreeAtParser() { 15298eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("Registering Handsfree AT commands"); 1530b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 1531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer 1533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('A', new AtCommandHandler() { 1534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 15361ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh sendURC("OK"); 15371ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh mBluetoothPhoneState.stopRing(); 15388343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.answerCall(mPhone.getRingingCall()); 15391ec7e6b9b3bf1dfc384676244bec1edb50fedc58Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 1540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1542b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('D', new AtCommandHandler() { 1543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1544b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 1545b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length() > 0) { 1546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(0) == '>') { 1547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Yuck - memory dialling requested. 1548b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Just dial last number for now 1549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.startsWith(">9999")) { // for PTS test 1550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1551b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1553b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1554b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Remove trailing ';' 1555b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(args.length() - 1) == ';') { 1556b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args = args.substring(0, args.length() - 1); 1557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1558b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 1559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", args, null)); 1560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 1562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 1564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 1565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1570b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang-up command 1572b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHUP", new AtCommandHandler() { 1573b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1575586668fe6a1259083fbbc67de8ecac850c1475f1Jaikumar Ganesh sendURC("OK"); 1576c786eb3f4a06317d8cd75bb69edf1b3a391b2c63Nick Pelly if (!mForegroundCall.isIdle()) { 15778343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangupActiveCall(mPhone.getForegroundCall()); 1578c786eb3f4a06317d8cd75bb69edf1b3a391b2c63Nick Pelly } else if (!mRingingCall.isIdle()) { 15798343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangupRingingCall(mPhone.getRingingCall()); 1580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!mBackgroundCall.isIdle()) { 15818343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangupHoldingCall(mPhone.getBackgroundCall()); 1582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1583586668fe6a1259083fbbc67de8ecac850c1475f1Jaikumar Ganesh return new AtCommandResult(AtCommandResult.UNSOLICITED); 1584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Retrieve Supported Features command 1588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BRSF", new AtCommandHandler() { 1589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult sendBRSF() { 1590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+BRSF: " + mLocalBrsf); 1591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+BRSF=<handsfree supported features bitmap> 1595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is telling us which features it supports. We 1596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // send the features we support 1597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 1 && (args[0] instanceof Integer)) { 1598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = (Integer) args[0]; 1599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "HF didn't sent BRSF assuming 0"); 1601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1604b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting notification on/off 1617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CCWA", new AtCommandHandler() { 1618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1619b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Seems to be out of spec, but lets return nicely 1621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting is always on 1626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: 1"); 1627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CCWA=<n> 1631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is trying to enable/disable call waiting. We 1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cannot disable in the current implementation. 1633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request for range of supported CCWA paramters 1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: (\"n\",(1))"); 1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Event Reporting enable/disable command 1643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Of the full 3GPP syntax paramters (mode, keyp, disp, ind, bfr) we 1644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only support paramter ind (disable/enable evert reporting using 1645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // +CDEV) 1646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMER", new AtCommandHandler() { 1647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+CMER: 3,0,0," + (mIndicatorsEnabled ? "1" : "0")); 1651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length < 4) { 1655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This is a syntax error 1656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3) && args[1].equals(0) && 1658b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args[2].equals(0)) { 16590966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly boolean valid = false; 1660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[3].equals(0)) { 1661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 16620966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 1663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[3].equals(1)) { 1664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = true; 16650966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 16660966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 16670966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (valid) { 16680966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) == 0x0) { 16690966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 16700966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly sendURC("OK"); // send immediately, then initiate audio 16710966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 16720966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 16730966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 16740966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // only send OK once 16750966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 16760966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } else { 16770966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.OK); 16780966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 1679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 16810966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 1682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMER: (3),(0),(0),(0-1)"); 1686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1689b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Error Reporting enable/disable 1690b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMEE", new AtCommandHandler() { 1691b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1693b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // out of spec, assume they want to enable 1694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = true; 1695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: " + (mCmee ? "1" : "0")); 1700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1702b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CMEE=<n> 1704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 0) { 1705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // <n> ommitted - default to 0 1706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 1707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!(args[0] instanceof Integer)) { 1709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Syntax error 1710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = ((Integer)args[0] == 1); 1713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1718b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Probably not required but spec, but no harm done 1719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: (0-1)"); 1720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Last Dialled Number 1724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BLDN", new AtCommandHandler() { 1725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Indicator Update command 1732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIND", new AtCommandHandler() { 1733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 17351dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCindResult(); 1736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 17391dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.getCindTestResult(); 1740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query Signal Quality (legacy) 1744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CSQ", new AtCommandHandler() { 1745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 17471dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCsqResult(); 1748b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query network registration state 1752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CREG", new AtCommandHandler() { 1753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 17551dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return new AtCommandResult(mBluetoothPhoneState.toCregString()); 1756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Send DTMF. I don't know if we are also expected to play the DTMF tone 1760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // locally, right now we don't 1761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VTS", new AtCommandHandler() { 1762b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1763b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1764b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project char c; 1766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0] instanceof Integer) { 1767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((Integer) args[0]).toString().charAt(0); 1768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((String) args[0]).charAt(0); 1770b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1771b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isValidDtmf(c)) { 1772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone.sendDtmf(c); 1773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1774b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1775b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isValidDtmf(char c) { 1779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c) { 1780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '#': 1781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '*': 1782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1784b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (Character.digit(c, 14) != -1) { 1785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; // 0-9 and A-D 1786b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1787b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1788b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // List calls 1793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLCC", new AtCommandHandler() { 1794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 179679b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = mPhone.getPhoneType(); 179779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1798c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return cdmaGetClccResult(); 179979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 1800c9d9ed30aa547b79b81adc13a4d148a003b6ee62w return gsmGetClccResult(); 180179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 180279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1803c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call Hold and Multiparty Handling command 1808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHLD", new AtCommandHandler() { 1809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 181179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = mPhone.getPhoneType(); 1812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 1814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean result; 1815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.isRinging()) { 18168343169cc89621d46dce86449f5ee1ff5d3a4919John Wang result = PhoneUtils.hangupRingingCall(mPhone.getRingingCall()); 1817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 18188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang result = PhoneUtils.hangupHoldingCall(mPhone.getBackgroundCall()); 1819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result) { 1821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 182679b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1827c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (mRingingCall.isRinging()) { 1828c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If there is Call waiting then answer the call and 1829c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // put the first call on hold. 18308eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:1 Callwaiting Answer call"); 18318343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.answerCall(mPhone.getRingingCall()); 1832c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneUtils.setMute(mPhone, false); 1833c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Setting the second callers state flag to TRUE (i.e. active) 1834c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1835c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else { 1836c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If there is no Call waiting then just hangup 1837c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // the active call. In CDMA this mean that the complete 1838c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // call session would be ended 18398eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:1 Hangup Call"); 18408343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.hangup(PhoneApp.getInstance().mCM); 1841c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 1842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 184379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 1844a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // Hangup active call, answer held call 18458343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (PhoneUtils.answerAndEndActive( 18468343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneApp.getInstance().mCM, mPhone.getRingingCall())) { 1847a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman return new AtCommandResult(AtCommandResult.OK); 1848a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } else { 1849a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman return new AtCommandResult(AtCommandResult.ERROR); 1850a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 185179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 185279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(2)) { 185579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1856a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // For CDMA, the way we switch to a new incoming call is by 1857a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // calling PhoneUtils.answerCall(). switchAndHoldActive() won't 1858a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman // properly update the call state within telephony. 1859c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If the Phone state is already in CONF_CALL then we simply send 1860c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // a flash cmd by calling switchHoldingAndActive() 1861c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (mRingingCall.isRinging()) { 18628eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:2 Callwaiting Answer call"); 18638343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.answerCall(mPhone.getRingingCall()); 1864c9d9ed30aa547b79b81adc13a4d148a003b6ee62w PhoneUtils.setMute(mPhone, false); 1865c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Setting the second callers state flag to TRUE (i.e. active) 1866c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSetSecondCallState(true); 1867c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } else if (PhoneApp.getInstance().cdmaPhoneCallState 1868c9d9ed30aa547b79b81adc13a4d148a003b6ee62w .getCurrentCallState() 1869c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.CONF_CALL) { 18708eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:2 Swap Calls"); 18718343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.switchHoldingAndActive(mPhone.getBackgroundCall()); 1872c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // Toggle the second callers active state flag 1873c9d9ed30aa547b79b81adc13a4d148a003b6ee62w cdmaSwapSecondCallState(); 1874c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 187579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 18768343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneUtils.switchHoldingAndActive(mPhone.getBackgroundCall()); 187779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 187879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1879a76113dcb0def438d0b3019aeb88fdbfbfbe90d4Paul Berman } 1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3)) { 188279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 1883c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // For CDMA, we need to check if the call is in THRWAY_ACTIVE state 1884c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (PhoneApp.getInstance().cdmaPhoneCallState.getCurrentCallState() 1885c9d9ed30aa547b79b81adc13a4d148a003b6ee62w == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 18868eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("CHLD:3 Merge Calls"); 1887b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan PhoneUtils.mergeCalls(); 1888c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 188979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else if (phoneType == Phone.PHONE_TYPE_GSM) { 1890c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (mForegroundCall.getState().isAlive() && 1891c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mBackgroundCall.getState().isAlive()) { 1892b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan PhoneUtils.mergeCalls(); 1893c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 189479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 189579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 1896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 19040966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 1905d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("+CHLD: (0,1,2,3)"); 1906d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("OK"); // send reply first, then connect audio 19070966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 19080966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 19090966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 19100966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // already replied 19110966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 1912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get Network operator name 1916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+COPS", new AtCommandHandler() { 1917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String operatorName = mPhone.getServiceState().getOperatorAlphaLong(); 1920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName != null) { 1921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName.length() > 16) { 1922b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project operatorName = operatorName.substring(0, 16); 1923b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1924b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1925b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+COPS: 0,0,\"" + operatorName + "\""); 1926b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1928b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+COPS: 0,0,\"UNKNOWN\",0"); 1929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree only supports AT+COPS=3,0 1934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 2 || !(args[0] instanceof Integer) 1935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project || !(args[1] instanceof Integer)) { 1936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // syntax error 1937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if ((Integer)args[0] != 3 || (Integer)args[1] != 0) { 1939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 1940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Out of spec, but lets be friendly 1947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+COPS: (3),(0)"); 1948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile PIN 1952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CPIN is not in the handsfree spec (although it is in 3GPP) 1953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPIN", new AtCommandHandler() { 1954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPIN: READY"); 1957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Response and Hold 1961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Only supported on PDC (Japan) and CDMA networks. 1962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BTRH", new AtCommandHandler() { 1963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Replying with just OK indicates no response and hold 1966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // features in use now 1967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Neeed PDC or CDMA 1972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request International Mobile Subscriber Identity (IMSI) 1977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Not in bluetooth handset spec 1978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIMI", new AtCommandHandler() { 1979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CIMI 1982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String imsi = mPhone.getSubscriberId(); 1983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (imsi == null || imsi.length() == 0) { 1984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.SIM_FAILURE); 1985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(imsi); 1987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1989b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1990b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Calling Line Identification Presentation 1992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLIP", new AtCommandHandler() { 1993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Currently assumes the network is provisioned for CLIP 1996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: " + (mClip ? "1" : "0") + ",1"); 1997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1998b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1999b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2000b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CLIP=<n> 2001b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && (args[0].equals(0) || args[0].equals(1))) { 2002b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = args[0].equals(1); 2003b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2004b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2005b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2006b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2007b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2008b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2009b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 2010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: (0-1)"); 2011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGSN - Returns the device IMEI number. 2015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGSN", new AtCommandHandler() { 2016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2017b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get the IMEI of the device. 2019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // mPhone will not be NULL at this point. 2020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGSN: " + mPhone.getDeviceId()); 2021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMM - Query Model Information 2025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMM", new AtCommandHandler() { 2026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 2029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String model = SystemProperties.get("ro.product.model"); 2030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (model != null) { 2031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMM: " + model); 2032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMI - Query Manufacturer Information 2039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMI", new AtCommandHandler() { 2040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 2043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String manuf = SystemProperties.get("ro.product.manufacturer"); 2044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (manuf != null) { 2045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMI: " + manuf); 2046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2052b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Noise Reduction and Echo Cancellation control 2053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+NREC", new AtCommandHandler() { 2054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2055b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2056b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 2057aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NREC+"=off"); 2058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 2060aa23e1c3c758bad23d8b6709147cc1ff7cd1e43cEric Laurent mAudioManager.setParameters(HEADSET_NREC+"=on"); 2061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2062b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2063b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Voice recognition (dialing) 2068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BVRA", new AtCommandHandler() { 2069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2071b8dbab241df3aa3487c1bdb488fd4e0b694d2d9aEric Laurent if (!BluetoothHeadset.isBluetoothVoiceDialingEnabled(mContext)) { 20726967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult(AtCommandResult.ERROR); 20736967e2d953bc077c99c4831946201f3d333b833fNick Pelly } 2074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && args[0].equals(1)) { 2075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project synchronized (BluetoothHandsfree.this) { 2076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mWaitingForVoiceRecognition) { 2077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 2078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(sVoiceCommandIntent); 2079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (ActivityNotFoundException e) { 2080b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectVoiceRecognition(); 2083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing yet 2086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args.length >= 1 && args[0].equals(0)) { 2087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 20946967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult("+BVRA: (0-1)"); 2095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Retrieve Subscriber Number 2099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CNUM", new AtCommandHandler() { 2100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = mPhone.getLine1Number(); 2103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 2104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CNUM: ,\"" + number + "\"," + 2107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneNumberUtils.toaFromString(number) + ",,4"); 2108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Microphone Gain 2112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGM", new AtCommandHandler() { 2113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGM=<gain> in range [0,15] 2116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset/Handsfree is reporting its current gain setting 2117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Speaker Gain 2122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGS", new AtCommandHandler() { 2123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 2125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGS=<gain> in range [0,15] 2126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 1 || !(args[0] instanceof Integer)) { 2127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = (Integer) args[0]; 2130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int flag = mAudioManager.isBluetoothScoOn() ? AudioManager.FLAG_SHOW_UI:0; 2131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, mScoGain, flag); 2133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 2134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Phone activity status 2138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPAS", new AtCommandHandler() { 2139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 2141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int status = 0; 2142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (mPhone.getState()) { 2143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case IDLE: 2144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 0; 2145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RINGING: 2147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 3; 2148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case OFFHOOK: 2150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 4; 2151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPAS: " + status); 2154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 2156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook.register(parser); 2157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void sendScoGainUpdate(int gain) { 2160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mScoGain != gain && (mRemoteBrsf & BRSF_HF_REMOTE_VOL_CONTROL) != 0x0) { 2161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+VGS:" + gain); 2162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = gain; 2163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult reportCmeError(int error) { 2167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCmee) { 2168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 2169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CME ERROR: " + error); 2170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 2171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 2173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_CALL_TIMEOUT = 10000; // ms 2177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectCallStart() { 2179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = true; 2180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_CALL_STARTED); 2181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_CALL_TIMEOUT); 2182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartCallWakeLock.isHeld()) { 2183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.acquire(START_CALL_TIMEOUT); 2184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void callStarted() { 2188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForCallStart) { 2189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = false; 2190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 2191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartCallWakeLock.isHeld()) { 2192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.release(); 2193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_VOICE_RECOGNITION_TIMEOUT = 5000; // ms 2198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectVoiceRecognition() { 2200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = true; 2201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_VOICE_RECOGNITION_STARTED); 2202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_VOICE_RECOGNITION_TIMEOUT); 2203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartVoiceRecognitionWakeLock.isHeld()) { 2204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.acquire(START_VOICE_RECOGNITION_TIMEOUT); 2205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean startVoiceRecognition() { 2209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForVoiceRecognition) { 2210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HF initiated 2211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = false; 2212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 2213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AG initiated 2215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 1"); 2216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean ret = audioOn(); 2218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartVoiceRecognitionWakeLock.isHeld()) { 2219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.release(); 2220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return ret; 2222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean stopVoiceRecognition() { 2225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 0"); 2226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 2228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean inDebug() { 2231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return DBG && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE, false); 2232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean allowAudioAnytime() { 2235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return inDebug() && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE_AUDIO_ANYTIME, 2236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project false); 2237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void startDebug() { 2240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG && mDebugThread == null) { 2241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = new DebugThread(); 2242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.start(); 2243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void stopDebug() { 2247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mDebugThread != null) { 2248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.interrupt(); 2249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = null; 2250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug thread to read debug properties - runs when debug.bt.hfp is true 2254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * at the time a bluetooth handsfree device is connected. Debug properties 2255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * are polled and mock updates sent every 1 second */ 2256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class DebugThread extends Thread { 2257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Turns on/off handsfree profile debugging mode */ 2258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE = "debug.bt.hfp"; 2259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock battery level change - use 0 to 5 */ 2261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_BATTERY = "debug.bt.hfp.battery"; 2262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock no cellular service when false */ 2264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SERVICE = "debug.bt.hfp.service"; 2265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock cellular roaming when true */ 2267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_ROAM = "debug.bt.hfp.roam"; 2268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** false to true transition will force an audio (SCO) connection to 2270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * be established. true to false will force audio to be disconnected 2271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO = "debug.bt.hfp.audio"; 2273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** true allows incoming SCO connection out of call. 2275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO_ANYTIME = "debug.bt.hfp.audio_anytime"; 2277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock signal strength change in ASU - use 0 to 31 */ 2279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SIGNAL = "debug.bt.hfp.signal"; 2280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+CLCC: print +CLCC result */ 2282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_CLCC = "debug.bt.hfp.clcc"; 2283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+BSIR - Send In Band Ringtones Unsolicited AT command. 2285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 0 => AT+BSIR = 0 sent by the AG 2286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 1 => AT+BSIR = 0 sent by the AG 2287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Other values are ignored. 2288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_UNSOL_INBAND_RINGTONE = 2291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "debug.bt.unsol.inband"; 2292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 2294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void run() { 2295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldService = true; 2296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldRoam = false; 2297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldAudio = false; 2298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!isInterrupted() && inDebug()) { 2300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = SystemProperties.getInt(DEBUG_HANDSFREE_BATTERY, -1); 2301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel >= 0 && batteryLevel <= 5) { 2302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 2303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("level", batteryLevel); 2304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("scale", 5); 23051dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBatteryState(intent); 2306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean serviceStateChanged = false; 2309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_SERVICE, true) != oldService) { 2310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldService = !oldService; 2311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 2312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_ROAM, false) != oldRoam) { 2314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldRoam = !oldRoam; 2315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 2316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (serviceStateChanged) { 2318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Bundle b = new Bundle(); 2319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putInt("state", oldService ? 0 : 1); 2320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putBoolean("roaming", oldRoam); 23211dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateServiceState(true, ServiceState.newFromBundle(b)); 2322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_AUDIO, false) != oldAudio) { 2325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldAudio = !oldAudio; 2326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (oldAudio) { 2327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 2328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 2329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 2330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signalLevel = SystemProperties.getInt(DEBUG_HANDSFREE_SIGNAL, -1); 2334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (signalLevel >= 0 && signalLevel <= 31) { 2335404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = new SignalStrength(signalLevel, -1, -1, -1, 2336404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville -1, -1, -1, true); 2337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 2338404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Bundle data = new Bundle(); 2339404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signalStrength.fillInNotifierBundle(data); 2340404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville intent.putExtras(data); 23411dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateSignalState(intent); 2342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_CLCC, false)) { 2345c9d9ed30aa547b79b81adc13a4d148a003b6ee62w log(gsmGetClccResult().toString()); 2346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 2348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sleep(1000); // 1 second 2349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (InterruptedException e) { 2350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 2351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int inBandRing = 2354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SystemProperties.getInt(DEBUG_UNSOL_INBAND_RINGTONE, -1); 2355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (inBandRing == 0 || inBandRing == 1) { 2356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = 2357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new AtCommandResult(AtCommandResult.UNSOLICITED); 2358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+BSIR: " + inBandRing); 2359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 2360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2365c9d9ed30aa547b79b81adc13a4d148a003b6ee62w public void cdmaSwapSecondCallState() { 23668eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("cdmaSetSecondCallState: Toggling mCdmaIsSecondCallActive"); 2367c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mCdmaIsSecondCallActive = !mCdmaIsSecondCallActive; 2368c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 2369c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 2370c9d9ed30aa547b79b81adc13a4d148a003b6ee62w public void cdmaSetSecondCallState(boolean state) { 23718eb32ddb60cfe1a0d0733735c30ecfc814452806Jackson Fan if (VDBG) log("cdmaSetSecondCallState: Setting mCdmaIsSecondCallActive to " + state); 2372c9d9ed30aa547b79b81adc13a4d148a003b6ee62w mCdmaIsSecondCallActive = state; 2373c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 2374c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 2375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 2376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.d(TAG, msg); 2377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 2379