BluetoothHandsfree.java revision b01429c99653aef893ca3b9a92a85ab31ae85bc0
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; 22b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.BluetoothDevice; 234079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Projectimport android.bluetooth.BluetoothHeadset; 244079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Projectimport android.bluetooth.BluetoothIntent; 25b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.HeadsetBase; 26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.bluetooth.ScoSocket; 27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.ActivityNotFoundException; 28b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.BroadcastReceiver; 29b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Intent; 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.IntentFilter; 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.AudioManager; 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri; 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult; 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Bundle; 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message; 38b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager; 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.PowerManager.WakeLock; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.SystemProperties; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.ServiceState; 43404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.telephony.SignalStrength; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Call; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Connection; 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Phone; 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.TelephonyIntents; 50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.LinkedList; 52b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 53b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Bluetooth headset manager for the Phone app. 54b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @hide 55b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class BluetoothHandsfree { 57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String TAG = "BT HS/HF"; 58b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 2); 59b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean VDBG = false; // even more logging 60b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 61b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_UNKNOWN = 0; 62b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HEADSET = 1; 63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static final int TYPE_HANDSFREE = 2; 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 654079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private final Context mContext; 664079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private final Phone mPhone; 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ServiceState mServiceState; 68b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private HeadsetBase mHeadset; // null when not connected 69b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mHeadsetType; 70b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mAudioPossible; 71b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mIncomingSco; 72b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mOutgoingSco; 73b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket mConnectedSco; 74b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 75b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mForegroundCall; 76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mBackgroundCall; 77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Call mRingingCall; 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AudioManager mAudioManager; 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private PowerManager mPowerManager; 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mUserWantsAudio; 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartCallWakeLock; // held while waiting for the intent to start call 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private WakeLock mStartVoiceRecognitionWakeLock; // held while waiting for voice recognition 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT command state 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int MAX_CONNECTIONS = 6; // Max connections allowed by GSM 88b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 89b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long mBgndEarliestConnectionTime = 0; 90b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mClip = false; // Calling Line Information Presentation 91b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIndicatorsEnabled = false; 92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mCmee = false; // Extended Error reporting 93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private long[] mClccTimestamps; // Timestamps associated with each clcc index 94b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean[] mClccUsed; // Is this clcc index in use 95b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForCallStart; 96b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mWaitingForVoiceRecognition; 970966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // do not connect audio until service connection is established 980966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for 3-way supported devices, this is after AT+CHLD 990966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // for non-3-way supported devices, this is after AT+CMER (see spec) 1000966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly private boolean mServiceConnectionEstablished; 1011dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private final BluetoothPhoneState mBluetoothPhoneState; // for CIND and CIEV updates 102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BluetoothAtPhonebook mPhonebook; 1031dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh private Phone.State mPhoneState = Phone.State.IDLE; 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private DebugThread mDebugThread; 106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mScoGain = Integer.MIN_VALUE; 107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static Intent sVoiceCommandIntent; 109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Audio parameters 111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NREC = "bt_headset_nrec"; 112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String HEADSET_NAME = "bt_headset_name"; 113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRemoteBrsf = 0; 115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mLocalBrsf = 0; 116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Constants from Bluetooth Specification Hands-Free profile version 1.5 */ 1186967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_THREE_WAY_CALLING = 1 << 0; 1196967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_EC_NR = 1 << 1; 1206967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_RECOG = 1 << 2; 1216967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_IN_BAND_RING = 1 << 3; 1226967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_VOICE_TAG_NUMBE = 1 << 4; 1236967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_REJECT_CALL = 1 << 5; 1246967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_STATUS = 1 << 6; 1256967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_CALL_CONTROL = 1 << 7; 1266967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_AG_ENHANCED_ERR_RESULT_CODES = 1 << 8; 1276967e2d953bc077c99c4831946201f3d333b833fNick Pelly 1286967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_EC_NR = 1 << 0; 1296967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CW_THREE_WAY_CALLING = 1 << 1; 1306967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_CLIP = 1 << 2; 1316967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_VOICE_REG_ACT = 1 << 3; 1326967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_REMOTE_VOL_CONTROL = 1 << 4; 1336967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_STATUS = 1 << 5; 1346967e2d953bc077c99c4831946201f3d333b833fNick Pelly private static final int BRSF_HF_ENHANCED_CALL_CONTROL = 1 << 6; 135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static String typeToString(int type) { 137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (type) { 138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_UNKNOWN: 139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "unknown"; 140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HEADSET: 141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "headset"; 142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case TYPE_HANDSFREE: 143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return "handsfree"; 144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public BluetoothHandsfree(Context context, Phone phone) { 149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone = phone; 150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext = context; 151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BluetoothDevice bluetooth = 152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (BluetoothDevice)context.getSystemService(Context.BLUETOOTH_SERVICE); 153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean bluetoothCapable = (bluetooth != null); 154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; // nothing connected yet 155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":StartCall"); 159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.setReferenceCounted(false); 160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project TAG + ":VoiceRecognition"); 162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.setReferenceCounted(false); 163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf = BRSF_AG_THREE_WAY_CALLING | 165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_EC_NR | 166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_REJECT_CALL | 167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project BRSF_AG_ENHANCED_CALL_STATUS; 1684b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project 169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sVoiceCommandIntent == null) { 170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent = new Intent(Intent.ACTION_VOICE_COMMAND); 171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sVoiceCommandIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1736967e2d953bc077c99c4831946201f3d333b833fNick Pelly if (mContext.getPackageManager().resolveActivity(sVoiceCommandIntent, 0) != null && 1746967e2d953bc077c99c4831946201f3d333b833fNick Pelly !BluetoothHeadset.DISABLE_BT_VOICE_DIALING) { 175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mLocalBrsf |= BRSF_AG_VOICE_RECOG; 176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (bluetoothCapable) { 179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project resetAtState(); 180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingCall = mPhone.getRingingCall(); 183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mForegroundCall = mPhone.getForegroundCall(); 184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBackgroundCall = mPhone.getBackgroundCall(); 1851dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState = new BluetoothPhoneState(); 186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook = new BluetoothAtPhonebook(mContext, this); 188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothEnabled() { 192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* Bluez has a bug where it will always accept and then orphan 193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * incoming SCO connections, regardless of whether we have a listening 194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * SCO socket. So the best thing to do is always run a listening socket 195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * while bluetooth is on so that at least we can diconnect it 196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * immediately when we don't want it. 197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco == null) { 199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = createScoSocket(); 200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.accept(); 201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void onBluetoothDisabled() { 205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(false); 2074079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED); 208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco.close(); 209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = null; 210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco.close(); 213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mIncomingSco != null) { 216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.close(); 217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = null; 218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isHeadsetConnected() { 222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset == null) { 223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return mHeadset.isConnected(); 226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void connectHeadset(HeadsetBase headset, int headsetType) { 229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = headset; 230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadsetType = headsetType; 231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadsetType == TYPE_HEADSET) { 232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHeadsetAtParser(); 233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project initializeHandsfreeAtParser(); 235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project headset.startEventThread(); 237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project configAudioParameters(); 238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (inDebug()) { 240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project startDebug(); 241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isIncallAudio()) { 244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* returns true if there is some kind of in-call audio we may wish to route 249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth to */ 250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isIncallAudio() { 251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call.State state = mForegroundCall.getState(); 252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (state == Call.State.ACTIVE || state == Call.State.ALERTING); 254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void disconnectHeadset() { 257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset = null; 258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stopDebug(); 259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project resetAtState(); 260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void resetAtState() { 263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = false; 264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 2650966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = false; 266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccTimestamps = new long[MAX_CONNECTIONS]; 268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed = new boolean[MAX_CONNECTIONS]; 269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < MAX_CONNECTIONS; i++) { 270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = 0; 273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void configAudioParameters() { 276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String name = mHeadset.getName(); 277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (name == null) { 278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project name = "<unknown>"; 279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setParameter(HEADSET_NAME, name); 281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setParameter(HEADSET_NREC, "on"); 282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Represents the data that we send in a +CIND or +CIEV command to the HF 286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class BluetoothPhoneState { 288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no service 289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: service 290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mService; 291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no active call 293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: active call (where active means audio is routed - not held call) 294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCall; 295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not in call setup 297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: incoming call setup 298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: outgoing call setup 299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3: remote party being alerted in an outgoing call setup 300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallsetup; 301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: no calls held 303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: held call and active call 304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2: held call only 305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mCallheld; 306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength of AG: 0-5 308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mSignal; 309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cellular signal strength in CSQ rssi scale 311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRssi; // for CSQ 312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: roaming not active (home) 314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: roaming active 315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRoam; 316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // battery charge of AG: 0-5 318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mBattchg; 319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 0: not registered 321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1: registered, home network 322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 5: registered, roaming 323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mStat; // for CREG 324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String mRingingNumber; // Context for in-progress RING's 326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int mRingingType; 327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean mIgnoreRing = false; 328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SERVICE_STATE_CHANGED = 1; 330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int PHONE_STATE_CHANGED = 2; 331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int RING = 3; 332b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville private static final int PHONE_CDMA_CALL_WAITING = 4; 333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private Handler mStateChangeHandler = new Handler() { 335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void handleMessage(Message msg) { 337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(msg.what) { 338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RING: 339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = ring(); 340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result != null) { 341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SERVICE_STATE_CHANGED: 345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ServiceState state = (ServiceState) ((AsyncResult) msg.obj).result; 346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateServiceState(sendUpdate(), state); 347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case PHONE_STATE_CHANGED: 349b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville case PHONE_CDMA_CALL_WAITING: 350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection connection = null; 351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (((AsyncResult) msg.obj).result instanceof Connection) { 352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connection = (Connection) ((AsyncResult) msg.obj).result; 353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updatePhoneState(sendUpdate(), connection); 355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private BluetoothPhoneState() { 361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // init members 362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateServiceState(false, mPhone.getServiceState()); 363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updatePhoneState(false, null); 364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = 5; // There is currently no API to get battery level 365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // on demand, so set to 5 and wait for an update 366404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mSignal = asuToSignal(mPhone.getSignalStrength()); 367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // register for updates 369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone.registerForServiceStateChanged(mStateChangeHandler, 370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SERVICE_STATE_CHANGED, null); 371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone.registerForPhoneStateChanged(mStateChangeHandler, 372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PHONE_STATE_CHANGED, null); 373b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville if (mPhone.getPhoneName().equals("CDMA")) { 374b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville mPhone.registerForCallWaiting(mStateChangeHandler, 375b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PHONE_CDMA_CALL_WAITING, null); 376b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } 377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project IntentFilter filter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); 378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project filter.addAction(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED); 379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.registerReceiver(mStateReceiver, filter); 380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 382a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville private void updateBtPhoneStateAfterRadioTechnologyChange() { 383a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville if(DBG) Log.d(TAG, "updateBtPhoneStateAfterRadioTechnologyChange..."); 384a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 385a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Unregister all events from the old obsolete phone 386a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mPhone.unregisterForServiceStateChanged(mStateChangeHandler); 387a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mPhone.unregisterForPhoneStateChanged(mStateChangeHandler); 388b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville mPhone.unregisterForCallWaiting(mStateChangeHandler); 389a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 390a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Register all events new to the new active phone 391a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mPhone.registerForServiceStateChanged(mStateChangeHandler, SERVICE_STATE_CHANGED, null); 392a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mPhone.registerForPhoneStateChanged(mStateChangeHandler, PHONE_STATE_CHANGED, null); 393b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville if (mPhone.getPhoneName().equals("CDMA")) { 394b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville mPhone.registerForCallWaiting(mStateChangeHandler, 395b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PHONE_CDMA_CALL_WAITING, null); 396b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } 397a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 398a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendUpdate() { 400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mIndicatorsEnabled; 401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean sendClipUpdate() { 404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return isHeadsetConnected() && mHeadsetType == TYPE_HANDSFREE && mClip; 405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 407b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,31] ASU signal strength to the [0,5] expected by 408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * bluetooth devices. Scale is similar to status bar policy 409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 410404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville private int gsmAsuToSignal(int asu) { 411b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (asu >= 16) return 5; 412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 8) return 4; 413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 4) return 3; 414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 2) return 2; 415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else if (asu >= 1) return 1; 416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project else return 0; 417b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 419404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville /* convert cdma dBm signal strength to the [0,5] expected by 420404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville * bluetooth devices. Scale is similar to status bar policy 421404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville */ 422404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville private int cdmaDbmToSignal(int cdmaDbm) { 423404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (cdmaDbm >= -75) return 5; 424404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville else if (cdmaDbm >= -85) return 4; 425404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville else if (cdmaDbm >= -95) return 3; 426404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville else if (cdmaDbm >= -100) return 2; 427404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville else if (cdmaDbm >= -105) return 2; 428404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville else return 0; 429404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 430404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 431404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 432404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville private int asuToSignal(SignalStrength signalStrength) { 433404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (!signalStrength.isGsm()) { 434404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville return gsmAsuToSignal(signalStrength.getCdmaDbm()); 435404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 436404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville return cdmaDbmToSignal(signalStrength.getGsmSignalStrength()); 437404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 438404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 439404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 440404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* convert [0,5] signal strength to a rssi signal strength for CSQ 442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * which is [0,31]. Despite the same scale, this is not the same value 443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * as ASU. 444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private int signalToRssi(int signal) { 446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // using C4A suggested values 447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (signal) { 448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 0: return 0; 449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 1: return 4; 450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 2: return 8; 451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 3: return 13; 452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 4: return 19; 453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case 5: return 31; 454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return 0; 456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final BroadcastReceiver mStateReceiver = new BroadcastReceiver() { 460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 461b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void onReceive(Context context, Intent intent) { 462b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_BATTERY_CHANGED)) { 463b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateBatteryState(intent); 464b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (intent.getAction().equals(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED)) { 465b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project updateSignalState(intent); 466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 468b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateBatteryState(Intent intent) { 471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = intent.getIntExtra("level", -1); 472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int scale = intent.getIntExtra("scale", -1); 473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel == -1 || scale == -1) { 474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; // ignore 475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project batteryLevel = batteryLevel * 5 / scale; 477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mBattchg != batteryLevel) { 478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBattchg = batteryLevel; 479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 7," + mBattchg); 481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 483b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateSignalState(Intent intent) { 486404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // NOTE this function is called by the BroadcastReceiver mStateReceiver after intent 487404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville // ACTION_SIGNAL_STRENGTH_CHANGED and by the DebugThread mDebugThread 488404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = SignalStrength.newFromBundle(intent.getExtras()); 489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signal; 490404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville 491404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signalStrength != null) { 492404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signal = asuToSignal(signalStrength); 493404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mRssi = signalToRssi(signal); // no unsolicited CSQ 494404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (signal != mSignal) { 495404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville mSignal = signal; 496404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville if (sendUpdate()) { 497404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville sendURC("+CIEV: 5," + mSignal); 498404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } 499b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 500404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville } else { 501404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Log.e(TAG, "Signal Strength null"); 502b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 503b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 504b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 505b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updateServiceState(boolean sendUpdate, ServiceState state) { 506b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int service = state.getState() == ServiceState.STATE_IN_SERVICE ? 1 : 0; 507b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int roam = state.getRoaming() ? 1 : 0; 508b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int stat; 509b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 510b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 511b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service == 0) { 512b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = 0; 513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project stat = (roam == 1) ? 5 : 1; 515b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (service != mService) { 518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mService = service; 519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 1," + mService); 521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (roam != mRoam) { 524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRoam = roam; 525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 6," + mRoam); 527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 529b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (stat != mStat) { 530b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStat = stat; 531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(toCregString()); 533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 537b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void updatePhoneState(boolean sendUpdate, Connection connection) { 540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int call = 0; 541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callsetup = 0; 542b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int callheld = 0; 543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int prevCallsetup = mCallsetup; 544b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 545b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("updatePhoneState()"); 547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 5481dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh Phone.State newState = mPhone.getState(); 5491dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh if (newState != mPhoneState) { 5501dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mPhoneState = newState; 5511dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh switch (mPhoneState) { 5521dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh case IDLE: 5531dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mUserWantsAudio = true; // out of call - reset state 5541dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh audioOff(); 5551dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh break; 5561dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh default: 5571dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh callStarted(); 5581dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh } 559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mForegroundCall.getState()) { 562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 2; 568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = false; 569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 570b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 3; 572b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Open the SCO channel for the outgoing call. 573b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = true; 575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioPossible = false; 578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mRingingCall.getState()) { 581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 583b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callsetup = 1; 584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch(mBackgroundCall.getState()) { 588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 1; 591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project call = 1; 593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project callheld = 2; 594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCall != call) { 599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call == 1) { 600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This means that a call has transitioned from NOT ACTIVE to ACTIVE. 601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Switch on audio. 602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 604b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCall = call; 605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 2," + mCall); 607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallsetup != callsetup) { 610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = callsetup; 611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 6124b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // If mCall = 0, send CIEV 6134b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 0, send CIEV 6144b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 1, send CIEV after CCWA, 6154b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way supported. 6164b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // mCall = 1, mCallsetup = 2 / 3 -> send CIEV, 6174b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project // if 3 way is supported 6184b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project if (mCall != 1 || mCallsetup == 0 || 6194b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project mCallsetup != 1 && (mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 3," + mCallsetup); 621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean callsSwitched = 626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (callheld == 1 && ! (mBackgroundCall.getEarliestConnectTime() == 627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBgndEarliestConnectionTime)); 628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBgndEarliestConnectionTime = mBackgroundCall.getEarliestConnectTime(); 630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCallheld != callheld || callsSwitched) { 632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld = callheld; 633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate) { 634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CIEV: 4," + mCallheld); 635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (callsetup == 1 && callsetup != prevCallsetup) { 639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // new incoming call 640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = null; 641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = 128; 642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // find incoming phone number and type 643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connection = mRingingCall.getEarliestConnection(); 645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection == null) { 646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Could not get a handle on Connection object for new " + 647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "incoming call"); 648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (connection != null) { 651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = connection.getAddress(); 652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project number = ""; 658b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 659b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((call != 0 || callheld != 0) && sendUpdate) { 660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // call waiting 661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) != 0x0) { 662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CCWA: \"" + number + "\"," + type); 6634b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project result.addResponse("+CIEV: 3," + callsetup); 664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 665b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 666b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // regular new incoming call 667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingNumber = number; 668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRingingType = type; 669b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = false; 670b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 671b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((mLocalBrsf & BRSF_AG_IN_BAND_RING) == 0x1) { 672b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResult(ring()); 675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult ring() { 681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mIgnoreRing && mRingingCall.isRinging()) { 682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("RING"); 684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendClipUpdate()) { 685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CLIP: \"" + mRingingNumber + "\"," + mRingingType); 686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = mStateChangeHandler.obtainMessage(RING); 689b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStateChangeHandler.sendMessageDelayed(msg, 3000); 690b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 691b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 693b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized String toCregString() { 696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new String("+CREG: 1," + mStat); 697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCindResult() { 700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CIND: " + mService + "," + mCall + "," + mCallsetup + "," + 702b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallheld + "," + mSignal + "," + mRoam + "," + mBattchg; 703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult toCsqResult() { 708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String status = "+CSQ: " + mRssi + ",99"; 710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(status); 711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult getCindTestResult() { 716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CIND: (\"service\",(0-1))," + "(\"call\",(0-1))," + 717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"callsetup\",(0-3)),(\"callheld\",(0-2)),(\"signal\",(0-5))," + 718b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "(\"roam\",(0-1)),(\"battchg\",(0-5))"); 719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void ignoreRing() { 722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCallsetup = 0; 723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIgnoreRing = true; 724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sendUpdate()) { 725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+CIEV: 3," + mCallsetup); 726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_ACCEPTED = 1; 732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CONNECTED = 2; 733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int SCO_CLOSED = 3; 734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_CALL_STARTED = 4; 735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int CHECK_VOICE_RECOGNITION_STARTED = 5; 736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private final Handler mHandler = new Handler() { 738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public synchronized void handleMessage(Message msg) { 740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (msg.what) { 741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SCO_ACCEPTED: 742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isHeadsetConnected() && (mAudioPossible || allowAudioAnytime()) && 744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco == null) { 745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.i(TAG, "Routing audio for incoming SCO connection"); 746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = (ScoSocket)msg.obj; 747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(true); 7484079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED); 749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.i(TAG, "Rejecting incoming SCO connection"); 751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((ScoSocket)msg.obj).close(); 752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } // else error trying to accept, try again 754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = createScoSocket(); 755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco.accept(); 756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SCO_CONNECTED: 758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (msg.arg1 == ScoSocket.STATE_CONNECTED && isHeadsetConnected() && 759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco == null) { 760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("Routing audio for outgoing SCO conection"); 761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = (ScoSocket)msg.obj; 762b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(true); 7634079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_CONNECTED); 764b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (msg.arg1 == ScoSocket.STATE_CONNECTED) { 765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("Rejecting new connected outgoing SCO socket"); 766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((ScoSocket)msg.obj).close(); 767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco.close(); 768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 770b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 771b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case SCO_CLOSED: 772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco == (ScoSocket)msg.obj) { 773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = null; 774b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(false); 7754079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED); 776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (mOutgoingSco == (ScoSocket)msg.obj) { 777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (mIncomingSco == (ScoSocket)msg.obj) { 779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIncomingSco = null; 780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case CHECK_CALL_STARTED: 783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForCallStart) { 784b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = false; 785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Timeout waiting for call to start"); 786b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("ERROR"); 787b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartCallWakeLock.isHeld()) { 788b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.release(); 789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case CHECK_VOICE_RECOGNITION_STARTED: 793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForVoiceRecognition) { 794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = false; 795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(TAG, "Timeout waiting for voice recognition to start"); 796b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("ERROR"); 797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 802b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 803b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private ScoSocket createScoSocket() { 804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new ScoSocket(mPowerManager, mHandler, SCO_ACCEPTED, SCO_CONNECTED, SCO_CLOSED); 805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 8074079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project private void broadcastAudioStateIntent(int state) { 8084079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project if (VDBG) log("broadcastAudioStateIntent(" + state + ")"); 8094079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project Intent intent = new Intent(BluetoothIntent.HEADSET_AUDIO_STATE_CHANGED_ACTION); 8104079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project intent.putExtra(BluetoothIntent.HEADSET_AUDIO_STATE, state); 8114079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project mContext.sendBroadcast(intent, android.Manifest.permission.BLUETOOTH); 8124079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project } 8134079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project 814a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 815a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville void updateBtHandsfreeAfterRadioTechnologyChange() { 816a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville if(DBG) Log.d(TAG, "updateBtHandsfreeAfterRadioTechnologyChange..."); 817a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 818a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville //Get the Call references from the new active phone again 819a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mRingingCall = mPhone.getRingingCall(); 820a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mForegroundCall = mPhone.getForegroundCall(); 821a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville mBackgroundCall = mPhone.getBackgroundCall(); 822a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 8231dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBtPhoneStateAfterRadioTechnologyChange(); 824a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville } 825a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to establish SCO (audio) connection to bluetooth 827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 828b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns false if the user has requested audio off, or if there 829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * is some other immediate problem that will prevent BT audio. 830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean audioOn() { 832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (VDBG) log("audioOn()"); 833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isHeadsetConnected()) { 834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): headset is not connected!"); 835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 8370966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (mHeadsetType == TYPE_HANDSFREE && !mServiceConnectionEstablished) { 8380966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (DBG) log("audioOn(): service connection not yet established!"); 8390966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return false; 8400966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): audio is already connected"); 844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mUserWantsAudio) { 848b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): user requested no audio, ignoring"); 849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("audioOn(): outgoing SCO already in progress"); 854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = createScoSocket(); 857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mOutgoingSco.connect(mHeadset.getAddress())) { 858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio on. 865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will establish SCO (BT audio), even if the user requested it off 866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * previously on this call. 867b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 868b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOn() { 869b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = true; 870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 871b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 872b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Used to indicate the user requested BT audio off. 873b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This will prevent us from establishing BT audio again during this call 874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if audioOn() is called. 875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void userWantsAudioOff() { 877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mUserWantsAudio = false; 878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Request to disconnect SCO (audio) connection to bluetooth 882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * headset/handsfree, if one is connected. Does not block. 883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized void audioOff() { 885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (VDBG) log("audioOff()"); 886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectedSco != null) { 888b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setBluetoothScoOn(false); 8894079f559beb3e414036056b4b33ad40de5e89c4aThe Android Open Source Project broadcastAudioStateIntent(BluetoothHeadset.AUDIO_STATE_DISCONNECTED); 890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco.close(); 891b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectedSco = null; 892b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 893b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mOutgoingSco != null) { 894b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco.close(); 895b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mOutgoingSco = null; 896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ boolean isAudioOn() { 900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return (mConnectedSco != null); 901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ void ignoreRing() { 9041dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.ignoreRing(); 905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 906b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 907b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void sendURC(String urc) { 908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isHeadsetConnected()) { 909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHeadset.sendURC(urc); 910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 911b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** helper to redial last dialled number */ 914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult redial() { 915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = mPhonebook.getLastDialledNumber(); 916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // spec seems to suggest sending ERROR if we dont have a 918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // number to redial 919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("Bluetooth redial requested (+BLDN), but no previous " + 920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "outgoing calls found. Ignoring"); 921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 922b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 923b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 924b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", number, null)); 925b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 926b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 928b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // We do not immediately respond OK, wait until we get a phone state 929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update. If we return OK now and the handsfree immeidately requests 930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // our phone state it will say we are not in call yet which confuses 931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // some devices 932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Build the +CLCC result 937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * The complexity arises from the fact that we need to maintain the same 938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CLCC index even as a call moves between states. */ 939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized AtCommandResult getClccResult() { 940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Collect all known connections 941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection[] clccConnections = new Connection[MAX_CONNECTIONS]; // indexed by CLCC index 942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> newConnections = new LinkedList<Connection>(); 943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LinkedList<Connection> connections = new LinkedList<Connection>(); 944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.getState().isAlive()) { 945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mRingingCall.getConnections()); 946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mForegroundCall.getState().isAlive()) { 948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mForegroundCall.getConnections()); 949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mBackgroundCall.getState().isAlive()) { 951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project connections.addAll(mBackgroundCall.getConnections()); 952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mark connections that we already known about 955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean clccUsed[] = new boolean[MAX_CONNECTIONS]; 956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < MAX_CONNECTIONS; i++) { 957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccUsed[i] = mClccUsed[i]; 958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = false; 959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection c : connections) { 961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean found = false; 962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = c.getCreateTime(); 963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < MAX_CONNECTIONS; i++) { 964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccUsed[i] && timestamp == mClccTimestamps[i]) { 965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project found = true; 967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = c; 968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!found) { 972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.add(c); 973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find a CLCC index for new connections 977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!newConnections.isEmpty()) { 978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find lowest empty index 979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int i = 0; 980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (mClccUsed[i]) i++; 981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Find earliest connection 982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long earliestTimestamp = newConnections.get(0).getCreateTime(); 983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection earliestConnection = newConnections.get(0); 984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int j = 0; j < newConnections.size(); j++) { 985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project long timestamp = newConnections.get(j).getCreateTime(); 986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (timestamp < earliestTimestamp) { 987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestTimestamp = timestamp; 988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project earliestConnection = newConnections.get(j); 989b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 990b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update 993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccUsed[i] = true; 994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClccTimestamps[i] = earliestTimestamp; 995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project clccConnections[i] = earliestConnection; 996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newConnections.remove(earliestConnection); 997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 998b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 999b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Build CLCC 1000b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.OK); 1001b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (int i = 0; i < clccConnections.length; i++) { 1002b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mClccUsed[i]) { 1003b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String clccEntry = connectionToClccEntry(i, clccConnections[i]); 1004b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (clccEntry != null) { 1005b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse(clccEntry); 1006b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1007b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1008b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1009b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Convert a Connection object into a single +CLCC result */ 1014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private String connectionToClccEntry(int index, Connection c) { 1015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int state; 1016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c.getState()) { 1017b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ACTIVE: 1018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 0; 1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case HOLDING: 1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 1; 1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case DIALING: 1024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 2; 1025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case ALERTING: 1027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 3; 1028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case INCOMING: 1030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 4; 1031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case WAITING: 1033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project state = 5; 1034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; // bad state 1037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int mpty = 0; 1040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Call call = c.getCall(); 1041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (call != null) { 1042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mpty = call.isMultiparty() ? 1 : 0; 1043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int direction = c.isIncoming() ? 1 : 0; 1046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int type = -1; 1049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project type = PhoneNumberUtils.toaFromString(number); 1051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1052b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String result = "+CLCC: " + (index + 1) + "," + direction + "," + state + ",0," + mpty; 1054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number != null) { 1055b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result += ",\"" + number + "\"," + type; 1056b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1057b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1060b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Headset profile 1061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1062b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHeadsetAtParser() { 1063b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("Registering Headset AT commands"); 1064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 1065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset's usually only have one button, which is meant to cause the 1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HS to send us AT+CKPD=200 or AT+CKPD. 1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CKPD", new AtCommandHandler() { 1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult headsetButtonPress() { 1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.isRinging()) { 1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer the call 1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.answerCall(mPhone); 1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If in-band ring tone is supported, SCO connection will already 1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // be up and the following call will just return. 1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (mForegroundCall.getState().isAlive()) { 1076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isAudioOn()) { 1077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Transfer audio from AG to HS 1078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1080b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mHeadset.getDirection() == HeadsetBase.DIRECTION_INCOMING && 1081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (System.currentTimeMillis() - mHeadset.getConnectTimestamp()) < 5000) { 1082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset made a recent ACL connection to us - and 1083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // made a mandatory AT+CKPD request to connect 1084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // audio which races with our automatic audio 1085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // setup. ignore 1086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang up the call 1088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.hangup(mPhone); 1090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No current call - redial last number 1094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return headsetButtonPress(); 1105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register AT Command handlers to implement the Handsfree profile 1111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void initializeHandsfreeAtParser() { 1113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("Registering Handsfree AT commands"); 1114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtParser parser = mHeadset.getAtParser(); 1115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Answer 1117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('A', new AtCommandHandler() { 1118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 1120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.answerCall(mPhone); 1121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register('D', new AtCommandHandler() { 1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleBasicCommand(String args) { 1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length() > 0) { 1128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(0) == '>') { 1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Yuck - memory dialling requested. 1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Just dial last number for now 1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.startsWith(">9999")) { // for PTS test 1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Remove trailing ';' 1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.charAt(args.length() - 1) == ';') { 1138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args = args.substring(0, args.length() - 1); 1139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_CALL_PRIVILEGED, 1141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Uri.fromParts("tel", args, null)); 1142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(intent); 1144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectCallStart(); 1146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing 1147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1150b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Hang-up command 1154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHUP", new AtCommandHandler() { 1155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mForegroundCall.isIdle()) { 1158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.hangup(mForegroundCall); 1159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!mRingingCall.isIdle()) { 1160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.hangup(mRingingCall); 1161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!mBackgroundCall.isIdle()) { 1162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.hangup(mBackgroundCall); 1163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Retrieve Supported Features command 1169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BRSF", new AtCommandHandler() { 1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private AtCommandResult sendBRSF() { 1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+BRSF: " + mLocalBrsf); 1172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+BRSF=<handsfree supported features bitmap> 1176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is telling us which features it supports. We 1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // send the features we support 1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 1 && (args[0] instanceof Integer)) { 1179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mRemoteBrsf = (Integer) args[0]; 1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(TAG, "HF didn't sent BRSF assuming 0"); 1182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This seems to be out of spec, but lets do the nice thing 1193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return sendBRSF(); 1194b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1197b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting notification on/off 1198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CCWA", new AtCommandHandler() { 1199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1200b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Seems to be out of spec, but lets return nicely 1202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1203b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call waiting is always on 1207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: 1"); 1208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CCWA=<n> 1212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree is trying to enable/disable call waiting. We 1213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // cannot disable in the current implementation. 1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request for range of supported CCWA paramters 1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CCWA: (\"n\",(1))"); 1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Event Reporting enable/disable command 1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Of the full 3GPP syntax paramters (mode, keyp, disp, ind, bfr) we 1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only support paramter ind (disable/enable evert reporting using 1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // +CDEV) 1227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMER", new AtCommandHandler() { 1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+CMER: 3,0,0," + (mIndicatorsEnabled ? "1" : "0")); 1232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length < 4) { 1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This is a syntax error 1237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3) && args[1].equals(0) && 1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project args[2].equals(0)) { 12400966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly boolean valid = false; 1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[3].equals(0)) { 1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = false; 12430966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 1244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[3].equals(1)) { 1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mIndicatorsEnabled = true; 12460966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly valid = true; 12470966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 12480966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (valid) { 12490966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if ((mRemoteBrsf & BRSF_HF_CW_THREE_WAY_CALLING) == 0x0) { 12500966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 12510966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly sendURC("OK"); // send immediately, then initiate audio 12520966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 12530966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 12540966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 12550966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // only send OK once 12560966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 12570966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } else { 12580966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.OK); 12590966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 12620966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMER: (3),(0),(0),(0-1)"); 1267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile Equipment Error Reporting enable/disable 1271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CMEE", new AtCommandHandler() { 1272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // out of spec, assume they want to enable 1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = true; 1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: " + (mCmee ? "1" : "0")); 1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CMEE=<n> 1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length == 0) { 1286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // <n> ommitted - default to 0 1287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = false; 1288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!(args[0] instanceof Integer)) { 1290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Syntax error 1291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mCmee = ((Integer)args[0] == 1); 1294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1296b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1297b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Probably not required but spec, but no harm done 1300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CMEE: (0-1)"); 1301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Last Dialled Number 1305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BLDN", new AtCommandHandler() { 1306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return redial(); 1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Indicator Update command 1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIND", new AtCommandHandler() { 1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 13161dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCindResult(); 1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 13201dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.getCindTestResult(); 1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query Signal Quality (legacy) 1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CSQ", new AtCommandHandler() { 1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 13281dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return mBluetoothPhoneState.toCsqResult(); 1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Query network registration state 1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CREG", new AtCommandHandler() { 1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 13361dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh return new AtCommandResult(mBluetoothPhoneState.toCregString()); 1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Send DTMF. I don't know if we are also expected to play the DTMF tone 1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // locally, right now we don't 1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VTS", new AtCommandHandler() { 1343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project char c; 1347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0] instanceof Integer) { 1348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((Integer) args[0]).toString().charAt(0); 1349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c = ((String) args[0]).charAt(0); 1351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isValidDtmf(c)) { 1353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhone.sendDtmf(c); 1354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean isValidDtmf(char c) { 1360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (c) { 1361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '#': 1362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case '*': 1363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (Character.digit(c, 14) != -1) { 1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; // 0-9 and A-D 1367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // List calls 1374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLCC", new AtCommandHandler() { 1375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return getClccResult(); 1378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Call Hold and Multiparty Handling command 1382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CHLD", new AtCommandHandler() { 1383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1) { 1386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 1387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean result; 1388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mRingingCall.isRinging()) { 1389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result = PhoneUtils.hangupRingingCall(mPhone); 1390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result = PhoneUtils.hangupHoldingCall(mPhone); 1392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (result) { 1394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 1399b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville if (mPhone.getPhoneName().equals("CDMA")) { 1400b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // For CDMA, there is no answerAndEndActive, so we can behave 1401b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // the same way as CHLD=2 here 1402b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PhoneUtils.answerCall(mPhone); 1403b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PhoneUtils.setMute(mPhone, false); 1404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1406b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // Hangup active call, answer held call 1407b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville if (PhoneUtils.answerAndEndActive(mPhone)) { 1408b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville return new AtCommandResult(AtCommandResult.OK); 1409b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } else { 1410b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville return new AtCommandResult(AtCommandResult.ERROR); 1411b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } 1412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(2)) { 1414b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville if (mPhone.getPhoneName().equals("CDMA")) { 1415b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // For CDMA, the way we switch to a new incoming call is by 1416b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // calling PhoneUtils.answerCall(). switchAndHoldActive() won't 1417b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville // properly update the call state within telephony. 1418b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PhoneUtils.answerCall(mPhone); 1419b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PhoneUtils.setMute(mPhone, false); 1420b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } else { 1421b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville PhoneUtils.switchHoldingAndActive(mPhone); 1422b01429c99653aef893ca3b9a92a85ab31ae85bc0Wink Saville } 1423b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1424b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(3)) { 1425b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mForegroundCall.getState().isAlive() && 1426b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mBackgroundCall.getState().isAlive()) { 1427b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneUtils.mergeCalls(mPhone); 1428b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1429b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1430b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1431b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1432b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1434b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 14360966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly mServiceConnectionEstablished = true; 1437d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("+CHLD: (0,1,2,3)"); 1438d2b5e78809bc2532b2377ba2c351d48710097c0cNick Pelly sendURC("OK"); // send reply first, then connect audio 14390966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly if (isIncallAudio()) { 14400966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly audioOn(); 14410966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly } 14420966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly // already replied 14430966f42d45611b961635c8d23fc4a4df0f5e29c4Nick Pelly return new AtCommandResult(AtCommandResult.UNSOLICITED); 1444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get Network operator name 1448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+COPS", new AtCommandHandler() { 1449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String operatorName = mPhone.getServiceState().getOperatorAlphaLong(); 1452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName != null) { 1453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (operatorName.length() > 16) { 1454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project operatorName = operatorName.substring(0, 16); 1455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+COPS: 0,0,\"" + operatorName + "\""); 1458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult( 1460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "+COPS: 0,0,\"UNKNOWN\",0"); 1461b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1462b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1463b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1464b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1465b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Handsfree only supports AT+COPS=3,0 1466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 2 || !(args[0] instanceof Integer) 1467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project || !(args[1] instanceof Integer)) { 1468b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // syntax error 1469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if ((Integer)args[0] != 3 || (Integer)args[1] != 0) { 1471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.OPERATION_NOT_SUPPORTED); 1472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Out of spec, but lets be friendly 1479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+COPS: (3),(0)"); 1480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1483b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Mobile PIN 1484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CPIN is not in the handsfree spec (although it is in 3GPP) 1485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPIN", new AtCommandHandler() { 1486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1487b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1488b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPIN: READY"); 1489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1490b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1492b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Bluetooth Response and Hold 1493b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Only supported on PDC (Japan) and CDMA networks. 1494b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BTRH", new AtCommandHandler() { 1495b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1496b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1497b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Replying with just OK indicates no response and hold 1498b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // features in use now 1499b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1500b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1501b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1502b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1503b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Neeed PDC or CDMA 1504b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1505b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1506b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1507b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1508b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Request International Mobile Subscriber Identity (IMSI) 1509b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Not in bluetooth handset spec 1510b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CIMI", new AtCommandHandler() { 1511b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1512b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CIMI 1514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String imsi = mPhone.getSubscriberId(); 1515b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (imsi == null || imsi.length() == 0) { 1516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return reportCmeError(BluetoothCmeError.SIM_FAILURE); 1517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(imsi); 1519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Calling Line Identification Presentation 1524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CLIP", new AtCommandHandler() { 1525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleReadCommand() { 1527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Currently assumes the network is provisioned for CLIP 1528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: " + (mClip ? "1" : "0") + ",1"); 1529b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1530b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CLIP=<n> 1533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && (args[0].equals(0) || args[0].equals(1))) { 1534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mClip = args[0].equals(1); 1535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1537b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 1542b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CLIP: (0-1)"); 1543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1544b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1545b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGSN - Returns the device IMEI number. 1547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGSN", new AtCommandHandler() { 1548b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Get the IMEI of the device. 1551b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // mPhone will not be NULL at this point. 1552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGSN: " + mPhone.getDeviceId()); 1553b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1554b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1555b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1556b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMM - Query Model Information 1557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMM", new AtCommandHandler() { 1558b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 1561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String model = SystemProperties.get("ro.product.model"); 1562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (model != null) { 1563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMM: " + model); 1564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1570b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+CGMI - Query Manufacturer Information 1571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CGMI", new AtCommandHandler() { 1572b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1573b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return the Model Information. 1575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String manuf = SystemProperties.get("ro.product.manufacturer"); 1576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (manuf != null) { 1577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CGMI: " + manuf); 1578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1583b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Noise Reduction and Echo Cancellation control 1585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+NREC", new AtCommandHandler() { 1586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args[0].equals(0)) { 1589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setParameter(HEADSET_NREC, "off"); 1590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args[0].equals(1)) { 1592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setParameter(HEADSET_NREC, "on"); 1593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Voice recognition (dialing) 1600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+BVRA", new AtCommandHandler() { 1601b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 16036967e2d953bc077c99c4831946201f3d333b833fNick Pelly if (BluetoothHeadset.DISABLE_BT_VOICE_DIALING) { 16046967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult(AtCommandResult.ERROR); 16056967e2d953bc077c99c4831946201f3d333b833fNick Pelly } 1606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length >= 1 && args[0].equals(1)) { 1607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project synchronized (BluetoothHandsfree.this) { 1608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mWaitingForVoiceRecognition) { 1609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 1610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mContext.startActivity(sVoiceCommandIntent); 1611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (ActivityNotFoundException e) { 1612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project expectVoiceRecognition(); 1615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.UNSOLICITED); // send nothing yet 1618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (args.length >= 1 && args[0].equals(0)) { 1619b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleTestCommand() { 16266967e2d953bc077c99c4831946201f3d333b833fNick Pelly return new AtCommandResult("+BVRA: (0-1)"); 1627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Retrieve Subscriber Number 1631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CNUM", new AtCommandHandler() { 1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = mPhone.getLine1Number(); 1635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (number == null) { 1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CNUM: ,\"" + number + "\"," + 1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneNumberUtils.toaFromString(number) + ",,4"); 1640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Microphone Gain 1644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGM", new AtCommandHandler() { 1645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGM=<gain> in range [0,15] 1648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Headset/Handsfree is reporting its current gain setting 1649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Speaker Gain 1654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+VGS", new AtCommandHandler() { 1655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleSetCommand(Object[] args) { 1657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AT+VGS=<gain> in range [0,15] 1658b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (args.length != 1 || !(args[0] instanceof Integer)) { 1659b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = (Integer) args[0]; 1662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int flag = mAudioManager.isBluetoothScoOn() ? AudioManager.FLAG_SHOW_UI:0; 1663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mAudioManager.setStreamVolume(AudioManager.STREAM_BLUETOOTH_SCO, mScoGain, flag); 1665b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.OK); 1666b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1669b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Phone activity status 1670b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project parser.register("+CPAS", new AtCommandHandler() { 1671b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1672b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult handleActionCommand() { 1673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int status = 0; 1674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (mPhone.getState()) { 1675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case IDLE: 1676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 0; 1677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case RINGING: 1679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 3; 1680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case OFFHOOK: 1682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = 4; 1683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult("+CPAS: " + status); 1686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }); 1688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mPhonebook.register(parser); 1689b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1690b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1691b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void sendScoGainUpdate(int gain) { 1692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mScoGain != gain && (mRemoteBrsf & BRSF_HF_REMOTE_VOL_CONTROL) != 0x0) { 1693b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+VGS:" + gain); 1694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mScoGain = gain; 1695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public AtCommandResult reportCmeError(int error) { 1699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mCmee) { 1700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = new AtCommandResult(AtCommandResult.UNSOLICITED); 1701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+CME ERROR: " + error); 1702b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return result; 1703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return new AtCommandResult(AtCommandResult.ERROR); 1705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_CALL_TIMEOUT = 10000; // ms 1709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectCallStart() { 1711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = true; 1712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_CALL_STARTED); 1713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_CALL_TIMEOUT); 1714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartCallWakeLock.isHeld()) { 1715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.acquire(START_CALL_TIMEOUT); 1716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1718b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void callStarted() { 1720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForCallStart) { 1721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForCallStart = false; 1722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 1723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartCallWakeLock.isHeld()) { 1724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartCallWakeLock.release(); 1725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int START_VOICE_RECOGNITION_TIMEOUT = 5000; // ms 1730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private synchronized void expectVoiceRecognition() { 1732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = true; 1733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message msg = Message.obtain(mHandler, CHECK_VOICE_RECOGNITION_STARTED); 1734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mHandler.sendMessageDelayed(msg, START_VOICE_RECOGNITION_TIMEOUT); 1735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!mStartVoiceRecognitionWakeLock.isHeld()) { 1736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.acquire(START_VOICE_RECOGNITION_TIMEOUT); 1737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1740b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean startVoiceRecognition() { 1741b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mWaitingForVoiceRecognition) { 1742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // HF initiated 1743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mWaitingForVoiceRecognition = false; 1744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("OK"); 1745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // AG initiated 1747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 1"); 1748b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean ret = audioOn(); 1750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mStartVoiceRecognitionWakeLock.isHeld()) { 1751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mStartVoiceRecognitionWakeLock.release(); 1752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return ret; 1754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ synchronized boolean stopVoiceRecognition() { 1757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC("+BVRA: 0"); 1758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1762b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean inDebug() { 1763b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return DBG && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE, false); 1764b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private boolean allowAudioAnytime() { 1767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return inDebug() && SystemProperties.getBoolean(DebugThread.DEBUG_HANDSFREE_AUDIO_ANYTIME, 1768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project false); 1769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1770b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1771b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void startDebug() { 1772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG && mDebugThread == null) { 1773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = new DebugThread(); 1774b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.start(); 1775b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private void stopDebug() { 1779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mDebugThread != null) { 1780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread.interrupt(); 1781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mDebugThread = null; 1782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1784b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug thread to read debug properties - runs when debug.bt.hfp is true 1786b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * at the time a bluetooth handsfree device is connected. Debug properties 1787b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * are polled and mock updates sent every 1 second */ 1788b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private class DebugThread extends Thread { 1789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Turns on/off handsfree profile debugging mode */ 1790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE = "debug.bt.hfp"; 1791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock battery level change - use 0 to 5 */ 1793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_BATTERY = "debug.bt.hfp.battery"; 1794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock no cellular service when false */ 1796b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SERVICE = "debug.bt.hfp.service"; 1797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock cellular roaming when true */ 1799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_ROAM = "debug.bt.hfp.roam"; 1800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** false to true transition will force an audio (SCO) connection to 1802b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * be established. true to false will force audio to be disconnected 1803b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO = "debug.bt.hfp.audio"; 1805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** true allows incoming SCO connection out of call. 1807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_AUDIO_ANYTIME = "debug.bt.hfp.audio_anytime"; 1809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Mock signal strength change in ASU - use 0 to 31 */ 1811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_SIGNAL = "debug.bt.hfp.signal"; 1812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+CLCC: print +CLCC result */ 1814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_HANDSFREE_CLCC = "debug.bt.hfp.clcc"; 1815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Debug AT+BSIR - Send In Band Ringtones Unsolicited AT command. 1817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 0 => AT+BSIR = 0 sent by the AG 1818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * debug.bt.unsol.inband = 1 => AT+BSIR = 0 sent by the AG 1819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Other values are ignored. 1820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String DEBUG_UNSOL_INBAND_RINGTONE = 1823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project "debug.bt.unsol.inband"; 1824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project @Override 1826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void run() { 1827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldService = true; 1828b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldRoam = false; 1829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean oldAudio = false; 1830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project while (!isInterrupted() && inDebug()) { 1832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int batteryLevel = SystemProperties.getInt(DEBUG_HANDSFREE_BATTERY, -1); 1833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (batteryLevel >= 0 && batteryLevel <= 5) { 1834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 1835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("level", batteryLevel); 1836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra("scale", 5); 18371dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateBatteryState(intent); 1838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean serviceStateChanged = false; 1841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_SERVICE, true) != oldService) { 1842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldService = !oldService; 1843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 1844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_ROAM, false) != oldRoam) { 1846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldRoam = !oldRoam; 1847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project serviceStateChanged = true; 1848b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (serviceStateChanged) { 1850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Bundle b = new Bundle(); 1851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putInt("state", oldService ? 0 : 1); 1852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project b.putBoolean("roaming", oldRoam); 18531dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateServiceState(true, ServiceState.newFromBundle(b)); 1854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_AUDIO, false) != oldAudio) { 1857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project oldAudio = !oldAudio; 1858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (oldAudio) { 1859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOn(); 1860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioOff(); 1862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int signalLevel = SystemProperties.getInt(DEBUG_HANDSFREE_SIGNAL, -1); 1866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (signalLevel >= 0 && signalLevel <= 31) { 1867404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville SignalStrength signalStrength = new SignalStrength(signalLevel, -1, -1, -1, 1868404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville -1, -1, -1, true); 1869b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(); 1870404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville Bundle data = new Bundle(); 1871404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville signalStrength.fillInNotifierBundle(data); 1872404edc94de563aef5fd5ba48be9114a970cb93bbWink Saville intent.putExtras(data); 18731dad0387bf2f280c12bdac172604e9779134fbcdJaikumar Ganesh mBluetoothPhoneState.updateSignalState(intent); 1874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (SystemProperties.getBoolean(DEBUG_HANDSFREE_CLCC, false)) { 1877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project log(getClccResult().toString()); 1878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sleep(1000); // 1 second 1881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (InterruptedException e) { 1882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int inBandRing = 1886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project SystemProperties.getInt(DEBUG_UNSOL_INBAND_RINGTONE, -1); 1887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (inBandRing == 0 || inBandRing == 1) { 1888b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AtCommandResult result = 1889b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new AtCommandResult(AtCommandResult.UNSOLICITED); 1890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project result.addResponse("+BSIR: " + inBandRing); 1891b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sendURC(result.toString()); 1892b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1893b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1894b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1895b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 1898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.d(TAG, msg); 1899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 1901a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1902a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1903a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 1904