1b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/* 2b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Copyright (C) 2006 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.app.AlertDialog; 20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.app.Dialog; 21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.app.ProgressDialog; 22404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.content.ComponentName; 233d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Cataniaimport android.content.ContentResolver; 24b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context; 25b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.DialogInterface; 26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Intent; 27404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.content.ServiceConnection; 282cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Cataniaimport android.content.pm.ApplicationInfo; 292cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Cataniaimport android.content.pm.PackageManager; 305e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Cataniaimport android.graphics.drawable.Drawable; 31b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.AudioManager; 32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.net.Uri; 3358a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyanimport android.net.sip.SipManager; 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult; 35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 36404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.os.IBinder; 37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message; 38404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.os.RemoteException; 39aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brownimport android.os.SystemProperties; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.text.TextUtils; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.KeyEvent; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.LayoutInflater; 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.View; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.WindowManager; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.EditText; 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.Toast; 49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 50a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Call; 51a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallStateException; 52a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallerInfo; 53a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallerInfoAsyncQuery; 54a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Connection; 55404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport com.android.internal.telephony.IExtendedNetworkService; 56a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.MmiCode; 57a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Phone; 58aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brownimport com.android.internal.telephony.TelephonyProperties; 593d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Cataniaimport com.android.internal.telephony.cdma.CdmaConnection; 608343169cc89621d46dce86449f5ee1ff5d3a4919John Wangimport com.android.internal.telephony.CallManager; 618343169cc89621d46dce86449f5ee1ff5d3a4919John Wangimport com.android.internal.telephony.sip.SipPhone; 628343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 631ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jiaimport java.util.ArrayList; 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.Hashtable; 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.Iterator; 66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.List; 67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 68b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/** 69b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Misc utilities for the Phone app. 70b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 71b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class PhoneUtils { 72b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final String LOG_TAG = "PhoneUtils"; 73796c70c99bc39295bf685061056f06ab8949c742David Brown private static final boolean DBG = (PhoneApp.DBG_LEVEL >= 2); 74796c70c99bc39295bf685061056f06ab8949c742David Brown 75b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Control stack trace for Audio Mode settings */ 76b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean DBG_SETAUDIOMODE_STACK = false; 77b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 78b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Identifier for the "Add Call" intent extra. */ 79b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final String ADD_CALL_MODE_KEY = "add_call_mode"; 80b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 81b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Return codes from placeCall() 82b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int CALL_STATUS_DIALED = 0; // The number was successfully dialed 83b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int CALL_STATUS_DIALED_MMI = 1; // The specified number was an MMI code 84b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int CALL_STATUS_FAILED = 2; // The call failed 85b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 86b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // State of the Phone's audio modes 87b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Each state can move to the other states, but within the state only certain 88b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // transitions for AudioManager.setMode() are allowed. 89b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int AUDIO_IDLE = 0; /** audio behaviour at phone idle */ 90b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int AUDIO_RINGING = 1; /** audio behaviour while ringing */ 91b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static final int AUDIO_OFFHOOK = 2; /** audio behaviour while in call. */ 92b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 93b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Speaker state, persisting between wired headset connection events */ 94b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static boolean sIsSpeakerEnabled = false; 95b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 96b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Hash table to store mute (Boolean) values based upon the connection.*/ 97b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static Hashtable<Connection, Boolean> sConnectionMuteTable = 98b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new Hashtable<Connection, Boolean>(); 99b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Static handler for the connection/mute tracking */ 101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static ConnectionHandler mConnectionHandler; 102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** Phone state changed event*/ 104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int PHONE_STATE_CHANGED = -1; 105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 10686c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu /** Define for not a special CNAP string */ 10786c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu private static final int CNAP_SPECIAL_CASE_NO = -1; 10886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu 1094ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Extended network service interface instance 1104ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang private static IExtendedNetworkService mNwService = null; 1114ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // used to cancel MMI command after 15 seconds timeout for NWService requirement 1124ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang private static Message mMmiTimeoutCbMsg = null; 1134ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 114055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent /** Noise suppression status as selected by user */ 115055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent private static boolean sIsNoiseSuppressionEnabled = true; 116055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handler that tracks the connections and updates the value of the 119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Mute settings for each connection as needed. 120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static class ConnectionHandler extends Handler { 122153b94130a5e7a0e7bb17f17ce8f1ed294453d9eDmitri Plotnikov @Override 123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void handleMessage(Message msg) { 124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AsyncResult ar = (AsyncResult) msg.obj; 125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (msg.what) { 126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case PHONE_STATE_CHANGED: 127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("ConnectionHandler: updating mute state for each connection"); 128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1298343169cc89621d46dce86449f5ee1ff5d3a4919John Wang CallManager cm = (CallManager) ar.userObj; 1308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update the foreground connections, if there are new connections. 132a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // Have to get all foreground calls instead of the active one 133a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // because there may two foreground calls co-exist in shore period 134a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // (a racing condition based on which phone changes firstly) 135a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // Otherwise the connection may get deleted. 136a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang List<Connection> fgConnections = new ArrayList<Connection>(); 137a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang for (Call fgCall : cm.getForegroundCalls()) { 138a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (!fgCall.isIdle()) { 139a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang fgConnections.addAll(fgCall.getConnections()); 140a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang } 141a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang } 142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection cn : fgConnections) { 143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sConnectionMuteTable.get(cn) == null) { 144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sConnectionMuteTable.put(cn, Boolean.FALSE); 145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 148a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // mute is connection based operation, we need loop over 149a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // all background calls instead of the first one to update 150a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang // the background connections, if there are new connections. 151a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang List<Connection> bgConnections = new ArrayList<Connection>(); 152a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang for (Call bgCall : cm.getBackgroundCalls()) { 153a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (!bgCall.isIdle()) { 154a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang bgConnections.addAll(bgCall.getConnections()); 155a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang } 156a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang } 157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection cn : bgConnections) { 158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sConnectionMuteTable.get(cn) == null) { 159a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang sConnectionMuteTable.put(cn, Boolean.FALSE); 160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Check to see if there are any lingering connections here 164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (disconnected connections), use old-school iterators to avoid 165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // concurrent modification exceptions. 166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection cn; 167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Iterator<Connection> cnlist = sConnectionMuteTable.keySet().iterator(); 168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cnlist.hasNext();) { 169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cn = cnlist.next(); 170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!fgConnections.contains(cn) && !bgConnections.contains(cn)) { 171211ff4c5c95f63f845b953f0020dfb516c01fcadDavid Brown if (DBG) log("connection '" + cn + "' not accounted for, removing."); 172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cnlist.remove(); 173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Restore the mute state of the foreground call if we're not IDLE, 177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // otherwise just clear the mute state. This is really saying that 178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // as long as there is one or more connections, we should update 179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the mute state with the earliest connection on the foreground 180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // call, and that with no connections, we should be back to a 181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // non-mute state. 1828343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (cm.getState() != Phone.State.IDLE) { 183a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang restoreMuteState(); 184b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 185a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMuteInternal(cm.getFgPhone(), false); 186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 19219dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh 1934ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 1944ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang private static ServiceConnection ExtendedNetworkServiceConnection = new ServiceConnection() { 1954ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang public void onServiceConnected(ComponentName name, IBinder iBinder) { 1964ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW onServiceConnected"); 1974ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = IExtendedNetworkService.Stub.asInterface(iBinder); 1984ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 1994ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 2004ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang public void onServiceDisconnected(ComponentName arg0) { 2014ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW onServiceDisconnected"); 2024ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 20319dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh } 2044ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang }; 205b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Register the ConnectionHandler with the phone, to receive connection events 208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2098343169cc89621d46dce86449f5ee1ff5d3a4919John Wang public static void initializeConnectionHandler(CallManager cm) { 210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mConnectionHandler == null) { 211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mConnectionHandler = new ConnectionHandler(); 212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // pass over cm as user.obj 2158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.registerForPreciseCallStateChanged(mConnectionHandler, PHONE_STATE_CHANGED, cm); 2164ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Extended NW service 2174ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang Intent intent = new Intent("com.android.ussd.IExtendedNetworkService"); 2188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.getDefaultPhone().getContext().bindService(intent, 2194ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang ExtendedNetworkServiceConnection, Context.BIND_AUTO_CREATE); 2204ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW bindService IExtendedNetworkService"); 2214ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** This class is never instantiated. */ 225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private PhoneUtils() { 226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Answer the currently-ringing call. 230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we answered the call, or false if there wasn't 232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * actually a ringing incoming call, or some other error occurred. 233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @see answerAndEndHolding() 235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @see answerAndEndActive() 236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2378343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean answerCall(Call ringing) { 2384158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("answerCall(" + ringing + ")..."); 239df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If the ringer is currently ringing and/or vibrating, stop it 242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // right now (before actually answering the call.) 243df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown app.getRinger().stopRing(); 244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean answered = false; 2468343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Phone phone = ringing.getPhone(); 24779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink boolean phoneIsCdma = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA); 248ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu BluetoothHandsfree bthf = null; 249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 25079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneIsCdma) { 25105fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu // Stop any signalInfo tone being played when a Call waiting gets answered 2528343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (ringing.getState() == Call.State.WAITING) { 253329dc035267d5f65f96021e26601df3f7cc57659Peng Zhu final CallNotifier notifier = app.notifier; 25405fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu notifier.stopSignalInfoTone(); 25505fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu } 25605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu } 25705fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu 2588343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (ringing != null && ringing.isRinging()) { 2598343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (DBG) log("answerCall: call state = " + ringing.getState()); 260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 26179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneIsCdma) { 2620fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (app.cdmaPhoneCallState.getCurrentCallState() 2630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville == CdmaPhoneCallState.PhoneCallState.IDLE) { 2640fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // This is the FIRST incoming call being answered. 2650fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Set the Phone Call State to SINGLE_ACTIVE 2660fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville app.cdmaPhoneCallState.setCurrentCallState( 2670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE); 2680fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } else { 2690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // This is the CALL WAITING call being answered. 2700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Set the Phone Call State to CONF_CALL 2710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville app.cdmaPhoneCallState.setCurrentCallState( 2720fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville CdmaPhoneCallState.PhoneCallState.CONF_CALL); 27339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // Enable "Add Call" option after answering a Call Waiting as the user 27439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // should be allowed to add another call in case one of the parties 27539a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // drops off 27639a84144262f12df44861d746788b9de92259e4fAbhishek Pillai app.cdmaPhoneCallState.setAddCallMenuStateAfterCallWaiting(true); 277c9d9ed30aa547b79b81adc13a4d148a003b6ee62w 278c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // If a BluetoothHandsfree is valid we need to set the second call state 279c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // so that the Bluetooth client can update the Call state correctly when 280c9d9ed30aa547b79b81adc13a4d148a003b6ee62w // a call waiting is answered from the Phone. 281ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu bthf = app.getBluetoothHandsfree(); 282c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (bthf != null) { 283c9d9ed30aa547b79b81adc13a4d148a003b6ee62w bthf.cdmaSetSecondCallState(true); 284c9d9ed30aa547b79b81adc13a4d148a003b6ee62w } 2850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 28762b318a7a708e464b1fc13692feeef88860064cdPeng Zhu 28862b318a7a708e464b1fc13692feeef88860064cdPeng Zhu //if (DBG) log("sPhone.acceptCall"); 289df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown app.mCM.acceptCall(ringing); 29062b318a7a708e464b1fc13692feeef88860064cdPeng Zhu answered = true; 29195bef36fa7efe381db81ec08b6244daf02414a28David Brown 29295bef36fa7efe381db81ec08b6244daf02414a28David Brown // Always reset to "unmuted" for a freshly-answered call 293a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(false); 29495bef36fa7efe381db81ec08b6244daf02414a28David Brown 295a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(); 2962eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 2972eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu // Check is phone in any dock, and turn on speaker accordingly 2982eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu activateSpeakerIfDocked(phone); 299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "answerCall: caught " + ex, ex); 301ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu 30279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneIsCdma) { 303ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu // restore the cdmaPhoneCallState and bthf.cdmaSetSecondCallState: 304ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu app.cdmaPhoneCallState.setCurrentCallState( 305ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu app.cdmaPhoneCallState.getPreviousCallState()); 306ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu if (bthf != null) { 307ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu bthf.cdmaSetSecondCallState(false); 308ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu } 309ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu } 310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return answered; 313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Smart "hang up" helper method which hangs up exactly one connection, 317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * based on the current Phone state, as follows: 318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <ul> 319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <li>If there's a ringing call, hang that up. 320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <li>Else if there's a foreground call, hang that up. 321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <li>Else if there's a background call, hang that up. 322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <li>Otherwise do nothing. 323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * </ul> 324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we successfully hung up, or false 325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if there were no active calls at all. 326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 3278343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangup(CallManager cm) { 328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean hungup = false; 3298343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Call ringing = cm.getFirstActiveRingingCall(); 3308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Call fg = cm.getActiveFgCall(); 3318343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Call bg = cm.getFirstActiveBgCall(); 332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!ringing.isIdle()) { 3344158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangup(): hanging up ringing call"); 3358343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungup = hangupRingingCall(ringing); 336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!fg.isIdle()) { 3374158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangup(): hanging up foreground call"); 338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hungup = hangup(fg); 339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!bg.isIdle()) { 3404158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangup(): hanging up background call"); 341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hungup = hangup(bg); 3424158ed3e7bdff5212a5542e662240ea0063664b2David Brown } else { 3434158ed3e7bdff5212a5542e662240ea0063664b2David Brown // No call to hang up! This is unlikely in normal usage, 3444158ed3e7bdff5212a5542e662240ea0063664b2David Brown // since the UI shouldn't be providing an "End call" button in 3454158ed3e7bdff5212a5542e662240ea0063664b2David Brown // the first place. (But it *can* happen, rarely, if an 3464158ed3e7bdff5212a5542e662240ea0063664b2David Brown // active call happens to disconnect on its own right when the 3474158ed3e7bdff5212a5542e662240ea0063664b2David Brown // user is trying to hang up..) 3484158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangup(): no active call to hang up"); 349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 3504158ed3e7bdff5212a5542e662240ea0063664b2David Brown if (DBG) log("==> hungup = " + hungup); 351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return hungup; 353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 3558343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupRingingCall(Call ringing) { 356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup ringing call"); 3578343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = ringing.getPhone().getPhoneType(); 35895bef36fa7efe381db81ec08b6244daf02414a28David Brown Call.State state = ringing.getState(); 35995bef36fa7efe381db81ec08b6244daf02414a28David Brown 36095bef36fa7efe381db81ec08b6244daf02414a28David Brown if (state == Call.State.INCOMING) { 36195bef36fa7efe381db81ec08b6244daf02414a28David Brown // Regular incoming call (with no other active calls) 3624158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangupRingingCall(): regular incoming call: hangup()"); 36395bef36fa7efe381db81ec08b6244daf02414a28David Brown return hangup(ringing); 36495bef36fa7efe381db81ec08b6244daf02414a28David Brown } else if (state == Call.State.WAITING) { 36595bef36fa7efe381db81ec08b6244daf02414a28David Brown // Call-waiting: there's an incoming call, but another call is 36695bef36fa7efe381db81ec08b6244daf02414a28David Brown // already active. 36795bef36fa7efe381db81ec08b6244daf02414a28David Brown // TODO: It would be better for the telephony layer to provide 36895bef36fa7efe381db81ec08b6244daf02414a28David Brown // a "hangupWaitingCall()" API that works on all devices, 36995bef36fa7efe381db81ec08b6244daf02414a28David Brown // rather than us having to check the phone type here and do 37095bef36fa7efe381db81ec08b6244daf02414a28David Brown // the notifier.sendCdmaCallWaitingReject() hack for CDMA phones. 3719afe1de771110096822a2501d78135575101421dJohn Wang if (phoneType == Phone.PHONE_TYPE_CDMA) { 37295bef36fa7efe381db81ec08b6244daf02414a28David Brown // CDMA: Ringing call and Call waiting hangup is handled differently. 37395bef36fa7efe381db81ec08b6244daf02414a28David Brown // For Call waiting we DO NOT call the conventional hangup(call) function 37495bef36fa7efe381db81ec08b6244daf02414a28David Brown // as in CDMA we just want to hangup the Call waiting connection. 3754158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangupRingingCall(): CDMA-specific call-waiting hangup"); 3767fe7f7e57aaa38290c37ab48867d34a279d198f3w final CallNotifier notifier = PhoneApp.getInstance().notifier; 37777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown notifier.sendCdmaCallWaitingReject(); 3787fe7f7e57aaa38290c37ab48867d34a279d198f3w return true; 379fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } else { 38095bef36fa7efe381db81ec08b6244daf02414a28David Brown // Otherwise, the regular hangup() API works for 38195bef36fa7efe381db81ec08b6244daf02414a28David Brown // call-waiting calls too. 3824158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangupRingingCall(): call-waiting call: hangup()"); 38395bef36fa7efe381db81ec08b6244daf02414a28David Brown return hangup(ringing); 3847fe7f7e57aaa38290c37ab48867d34a279d198f3w } 38579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 38695bef36fa7efe381db81ec08b6244daf02414a28David Brown // Unexpected state: the ringing call isn't INCOMING or 38795bef36fa7efe381db81ec08b6244daf02414a28David Brown // WAITING, so there's no reason to have called 38895bef36fa7efe381db81ec08b6244daf02414a28David Brown // hangupRingingCall() in the first place. 38995bef36fa7efe381db81ec08b6244daf02414a28David Brown // (Presumably the incoming call went away at the exact moment 39095bef36fa7efe381db81ec08b6244daf02414a28David Brown // we got here, so just do nothing.) 39195bef36fa7efe381db81ec08b6244daf02414a28David Brown Log.w(LOG_TAG, "hangupRingingCall: no INCOMING or WAITING call"); 39295bef36fa7efe381db81ec08b6244daf02414a28David Brown return false; 3937fe7f7e57aaa38290c37ab48867d34a279d198f3w } 394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 3968343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupActiveCall(Call foreground) { 397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup active call"); 3988343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return hangup(foreground); 399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupHoldingCall(Call background) { 402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup holding call"); 4038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return hangup(background); 404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 406bab058c1c34d10f0707cf654e9ed917f631925d1David Brown /** 407fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * Used in CDMA phones to end the complete Call session 408fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * @param phone the Phone object. 409fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * @return true if *any* call was successfully hung up 410fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai */ 411fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai static boolean hangupRingingAndActive(Phone phone) { 412fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai boolean hungUpRingingCall = false; 413fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai boolean hungUpFgCall = false; 414fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai Call ringingCall = phone.getRingingCall(); 415fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai Call fgCall = phone.getForegroundCall(); 416fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 417fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // Hang up any Ringing Call 418fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (!ringingCall.isIdle()) { 4194158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangupRingingAndActive: Hang up Ringing Call"); 4208343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungUpRingingCall = hangupRingingCall(ringingCall); 421fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 422fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 423fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // Hang up any Active Call 424fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (!fgCall.isIdle()) { 4254158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("hangupRingingAndActive: Hang up Foreground Call"); 4268343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungUpFgCall = hangupActiveCall(fgCall); 427fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 428fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 429fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai return hungUpRingingCall || hungUpFgCall; 430fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 431fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 432fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai /** 433bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * Trivial wrapper around Call.hangup(), except that we return a 434bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * boolean success code rather than throwing CallStateException on 435bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * failure. 436bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * 437bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * @return true if the call was successfully hung up, or false 438bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * if the call wasn't actually active. 439bab058c1c34d10f0707cf654e9ed917f631925d1David Brown */ 440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean hangup(Call call) { 441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 442f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang CallManager cm = PhoneApp.getInstance().mCM; 443f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang 444f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang if (call.getState() == Call.State.ACTIVE && cm.hasActiveBgCall()) { 445f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang // handle foreground call hangup while there is background call 4464158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("- hangup(Call): hangupForegroundResumeBackground..."); 447f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang cm.hangupForegroundResumeBackground(cm.getFirstActiveBgCall()); 448f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang } else { 4494158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("- hangup(Call): regular hangup()..."); 450f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang call.hangup(); 451f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang } 452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(LOG_TAG, "Call hangup: caught " + ex, ex); 455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 460bab058c1c34d10f0707cf654e9ed917f631925d1David Brown /** 461bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * Trivial wrapper around Connection.hangup(), except that we silently 462bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * do nothing (rather than throwing CallStateException) if the 463bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * connection wasn't actually active. 464bab058c1c34d10f0707cf654e9ed917f631925d1David Brown */ 465b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void hangup(Connection c) { 466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 468b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.hangup(); 469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "Connection hangup: caught " + ex, ex); 472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4758343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean answerAndEndHolding(CallManager cm, Call ringing) { 476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("end holding & answer waiting: 1"); 4778343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (!hangupHoldingCall(cm.getFirstActiveBgCall())) { 478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(LOG_TAG, "end holding failed!"); 479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("end holding & answer waiting: 2"); 4838343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return answerCall(ringing); 484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean answerAndEndActive(CallManager cm, Call ringing) { 488b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("answerAndEndActive()..."); 489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 490b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Unlike the answerCall() method, we *don't* need to stop the 491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringer or change audio modes here since the user is already 492b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in-call, which means that the audio mode is already set 493b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // correctly, and that we wouldn't have started the ringer in the 494b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // first place. 495b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 496b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // hanging up the active call also accepts the waiting call 497e31a470b6c96f571880638b039c48e8942fa632aJohn Wang // while active call and waiting call are from the same phone 498e31a470b6c96f571880638b039c48e8942fa632aJohn Wang // i.e. both from GSM phone 4998343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if ( !hangupActiveCall(cm.getActiveFgCall())) { 5008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.w(LOG_TAG, "end active call failed!"); 5018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return false; 5028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 5038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 504e31a470b6c96f571880638b039c48e8942fa632aJohn Wang // since hangupActiveCall() also accepts the ringing call 505e31a470b6c96f571880638b039c48e8942fa632aJohn Wang // check if the ringing call was already answered or not 506e31a470b6c96f571880638b039c48e8942fa632aJohn Wang // only answer it when the call still is ringing 507e31a470b6c96f571880638b039c48e8942fa632aJohn Wang if (ringing.isRinging()) { 508e31a470b6c96f571880638b039c48e8942fa632aJohn Wang return answerCall(ringing); 509e31a470b6c96f571880638b039c48e8942fa632aJohn Wang } 510e31a470b6c96f571880638b039c48e8942fa632aJohn Wang 511e31a470b6c96f571880638b039c48e8942fa632aJohn Wang return true; 512b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 513b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 514b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 5153d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * For a CDMA phone, advance the call state upon making a new 5163d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * outgoing call. 5173d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * 5183d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * <pre> 5193d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * IDLE -> SINGLE_ACTIVE 5203d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * or 5213d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * SINGLE_ACTIVE -> THRWAY_ACTIVE 5223d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * </pre> 5233d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @param app The phone instance. 5243d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania */ 5257f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown private static void updateCdmaCallStateOnNewOutgoingCall(PhoneApp app) { 5263d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (app.cdmaPhoneCallState.getCurrentCallState() == 5273d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.IDLE) { 5283d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // This is the first outgoing call. Set the Phone Call State to ACTIVE 5293d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania app.cdmaPhoneCallState.setCurrentCallState( 5303d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE); 5313d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } else { 5323d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // This is the second outgoing call. Set the Phone Call State to 3WAY 5333d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania app.cdmaPhoneCallState.setCurrentCallState( 5343d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE); 5353d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 5363d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 5373d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 5383d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania /** 539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Dial the number using the phone passed in. 540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 5413d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * If the connection is establised, this method issues a sync call 5423d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * that may block to query the caller info. 5433d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * TODO: Change the logic to use the async query. 5447a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * 5453d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @param context To perform the CallerInfo query. 546b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * @param phone the Phone object. 5477a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param number to be dialed as requested by the user. This is 5487a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * NOT the phone number to connect to. It is used only to build the 5493d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * call card and to update the call log. See above for restrictions. 5507a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param contactRef that triggered the call. Typically a 'tel:' 5517a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * uri but can also be a 'content://contacts' one. 552b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * @param isEmergencyCall indicates that whether or not this is an 553b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * emergency call 554b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * @param gatewayUri Is the address used to setup the connection, null 555b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * if not using a gateway 556b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon * 5573d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @return either CALL_STATUS_DIALED or CALL_STATUS_FAILED 5587a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania */ 559b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon public static int placeCall(Context context, Phone phone, 560df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown String number, Uri contactRef, boolean isEmergencyCall, 561b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon Uri gatewayUri) { 562b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon if (DBG) log("placeCall '" + number + "' GW:'" + gatewayUri + "'"); 563df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 564df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown 565b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon boolean useGateway = false; 566b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon if (null != gatewayUri && 567b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon !isEmergencyCall && 568b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon PhoneUtils.isRoutableViaGateway(number)) { // Filter out MMI, OTA and other codes. 569b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon useGateway = true; 570b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon } 5713d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 572ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon int status = CALL_STATUS_DIALED; 5733d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania Connection connection; 574ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon String numberToDial; 575b56ef54ecafce9304d8461a56a5e977ef9ed3e36Martin Hibdon if (useGateway) { 576ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // TODO: 'tel' should be a constant defined in framework base 577ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // somewhere (it is in webkit.) 57865454c803eb305c4740885ad4995a871b034a58aDavid Brown if (null == gatewayUri || !Constants.SCHEME_TEL.equals(gatewayUri.getScheme())) { 579ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon Log.e(LOG_TAG, "Unsupported URL:" + gatewayUri); 580ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon return CALL_STATUS_FAILED; 581ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 582ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon 583ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // We can use getSchemeSpecificPart because we don't allow # 584ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // in the gateway numbers (treated a fragment delim.) However 585ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // if we allow more complex gateway numbers sequence (with 586ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // passwords or whatnot) that use #, this may break. 587ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // TODO: Need to support MMI codes. 588ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon numberToDial = gatewayUri.getSchemeSpecificPart(); 589ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 590ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon numberToDial = number; 591ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 592ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon 5933d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania try { 594df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown connection = app.mCM.dial(phone, numberToDial); 5953d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } catch (CallStateException ex) { 596f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // CallStateException means a new outgoing call is not currently 597f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // possible: either no more call slots exist, or there's another 598f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // call already in the process of dialing or ringing. 599f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown Log.w(LOG_TAG, "Exception from app.mCM.dial()", ex); 600f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown return CALL_STATUS_FAILED; 601f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown 602f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // Note that it's possible for CallManager.dial() to return 603f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // null *without* throwing an exception; that indicates that 604f85fdcac8bb2b3edb2f78d788bc0ee9989a841ebDavid Brown // we dialed an MMI (see below). 6053d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6063d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 607ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon int phoneType = phone.getPhoneType(); 608ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon 609ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // On GSM phones, null is returned for MMI codes 6103d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (null == connection) { 611ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (phoneType == Phone.PHONE_TYPE_GSM && gatewayUri == null) { 612ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (DBG) log("dialed MMI code: " + number); 613ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon status = CALL_STATUS_DIALED_MMI; 614ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // Set dialed MMI command to service 615ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (mNwService != null) { 616ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon try { 617ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon mNwService.setMmiString(number); 618ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (DBG) log("Extended NW bindService setUssdString (" + number + ")"); 619ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } catch (RemoteException e) { 620ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon mNwService = null; 621ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 622ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 623ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 624ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon status = CALL_STATUS_FAILED; 625ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 626ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 627ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (phoneType == Phone.PHONE_TYPE_CDMA) { 628ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon updateCdmaCallStateOnNewOutgoingCall(app); 629ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 6303d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 631ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // Clean up the number to be displayed. 632ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (phoneType == Phone.PHONE_TYPE_CDMA) { 633ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon number = CdmaConnection.formatDialString(number); 634ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 635ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon number = PhoneNumberUtils.extractNetworkPortion(number); 636ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon number = PhoneNumberUtils.convertKeypadLettersToDigits(number); 637ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon number = PhoneNumberUtils.formatNumber(number); 6383d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 639ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (gatewayUri == null) { 640ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // phone.dial() succeeded: we're now in a normal phone call. 641ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // attach the URI to the CallerInfo Object if it is there, 642ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // otherwise just attach the Uri Reference. 643ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // if the uri does not have a "content" scheme, then we treat 644ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // it as if it does NOT have a unique reference. 645ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon String content = context.getContentResolver().SCHEME_CONTENT; 646ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if ((contactRef != null) && (contactRef.getScheme().equals(content))) { 647ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon Object userDataObject = connection.getUserData(); 648ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (userDataObject == null) { 649ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon connection.setUserData(contactRef); 650ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 651ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // TODO: This branch is dead code, we have 652ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // just created the connection which has 653ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // no user data (null) by default. 654ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (userDataObject instanceof CallerInfo) { 655ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon ((CallerInfo) userDataObject).contactRefUri = contactRef; 656ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 657ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon ((CallerInfoToken) userDataObject).currentInfo.contactRefUri = 658ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon contactRef; 659ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 660ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 661ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 662ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } else { 663ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // Get the caller info synchronously because we need the final 664ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // CallerInfo object to update the dialed number with the one 665ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // requested by the user (and not the provider's gateway number). 666ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon CallerInfo info = null; 667ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon String content = phone.getContext().getContentResolver().SCHEME_CONTENT; 668ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if ((contactRef != null) && (contactRef.getScheme().equals(content))) { 669ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon info = CallerInfo.getCallerInfo(context, contactRef); 670ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 6713d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 672ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // Fallback, lookup contact using the phone number if the 673ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // contact's URI scheme was not content:// or if is was but 674ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // the lookup failed. 675ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (null == info) { 676ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon info = CallerInfo.getCallerInfo(context, number); 677ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 678ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon info.phoneNumber = number; 679ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon connection.setUserData(info); 680ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon } 681a4f8d09a653f1322bb3d38cd65a8cc038a984280Hung-ying Tyan setAudioMode(); 6823d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 683ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon if (DBG) log("about to activate speaker"); 684ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon // Check is phone in any dock, and turn on speaker accordingly 685ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon activateSpeakerIfDocked(phone); 6863d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6877a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 688ca3691037d0a15cc1f13a392e4fbdf2b68a728e1Martin Hibdon return status; 6897a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 6907a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 691008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman /** 692008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * Wrapper function to control when to send an empty Flash command to the network. 693008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * Mainly needed for CDMA networks, such as scenarios when we need to send a blank flash 694008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * to the network prior to placing a 3-way call for it to be successful. 695008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman */ 696008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman static void sendEmptyFlash(Phone phone) { 697008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 698008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman Call fgCall = phone.getForegroundCall(); 699008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (fgCall.getState() == Call.State.ACTIVE) { 700008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman // Send the empty flash 701008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (DBG) Log.d(LOG_TAG, "onReceive: (CDMA) sending empty flash to network"); 7028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang switchHoldingAndActive(phone.getBackgroundCall()); 703008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 704008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 705008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 706008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman 7078343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /** 7088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang * @param heldCall is the background call want to be swapped 7098343169cc89621d46dce86449f5ee1ff5d3a4919John Wang */ 7108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void switchHoldingAndActive(Call heldCall) { 7114158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("switchHoldingAndActive()..."); 712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 7138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang CallManager cm = PhoneApp.getInstance().mCM; 7148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (heldCall.isIdle()) { 7158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // no heldCall, so it is to hold active call 7168343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.switchHoldingAndActive(cm.getFgPhone().getBackgroundCall()); 7178343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } else { 7188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // has particular heldCall, so to switch 7198343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.switchHoldingAndActive(heldCall); 7208343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 721a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(cm); 722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "switchHoldingAndActive: caught " + ex, ex); 724b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 726b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Restore the mute setting from the earliest connection of the 729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * foreground call. 730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 731a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static Boolean restoreMuteState() { 732a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang Phone phone = PhoneApp.getInstance().mCM.getFgPhone(); 733a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //get the earliest connection 735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection c = phone.getForegroundCall().getEarliestConnection(); 736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only do this if connection is not null. 738b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 739b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 74079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 74179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink 742b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // retrieve the mute value. 74302a199cd143518a01b2014c303908b95dfc58afbjsh Boolean shouldMute = null; 7441f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu 7451f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // In CDMA, mute is not maintained per Connection. Single mute apply for 7461f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // a call where call can have multiple connections such as 7471f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // Three way and Call Waiting. Therefore retrieving Mute state for 7481f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // latest connection can apply for all connection in that call 7491f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu if (phoneType == Phone.PHONE_TYPE_CDMA) { 750c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman shouldMute = sConnectionMuteTable.get( 751c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman phone.getForegroundCall().getLatestConnection()); 752872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 753872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 754a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang shouldMute = sConnectionMuteTable.get(c); 755c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman } 756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (shouldMute == null) { 757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("problem retrieving mute value for this connection."); 758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project shouldMute = Boolean.FALSE; 759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set the mute value and return the result. 762a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute (shouldMute.booleanValue()); 763b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return shouldMute; 764b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 765a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang return Boolean.valueOf(getMute()); 766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 768b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan static void mergeCalls() { 769b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan mergeCalls(PhoneApp.getInstance().mCM); 770b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } 771b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan 772b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan static void mergeCalls(CallManager cm) { 773b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan int phoneType = cm.getFgPhone().getPhoneType(); 774b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan if (phoneType == Phone.PHONE_TYPE_CDMA) { 7754158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("mergeCalls(): CDMA..."); 7760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 7770fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (app.cdmaPhoneCallState.getCurrentCallState() 7780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 7798ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh // Set the Phone Call State to conference 7808ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh app.cdmaPhoneCallState.setCurrentCallState( 7818ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.CONF_CALL); 7828ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh 7830fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Send flash cmd 7849fd5e84fd6f5c2c5f488bf08d8dd9a2c0aab1370Wink Saville // TODO: Need to change the call from switchHoldingAndActive to 7850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // something meaningful as we are not actually trying to swap calls but 7860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // instead are merging two calls by sending a Flash command. 7874158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("- sending flash..."); 788b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan switchHoldingAndActive(cm.getFirstActiveBgCall()); 7890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 79079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 791b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan try { 7924158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("mergeCalls(): calling cm.conference()..."); 793b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan cm.conference(cm.getFirstActiveBgCall()); 794b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } catch (CallStateException ex) { 795b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex); 796b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } 797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void separateCall(Connection c) { 801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 802b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("separateCall: " + c.getAddress()); 803b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.separate(); 804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "separateCall: caught " + ex, ex); 806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handle the MMIInitiate message and put up an alert that lets 811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * the user cancel the operation, if applicable. 812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context context to get strings. 814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param mmiCode the MmiCode object being started. 815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param buttonCallbackMessage message to post when button is clicked. 816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param previousAlert a previous alert used in this activity. 817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return the dialog handle 818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static Dialog displayMMIInitiate(Context context, 820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode mmiCode, 821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message buttonCallbackMessage, 822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Dialog previousAlert) { 823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displayMMIInitiate: " + mmiCode); 824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (previousAlert != null) { 825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project previousAlert.dismiss(); 826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 828b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // The UI paradigm we are using now requests that all dialogs have 829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // user interaction, and that any other messages to the user should 830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // be by way of Toasts. 831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In adhering to this request, all MMI initiating "OK" dialogs 833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (non-cancelable MMIs) that end up being closed when the MMI 834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // completes (thereby showing a completion dialog) are being 835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // replaced with Toasts. 836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // As a side effect, moving to Toasts for the non-cancelable MMIs 838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // also means that buttonCallbackMessage (which was tied into "OK") 839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is no longer invokable for these dialogs. This is not a problem 840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // since the only callback messages we supported were for cancelable 841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // MMIs anyway. 842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // A cancelable MMI is really just a USSD request. The term 844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // "cancelable" here means that we can cancel the request when the 845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // system prompts us for a response, NOT while the network is 846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // processing the MMI request. Any request to cancel a USSD while 847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the network is NOT ready for a response may be ignored. 848b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // With this in mind, we replace the cancelable alert dialog with 850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // a progress dialog, displayed until we receive a request from 851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the the network. For more information, please see the comments 852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in the displayMMIComplete() method below. 853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Anything that is NOT a USSD request is a normal MMI request, 855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // which will bring up a toast (desribed above). 8564ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Optional code for Extended USSD running prompt 8574ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 8584ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("running USSD code, displaying indeterminate progress."); 8594ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // create the indeterminate progress dialog and display it. 8604ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang ProgressDialog pd = new ProgressDialog(context); 8614ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang CharSequence textmsg = ""; 8624ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 8634ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang textmsg = mNwService.getMmiRunningText(); 86419dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh 8654ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 8664ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 86719dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh textmsg = context.getText(R.string.ussdRunning); 8684ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 8694ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIInitiate (" + textmsg+ ")"); 8704ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setMessage(textmsg); 8714ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setCancelable(false); 8724ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setIndeterminate(true); 8734ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 8744ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 8754ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.show(); 8764ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // trigger a 15 seconds timeout to clear this progress dialog 8774ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = buttonCallbackMessage; 8784ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 8794ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg.getTarget().sendMessageDelayed(buttonCallbackMessage, 15000); 8804ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch(NullPointerException e) { 8814ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 8824ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 88319dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh return pd; 8844ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 8854ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean isCancelable = (mmiCode != null) && mmiCode.isCancelable(); 887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 888b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isCancelable) { 889b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("not a USSD code, displaying status toast."); 890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CharSequence text = context.getText(R.string.mmiStarted); 891b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Toast.makeText(context, text, Toast.LENGTH_SHORT) 892b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .show(); 893b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 894b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 895b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("running USSD code, displaying indeterminate progress."); 896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // create the indeterminate progress dialog and display it. 898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ProgressDialog pd = new ProgressDialog(context); 899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setMessage(context.getText(R.string.ussdRunning)); 900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setCancelable(false); 901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setIndeterminate(true); 902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 904b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.show(); 905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 906b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return pd; 907b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 911b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handle the MMIComplete message and fire off an intent to display 913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * the message. 914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context context to get strings. 916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param mmiCode MMI result. 917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param previousAlert a previous alert used in this activity. 918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void displayMMIComplete(final Phone phone, Context context, final MmiCode mmiCode, 920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message dismissCallbackMessage, 921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AlertDialog previousAlert) { 922df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 923b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CharSequence text; 924b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int title = 0; // title for the progress dialog, if needed. 925b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode.State state = mmiCode.getState(); 926b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 927b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displayMMIComplete: state=" + state); 9284ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Clear timeout trigger message 9294ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if(mMmiTimeoutCbMsg != null) { 9304ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try{ 9314ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg.getTarget().removeMessages(mMmiTimeoutCbMsg.what); 9324ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIComplete removeMsg"); 9334ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (NullPointerException e) { 9344ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 9354ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 9364ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 9374ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (state) { 940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case PENDING: 941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // USSD code asking for feedback from user. 942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = mmiCode.getMessage(); 943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("- using text from PENDING MMI message: '" + text + "'"); 944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case CANCELLED: 946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = context.getText(R.string.mmiCancelled); 947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case COMPLETE: 949df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown if (app.getPUKEntryActivity() != null) { 950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if an attempt to unPUK the device was made, we specify 951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the title and the message here. 952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project title = com.android.internal.R.string.PinMmi; 953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = context.getText(R.string.puk_unlocked); 954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // All other conditions for the COMPLETE mmi state will cause 957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the case to fall through to message logic in common with 958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the FAILED case. 959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case FAILED: 961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = mmiCode.getMessage(); 962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("- using text from MMI message: '" + text + "'"); 963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throw new IllegalStateException("Unexpected MmiCode state: " + state); 966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (previousAlert != null) { 969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project previousAlert.dismiss(); 970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Check to see if a UI exists for the PUK activation. If it does 973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // exist, then it indicates that we're trying to unblock the PUK. 97405fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu if ((app.getPUKEntryActivity() != null) && (state == MmiCode.State.COMPLETE)) { 975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displaying PUK unblocking progress dialog."); 976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // create the progress dialog, make sure the flags and type are 978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set correctly. 979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ProgressDialog pd = new ProgressDialog(app); 980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setTitle(title); 981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setMessage(text); 982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setCancelable(false); 983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setIndeterminate(true); 984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // display the dialog 988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.show(); 989b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 990b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // indicate to the Phone app that the progress dialog has 991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // been assigned for the PUK unlock / SIM READY process. 992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.setPukEntryProgressDialog(pd); 993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In case of failure to unlock, we'll need to reset the 996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // PUK unlock activity, so that the user may try again. 997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (app.getPUKEntryActivity() != null) { 998b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.setPukEntryActivity(null); 999b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1000b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1001b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // A USSD in a pending state means that it is still 1002b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // interacting with the user. 1003b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (state != MmiCode.State.PENDING) { 1004b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("MMI code has finished running."); 1005b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 10064ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Replace response message with Extended Mmi wording 10074ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 10084ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 10094ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang text = mNwService.getUserMessage(text); 10104ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 10114ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 10124ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 10134ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIInitiate (" + text + ")"); 10141b8e24dac994b507540d25b02e2c56f52bff04abDaisuke Miyakawa if (text == null || text.length() == 0) 10154ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang return; 10164ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 10174ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 1018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // displaying system alert dialog on the screen instead of 1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // using another activity to display the message. This 1020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // places the message at the forefront of the UI. 1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AlertDialog newDialog = new AlertDialog.Builder(context) 1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setMessage(text) 1023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setPositiveButton(R.string.ok, null) 1024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setCancelable(true) 1025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .create(); 1026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().setType( 1028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 1029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().addFlags( 1030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.FLAG_DIM_BEHIND); 1031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.show(); 1033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("USSD code has requested user input. Constructing input dialog."); 1035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // USSD MMI code that is interacting with the user. The 1037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // basic set of steps is this: 1038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1. User enters a USSD request 1039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2. We recognize the request and displayMMIInitiate 1040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (above) creates a progress dialog. 1041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3. Request returns and we get a PENDING or COMPLETE 1042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // message. 1043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 4. These MMI messages are caught in the PhoneApp 1044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (onMMIComplete) and the InCallScreen 1045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (mHandler.handleMessage) which bring up this dialog 1046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // and closes the original progress dialog, 1047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // respectively. 1048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 5. If the message is anything other than PENDING, 1049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we are done, and the alert dialog (directly above) 1050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // displays the outcome. 1051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 6. If the network is requesting more information from 1052b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the user, the MMI will be in a PENDING state, and 1053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we display this dialog with the message. 1054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 7. User input, or cancel requests result in a return 1055b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // to step 1. Keep in mind that this is the only 1056b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // time that a USSD should be canceled. 1057b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // inflate the layout with the scrolling text area for the dialog. 1059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LayoutInflater inflater = (LayoutInflater) context.getSystemService( 1060b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Context.LAYOUT_INFLATER_SERVICE); 1061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project View dialogView = inflater.inflate(R.layout.dialog_ussd_response, null); 1062b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1063b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // get the input field. 1064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final EditText inputText = (EditText) dialogView.findViewById(R.id.input_field); 1065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // specify the dialog's click listener, with SEND and CANCEL logic. 1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final DialogInterface.OnClickListener mUSSDDialogListener = 1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new DialogInterface.OnClickListener() { 1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void onClick(DialogInterface dialog, int whichButton) { 1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (whichButton) { 1071edbbd998abc6d1d1d2c2f3b54c939779c91a2708Christian Mehlmauer case DialogInterface.BUTTON_POSITIVE: 1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project phone.sendUssdResponse(inputText.getText().toString()); 1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1074edbbd998abc6d1d1d2c2f3b54c939779c91a2708Christian Mehlmauer case DialogInterface.BUTTON_NEGATIVE: 1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mmiCode.isCancelable()) { 1076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mmiCode.cancel(); 1077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1080b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // build the dialog 1084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final AlertDialog newDialog = new AlertDialog.Builder(context) 1085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setMessage(text) 1086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setView(dialogView) 1087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setPositiveButton(R.string.send_button, mUSSDDialogListener) 1088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setNegativeButton(R.string.cancel, mUSSDDialogListener) 1089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setCancelable(false) 1090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .create(); 1091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // attach the key listener to the dialog's input field and make 1093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // sure focus is set. 1094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final View.OnKeyListener mUSSDDialogInputListener = 1095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new View.OnKeyListener() { 1096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public boolean onKey(View v, int keyCode, KeyEvent event) { 1097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (keyCode) { 1098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case KeyEvent.KEYCODE_CALL: 1099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case KeyEvent.KEYCODE_ENTER: 11009166a0644e64c7110dac3945503b13c5be013fddSang-Jun Park if(event.getAction() == KeyEvent.ACTION_DOWN) { 11019166a0644e64c7110dac3945503b13c5be013fddSang-Jun Park phone.sendUssdResponse(inputText.getText().toString()); 11029166a0644e64c7110dac3945503b13c5be013fddSang-Jun Park newDialog.dismiss(); 11039166a0644e64c7110dac3945503b13c5be013fddSang-Jun Park } 1104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project inputText.setOnKeyListener(mUSSDDialogInputListener); 1110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project inputText.requestFocus(); 1111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set the window properties of the dialog 1113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().setType( 1114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 1115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().addFlags( 1116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.FLAG_DIM_BEHIND); 1117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // now show the dialog! 1119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.show(); 1120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Cancels the current pending MMI operation, if applicable. 1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we canceled an MMI operation, or false 1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if the current pending MMI wasn't cancelable 1128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * or if there was no current pending MMI at all. 1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @see displayMMIInitiate 1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean cancelMmiCode(Phone phone) { 1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project List<? extends MmiCode> pendingMmis = phone.getPendingMmiCodes(); 1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int count = pendingMmis.size(); 1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("cancelMmiCode: num pending MMIs = " + count); 1136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean canceled = false; 1138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (count > 0) { 1139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // assume that we only have one pending MMI operation active at a time. 1140b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // I don't think it's possible to enter multiple MMI codes concurrently 1141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in the phone UI, because during the MMI operation, an Alert panel 1142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is displayed, which prevents more MMI code from being entered. 1143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode mmiCode = pendingMmis.get(0); 1144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mmiCode.isCancelable()) { 1145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mmiCode.cancel(); 1146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project canceled = true; 1147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 11504ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang //clear timeout message and pre-set MMI command 11514ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 11524ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 11534ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService.clearMmiString(); 11544ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 11554ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 115619dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh } 11574ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 11584ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mMmiTimeoutCbMsg != null) { 11594ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 11604ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 1161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return canceled; 1162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static class VoiceMailNumberMissingException extends Exception { 1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project VoiceMailNumberMissingException() { 1166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project super(); 1167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project VoiceMailNumberMissingException(String msg) { 1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project super(msg); 1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1174b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1175b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Gets the phone number to be called from an intent. Requires a Context 1176b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * to access the contacts database, and a Phone to access the voicemail 1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * number. 1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <p>If <code>phone</code> is <code>null</code>, the function will return 1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <code>null</code> for <code>voicemail:</code> URIs; 1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if <code>context</code> is <code>null</code>, the function will return 1182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <code>null</code> for person/phone URIs.</p> 1183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1184bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * <p>If the intent contains a <code>sip:</code> URI, the returned 1185bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * "number" is actually the SIP address. 1186bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * 1187b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context a context to use (or 1188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param intent the intent 1189b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1190b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @throws VoiceMailNumberMissingException if <code>intent</code> contains 1191b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * a <code>voicemail:</code> URI, but <code>phone</code> does not 1192b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * have a voicemail number set. 1193b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1194bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @return the phone number (or SIP address) that would be called by the intent, 1195b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * or <code>null</code> if the number cannot be found. 1196b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 119761bde155c038489befc9c6cb9eb1765f44daaae0John Wang static String getNumberFromIntent(Context context, Intent intent) 1198b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throws VoiceMailNumberMissingException { 1199bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown Uri uri = intent.getData(); 1200bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown String scheme = uri.getScheme(); 1201bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1202bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // The sip: scheme is simple: just treat the rest of the URI as a 1203bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // SIP address. 120465454c803eb305c4740885ad4995a871b034a58aDavid Brown if (Constants.SCHEME_SIP.equals(scheme)) { 1205bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown return uri.getSchemeSpecificPart(); 1206bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown } 1207bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1208bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // Otherwise, let PhoneNumberUtils.getNumberFromIntent() handle 1209bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // the other cases (i.e. tel: and voicemail: and contact: URIs.) 1210bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final String number = PhoneNumberUtils.getNumberFromIntent(intent, context); 1212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1213bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // Check for a voicemail-dialing request. If the voicemail number is 1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // empty, throw a VoiceMailNumberMissingException. 121565454c803eb305c4740885ad4995a871b034a58aDavid Brown if (Constants.SCHEME_VOICEMAIL.equals(scheme) && 1216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (number == null || TextUtils.isEmpty(number))) 1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throw new VoiceMailNumberMissingException(); 1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return number; 1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns the caller-id info corresponding to the specified Connection. 1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * (This is just a simple wrapper around CallerInfo.getCallerInfo(): we 1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * extract a phone number from the specified Connection, and feed that 1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * number into CallerInfo.getCallerInfo().) 1227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * The returned CallerInfo may be null in certain error cases, like if the 1229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * specified Connection was null, or if we weren't able to get a valid 1230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * phone number from the Connection. 1231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Finally, if the getCallerInfo() call did succeed, we save the resulting 1233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CallerInfo object in the "userData" field of the Connection. 1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * NOTE: This API should be avoided, with preference given to the 1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * asynchronous startGetCallerInfo API. 1237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfo getCallerInfo(Context context, Connection c) { 1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfo info = null; 1240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //See if there is a URI attached. If there is, this means 1243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //that there is no CallerInfo queried yet, so we'll need to 1244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //replace the URI with a full CallerInfo object. 1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Object userDataObject = c.getUserData(); 1246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof Uri) { 1247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = CallerInfo.getCallerInfo(context, (Uri) userDataObject); 1248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info != null) { 1249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(info); 1250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof CallerInfoToken) { 1253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //temporary result, while query is running 1254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = ((CallerInfoToken) userDataObject).currentInfo; 1255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //final query result 1257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = (CallerInfo) userDataObject; 1258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info == null) { 1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No URI, or Existing CallerInfo, so we'll have to make do with 1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // querying a new CallerInfo using the connection's phone number. 1262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("getCallerInfo: number = " + number); 1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!TextUtils.isEmpty(number)) { 1267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = CallerInfo.getCallerInfo(context, number); 1268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info != null) { 1269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(info); 1270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return info; 1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Class returned by the startGetCallerInfo call to package a temporary 1280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CallerInfo Object, to be superceded by the CallerInfo Object passed 1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * into the listener when the query with token mAsyncQueryToken is complete. 1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static class CallerInfoToken { 1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /**indicates that there will no longer be updates to this request.*/ 1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public boolean isFinal; 1286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public CallerInfo currentInfo; 1288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public CallerInfoAsyncQuery asyncQuery; 1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1290b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Start a CallerInfo Query based on the earliest connection in the call. 1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1294b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoToken startGetCallerInfo(Context context, Call call, 1295b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) { 12960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville Connection conn = null; 1297872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan int phoneType = call.getPhone().getPhoneType(); 129879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 12990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville conn = call.getLatestConnection(); 1300872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 1301872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 13020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville conn = call.getEarliestConnection(); 130379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 130479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 13050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 13060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return startGetCallerInfo(context, conn, listener, cookie); 1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * place a temporary callerinfo object in the hands of the caller and notify 1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * caller when the actual query is done. 1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoToken startGetCallerInfo(Context context, Connection c, 1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) { 1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoToken cit; 1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c == null) { 1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //TODO: perhaps throw an exception here. 1320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = null; 1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return cit; 1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1325a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown Object userDataObject = c.getUserData(); 1326a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1327a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // There are now 3 states for the Connection's userData object: 1328a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // 1329a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // (1) Uri - query has not been executed yet 1330a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // 1331a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // (2) CallerInfoToken - query is executing, but has not completed. 1332a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // 1333a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // (3) CallerInfo - query has executed. 1334a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // 1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In each case we have slightly different behaviour: 1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1. If the query has not been executed yet (Uri or null), we start 1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // query execution asynchronously, and note it by attaching a 1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // CallerInfoToken as the userData. 1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2. If the query is executing (CallerInfoToken), we've essentially 1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // reached a state where we've received multiple requests for the 1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // same callerInfo. That means that once the query is complete, 1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we'll need to execute the additional listener requested. 1343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3. If the query has already been executed (CallerInfo), we just 1344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return the CallerInfo object as expected. 1345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 4. Regarding isFinal - there are cases where the CallerInfo object 1346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // will not be attached, like when the number is empty (caller id 1347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // blocking). This flag is used to indicate that the 1348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // CallerInfoToken object is going to be permanent since no 1349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // query results will be returned. In the case where a query 1350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // has been completed, this flag is used to indicate to the caller 1351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // that the data will not be updated since it is valid. 1352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Note: For the case where a number is NOT retrievable, we leave 1354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the CallerInfo as null in the CallerInfoToken. This is 1355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // something of a departure from the original code, since the old 1356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // code manufactured a CallerInfo object regardless of the query 1357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // outcome. From now on, we will append an empty CallerInfo 1358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // object, to mirror previous behaviour, and to avoid Null Pointer 1359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Exceptions. 1360a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof Uri) { 1362a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // State (1): query has not been executed yet 1363a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //create a dummy callerinfo, populate with what we know from URI. 1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = new CallerInfo(); 1367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 1368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (Uri) userDataObject, sCallerInfoQueryListener, c); 1369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 1370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = false; 1371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(cit); 1373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query based on Uri: " + userDataObject); 1375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (userDataObject == null) { 1377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No URI, or Existing CallerInfo, so we'll have to make do with 1378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // querying a new CallerInfo using the connection's phone number. 1379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 138108cd080c56979c22092ee611a416adb86618f868David Brown if (DBG) { 13824158ed3e7bdff5212a5542e662240ea0063664b2David Brown log("PhoneUtils.startGetCallerInfo: new query for phone number..."); 138308cd080c56979c22092ee611a416adb86618f868David Brown log("- number (address): " + number); 138408cd080c56979c22092ee611a416adb86618f868David Brown log("- c: " + c); 138508cd080c56979c22092ee611a416adb86618f868David Brown log("- phone: " + c.getCall().getPhone()); 138608cd080c56979c22092ee611a416adb86618f868David Brown int phoneType = c.getCall().getPhone().getPhoneType(); 138708cd080c56979c22092ee611a416adb86618f868David Brown log("- phoneType: " + phoneType); 138808cd080c56979c22092ee611a416adb86618f868David Brown switch (phoneType) { 138908cd080c56979c22092ee611a416adb86618f868David Brown case Phone.PHONE_TYPE_NONE: log(" ==> PHONE_TYPE_NONE"); break; 139008cd080c56979c22092ee611a416adb86618f868David Brown case Phone.PHONE_TYPE_GSM: log(" ==> PHONE_TYPE_GSM"); break; 139108cd080c56979c22092ee611a416adb86618f868David Brown case Phone.PHONE_TYPE_CDMA: log(" ==> PHONE_TYPE_CDMA"); break; 139208cd080c56979c22092ee611a416adb86618f868David Brown case Phone.PHONE_TYPE_SIP: log(" ==> PHONE_TYPE_SIP"); break; 139308cd080c56979c22092ee611a416adb86618f868David Brown default: log(" ==> Unknown phone type"); break; 139408cd080c56979c22092ee611a416adb86618f868David Brown } 139508cd080c56979c22092ee611a416adb86618f868David Brown } 139608cd080c56979c22092ee611a416adb86618f868David Brown 1397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1398b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = new CallerInfo(); 1399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1400de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Store CNAP information retrieved from the Connection (we want to do this 1401de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // here regardless of whether the number is empty or not). 1402de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.cnapName = c.getCnapName(); 1403de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.name = cit.currentInfo.cnapName; // This can still get overwritten 1404de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // by ContactInfo later 1405de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.numberPresentation = c.getNumberPresentation(); 1406de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 1407de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1408a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania if (DBG) { 1409a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania log("startGetCallerInfo: number = " + number); 1410a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania log("startGetCallerInfo: CNAP Info from FW(1): name=" 1411de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + cit.currentInfo.cnapName 1412de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 1413a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania } 1414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // handling case where number is null (caller id hidden) as well. 1416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!TextUtils.isEmpty(number)) { 1417153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // Check for special CNAP cases and modify the CallerInfo accordingly 1418153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // to be sure we keep the right information to display/log later 1419153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = modifyForSpecialCnapCases(context, cit.currentInfo, number, 1420153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman cit.currentInfo.numberPresentation); 142186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu 142286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu cit.currentInfo.phoneNumber = number; 14232f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // For scenarios where we may receive a valid number from the network but a 14242f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // restricted/unavailable presentation, we do not want to perform a contact query 14252f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // (see note on isFinal above). So we set isFinal to true here as well. 14262f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman if (cit.currentInfo.numberPresentation != Connection.PRESENTATION_ALLOWED) { 14272f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = true; 14282f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } else { 142908cd080c56979c22092ee611a416adb86618f868David Brown if (DBG) log("==> Actually starting CallerInfoAsyncQuery.startQuery()..."); 14302f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 14312f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman number, sCallerInfoQueryListener, c); 14322f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 14332f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = false; 14342f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } 1435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1436b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This is the case where we are querying on a number that 1437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is null or empty, like a caller whose caller id is 1438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // blocked or empty (CLIR). The previous behaviour was to 1439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // throw a null CallerInfo object back to the user, but 1440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // this departure is somewhat cleaner. 1441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: No query to start, send trivial reply."); 1442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = true; // please see note on isFinal, above. 1443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(cit); 1446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query based on number: " + number); 1448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (userDataObject instanceof CallerInfoToken) { 1450a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // State (2): query is executing, but has not completed. 1451a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1452a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // just tack on this listener to the queue. 1453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = (CallerInfoToken) userDataObject; 1454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // handling case where number is null (caller id hidden) as well. 1456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (cit.asyncQuery != null) { 1457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 1458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query already running, adding listener: " + 1460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project listener.getClass().toString()); 1461b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 146246532b66a467f247380054270c6151aa3dc7a761Wink Saville // handling case where number/name gets updated later on by the network 146346532b66a467f247380054270c6151aa3dc7a761Wink Saville String updatedNumber = c.getAddress(); 1464de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: updatedNumber initially = " + updatedNumber); 146546532b66a467f247380054270c6151aa3dc7a761Wink Saville if (!TextUtils.isEmpty(updatedNumber)) { 146646532b66a467f247380054270c6151aa3dc7a761Wink Saville // Store CNAP information retrieved from the Connection 146746532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.cnapName = c.getCnapName(); 146846532b66a467f247380054270c6151aa3dc7a761Wink Saville // This can still get overwritten by ContactInfo 146946532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.name = cit.currentInfo.cnapName; 147046532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.numberPresentation = c.getNumberPresentation(); 147146532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 147246532b66a467f247380054270c6151aa3dc7a761Wink Saville 1473de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman updatedNumber = modifyForSpecialCnapCases(context, cit.currentInfo, 1474de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman updatedNumber, cit.currentInfo.numberPresentation); 1475de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1476de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.phoneNumber = updatedNumber; 1477de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: updatedNumber=" + updatedNumber); 1478de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: CNAP Info from FW(2): name=" 147946532b66a467f247380054270c6151aa3dc7a761Wink Saville + cit.currentInfo.cnapName 148046532b66a467f247380054270c6151aa3dc7a761Wink Saville + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 14812f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // For scenarios where we may receive a valid number from the network but a 14822f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // restricted/unavailable presentation, we do not want to perform a contact query 14832f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // (see note on isFinal above). So we set isFinal to true here as well. 14842f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman if (cit.currentInfo.numberPresentation != Connection.PRESENTATION_ALLOWED) { 14852f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = true; 14862f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } else { 14872f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 14882f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman updatedNumber, sCallerInfoQueryListener, c); 14892f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 14902f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = false; 14912f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } 149246532b66a467f247380054270c6151aa3dc7a761Wink Saville } else { 149346532b66a467f247380054270c6151aa3dc7a761Wink Saville if (DBG) log("startGetCallerInfo: No query to attach to, send trivial reply."); 149446532b66a467f247380054270c6151aa3dc7a761Wink Saville if (cit.currentInfo == null) { 149546532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo = new CallerInfo(); 149646532b66a467f247380054270c6151aa3dc7a761Wink Saville } 1497de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Store CNAP information retrieved from the Connection 1498de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.cnapName = c.getCnapName(); // This can still get 1499de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // overwritten by ContactInfo 1500de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.name = cit.currentInfo.cnapName; 1501de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.numberPresentation = c.getNumberPresentation(); 1502de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 1503de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1504de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: CNAP Info from FW(3): name=" 1505de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + cit.currentInfo.cnapName 1506de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 150746532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.isFinal = true; // please see note on isFinal, above. 1508b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1509b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1510b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1511a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // State (3): query is complete. 1512a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1513a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // The connection's userDataObject is a full-fledged 1514a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // CallerInfo instance. Wrap it in a CallerInfoToken and 1515a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // return it to the user. 1516a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = (CallerInfo) userDataObject; 1519b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = null; 1520b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = true; 1521b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // since the query is already done, call the listener. 1522b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query already done, returning CallerInfo"); 1523a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown if (DBG) log("==> cit.currentInfo = " + cit.currentInfo); 1524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return cit; 1526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1529a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown * Static CallerInfoAsyncQuery.OnQueryCompleteListener instance that 1530a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown * we use with all our CallerInfoAsyncQuery.startQuery() requests. 1531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int QUERY_TOKEN = -1; 1533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoAsyncQuery.OnQueryCompleteListener sCallerInfoQueryListener = 1534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new CallerInfoAsyncQuery.OnQueryCompleteListener () { 1535a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown /** 1536a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown * When the query completes, we stash the resulting CallerInfo 1537a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown * object away in the Connection's "userData" (where it will 1538a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown * later be retrieved by the in-call UI.) 1539a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown */ 154005fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu public void onQueryComplete(int token, Object cookie, CallerInfo ci) { 1541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("query complete, updating connection.userdata"); 15423ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania Connection conn = (Connection) cookie; 1543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1544e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai // Added a check if CallerInfo is coming from ContactInfo or from Connection. 1545e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai // If no ContactInfo, then we want to use CNAP information coming from network 154664824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania if (DBG) log("- onQueryComplete: CallerInfo:" + ci); 154764824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania if (ci.contactExists || ci.isEmergencyNumber() || ci.isVoiceMailNumber()) { 15483ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // If the number presentation has not been set by 15493ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // the ContactInfo, use the one from the 15503ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // connection. 15513ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania 15523ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // TODO: Need a new util method to merge the info 15533ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // from the Connection in a CallerInfo object. 15543ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // Here 'ci' is a new CallerInfo instance read 15553ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // from the DB. It has lost all the connection 15563ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // info preset before the query (see PhoneUtils 15573ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // line 1334). We should have a method to merge 15583ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // back into this new instance the info from the 15593ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // connection object not set by the DB. If the 15603ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // Connection already has a CallerInfo instance in 15613ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // userData, then we could use this instance to 15623ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // fill 'ci' in. The same routine could be used in 15633ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // PhoneUtils. 15643ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania if (0 == ci.numberPresentation) { 15653ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania ci.numberPresentation = conn.getNumberPresentation(); 15663ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania } 1567e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai } else { 1568a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // No matching contact was found for this number. 1569a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // Return a new CallerInfo based solely on the CNAP 1570a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // information from the network. 1571a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 15723ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania CallerInfo newCi = getCallerInfo(null, conn); 1573a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1574a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // ...but copy over the (few) things we care about 1575a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown // from the original CallerInfo object: 1576e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai if (newCi != null) { 1577e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai newCi.phoneNumber = ci.phoneNumber; // To get formatted phone number 1578a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown newCi.geoDescription = ci.geoDescription; // To get geo description string 15793ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania ci = newCi; 158064824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania } 1581e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai } 1582a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown 1583a232063e9bb9f7b8875a24af212287ba0d2cd0c3David Brown if (DBG) log("==> Stashing CallerInfo " + ci + " into the connection..."); 15843ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania conn.setUserData(ci); 1585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns a single "name" for the specified given a CallerInfo object. 1591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * If the name is null, return defaultString as the default value, usually 1592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * context.getString(R.string.unknown). 1593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static String getCompactNameFromCallerInfo(CallerInfo ci, Context context) { 1595b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("getCompactNameFromCallerInfo: info = " + ci); 1596b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String compactName = null; 1598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (ci != null) { 1599a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania if (TextUtils.isEmpty(ci.name)) { 1600a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // Perform any modifications for special CNAP cases to 1601a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // the phone number being displayed, if applicable. 1602a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania compactName = modifyForSpecialCnapCases(context, ci, ci.phoneNumber, 1603a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania ci.numberPresentation); 1604a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania } else { 1605a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // Don't call modifyForSpecialCnapCases on regular name. See b/2160795. 1606a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania compactName = ci.name; 1607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1609de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 16100fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if ((compactName == null) || (TextUtils.isEmpty(compactName))) { 1611de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // If we're still null/empty here, then check if we have a presentation 1612de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // string that takes precedence that we could return, otherwise display 1613de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // "unknown" string. 1614de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (ci != null && ci.numberPresentation == Connection.PRESENTATION_RESTRICTED) { 1615de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.private_num); 1616de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } else if (ci != null && ci.numberPresentation == Connection.PRESENTATION_PAYPHONE) { 1617de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.payphone); 1618de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } else { 1619de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.unknown); 1620de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } 1621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1622de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("getCompactNameFromCallerInfo: compactName=" + compactName); 1623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return compactName; 1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns true if the specified Call is a "conference call", meaning 1628b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * that it owns more than one Connection object. This information is 1629b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * used to trigger certain UI changes that appear when a conference 1630b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * call is active (like displaying the label "Conference call", and 1631b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * enabling the "Manage conference" UI.) 1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Watch out: This method simply checks the number of Connections, 1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * *not* their states. So if a Call has (for example) one ACTIVE 1635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * connection and one DISCONNECTED connection, this method will return 1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * true (which is unintuitive, since the Call isn't *really* a 1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * conference call any more.) 1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if the specified call has more than one connection (in any state.) 1640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean isConferenceCall(Call call) { 1642b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // CDMA phones don't have the same concept of "conference call" as 1643b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // GSM phones do; there's no special "conference call" state of 1644b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // the UI or a "manage conference" function. (Instead, when 1645b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // you're in a 3-way call, all we can do is display the "generic" 1646b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // state of the UI.) So as far as the in-call UI is concerned, 16470fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Conference corresponds to generic display. 1648df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1649b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan int phoneType = call.getPhone().getPhoneType(); 165079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 165139a84144262f12df44861d746788b9de92259e4fAbhishek Pillai CdmaPhoneCallState.PhoneCallState state = app.cdmaPhoneCallState.getCurrentCallState(); 165239a84144262f12df44861d746788b9de92259e4fAbhishek Pillai if ((state == CdmaPhoneCallState.PhoneCallState.CONF_CALL) 165339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai || ((state == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 165439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai && !app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing())) { 16550fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return true; 16560fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 1657b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } else { 16580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville List<Connection> connections = call.getConnections(); 16590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (connections != null && connections.size() > 1) { 16600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return true; 16610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 1662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1665b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // TODO: We may still want to change the semantics of this method 1666b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // to say that a given call is only really a conference call if 1667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the number of ACTIVE connections, not the total number of 1668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // connections, is greater than one. (See warning comment in the 1669b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // javadoc above.) 1670b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Here's an implementation of that: 1671b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (connections == null) { 1672b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return false; 1673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // int numActiveConnections = 0; 1675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // for (Connection conn : connections) { 1676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (DBG) log(" - CONN: " + conn + ", state = " + conn.getState()); 1677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (conn.getState() == Call.State.ACTIVE) numActiveConnections++; 1678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (numActiveConnections > 1) { 1679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return true; 1680b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1681b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return false; 1683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Launch the Dialer to start a new call. 1687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This is just a wrapper around the ACTION_DIAL intent. 1688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 16898343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void startNewCall(final CallManager cm) { 1690df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1691df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown 1692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Sanity-check that this is OK given the current state of the phone. 16938343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (!okToAddCall(cm)) { 1694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "startNewCall: can't add a new call in the current state"); 16958343169cc89621d46dce86449f5ee1ff5d3a4919John Wang dumpCallManager(); 1696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; 1697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if applicable, mute the call while we're showing the add call UI. 17008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (cm.hasActiveFgCall()) { 17018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang setMuteInternal(cm.getActiveFgCall().getPhone(), true); 1702b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Inform the phone app that this mute state was NOT done 1703b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // voluntarily by the User. 1704df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown app.setRestoreMuteOnInCallResume(true); 1705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1706b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1707b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_DIAL); 1708b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1709b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1710b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // when we request the dialer come up, we also want to inform 1711b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // it that we're going through the "add call" option from the 1712b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // InCallScreen / PhoneUtils. 1713b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra(ADD_CALL_MODE_KEY, true); 1714b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1715df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown app.startActivity(intent); 1716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1718425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent static void turnOnSpeaker(Context context, boolean flag, boolean store) { 17196b0efb615a5b1a65984192384c88965fa7dd06a0David Brown if (DBG) log("turnOnSpeaker(flag=" + flag + ", store=" + store + ")..."); 1720df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1722238e0a1134e5ce2394a382fe9630d0d8fab1b593David Brown AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioManager.setSpeakerphoneOn(flag); 1724238e0a1134e5ce2394a382fe9630d0d8fab1b593David Brown 1725b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // record the speaker-enable value 1726425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent if (store) { 1727425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent sIsSpeakerEnabled = flag; 1728425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent } 1729238e0a1134e5ce2394a382fe9630d0d8fab1b593David Brown 1730238e0a1134e5ce2394a382fe9630d0d8fab1b593David Brown // Update the status bar icon 1731238e0a1134e5ce2394a382fe9630d0d8fab1b593David Brown app.notificationMgr.updateSpeakerNotification(flag); 1732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1733b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // We also need to make a fresh call to PhoneApp.updateWakeState() 1734b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // any time the speaker state changes, since the screen timeout is 1735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // sometimes different depending on whether or not the speaker is 1736b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in use. 1737b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.updateWakeState(); 1738d3744ff481f7d96669740b015a39d7441208152bAbhishek Pillai 1739d3744ff481f7d96669740b015a39d7441208152bAbhishek Pillai // Update the Proximity sensor based on speaker state 1740089160b0b93bfe7faf67a2204475cc901cb32e55John Wang app.updateProximitySensorMode(app.mCM.getState()); 1741b9d29011e5478a48e82013b7a776c8e8d6d0816fHung-ying Tyan 1742b9d29011e5478a48e82013b7a776c8e8d6d0816fHung-ying Tyan app.mCM.setEchoSuppressionEnabled(flag); 1743b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1744b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1745b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1746b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Restore the speaker mode, called after a wired headset disconnect 1747b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * event. 1748b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void restoreSpeakerMode(Context context) { 1750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("restoreSpeakerMode, restoring to: " + sIsSpeakerEnabled); 1751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // change the mode if needed. 1753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isSpeakerOn(context) != sIsSpeakerEnabled) { 1754425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent turnOnSpeaker(context, sIsSpeakerEnabled, false); 1755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean isSpeakerOn(Context context) { 1759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return audioManager.isSpeakerphoneOn(); 1761b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1762b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1763055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1764055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static void turnOnNoiseSuppression(Context context, boolean flag, boolean store) { 1765055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("turnOnNoiseSuppression: " + flag); 1766055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1767055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1768055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1769055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return; 1770055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1771055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1772055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (flag) { 1773055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent audioManager.setParameters("noise_suppression=auto"); 1774055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } else { 1775055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent audioManager.setParameters("noise_suppression=off"); 1776055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1777055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1778055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // record the speaker-enable value 1779055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (store) { 1780055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent sIsNoiseSuppressionEnabled = flag; 1781055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1782055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1783055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // TODO: implement and manage ICON 1784055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1785055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1786055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1787055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static void restoreNoiseSuppression(Context context) { 1788055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("restoreNoiseSuppression, restoring to: " + sIsNoiseSuppressionEnabled); 1789055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1790055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1791055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return; 1792055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1793055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1794055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // change the mode if needed. 1795055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (isNoiseSuppressionOn(context) != sIsNoiseSuppressionEnabled) { 1796055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent turnOnNoiseSuppression(context, sIsNoiseSuppressionEnabled, false); 1797055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1798055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1799055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1800055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static boolean isNoiseSuppressionOn(Context context) { 1801055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1802055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1803055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return false; 1804055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1805055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1806055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1807055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent String noiseSuppression = audioManager.getParameters("noise_suppression"); 1808055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("isNoiseSuppressionOn: " + noiseSuppression); 1809055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (noiseSuppression.contains("off")) { 1810055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return false; 1811055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } else { 1812055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return true; 1813055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1814055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1815055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1817a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1818a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Mute / umute the foreground phone, which has the current foreground call 1819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * All muting / unmuting from the in-call UI should go through this 1821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * wrapper. 1822a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1823a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Wrapper around Phone.setMute() and setMicrophoneMute(). 1824a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * It also updates the connectionMuteTable and mute icon in the status bar. 1825a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1827a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static void setMute(boolean muted) { 1828a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang CallManager cm = PhoneApp.getInstance().mCM; 1829a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // make the call to mute the audio 1831a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMuteInternal(cm.getFgPhone(), muted); 1832a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update the foreground connections to match. This includes 1834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // all the connections on conference calls. 1835a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang for (Connection cn : cm.getActiveFgCall().getConnections()) { 1836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sConnectionMuteTable.get(cn) == null) { 1837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("problem retrieving mute value for this connection."); 1838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sConnectionMuteTable.put(cn, Boolean.valueOf(muted)); 1840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1844a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Internally used muting function. 1845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1846a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang private static void setMuteInternal(Phone phone, boolean muted) { 1847df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1848c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi Context context = phone.getContext(); 1849c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi boolean routeToAudioManager = 1850c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi context.getResources().getBoolean(R.bool.send_mic_mute_to_AudioManager); 1851c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi if (routeToAudioManager) { 1852c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi AudioManager audioManager = 1853c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi (AudioManager) phone.getContext().getSystemService(Context.AUDIO_SERVICE); 18544158ed3e7bdff5212a5542e662240ea0063664b2David Brown if (DBG) log("setMuteInternal: using setMicrophoneMute(" + muted + ")..."); 1855c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi audioManager.setMicrophoneMute(muted); 1856c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } else { 18574158ed3e7bdff5212a5542e662240ea0063664b2David Brown if (DBG) log("setMuteInternal: using phone.setMute(" + muted + ")..."); 1858c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi phone.setMute(muted); 1859c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } 1860df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown app.notificationMgr.updateMuteNotification(); 1861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1863a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang /** 1864a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Get the mute state of foreground phone, which has the current 1865a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * foreground call 1866a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang */ 1867a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static boolean getMute() { 1868df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1869a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1870c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi boolean routeToAudioManager = 187172ecb67bc6d7fc5d7a08fa75e35ae3c098d8c2e2Hung-ying Tyan app.getResources().getBoolean(R.bool.send_mic_mute_to_AudioManager); 1872c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi if (routeToAudioManager) { 1873c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi AudioManager audioManager = 187472ecb67bc6d7fc5d7a08fa75e35ae3c098d8c2e2Hung-ying Tyan (AudioManager) app.getSystemService(Context.AUDIO_SERVICE); 1875c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi return audioManager.isMicrophoneMute(); 1876c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } else { 187772ecb67bc6d7fc5d7a08fa75e35ae3c098d8c2e2Hung-ying Tyan return app.mCM.getMute(); 1878c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } 1879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1881a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan /* package */ static void setAudioMode() { 1882a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(PhoneApp.getInstance().mCM); 1883a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan } 1884a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan 1885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1886a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan * Sets the audio mode per current phone state. 1887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1888a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan /* package */ static void setAudioMode(CallManager cm) { 1889a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (DBG) Log.d(LOG_TAG, "setAudioMode()..." + cm.getState()); 1890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1891a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan Context context = PhoneApp.getInstance(); 1892a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan AudioManager audioManager = (AudioManager) 1893a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan context.getSystemService(Context.AUDIO_SERVICE); 1894a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan int modeBefore = audioManager.getMode(); 1895a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan cm.setAudioMode(); 1896a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan int modeAfter = audioManager.getMode(); 1897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1898a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (modeBefore != modeAfter) { 1899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Enable stack dump only when actively debugging ("new Throwable()" is expensive!) 1900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG_SETAUDIOMODE_STACK) Log.d(LOG_TAG, "Stack:", new Throwable("stack dump")); 1901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1902a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (DBG) Log.d(LOG_TAG, "setAudioMode() no change: " 1903a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan + audioModeToString(modeBefore)); 1904b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1906b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static String audioModeToString(int mode) { 1907b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (mode) { 1908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_INVALID: return "MODE_INVALID"; 1909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_CURRENT: return "MODE_CURRENT"; 1910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_NORMAL: return "MODE_NORMAL"; 1911b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_RINGTONE: return "MODE_RINGTONE"; 1912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_IN_CALL: return "MODE_IN_CALL"; 1913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: return String.valueOf(mode); 1914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handles the wired headset button while in-call. 1919b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1920b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This is called from the PhoneApp, not from the InCallScreen, 1921b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * since the HEADSETHOOK button means "mute or unmute the current 1922b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * call" *any* time a call is active, even if the user isn't actually 1923b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * on the in-call screen. 1924b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1925b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we consumed the event. 1926b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1927893d0233193b2095293d890a9ad1c73b1dc6a9a2mah /* package */ static boolean handleHeadsetHook(Phone phone, KeyEvent event) { 1928893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook()..." + event.getAction() + " " + event.getRepeatCount()); 1929df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown final PhoneApp app = PhoneApp.getInstance(); 1930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If the phone is totally idle, we ignore HEADSETHOOK events 1932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (and instead let them fall through to the media player.) 1933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (phone.getState() == Phone.State.IDLE) { 1934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Ok, the phone is in use. 1938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // The headset button button means "Answer" if an incoming call is 1939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringing. If not, it toggles the mute / unmute state. 1940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // And in any case we *always* consume this event; this means 1942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // that the usual mediaplayer-related behavior of the headset 1943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // button will NEVER happen while the user is on a call. 1944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasRingingCall = !phone.getRingingCall().isIdle(); 1946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasActiveCall = !phone.getForegroundCall().isIdle(); 1947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle(); 1948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1949893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (hasRingingCall && 1950893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getRepeatCount() == 0 && 1951893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getAction() == KeyEvent.ACTION_UP) { 19522312eba1a4821fd8f10535038555d12874e6fc67Wink Saville // If an incoming call is ringing, answer it (just like with the 19532312eba1a4821fd8f10535038555d12874e6fc67Wink Saville // CALL button): 195479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 195579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 19568343169cc89621d46dce86449f5ee1ff5d3a4919John Wang answerCall(phone.getRingingCall()); 1957872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 1958872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 19590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (hasActiveCall && hasHoldingCall) { 19600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (DBG) log("handleHeadsetHook: ringing (both lines in use) ==> answer!"); 1961df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown answerAndEndActive(app.mCM, phone.getRingingCall()); 19620fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } else { 19630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (DBG) log("handleHeadsetHook: ringing ==> answer!"); 1964df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown // answerCall() will automatically hold the current 1965df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown // active call, if there is one. 1966df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown answerCall(phone.getRingingCall()); 19670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 196879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 196979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 19702312eba1a4821fd8f10535038555d12874e6fc67Wink Saville } 19712312eba1a4821fd8f10535038555d12874e6fc67Wink Saville } else { 1972a52f06a12e64113097010cb126a722421c7c9cf3Peng Zhu // No incoming ringing call. 1973893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (event.isLongPress()) { 1974893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: longpress -> hangup"); 1975df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown hangup(app.mCM); 1976893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } 1977893d0233193b2095293d890a9ad1c73b1dc6a9a2mah else if (event.getAction() == KeyEvent.ACTION_UP && 1978893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getRepeatCount() == 0) { 1979893d0233193b2095293d890a9ad1c73b1dc6a9a2mah Connection c = phone.getForegroundCall().getLatestConnection(); 1980893d0233193b2095293d890a9ad1c73b1dc6a9a2mah // If it is NOT an emg #, toggle the mute state. Otherwise, ignore the hook. 19811ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia if (c != null && !PhoneNumberUtils.isLocalEmergencyNumber(c.getAddress(), 19821ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia PhoneApp.getInstance())) { 1983a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (getMute()) { 1984893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: UNmuting..."); 1985a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(false); 1986893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } else { 1987893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: muting..."); 1988a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(true); 1989893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } 1990a52f06a12e64113097010cb126a722421c7c9cf3Peng Zhu } 1991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Even if the InCallScreen is the current activity, there's no 1995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // need to force it to update, because (1) if we answered a 1996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringing call, the InCallScreen will imminently get a phone 1997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // state change event (causing an update), and (2) if we muted or 1998b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // unmuted, the setMute() call automagically updates the status 1999b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // bar, and there's no "mute" indication in the InCallScreen 2000b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // itself (other than the menu item, which only ever stays 2001b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // onscreen for a second anyway.) 2002b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // TODO: (2) isn't entirely true anymore. Once we return our result 2003b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // to the PhoneApp, we ask InCallScreen to update its control widgets 2004b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // in case we changed mute or speaker state and phones with touch- 2005b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // screen [toggle] buttons need to update themselves. 2006b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2007b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 2008b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2009b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Look for ANY connections on the phone that qualify as being 2012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * disconnected. 2013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 2014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we find a connection that is disconnected over 2015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * all the phone's call objects. 2016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2017b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static boolean hasDisconnectedConnections(Phone phone) { 2018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return hasDisconnectedConnections(phone.getForegroundCall()) || 2019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hasDisconnectedConnections(phone.getBackgroundCall()) || 2020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hasDisconnectedConnections(phone.getRingingCall()); 2021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Iterate over all connections in a call to see if there are any 2025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * that are not alive (disconnected or idle). 2026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 2027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we find a connection that is disconnected, and 2028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * pending removal via 2029a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville * {@link com.android.internal.telephony.gsm.GsmCall#clearDisconnected()}. 2030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 2031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean hasDisconnectedConnections(Call call) { 2032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // look through all connections for non-active ones. 2033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection c : call.getConnections()) { 2034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!c.isAlive()) { 2035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 2036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 2039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Misc UI policy helper functions 2043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we're allowed to swap calls, given the current 2047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 2048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 20498343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToSwapCalls(CallManager cm) { 20508343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = cm.getDefaultPhone().getPhoneType(); 205179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 20520fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // CDMA: "Swap" is enabled only when the phone reaches a *generic*. 20530fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // state by either accepting a Call Waiting or by merging two calls 20540fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 20550fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return (app.cdmaPhoneCallState.getCurrentCallState() 20560fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville == CdmaPhoneCallState.PhoneCallState.CONF_CALL); 2057872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 2058872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 20590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Swap" is available if both lines are in use and there's no 20600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // incoming call. (Actually we need to verify that the active 20610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // call really is in the ACTIVE state and the holding call really 20620fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // is in the HOLDING state, since you *can't* actually swap calls 20630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // when the foreground call is DIALING or ALERTING.) 20648343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return !cm.hasActiveRingingCall() 20658343169cc89621d46dce86449f5ee1ff5d3a4919John Wang && (cm.getActiveFgCall().getState() == Call.State.ACTIVE) 20668343169cc89621d46dce86449f5ee1ff5d3a4919John Wang && (cm.getFirstActiveBgCall().getState() == Call.State.HOLDING); 206779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 206879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 20690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we're allowed to merge calls, given the current 2074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 2075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 20768343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToMergeCalls(CallManager cm) { 20778343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = cm.getFgPhone().getPhoneType(); 207879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 20790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // CDMA: "Merge" is enabled only when the user is in a 3Way call. 20800fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 208139a84144262f12df44861d746788b9de92259e4fAbhishek Pillai return ((app.cdmaPhoneCallState.getCurrentCallState() 208239a84144262f12df44861d746788b9de92259e4fAbhishek Pillai == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 208339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai && !app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()); 2084b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } else { 20850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Merge" is available if both lines are in use and there's no 20860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // incoming call, *and* the current conference isn't already 20870fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // "full". 20888343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // TODO: shall move all okToMerge logic to CallManager 2089b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan return !cm.hasActiveRingingCall() && cm.hasActiveFgCall() 2090b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan && cm.hasActiveBgCall() 2091b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan && cm.canConference(cm.getFirstActiveBgCall()); 20920fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if the UI should let you add a new call, given the current 2097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 2098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 20998343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToAddCall(CallManager cm) { 21008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Phone phone = cm.getActiveFgCall().getPhone(); 21018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 2102ef181fc2a6ab6b37caa69efb5ccfe8c2c3c80be7David Brown // "Add call" is never allowed in emergency callback mode (ECM). 2103ef181fc2a6ab6b37caa69efb5ccfe8c2c3c80be7David Brown if (isPhoneInEcm(phone)) { 2104ef181fc2a6ab6b37caa69efb5ccfe8c2c3c80be7David Brown return false; 2105ef181fc2a6ab6b37caa69efb5ccfe8c2c3c80be7David Brown } 2106ef181fc2a6ab6b37caa69efb5ccfe8c2c3c80be7David Brown 210779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 21088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final Call.State fgCallState = cm.getActiveFgCall().getState(); 210979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 21104ba332e62c4d54b2623ccdc59fafd46ecba08cf0David Brown // CDMA: "Add call" button is only enabled when: 211139a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // - ForegroundCall is in ACTIVE state 211239a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // - After 30 seconds of user Ignoring/Missing a Call Waiting call. 21130fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 211439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai return ((fgCallState == Call.State.ACTIVE) 21150fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && (app.cdmaPhoneCallState.getAddCallMenuStateAfterCallWaiting())); 2116872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 2117872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 21180fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Add call" is available only if ALL of the following are true: 21190fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - There's no incoming ringing call 21200fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - There's < 2 lines in use 21210fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - The foreground call is ACTIVE or IDLE or DISCONNECTED. 21220fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // (We mainly need to make sure it *isn't* DIALING or ALERTING.) 21238343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasRingingCall = cm.hasActiveRingingCall(); 21248343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasActiveCall = cm.hasActiveFgCall(); 21258343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasHoldingCall = cm.hasActiveBgCall(); 21260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville final boolean allLinesTaken = hasActiveCall && hasHoldingCall; 21270fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 21280fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return !hasRingingCall 21290fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && !allLinesTaken 21300fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && ((fgCallState == Call.State.ACTIVE) 21310fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville || (fgCallState == Call.State.IDLE) 21320fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville || (fgCallState == Call.State.DISCONNECTED)); 213379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 213479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 21350fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 213886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu /** 213986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * Based on the input CNAP number string, 214086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * @return _RESTRICTED or _UNKNOWN for all the special CNAP strings. 214186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * Otherwise, return CNAP_SPECIAL_CASE_NO. 214286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu */ 214386c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu private static int checkCnapSpecialCases(String n) { 214486c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (n.equals("PRIVATE") || 214586c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("P") || 214686c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("RES")) { 214786c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, PRIVATE string: " + n); 214886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return Connection.PRESENTATION_RESTRICTED; 214986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } else if (n.equals("UNAVAILABLE") || 215086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("UNKNOWN") || 215186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("UNA") || 215286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("U")) { 215386c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, UNKNOWN string: " + n); 215486c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return Connection.PRESENTATION_UNKNOWN; 215586c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } else { 215686c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, normal str. number: " + n); 215786c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return CNAP_SPECIAL_CASE_NO; 215886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } 215986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } 216086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu 2161153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman /** 2162153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * Handles certain "corner cases" for CNAP. When we receive weird phone numbers 2163153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * from the network to indicate different number presentations, convert them to 2164153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * expected number and presentation values within the CallerInfo object. 2165153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @param number number we use to verify if we are in a corner case 2166153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @param presentation presentation value used to verify if we are in a corner case 2167153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @return the new String that should be used for the phone number 2168153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman */ 2169153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman /* package */ static String modifyForSpecialCnapCases(Context context, CallerInfo ci, 2170153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman String number, int presentation) { 2171de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Obviously we return number if ci == null, but still return number if 2172de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // number == null, because in these cases the correct string will still be 2173de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // displayed/logged after this function returns based on the presentation value. 21745607afe15a507715078025beff1bd743c883a5ccPaul Berman if (ci == null || number == null) return number; 21755607afe15a507715078025beff1bd743c883a5ccPaul Berman 21765607afe15a507715078025beff1bd743c883a5ccPaul Berman if (DBG) log("modifyForSpecialCnapCases: initially, number=" + number 2177a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania + ", presentation=" + presentation + " ci " + ci); 2178153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2179153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // "ABSENT NUMBER" is a possible value we could get from the network as the 2180153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // phone number, so if this happens, change it to "Unknown" in the CallerInfo 2181153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // and fix the presentation to be the same. 2182de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (number.equals(context.getString(R.string.absent_num)) 2183de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman && presentation == Connection.PRESENTATION_ALLOWED) { 2184153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.unknown); 2185153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman ci.numberPresentation = Connection.PRESENTATION_UNKNOWN; 2186153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2187153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2188de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Check for other special "corner cases" for CNAP and fix them similarly. Corner 2189de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // cases only apply if we received an allowed presentation from the network, so check 2190de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // if we think we have an allowed presentation, or if the CallerInfo presentation doesn't 2191de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // match the presentation passed in for verification (meaning we changed it previously 2192de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // because it's a corner case and we're being called from a different entry point). 2193153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (ci.numberPresentation == Connection.PRESENTATION_ALLOWED 2194de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman || (ci.numberPresentation != presentation 2195de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman && presentation == Connection.PRESENTATION_ALLOWED)) { 2196153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman int cnapSpecialCase = checkCnapSpecialCases(number); 2197153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (cnapSpecialCase != CNAP_SPECIAL_CASE_NO) { 2198153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // For all special strings, change number & numberPresentation. 2199153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (cnapSpecialCase == Connection.PRESENTATION_RESTRICTED) { 2200153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.private_num); 2201153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } else if (cnapSpecialCase == Connection.PRESENTATION_UNKNOWN) { 2202153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.unknown); 2203153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2204153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (DBG) log("SpecialCnap: number=" + number 2205153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman + "; presentation now=" + cnapSpecialCase); 2206153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman ci.numberPresentation = cnapSpecialCase; 2207153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2208153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 22095607afe15a507715078025beff1bd743c883a5ccPaul Berman if (DBG) log("modifyForSpecialCnapCases: returning number string=" + number); 2210153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman return number; 2211153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2212153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 22147a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // Support for 3rd party phone service providers. 22157a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // 22167a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 22177a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania /** 2218d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * Check if all the provider's info is present in the intent. 2219d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * @param intent Expected to have the provider's extra. 2220d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * @return true if the intent has all the extras to build the 2221d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * in-call screen's provider info overlay. 2222d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania */ 2223d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /* package */ static boolean hasPhoneProviderExtras(Intent intent) { 22242cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania if (null == intent) { 22256fac3a6bdab79725a2ca2e3102eccb3f6e9c1ac4Nicolas Catania return false; 22266fac3a6bdab79725a2ca2e3102eccb3f6e9c1ac4Nicolas Catania } 22272cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania final String name = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 22282cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania final String gatewayUri = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI); 22292cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22305e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri); 2231d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania } 2232d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania 2233d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /** 22347a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * Copy all the expected extras set when a 3rd party provider is 22357a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * used from the source intent to the destination one. Checks all 22367a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * the required extras are present, if any is missing, none will 22377a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * be copied. 22387a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param src Intent which may contain the provider's extras. 22397a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param dst Intent where a copy of the extras will be added if applicable. 22407a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania */ 2241d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /* package */ static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) { 2242d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania if (!hasPhoneProviderExtras(src)) { 2243f24849566edae03c1123203b4362c688d8fa57a9Nicolas Catania Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing."); 2244d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania return; 22457a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 2246d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania 2247d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania dst.putExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE, 2248d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania src.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE)); 2249d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania dst.putExtra(InCallScreen.EXTRA_GATEWAY_URI, 2250d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania src.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI)); 22517a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 22527a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 225362ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania /** 22542cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Get the provider's label from the intent. 22552cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param context to lookup the provider's package name. 22562cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param intent with an extra set to the provider's package name. 22575e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @return The provider's application label. null if an error 22585e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * occurred during the lookup of the package name or the label. 22592cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 22602cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static CharSequence getProviderLabel(Context context, Intent intent) { 22612cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania String packageName = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 22622cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania PackageManager pm = context.getPackageManager(); 22632cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22642cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania try { 22652cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania ApplicationInfo info = pm.getApplicationInfo(packageName, 0); 22662cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22672cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return pm.getApplicationLabel(info); 22682cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } catch (PackageManager.NameNotFoundException e) { 22692cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return null; 22702cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22712cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22722cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22732cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 22745e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * Get the provider's icon. 22755e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @param context to lookup the provider's icon. 22765e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @param intent with an extra set to the provider's package name. 22775e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @return The provider's application icon. null if an error occured during the icon lookup. 22785e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania */ 22795e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania /* package */ static Drawable getProviderIcon(Context context, Intent intent) { 22805e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania String packageName = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 22815e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania PackageManager pm = context.getPackageManager(); 22825e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania 22835e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania try { 22845e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return pm.getApplicationIcon(packageName); 22855e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } catch (PackageManager.NameNotFoundException e) { 22865e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return null; 22875e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } 22885e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } 22895e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania 22905e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania /** 22912cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Return the gateway uri from the intent. 22922cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param intent With the gateway uri extra. 22932cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @return The gateway URI or null if not found. 22942cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 22952cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static Uri getProviderGatewayUri(Intent intent) { 22962cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania String uri = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI); 22972cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return TextUtils.isEmpty(uri) ? null : Uri.parse(uri); 22982cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22992cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 23002cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 23012cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Return a formatted version of the uri's scheme specific 23022cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * part. E.g for 'tel:12345678', return '1-234-5678'. 23032cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param uri A 'tel:' URI with the gateway phone number. 23042cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @return the provider's address (from the gateway uri) formatted 23052cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * for user display. null if uri was null or its scheme was not 'tel:'. 23062cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 23072cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static String formatProviderUri(Uri uri) { 23082cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania if (null != uri) { 230965454c803eb305c4740885ad4995a871b034a58aDavid Brown if (Constants.SCHEME_TEL.equals(uri.getScheme())) { 23102cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart()); 23112cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } else { 23122cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return uri.toString(); 23132cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 23142cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 23152cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return null; 23162cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 23172cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 23182cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 231962ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * Check if a phone number can be route through a 3rd party 232062ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * gateway. The number must be a global phone number in numerical 232162ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * form (1-800-666-SEXY won't work). 232262ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * 232362ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * MMI codes and the like cannot be used as a dial number for the 232462ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * gateway either. 232562ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * 232662ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * @param number To be dialed via a 3rd party gateway. 232762ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * @return true If the number can be routed through the 3rd party network. 232862ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania */ 232962ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania /* package */ static boolean isRoutableViaGateway(String number) { 233062ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania if (TextUtils.isEmpty(number)) { 233162ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return false; 233262ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 233362ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania number = PhoneNumberUtils.stripSeparators(number); 233462ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania if (!number.equals(PhoneNumberUtils.convertKeypadLettersToDigits(number))) { 233562ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return false; 233662ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 233762ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania number = PhoneNumberUtils.extractNetworkPortion(number); 233862ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return PhoneNumberUtils.isGlobalPhoneNumber(number); 233962ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 234062ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania 23412eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu /** 23422eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * This function is called when phone answers or places a call. 23432eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * Check if the phone is in a car dock or desk dock. 23442eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * If yes, turn on the speaker, when no wired or BT headsets are connected. 23452eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * Otherwise do nothing. 23462eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu */ 23472eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu private static void activateSpeakerIfDocked(Phone phone) { 23482eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu if (DBG) log("activateSpeakerIfDocked()..."); 23492eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 2350430f42b0bee5e778078354e072b4f3e5eee9c048Jeff Brown if (PhoneApp.mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 23517f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown if (DBG) log("activateSpeakerIfDocked(): In a dock -> may need to turn on speaker."); 23522eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu PhoneApp app = PhoneApp.getInstance(); 23532eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu BluetoothHandsfree bthf = app.getBluetoothHandsfree(); 23542eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 23552eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu if (!app.isHeadsetPlugged() && !(bthf != null && bthf.isAudioOn())) { 23562eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu turnOnSpeaker(phone.getContext(), true, true); 23572eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 23582eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 23592eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 23602eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 2361aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown 2362aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown /** 2363aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown * Returns whether the phone is in ECM ("Emergency Callback Mode") or not. 2364aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown */ 2365aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown /* package */ static boolean isPhoneInEcm(Phone phone) { 236698cdd546ec6b9224863ecef92307496761067cc6David Brown if ((phone != null) && TelephonyCapabilities.supportsEcm(phone)) { 236798cdd546ec6b9224863ecef92307496761067cc6David Brown // For phones that support ECM, return true iff PROPERTY_INECM_MODE == "true". 236898cdd546ec6b9224863ecef92307496761067cc6David Brown // TODO: There ought to be a better API for this than just 236998cdd546ec6b9224863ecef92307496761067cc6David Brown // exposing a system property all the way up to the app layer, 237098cdd546ec6b9224863ecef92307496761067cc6David Brown // probably a method like "inEcm()" provided by the telephony 237198cdd546ec6b9224863ecef92307496761067cc6David Brown // layer. 2372aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown String ecmMode = 2373aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE); 2374aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown if (ecmMode != null) { 237598cdd546ec6b9224863ecef92307496761067cc6David Brown return ecmMode.equals("true"); 2376aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2377aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 237898cdd546ec6b9224863ecef92307496761067cc6David Brown return false; 2379aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2380aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown 2381bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown /** 2382bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * Returns the most appropriate Phone object to handle a call 2383bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * to the specified number. 2384bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * 2385bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param cm the CallManager. 2386bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param scheme the scheme from the data URI that the number originally came from. 2387bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param number the phone number, or SIP address. 2388bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown */ 23892587d9c6437b680911e252efecc73788e876de76Chung-yih Wang public static Phone pickPhoneBasedOnNumber(CallManager cm, 23902587d9c6437b680911e252efecc73788e876de76Chung-yih Wang String scheme, String number, String primarySipUri) { 23912587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (DBG) log("pickPhoneBasedOnNumber: scheme " + scheme 23922587d9c6437b680911e252efecc73788e876de76Chung-yih Wang + ", number " + number + ", sipUri " + primarySipUri); 23932587d9c6437b680911e252efecc73788e876de76Chung-yih Wang 23942587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (primarySipUri != null) { 23952587d9c6437b680911e252efecc73788e876de76Chung-yih Wang Phone phone = getSipPhoneFromUri(cm, primarySipUri); 23962587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (phone != null) return phone; 23972587d9c6437b680911e252efecc73788e876de76Chung-yih Wang } 23982587d9c6437b680911e252efecc73788e876de76Chung-yih Wang return cm.getDefaultPhone(); 23992587d9c6437b680911e252efecc73788e876de76Chung-yih Wang } 24002587d9c6437b680911e252efecc73788e876de76Chung-yih Wang 24012587d9c6437b680911e252efecc73788e876de76Chung-yih Wang public static Phone getSipPhoneFromUri(CallManager cm, String target) { 2402872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan for (Phone phone : cm.getAllPhones()) { 2403872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan if (phone.getPhoneType() == Phone.PHONE_TYPE_SIP) { 2404872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan String sipUri = ((SipPhone) phone).getSipUri(); 24052587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (target.equals(sipUri)) { 24062587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (DBG) log("- pickPhoneBasedOnNumber:" + 2407872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan "found SipPhone! obj = " + phone + ", " 2408872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan + phone.getClass()); 2409872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan return phone; 24108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 2411aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2412aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 24132587d9c6437b680911e252efecc73788e876de76Chung-yih Wang return null; 2414aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2415f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang 24168343169cc89621d46dce86449f5ee1ff5d3a4919John Wang public static boolean isRealIncomingCall(Call.State state) { 24178343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return (state == Call.State.INCOMING && !PhoneApp.getInstance().mCM.hasActiveFgCall()); 24188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 24198343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 2420aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown 242158a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan private static boolean sVoipSupported = false; 242258a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan static { 242358a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan PhoneApp app = PhoneApp.getInstance(); 242458a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan sVoipSupported = SipManager.isVoipSupported(app) 242558a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan && app.getResources().getBoolean(com.android.internal.R.bool.config_built_in_sip_phone) 242658a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan && app.getResources().getBoolean(com.android.internal.R.bool.config_voice_capable); 242758a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan } 242858a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan 242958a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan /** 243058a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan * @return true if this device supports voice calls using the built-in SIP stack. 243158a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan */ 243258a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan static boolean isVoipSupported() { 243358a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan return sVoipSupported; 243458a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan } 243558a62f78a11fdb9c772a8544ad302603fd58bdebHung-ying Tyan 24367a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // 2437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // General phone and call state debugging/testing code 2438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static void dumpCallState(Phone phone) { 24410f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown PhoneApp app = PhoneApp.getInstance(); 24421e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, "dumpCallState():"); 2443b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown Log.d(LOG_TAG, "- Phone: " + phone + ", name = " + phone.getPhoneName() 2444b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown + ", state = " + phone.getState()); 2445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 24461e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown StringBuilder b = new StringBuilder(128); 24471e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24481e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Call call = phone.getForegroundCall(); 24491e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24501e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - FG call: ").append(call.getState()); 24511e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24521e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24531e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24541e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24551e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24561e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 24571e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24581e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown call = phone.getBackgroundCall(); 24591e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24601e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - BG call: ").append(call.getState()); 24611e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24621e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24631e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24641e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24651e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24661e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 24671e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24681e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown call = phone.getRingingCall(); 24691e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24701e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - RINGING call: ").append(call.getState()); 24711e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24721e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24731e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24741e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24751e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24761e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 2477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasRingingCall = !phone.getRingingCall().isIdle(); 2480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasActiveCall = !phone.getForegroundCall().isIdle(); 2481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle(); 2482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean allLinesTaken = hasActiveCall && hasHoldingCall; 24831e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24841e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - hasRingingCall ").append(hasRingingCall); 24851e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasActiveCall ").append(hasActiveCall); 24861e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasHoldingCall ").append(hasHoldingCall); 24871e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" allLinesTaken ").append(allLinesTaken); 24881e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 2489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 24900f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown // On CDMA phones, dump out the CdmaPhoneCallState too: 249179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 24920f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown if (app.cdmaPhoneCallState != null) { 24931e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - CDMA call state: " 24940f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown + app.cdmaPhoneCallState.getCurrentCallState()); 24950f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } else { 24961e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - CDMA device, but null cdmaPhoneCallState!"); 24970f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } 24980f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } 24990f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown 2500b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Watch out: the isRinging() call below does NOT tell us anything 2501b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // about the state of the telephony layer; it merely tells us whether 2502b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the Ringer manager is currently playing the ringtone. 25030f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown boolean ringing = app.getRinger().isRinging(); 25041e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - Ringer state: " + ringing); 2505b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2506b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2507b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 2508796c70c99bc39295bf685061056f06ab8949c742David Brown Log.d(LOG_TAG, msg); 2509b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 25108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25118343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void dumpCallManager() { 25128343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Call call; 25138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang CallManager cm = PhoneApp.getInstance().mCM; 25148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang StringBuilder b = new StringBuilder(128); 25158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 251602d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown 251702d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown 25188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "############### dumpCallManager() ##############"); 251902d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // TODO: Don't log "cm" itself, since CallManager.toString() 252002d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // already spews out almost all this same information. 252102d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // We should fix CallManager.toString() to be more minimal, and 252202d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // use an explicit dumpState() method for the verbose dump. 252302d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // Log.d(LOG_TAG, "CallManager: " + cm 252402d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown // + ", state = " + cm.getState()); 252502d1c632adde606031c1fe6ea0e3be1e288fd6c6David Brown Log.d(LOG_TAG, "CallManager: state = " + cm.getState()); 25268343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25278343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getActiveFgCall(); 25288343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - FG call: ").append(cm.hasActiveFgCall()? "YES ": "NO "); 25298343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 25308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getActiveFgCallState()); 25318343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(cm.getFgCallConnections()); 25328343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25338343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25348343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getFirstActiveBgCall(); 25358343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - BG call: ").append(cm.hasActiveBgCall()? "YES ": "NO "); 25368343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 25378343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getFirstActiveBgCall().getState()); 25388343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(cm.getBgCallConnections()); 25398343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25408343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25418343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getFirstActiveRingingCall(); 25428343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - RINGING call: ").append(cm.hasActiveRingingCall()? "YES ": "NO "); 25438343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 25448343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getFirstActiveRingingCall().getState()); 25458343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25468343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25478343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25488343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25498343169cc89621d46dce86449f5ee1ff5d3a4919John Wang for (Phone phone : CallManager.getInstance().getAllPhones()) { 25508343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (phone != null) { 25518343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "Phone: " + phone + ", name = " + phone.getPhoneName() 25528343169cc89621d46dce86449f5ee1ff5d3a4919John Wang + ", state = " + phone.getState()); 25538343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25548343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getForegroundCall(); 25558343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - FG call: ").append(call); 25568343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25578343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25588343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25598343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25608343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getBackgroundCall(); 25618343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - BG call: ").append(call); 25628343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25638343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25648343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString());b.setLength(0); 25658343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getRingingCall(); 25668343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - RINGING call: ").append(call); 25678343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25688343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25698343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25708343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 25718343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 25728343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25738343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "############## END dumpCallManager() ###############"); 25748343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 2575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 2576