PhoneUtils.java revision f8396c51f11b1044d236415f2ee88750b4e40e1f
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; 33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult; 34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler; 35404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.os.IBinder; 36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message; 37404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport android.os.RemoteException; 38aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brownimport android.os.SystemProperties; 39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneNumberUtils; 40b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.text.TextUtils; 41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log; 42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.KeyEvent; 43b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.LayoutInflater; 44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.View; 45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.view.WindowManager; 46b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.EditText; 47b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.widget.Toast; 48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 49a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Call; 50a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallStateException; 51a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallerInfo; 52a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.CallerInfoAsyncQuery; 53a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Connection; 54404edc94de563aef5fd5ba48be9114a970cb93bbWink Savilleimport com.android.internal.telephony.IExtendedNetworkService; 55a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.MmiCode; 56a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Savilleimport com.android.internal.telephony.Phone; 57aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brownimport com.android.internal.telephony.TelephonyProperties; 583d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Cataniaimport com.android.internal.telephony.cdma.CdmaConnection; 598343169cc89621d46dce86449f5ee1ff5d3a4919John Wangimport com.android.internal.telephony.CallManager; 608343169cc89621d46dce86449f5ee1ff5d3a4919John Wangimport com.android.internal.telephony.sip.SipPhone; 618343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 62a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville 63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.Hashtable; 64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.Iterator; 65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport java.util.List; 66a50e10e2efadac960987eaadc0938c6f92d3ee90John Wangimport java.util.ArrayList; 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)) { 171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 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) { 238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("answerCall()..."); 239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If the ringer is currently ringing and/or vibrating, stop it 241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // right now (before actually answering the call.) 242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp.getInstance().getRinger().stopRing(); 243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean answered = false; 245ada76244191b2bb56fe8911d503c91f241083d80Peng Zhu PhoneApp app = PhoneApp.getInstance(); 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"); 2898343169cc89621d46dce86449f5ee1ff5d3a4919John Wang PhoneApp.getInstance().mCM.acceptCall(ringing); 29062b318a7a708e464b1fc13692feeef88860064cdPeng Zhu answered = true; 2918343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 2928343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // Always reset to "unmuted" for a freshly-answered call 293a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(false); 2948343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 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()) { 334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("HANGUP ringing call"); 3358343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungup = hangupRingingCall(ringing); 336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!fg.isIdle()) { 337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("HANGUP foreground call"); 338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hungup = hangup(fg); 339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (!bg.isIdle()) { 340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("HANGUP background call"); 341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hungup = hangup(bg); 342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hungup=" + hungup); 345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return hungup; 347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 3498343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupRingingCall(Call ringing) { 350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup ringing call"); 3518343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = ringing.getPhone().getPhoneType(); 3527fe7f7e57aaa38290c37ab48867d34a279d198f3w 35379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 3547fe7f7e57aaa38290c37ab48867d34a279d198f3w // CDMA: Ringing call and Call waiting hangup is handled differently. 3557fe7f7e57aaa38290c37ab48867d34a279d198f3w // For Call waiting we DO NOT call the conventional hangup(call) function 3567fe7f7e57aaa38290c37ab48867d34a279d198f3w // as in CDMA we just want to hungup the Call waiting connection. 357fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai Call.State state = ringing.getState(); 358fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (state == Call.State.INCOMING) { 3597fe7f7e57aaa38290c37ab48867d34a279d198f3w if (DBG) log("hangup ringing call"); 3607fe7f7e57aaa38290c37ab48867d34a279d198f3w return hangup(ringing); 361fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } else if (state == Call.State.WAITING) { 3627fe7f7e57aaa38290c37ab48867d34a279d198f3w if (DBG) log("hangup Call waiting call"); 3637fe7f7e57aaa38290c37ab48867d34a279d198f3w final CallNotifier notifier = PhoneApp.getInstance().notifier; 36477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown notifier.sendCdmaCallWaitingReject(); 3657fe7f7e57aaa38290c37ab48867d34a279d198f3w return true; 366fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } else { 367fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // This should never happen cause hangupRingingCall should always be called 368fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // if the call.isRinging() returns TRUE, which basically means that the call 369fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // should either be in INCOMING or WAITING state 370fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (DBG) log("No Ringing call to hangup"); 371fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai return false; 3727fe7f7e57aaa38290c37ab48867d34a279d198f3w } 373872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 374872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 3757fe7f7e57aaa38290c37ab48867d34a279d198f3w // GSM: Ringing Call and Call waiting, both are hungup by calling 3767fe7f7e57aaa38290c37ab48867d34a279d198f3w // hangup(call) function. 3777fe7f7e57aaa38290c37ab48867d34a279d198f3w if (DBG) log("hangup ringing call"); 3787fe7f7e57aaa38290c37ab48867d34a279d198f3w return hangup(ringing); 37979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 38079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 3817fe7f7e57aaa38290c37ab48867d34a279d198f3w } 382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 3848343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupActiveCall(Call foreground) { 385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup active call"); 3868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return hangup(foreground); 387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 3898343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean hangupHoldingCall(Call background) { 390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("hangup holding call"); 3918343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return hangup(background); 392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 394bab058c1c34d10f0707cf654e9ed917f631925d1David Brown /** 395fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * Used in CDMA phones to end the complete Call session 396fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * @param phone the Phone object. 397fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai * @return true if *any* call was successfully hung up 398fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai */ 399fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai static boolean hangupRingingAndActive(Phone phone) { 400fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai boolean hungUpRingingCall = false; 401fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai boolean hungUpFgCall = false; 402fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai Call ringingCall = phone.getRingingCall(); 403fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai Call fgCall = phone.getForegroundCall(); 404fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 405fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // Hang up any Ringing Call 406fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (!ringingCall.isIdle()) { 407fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (DBG) log("endCallInternal: Hang up Ringing Call"); 4088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungUpRingingCall = hangupRingingCall(ringingCall); 409fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 410fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 411fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai // Hang up any Active Call 412fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (!fgCall.isIdle()) { 413fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai if (DBG) log("endCallInternal: Hang up Foreground Call"); 4148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hungUpFgCall = hangupActiveCall(fgCall); 415fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 416fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 417fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai return hungUpRingingCall || hungUpFgCall; 418fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai } 419fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai 420fe3abbbaea34fc41d6fa11f4abf5d69082e313d6Abhishek Pillai /** 421bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * Trivial wrapper around Call.hangup(), except that we return a 422bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * boolean success code rather than throwing CallStateException on 423bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * failure. 424bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * 425bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * @return true if the call was successfully hung up, or false 426bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * if the call wasn't actually active. 427bab058c1c34d10f0707cf654e9ed917f631925d1David Brown */ 428b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean hangup(Call call) { 429b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 430f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang CallManager cm = PhoneApp.getInstance().mCM; 431f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang 432f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang if (call.getState() == Call.State.ACTIVE && cm.hasActiveBgCall()) { 433f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang // handle foreground call hangup while there is background call 434f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang cm.hangupForegroundResumeBackground(cm.getFirstActiveBgCall()); 435f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang } else { 436f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang call.hangup(); 437f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang } 438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 439b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(LOG_TAG, "Call hangup: caught " + ex, ex); 441b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 444b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 445b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 446bab058c1c34d10f0707cf654e9ed917f631925d1David Brown /** 447bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * Trivial wrapper around Connection.hangup(), except that we silently 448bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * do nothing (rather than throwing CallStateException) if the 449bab058c1c34d10f0707cf654e9ed917f631925d1David Brown * connection wasn't actually active. 450bab058c1c34d10f0707cf654e9ed917f631925d1David Brown */ 451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void hangup(Connection c) { 452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 454b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.hangup(); 455b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 456b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 457b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "Connection hangup: caught " + ex, ex); 458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 459b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 460b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4618343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean answerAndEndHolding(CallManager cm, Call ringing) { 462b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("end holding & answer waiting: 1"); 4638343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (!hangupHoldingCall(cm.getFirstActiveBgCall())) { 464b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.e(LOG_TAG, "end holding failed!"); 465b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 468b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("end holding & answer waiting: 2"); 4698343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return answerCall(ringing); 470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 4738343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static boolean answerAndEndActive(CallManager cm, Call ringing) { 474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("answerAndEndActive()..."); 475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Unlike the answerCall() method, we *don't* need to stop the 477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringer or change audio modes here since the user is already 478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in-call, which means that the audio mode is already set 479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // correctly, and that we wouldn't have started the ringer in the 480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // first place. 481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // hanging up the active call also accepts the waiting call 4838343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if ( !hangupActiveCall(cm.getActiveFgCall())) { 4848343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.w(LOG_TAG, "end active call failed!"); 4858343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return false; 4868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 4878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 4888343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return answerCall(ringing); 489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 490b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 4923d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * For a CDMA phone, advance the call state upon making a new 4933d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * outgoing call. 4943d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * 4953d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * <pre> 4963d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * IDLE -> SINGLE_ACTIVE 4973d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * or 4983d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * SINGLE_ACTIVE -> THRWAY_ACTIVE 4993d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * </pre> 5003d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @param app The phone instance. 5013d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania */ 5027f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown private static void updateCdmaCallStateOnNewOutgoingCall(PhoneApp app) { 5033d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (app.cdmaPhoneCallState.getCurrentCallState() == 5043d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.IDLE) { 5053d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // This is the first outgoing call. Set the Phone Call State to ACTIVE 5063d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania app.cdmaPhoneCallState.setCurrentCallState( 5073d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE); 5083d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } else { 5093d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // This is the second outgoing call. Set the Phone Call State to 3WAY 5103d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania app.cdmaPhoneCallState.setCurrentCallState( 5113d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE); 5123d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 5133d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 5143d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 5153d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania /** 516b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Dial the number using the phone passed in. 517b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 518b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param phone the Phone object. 5197a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param number to be dialed as requested by the user. 5207a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param contactRef that triggered the call. Either a 'tel:' or a 5217a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * 'content://contacts' uri depending on how the call was 5227a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * initiated (dialpad vs contact). 523b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return either CALL_STATUS_DIALED, CALL_STATUS_DIALED_MMI, or CALL_STATUS_FAILED 524b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 525b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static int placeCall(Phone phone, String number, Uri contactRef) { 526b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int status = CALL_STATUS_DIALED; 527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("placeCall: '" + number + "'..."); 529b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 5308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Connection cn = PhoneApp.getInstance().mCM.dial(phone, number); 531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("===> phone.dial() returned: " + cn); 532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 53379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 53479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink 535fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal // On GSM phones, null is returned for MMI codes 536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (cn == null) { 53779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_GSM) { 538fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal if (DBG) log("dialed MMI code: " + number); 539fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal status = CALL_STATUS_DIALED_MMI; 540fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal // Set dialed MMI command to service 541fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal if (mNwService != null) { 542fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal try { 543fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal mNwService.setMmiString(number); 544fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal if (DBG) log("Extended NW bindService setUssdString (" + number + ")"); 545fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal } catch (RemoteException e) { 546fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal mNwService = null; 547fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal } 5484ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 549fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal } else { 550fa3fbeedf018e40f8d6696a382bbf316219cf4aeReli Tal status = PhoneUtils.CALL_STATUS_FAILED; 5514ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 5530fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 5540fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 55579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 5563d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania updateCdmaCallStateOnNewOutgoingCall(app); 5570fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 5580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // phone.dial() succeeded: we're now in a normal phone call. 560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // attach the URI to the CallerInfo Object if it is there, 561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // otherwise just attach the Uri Reference. 562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if the uri does not have a "content" scheme, then we treat 563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // it as if it does NOT have a unique reference. 564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String content = phone.getContext().getContentResolver().SCHEME_CONTENT; 565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if ((contactRef != null) && (contactRef.getScheme().equals(content))) { 566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Object userDataObject = cn.getUserData(); 567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject == null) { 568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cn.setUserData(contactRef); 569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 5707a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // TODO: This branch is dead code, we have 5717a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // just created the connection 'cn' which has 5727a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // no user data (null) by default. 573b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof CallerInfo) { 574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((CallerInfo) userDataObject).contactRefUri = contactRef; 575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ((CallerInfoToken) userDataObject).currentInfo.contactRefUri = 577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project contactRef; 578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 581a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(); 5822eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 5832eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu // Check is phone in any dock, and turn on speaker accordingly 5842eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu activateSpeakerIfDocked(phone); 585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 587d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania Log.w(LOG_TAG, "Exception from phone.dial()", ex); 588b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project status = CALL_STATUS_FAILED; 589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 591b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return status; 592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 5947a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania /** 5953d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * Dial the number using a 3rd party provider gateway. Should 5963d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * *NOT* be called if the number is either: 5973d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * . An emergency one 5983d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * . A GSM MMI code 5993d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * . A CDMA feature code 6003d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * None of the above is checked in this method, it's the caller's 6013d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * responsability to make sure the number is 'valid'. 6023d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * 6033d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * If the connection is establised, this method issues a sync call 6043d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * that may block to query the caller info. 6053d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * TODO: Change the logic to use the async query. 6067a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * 6077a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param phone the Phone object. 6083d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @param context To perform the CallerInfo query. 6097a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param number to be dialed as requested by the user. This is 6107a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * NOT the phone number to connect to. It is used only to build the 6113d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * call card and to update the call log. See above for restrictions. 6127a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param contactRef that triggered the call. Typically a 'tel:' 6137a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * uri but can also be a 'content://contacts' one. 614d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * @param gatewayUri Is the address used to setup the connection. 6153d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania * @return either CALL_STATUS_DIALED or CALL_STATUS_FAILED 6167a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania */ 6173d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania static int placeCallVia(Context context, Phone phone, 61869f61be83befb4effab14afd62951c9f01233d7bNicolas Catania String number, Uri contactRef, Uri gatewayUri) { 619d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania if (DBG) log("placeCallVia: '" + number + "' GW:'" + gatewayUri + "'"); 620d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania 621d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // TODO: 'tel' should be a contant defined in framework base 622d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // somewhere (it is in webkit.) 62369f61be83befb4effab14afd62951c9f01233d7bNicolas Catania if (null == gatewayUri || !"tel".equals(gatewayUri.getScheme())) { 62469f61be83befb4effab14afd62951c9f01233d7bNicolas Catania Log.e(LOG_TAG, "Unsupported URL:" + gatewayUri); 625d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania return CALL_STATUS_FAILED; 626d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania } 6273d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 628d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // We can use getSchemeSpecificPart because we don't allow # 629d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // in the gateway numbers (treated a fragment delim.) However 630d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // if we allow more complex gateway numbers sequence (with 631d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // passwords or whatnot) that use #, this may break. 632d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania // TODO: Need to support MMI codes. 63369f61be83befb4effab14afd62951c9f01233d7bNicolas Catania String gatewayNumber = gatewayUri.getSchemeSpecificPart(); 6343d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania Connection connection; 6353d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania try { 6363d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania connection = phone.dial(gatewayNumber); 6373d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } catch (CallStateException ex) { 638d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania Log.e(LOG_TAG, "Exception dialing gateway", ex); 6393d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania connection = null; 6403d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6413d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6423d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (null == connection) { 643d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania Log.e(LOG_TAG, "Got null connection."); 6443d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania return CALL_STATUS_FAILED; 6453d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6463d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6473d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania PhoneApp app = PhoneApp.getInstance(); 64879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink boolean phoneIsCdma = (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA); 6493d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 65079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneIsCdma) { 6513d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania updateCdmaCallStateOnNewOutgoingCall(app); 6523d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6533d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6543d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // Clean up the number to be displayed. 65579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneIsCdma) { 6563d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania number = CdmaConnection.formatDialString(number); 6573d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6583d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania number = PhoneNumberUtils.extractNetworkPortion(number); 6593d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania number = PhoneNumberUtils.convertKeypadLettersToDigits(number); 6603d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania number = PhoneNumberUtils.formatNumber(number); 6613d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6623d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // Get the caller info synchronously because we need the final 6633d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // CallerInfo object to update the dialed number with the one 6643d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // requested by the user (and not the provider's gateway number). 6653d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania CallerInfo info = null; 6663d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6673d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (ContentResolver.SCHEME_CONTENT.equals(contactRef.getScheme())) { 6683d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania info = CallerInfo.getCallerInfo(context, contactRef); 6693d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6703d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania 6713d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // Fallback, lookup contact using the phone number if the 6723d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // contact's URI scheme was not content:// or if is was but 6733d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania // the lookup failed. 6743d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania if (null == info) { 6753d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania info = CallerInfo.getCallerInfo(context, number); 6763d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania } 6773d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania info.phoneNumber = number; 6783d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania connection.setUserData(info); 6797a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 680a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(); 6813d04d787659f87a21e7414b7e13c1d53be6b859fNicolas Catania return CALL_STATUS_DIALED; 6827a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 6837a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 684008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman /** 685008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * Wrapper function to control when to send an empty Flash command to the network. 686008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * Mainly needed for CDMA networks, such as scenarios when we need to send a blank flash 687008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman * to the network prior to placing a 3-way call for it to be successful. 688008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman */ 689008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman static void sendEmptyFlash(Phone phone) { 690008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 691008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman Call fgCall = phone.getForegroundCall(); 692008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (fgCall.getState() == Call.State.ACTIVE) { 693008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman // Send the empty flash 694008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman if (DBG) Log.d(LOG_TAG, "onReceive: (CDMA) sending empty flash to network"); 6958343169cc89621d46dce86449f5ee1ff5d3a4919John Wang switchHoldingAndActive(phone.getBackgroundCall()); 696008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 697008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 698008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman } 699008791ca2a9a1406c2a9f7b39c794104d151b898Paul Berman 7008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /** 7018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang * @param heldCall is the background call want to be swapped 7028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang */ 7038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void switchHoldingAndActive(Call heldCall) { 704b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 705b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("switchHoldingAndActive"); 7068343169cc89621d46dce86449f5ee1ff5d3a4919John Wang CallManager cm = PhoneApp.getInstance().mCM; 7078343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (heldCall.isIdle()) { 7088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // no heldCall, so it is to hold active call 7098343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.switchHoldingAndActive(cm.getFgPhone().getBackgroundCall()); 7108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } else { 7118343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // has particular heldCall, so to switch 7128343169cc89621d46dce86449f5ee1ff5d3a4919John Wang cm.switchHoldingAndActive(heldCall); 7138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 714a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(cm); 715b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 716b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "switchHoldingAndActive: caught " + ex, ex); 717b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 718b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 719b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 720b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 721b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Restore the mute setting from the earliest connection of the 722b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * foreground call. 723b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 724a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static Boolean restoreMuteState() { 725a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang Phone phone = PhoneApp.getInstance().mCM.getFgPhone(); 726a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 727b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //get the earliest connection 728b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Connection c = phone.getForegroundCall().getEarliestConnection(); 729b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 730b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // only do this if connection is not null. 731b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 732b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 73379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 73479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink 735b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // retrieve the mute value. 73602a199cd143518a01b2014c303908b95dfc58afbjsh Boolean shouldMute = null; 7371f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu 7381f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // In CDMA, mute is not maintained per Connection. Single mute apply for 7391f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // a call where call can have multiple connections such as 7401f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // Three way and Call Waiting. Therefore retrieving Mute state for 7411f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu // latest connection can apply for all connection in that call 7421f2526b75112595d0d7c4c43b98a52f89dfe09d9Peng Zhu if (phoneType == Phone.PHONE_TYPE_CDMA) { 743c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman shouldMute = sConnectionMuteTable.get( 744c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman phone.getForegroundCall().getLatestConnection()); 745872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 746872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 747a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang shouldMute = sConnectionMuteTable.get(c); 748c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman } 749b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (shouldMute == null) { 750b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("problem retrieving mute value for this connection."); 751b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project shouldMute = Boolean.FALSE; 752b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 753b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 754b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set the mute value and return the result. 755a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute (shouldMute.booleanValue()); 756b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return shouldMute; 757b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 758a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang return Boolean.valueOf(getMute()); 759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 761b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan static void mergeCalls() { 762b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan mergeCalls(PhoneApp.getInstance().mCM); 763b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } 764b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan 765b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan static void mergeCalls(CallManager cm) { 766b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan int phoneType = cm.getFgPhone().getPhoneType(); 767b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan if (phoneType == Phone.PHONE_TYPE_CDMA) { 768c9d9ed30aa547b79b81adc13a4d148a003b6ee62w if (DBG) log("mergeCalls"); 7690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 7700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (app.cdmaPhoneCallState.getCurrentCallState() 7710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) { 7728ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh // Set the Phone Call State to conference 7738ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh app.cdmaPhoneCallState.setCurrentCallState( 7748ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh CdmaPhoneCallState.PhoneCallState.CONF_CALL); 7758ae7a57878143b10d0057cf63bfcc7466d4f2730Jaikumar Ganesh 7760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Send flash cmd 7779fd5e84fd6f5c2c5f488bf08d8dd9a2c0aab1370Wink Saville // TODO: Need to change the call from switchHoldingAndActive to 7780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // something meaningful as we are not actually trying to swap calls but 7790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // instead are merging two calls by sending a Flash command. 780b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan switchHoldingAndActive(cm.getFirstActiveBgCall()); 7810fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 78279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 783b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan try { 784b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan if (DBG) log("mergeCalls"); 785b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan cm.conference(cm.getFirstActiveBgCall()); 786b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } catch (CallStateException ex) { 787b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan Log.w(LOG_TAG, "mergeCalls: caught " + ex, ex); 788b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } 789b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 790b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 791b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 792b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void separateCall(Connection c) { 793b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project try { 794b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("separateCall: " + c.getAddress()); 795b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.separate(); 796b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } catch (CallStateException ex) { 797b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "separateCall: caught " + ex, ex); 798b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 802b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handle the MMIInitiate message and put up an alert that lets 803b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * the user cancel the operation, if applicable. 804b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 805b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context context to get strings. 806b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param mmiCode the MmiCode object being started. 807b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param buttonCallbackMessage message to post when button is clicked. 808b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param previousAlert a previous alert used in this activity. 809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return the dialog handle 810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static Dialog displayMMIInitiate(Context context, 812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode mmiCode, 813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message buttonCallbackMessage, 814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Dialog previousAlert) { 815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displayMMIInitiate: " + mmiCode); 816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (previousAlert != null) { 817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project previousAlert.dismiss(); 818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // The UI paradigm we are using now requests that all dialogs have 821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // user interaction, and that any other messages to the user should 822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // be by way of Toasts. 823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In adhering to this request, all MMI initiating "OK" dialogs 825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (non-cancelable MMIs) that end up being closed when the MMI 826b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // completes (thereby showing a completion dialog) are being 827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // replaced with Toasts. 828b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 829b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // As a side effect, moving to Toasts for the non-cancelable MMIs 830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // also means that buttonCallbackMessage (which was tied into "OK") 831b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is no longer invokable for these dialogs. This is not a problem 832b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // since the only callback messages we supported were for cancelable 833b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // MMIs anyway. 834b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 835b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // A cancelable MMI is really just a USSD request. The term 836b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // "cancelable" here means that we can cancel the request when the 837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // system prompts us for a response, NOT while the network is 838b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // processing the MMI request. Any request to cancel a USSD while 839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the network is NOT ready for a response may be ignored. 840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // With this in mind, we replace the cancelable alert dialog with 842b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // a progress dialog, displayed until we receive a request from 843b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the the network. For more information, please see the comments 844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in the displayMMIComplete() method below. 845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Anything that is NOT a USSD request is a normal MMI request, 847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // which will bring up a toast (desribed above). 8484ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Optional code for Extended USSD running prompt 8494ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 8504ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("running USSD code, displaying indeterminate progress."); 8514ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // create the indeterminate progress dialog and display it. 8524ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang ProgressDialog pd = new ProgressDialog(context); 8534ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang CharSequence textmsg = ""; 8544ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 8554ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang textmsg = mNwService.getMmiRunningText(); 85619dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh 8574ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 8584ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 85919dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh textmsg = context.getText(R.string.ussdRunning); 8604ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 8614ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIInitiate (" + textmsg+ ")"); 8624ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setMessage(textmsg); 8634ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setCancelable(false); 8644ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.setIndeterminate(true); 8654ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 8664ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 8674ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang pd.show(); 8684ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // trigger a 15 seconds timeout to clear this progress dialog 8694ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = buttonCallbackMessage; 8704ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 8714ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg.getTarget().sendMessageDelayed(buttonCallbackMessage, 15000); 8724ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch(NullPointerException e) { 8734ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 8744ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 87519dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh return pd; 8764ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 8774ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean isCancelable = (mmiCode != null) && mmiCode.isCancelable(); 879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!isCancelable) { 881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("not a USSD code, displaying status toast."); 882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CharSequence text = context.getText(R.string.mmiStarted); 883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Toast.makeText(context, text, Toast.LENGTH_SHORT) 884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .show(); 885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return null; 886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("running USSD code, displaying indeterminate progress."); 888b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 889b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // create the indeterminate progress dialog and display it. 890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ProgressDialog pd = new ProgressDialog(context); 891b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setMessage(context.getText(R.string.ussdRunning)); 892b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setCancelable(false); 893b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setIndeterminate(true); 894b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 895b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 896b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.show(); 897b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 898b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return pd; 899b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 900b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 901b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 902b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 903b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 904b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handle the MMIComplete message and fire off an intent to display 905b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * the message. 906b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 907b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context context to get strings. 908b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param mmiCode MMI result. 909b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param previousAlert a previous alert used in this activity. 910b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 911b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void displayMMIComplete(final Phone phone, Context context, final MmiCode mmiCode, 912b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Message dismissCallbackMessage, 913b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AlertDialog previousAlert) { 914b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CharSequence text; 915b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int title = 0; // title for the progress dialog, if needed. 916b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode.State state = mmiCode.getState(); 917b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 918b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displayMMIComplete: state=" + state); 9194ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Clear timeout trigger message 9204ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if(mMmiTimeoutCbMsg != null) { 9214ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try{ 9224ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg.getTarget().removeMessages(mMmiTimeoutCbMsg.what); 9234ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIComplete removeMsg"); 9244ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (NullPointerException e) { 9254ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 9264ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 9274ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 9284ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (state) { 931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case PENDING: 932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // USSD code asking for feedback from user. 933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = mmiCode.getMessage(); 934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("- using text from PENDING MMI message: '" + text + "'"); 935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case CANCELLED: 937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = context.getText(R.string.mmiCancelled); 938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 939b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case COMPLETE: 940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (PhoneApp.getInstance().getPUKEntryActivity() != null) { 941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if an attempt to unPUK the device was made, we specify 942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the title and the message here. 943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project title = com.android.internal.R.string.PinMmi; 944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = context.getText(R.string.puk_unlocked); 945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // All other conditions for the COMPLETE mmi state will cause 948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the case to fall through to message logic in common with 949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the FAILED case. 950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case FAILED: 952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project text = mmiCode.getMessage(); 953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("- using text from MMI message: '" + text + "'"); 954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: 956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throw new IllegalStateException("Unexpected MmiCode state: " + state); 957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (previousAlert != null) { 960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project previousAlert.dismiss(); 961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Check to see if a UI exists for the PUK activation. If it does 964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // exist, then it indicates that we're trying to unblock the PUK. 965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp app = PhoneApp.getInstance(); 96605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu if ((app.getPUKEntryActivity() != null) && (state == MmiCode.State.COMPLETE)) { 967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("displaying PUK unblocking progress dialog."); 968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // create the progress dialog, make sure the flags and type are 970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set correctly. 971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project ProgressDialog pd = new ProgressDialog(app); 972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setTitle(title); 973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setMessage(text); 974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setCancelable(false); 975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.setIndeterminate(true); 976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); 978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // display the dialog 980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project pd.show(); 981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // indicate to the Phone app that the progress dialog has 983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // been assigned for the PUK unlock / SIM READY process. 984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.setPukEntryProgressDialog(pd); 985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In case of failure to unlock, we'll need to reset the 988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // PUK unlock activity, so that the user may try again. 989b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (app.getPUKEntryActivity() != null) { 990b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.setPukEntryActivity(null); 991b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 992b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 993b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // A USSD in a pending state means that it is still 994b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // interacting with the user. 995b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (state != MmiCode.State.PENDING) { 996b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("MMI code has finished running."); 997b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 9984ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang // Replace response message with Extended Mmi wording 9994ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 10004ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 10014ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang text = mNwService.getUserMessage(text); 10024ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 10034ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 10044ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 10054ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (DBG) log("Extended NW displayMMIInitiate (" + text + ")"); 10061b8e24dac994b507540d25b02e2c56f52bff04abDaisuke Miyakawa if (text == null || text.length() == 0) 10074ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang return; 10084ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 10094ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang 1010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // displaying system alert dialog on the screen instead of 1011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // using another activity to display the message. This 1012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // places the message at the forefront of the UI. 1013b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AlertDialog newDialog = new AlertDialog.Builder(context) 1014b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setMessage(text) 1015b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setPositiveButton(R.string.ok, null) 1016b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setCancelable(true) 1017b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .create(); 1018b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().setType( 1020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().addFlags( 1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.FLAG_DIM_BEHIND); 1023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.show(); 1025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1026b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("USSD code has requested user input. Constructing input dialog."); 1027b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1028b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // USSD MMI code that is interacting with the user. The 1029b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // basic set of steps is this: 1030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1. User enters a USSD request 1031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2. We recognize the request and displayMMIInitiate 1032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (above) creates a progress dialog. 1033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3. Request returns and we get a PENDING or COMPLETE 1034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // message. 1035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 4. These MMI messages are caught in the PhoneApp 1036b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (onMMIComplete) and the InCallScreen 1037b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (mHandler.handleMessage) which bring up this dialog 1038b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // and closes the original progress dialog, 1039b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // respectively. 1040b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 5. If the message is anything other than PENDING, 1041b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we are done, and the alert dialog (directly above) 1042b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // displays the outcome. 1043b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 6. If the network is requesting more information from 1044b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the user, the MMI will be in a PENDING state, and 1045b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we display this dialog with the message. 1046b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 7. User input, or cancel requests result in a return 1047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // to step 1. Keep in mind that this is the only 1048b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // time that a USSD should be canceled. 1049b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1050b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // inflate the layout with the scrolling text area for the dialog. 1051b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project LayoutInflater inflater = (LayoutInflater) context.getSystemService( 1052b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Context.LAYOUT_INFLATER_SERVICE); 1053b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project View dialogView = inflater.inflate(R.layout.dialog_ussd_response, null); 1054b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1055b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // get the input field. 1056b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final EditText inputText = (EditText) dialogView.findViewById(R.id.input_field); 1057b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1058b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // specify the dialog's click listener, with SEND and CANCEL logic. 1059b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final DialogInterface.OnClickListener mUSSDDialogListener = 1060b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new DialogInterface.OnClickListener() { 1061b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public void onClick(DialogInterface dialog, int whichButton) { 1062b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (whichButton) { 1063edbbd998abc6d1d1d2c2f3b54c939779c91a2708Christian Mehlmauer case DialogInterface.BUTTON_POSITIVE: 1064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project phone.sendUssdResponse(inputText.getText().toString()); 1065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1066edbbd998abc6d1d1d2c2f3b54c939779c91a2708Christian Mehlmauer case DialogInterface.BUTTON_NEGATIVE: 1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mmiCode.isCancelable()) { 1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mmiCode.cancel(); 1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project break; 1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // build the dialog 1076b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final AlertDialog newDialog = new AlertDialog.Builder(context) 1077b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setMessage(text) 1078b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setView(dialogView) 1079b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setPositiveButton(R.string.send_button, mUSSDDialogListener) 1080b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setNegativeButton(R.string.cancel, mUSSDDialogListener) 1081b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .setCancelable(false) 1082b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project .create(); 1083b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1084b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // attach the key listener to the dialog's input field and make 1085b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // sure focus is set. 1086b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final View.OnKeyListener mUSSDDialogInputListener = 1087b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new View.OnKeyListener() { 1088b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public boolean onKey(View v, int keyCode, KeyEvent event) { 1089b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (keyCode) { 1090b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case KeyEvent.KEYCODE_CALL: 1091b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case KeyEvent.KEYCODE_ENTER: 1092b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project phone.sendUssdResponse(inputText.getText().toString()); 1093b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.dismiss(); 1094b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1095b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1096b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1097b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1098b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project inputText.setOnKeyListener(mUSSDDialogInputListener); 1100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project inputText.requestFocus(); 1101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // set the window properties of the dialog 1103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().setType( 1104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG); 1105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.getWindow().addFlags( 1106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project WindowManager.LayoutParams.FLAG_DIM_BEHIND); 1107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // now show the dialog! 1109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project newDialog.show(); 1110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Cancels the current pending MMI operation, if applicable. 1116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we canceled an MMI operation, or false 1117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if the current pending MMI wasn't cancelable 1118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * or if there was no current pending MMI at all. 1119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @see displayMMIInitiate 1121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean cancelMmiCode(Phone phone) { 1123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project List<? extends MmiCode> pendingMmis = phone.getPendingMmiCodes(); 1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project int count = pendingMmis.size(); 1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("cancelMmiCode: num pending MMIs = " + count); 1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project boolean canceled = false; 1128b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (count > 0) { 1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // assume that we only have one pending MMI operation active at a time. 1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // I don't think it's possible to enter multiple MMI codes concurrently 1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in the phone UI, because during the MMI operation, an Alert panel 1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is displayed, which prevents more MMI code from being entered. 1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project MmiCode mmiCode = pendingMmis.get(0); 1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (mmiCode.isCancelable()) { 1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project mmiCode.cancel(); 1136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project canceled = true; 1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1138b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1139b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 11404ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang //clear timeout message and pre-set MMI command 11414ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mNwService != null) { 11424ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang try { 11434ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService.clearMmiString(); 11444ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } catch (RemoteException e) { 11454ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mNwService = null; 114619dd8f9c63ba7471c76fc31847a8063d18a83b6dJaikumar Ganesh } 11474ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 11484ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang if (mMmiTimeoutCbMsg != null) { 11494ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang mMmiTimeoutCbMsg = null; 11504ccb1b7d68d5b5bb7ed54251a1f214162013bc60John Wang } 1151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return canceled; 1152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static class VoiceMailNumberMissingException extends Exception { 1155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project VoiceMailNumberMissingException() { 1156b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project super(); 1157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1158b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project VoiceMailNumberMissingException(String msg) { 1160b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project super(msg); 1161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1162b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1164b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1165b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Gets the phone number to be called from an intent. Requires a Context 1166b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * to access the contacts database, and a Phone to access the voicemail 1167b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * number. 1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1169b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <p>If <code>phone</code> is <code>null</code>, the function will return 1170b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <code>null</code> for <code>voicemail:</code> URIs; 1171b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * if <code>context</code> is <code>null</code>, the function will return 1172b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * <code>null</code> for person/phone URIs.</p> 1173b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1174bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * <p>If the intent contains a <code>sip:</code> URI, the returned 1175bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * "number" is actually the SIP address. 1176bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * 1177b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param context a context to use (or 1178b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @param intent the intent 1179b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1180b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @throws VoiceMailNumberMissingException if <code>intent</code> contains 1181b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * a <code>voicemail:</code> URI, but <code>phone</code> does not 1182b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * have a voicemail number set. 1183b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1184bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @return the phone number (or SIP address) that would be called by the intent, 1185b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * or <code>null</code> if the number cannot be found. 1186b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 118761bde155c038489befc9c6cb9eb1765f44daaae0John Wang static String getNumberFromIntent(Context context, Intent intent) 1188b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throws VoiceMailNumberMissingException { 1189bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown Uri uri = intent.getData(); 1190bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown String scheme = uri.getScheme(); 1191bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1192bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // The sip: scheme is simple: just treat the rest of the URI as a 1193bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // SIP address. 1194bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown if (scheme.equals("sip")) { 1195bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown return uri.getSchemeSpecificPart(); 1196bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown } 1197bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1198bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // Otherwise, let PhoneNumberUtils.getNumberFromIntent() handle 1199bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // the other cases (i.e. tel: and voicemail: and contact: URIs.) 1200bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown 1201b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final String number = PhoneNumberUtils.getNumberFromIntent(intent, context); 1202b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1203bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown // Check for a voicemail-dialing request. If the voicemail number is 1204b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // empty, throw a VoiceMailNumberMissingException. 1205bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown if (scheme.equals("voicemail") && 1206b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (number == null || TextUtils.isEmpty(number))) 1207b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project throw new VoiceMailNumberMissingException(); 1208b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1209b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return number; 1210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1212b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns the caller-id info corresponding to the specified Connection. 1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * (This is just a simple wrapper around CallerInfo.getCallerInfo(): we 1215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * extract a phone number from the specified Connection, and feed that 1216b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * number into CallerInfo.getCallerInfo().) 1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * The returned CallerInfo may be null in certain error cases, like if the 1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * specified Connection was null, or if we weren't able to get a valid 1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * phone number from the Connection. 1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Finally, if the getCallerInfo() call did succeed, we save the resulting 1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CallerInfo object in the "userData" field of the Connection. 1224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * NOTE: This API should be avoided, with preference given to the 1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * asynchronous startGetCallerInfo API. 1227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfo getCallerInfo(Context context, Connection c) { 1229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfo info = null; 1230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c != null) { 1232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //See if there is a URI attached. If there is, this means 1233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //that there is no CallerInfo queried yet, so we'll need to 1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //replace the URI with a full CallerInfo object. 1235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Object userDataObject = c.getUserData(); 1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof Uri) { 1237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = CallerInfo.getCallerInfo(context, (Uri) userDataObject); 1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info != null) { 1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(info); 1240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof CallerInfoToken) { 1243b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //temporary result, while query is running 1244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = ((CallerInfoToken) userDataObject).currentInfo; 1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //final query result 1247b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = (CallerInfo) userDataObject; 1248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info == null) { 1250b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No URI, or Existing CallerInfo, so we'll have to make do with 1251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // querying a new CallerInfo using the connection's phone number. 1252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1254b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("getCallerInfo: number = " + number); 1255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!TextUtils.isEmpty(number)) { 1257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project info = CallerInfo.getCallerInfo(context, number); 1258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (info != null) { 1259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(info); 1260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return info; 1266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Class returned by the startGetCallerInfo call to package a temporary 1270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * CallerInfo Object, to be superceded by the CallerInfo Object passed 1271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * into the listener when the query with token mAsyncQueryToken is complete. 1272b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public static class CallerInfoToken { 1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /**indicates that there will no longer be updates to this request.*/ 1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public boolean isFinal; 1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public CallerInfo currentInfo; 1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project public CallerInfoAsyncQuery asyncQuery; 1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Start a CallerInfo Query based on the earliest connection in the call. 1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoToken startGetCallerInfo(Context context, Call call, 1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) { 12860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 12870fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville Connection conn = null; 1288872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan int phoneType = call.getPhone().getPhoneType(); 128979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 12900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville conn = call.getLatestConnection(); 1291872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 1292872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 12930fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville conn = call.getEarliestConnection(); 129479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 129579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 12960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 12970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 1298b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return startGetCallerInfo(context, conn, listener, cookie); 1299b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1300b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1301b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1302b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * place a temporary callerinfo object in the hands of the caller and notify 1303b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * caller when the actual query is done. 1304b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1305b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoToken startGetCallerInfo(Context context, Connection c, 1306b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoAsyncQuery.OnQueryCompleteListener listener, Object cookie) { 1307b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project CallerInfoToken cit; 1308b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (c == null) { 1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //TODO: perhaps throw an exception here. 1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = null; 1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return cit; 1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // There are now 3 states for the userdata. 1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1. Uri - query has not been executed yet 1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2. CallerInfoToken - query is executing, but has not completed. 1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3. CallerInfo - query has executed. 1320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // In each case we have slightly different behaviour: 1321b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1. If the query has not been executed yet (Uri or null), we start 1322b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // query execution asynchronously, and note it by attaching a 1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // CallerInfoToken as the userData. 1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2. If the query is executing (CallerInfoToken), we've essentially 1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // reached a state where we've received multiple requests for the 1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // same callerInfo. That means that once the query is complete, 1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // we'll need to execute the additional listener requested. 1328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 3. If the query has already been executed (CallerInfo), we just 1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return the CallerInfo object as expected. 1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 4. Regarding isFinal - there are cases where the CallerInfo object 1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // will not be attached, like when the number is empty (caller id 1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // blocking). This flag is used to indicate that the 1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // CallerInfoToken object is going to be permanent since no 1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // query results will be returned. In the case where a query 1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // has been completed, this flag is used to indicate to the caller 1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // that the data will not be updated since it is valid. 1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Note: For the case where a number is NOT retrievable, we leave 1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the CallerInfo as null in the CallerInfoToken. This is 1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // something of a departure from the original code, since the old 1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // code manufactured a CallerInfo object regardless of the query 1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // outcome. From now on, we will append an empty CallerInfo 1343b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // object, to mirror previous behaviour, and to avoid Null Pointer 1344b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Exceptions. 1345b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Object userDataObject = c.getUserData(); 1346b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (userDataObject instanceof Uri) { 1347b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project //create a dummy callerinfo, populate with what we know from URI. 1348b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1349b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = new CallerInfo(); 1350b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 1351b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project (Uri) userDataObject, sCallerInfoQueryListener, c); 1352b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 1353b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = false; 1354b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(cit); 1356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query based on Uri: " + userDataObject); 1358b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1359b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (userDataObject == null) { 1360b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // No URI, or Existing CallerInfo, so we'll have to make do with 1361b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // querying a new CallerInfo using the connection's phone number. 1362b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String number = c.getAddress(); 1363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = new CallerInfo(); 1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1367de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Store CNAP information retrieved from the Connection (we want to do this 1368de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // here regardless of whether the number is empty or not). 1369de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.cnapName = c.getCnapName(); 1370de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.name = cit.currentInfo.cnapName; // This can still get overwritten 1371de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // by ContactInfo later 1372de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.numberPresentation = c.getNumberPresentation(); 1373de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 1374de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1375a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania if (DBG) { 1376a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania log("startGetCallerInfo: number = " + number); 1377a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania log("startGetCallerInfo: CNAP Info from FW(1): name=" 1378de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + cit.currentInfo.cnapName 1379de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 1380a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania } 1381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // handling case where number is null (caller id hidden) as well. 1383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!TextUtils.isEmpty(number)) { 1384153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // Check for special CNAP cases and modify the CallerInfo accordingly 1385153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // to be sure we keep the right information to display/log later 1386153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = modifyForSpecialCnapCases(context, cit.currentInfo, number, 1387153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman cit.currentInfo.numberPresentation); 138886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu 138986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu cit.currentInfo.phoneNumber = number; 13902f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // For scenarios where we may receive a valid number from the network but a 13912f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // restricted/unavailable presentation, we do not want to perform a contact query 13922f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // (see note on isFinal above). So we set isFinal to true here as well. 13932f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman if (cit.currentInfo.numberPresentation != Connection.PRESENTATION_ALLOWED) { 13942f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = true; 13952f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } else { 13962f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 13972f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman number, sCallerInfoQueryListener, c); 13982f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 13992f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = false; 14002f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } 1401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // This is the case where we are querying on a number that 1403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // is null or empty, like a caller whose caller id is 1404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // blocked or empty (CLIR). The previous behaviour was to 1405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // throw a null CallerInfo object back to the user, but 1406b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // this departure is somewhat cleaner. 1407b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: No query to start, send trivial reply."); 1408b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = true; // please see note on isFinal, above. 1409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1410b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1411b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project c.setUserData(cit); 1412b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1413b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query based on number: " + number); 1414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else if (userDataObject instanceof CallerInfoToken) { 1416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // query is running, just tack on this listener to the queue. 1417b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = (CallerInfoToken) userDataObject; 1418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1419b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // handling case where number is null (caller id hidden) as well. 1420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (cit.asyncQuery != null) { 1421b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 1422b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1423b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query already running, adding listener: " + 1424b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project listener.getClass().toString()); 1425b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 142646532b66a467f247380054270c6151aa3dc7a761Wink Saville // handling case where number/name gets updated later on by the network 142746532b66a467f247380054270c6151aa3dc7a761Wink Saville String updatedNumber = c.getAddress(); 1428de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: updatedNumber initially = " + updatedNumber); 142946532b66a467f247380054270c6151aa3dc7a761Wink Saville if (!TextUtils.isEmpty(updatedNumber)) { 143046532b66a467f247380054270c6151aa3dc7a761Wink Saville // Store CNAP information retrieved from the Connection 143146532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.cnapName = c.getCnapName(); 143246532b66a467f247380054270c6151aa3dc7a761Wink Saville // This can still get overwritten by ContactInfo 143346532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.name = cit.currentInfo.cnapName; 143446532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.numberPresentation = c.getNumberPresentation(); 143546532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 143646532b66a467f247380054270c6151aa3dc7a761Wink Saville 1437de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman updatedNumber = modifyForSpecialCnapCases(context, cit.currentInfo, 1438de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman updatedNumber, cit.currentInfo.numberPresentation); 1439de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1440de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.phoneNumber = updatedNumber; 1441de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: updatedNumber=" + updatedNumber); 1442de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: CNAP Info from FW(2): name=" 144346532b66a467f247380054270c6151aa3dc7a761Wink Saville + cit.currentInfo.cnapName 144446532b66a467f247380054270c6151aa3dc7a761Wink Saville + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 14452f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // For scenarios where we may receive a valid number from the network but a 14462f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // restricted/unavailable presentation, we do not want to perform a contact query 14472f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman // (see note on isFinal above). So we set isFinal to true here as well. 14482f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman if (cit.currentInfo.numberPresentation != Connection.PRESENTATION_ALLOWED) { 14492f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = true; 14502f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } else { 14512f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery = CallerInfoAsyncQuery.startQuery(QUERY_TOKEN, context, 14522f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman updatedNumber, sCallerInfoQueryListener, c); 14532f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.asyncQuery.addQueryListener(QUERY_TOKEN, listener, cookie); 14542f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman cit.isFinal = false; 14552f5a2e9b6dc69123abe36fd6deb93b7fb46c1cadPaul Berman } 145646532b66a467f247380054270c6151aa3dc7a761Wink Saville } else { 145746532b66a467f247380054270c6151aa3dc7a761Wink Saville if (DBG) log("startGetCallerInfo: No query to attach to, send trivial reply."); 145846532b66a467f247380054270c6151aa3dc7a761Wink Saville if (cit.currentInfo == null) { 145946532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.currentInfo = new CallerInfo(); 146046532b66a467f247380054270c6151aa3dc7a761Wink Saville } 1461de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Store CNAP information retrieved from the Connection 1462de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.cnapName = c.getCnapName(); // This can still get 1463de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // overwritten by ContactInfo 1464de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.name = cit.currentInfo.cnapName; 1465de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.numberPresentation = c.getNumberPresentation(); 1466de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman cit.currentInfo.namePresentation = c.getCnapNamePresentation(); 1467de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 1468de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("startGetCallerInfo: CNAP Info from FW(3): name=" 1469de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + cit.currentInfo.cnapName 1470de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman + ", Name/Number Pres=" + cit.currentInfo.numberPresentation); 147146532b66a467f247380054270c6151aa3dc7a761Wink Saville cit.isFinal = true; // please see note on isFinal, above. 1472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit = new CallerInfoToken(); 1476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.currentInfo = (CallerInfo) userDataObject; 1477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.asyncQuery = null; 1478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project cit.isFinal = true; 1479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // since the query is already done, call the listener. 1480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("startGetCallerInfo: query already done, returning CallerInfo"); 1481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return cit; 1483b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Implemented for CallerInfo.OnCallerInfoQueryCompleteListener interface. 1487b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Updates the connection's userData when called. 1488b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1489b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final int QUERY_TOKEN = -1; 1490b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static CallerInfoAsyncQuery.OnQueryCompleteListener sCallerInfoQueryListener = 1491b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project new CallerInfoAsyncQuery.OnQueryCompleteListener () { 149205fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu public void onQueryComplete(int token, Object cookie, CallerInfo ci) { 1493b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("query complete, updating connection.userdata"); 14943ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania Connection conn = (Connection) cookie; 1495b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1496e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai // Added a check if CallerInfo is coming from ContactInfo or from Connection. 1497e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai // If no ContactInfo, then we want to use CNAP information coming from network 149864824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania if (DBG) log("- onQueryComplete: CallerInfo:" + ci); 149964824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania if (ci.contactExists || ci.isEmergencyNumber() || ci.isVoiceMailNumber()) { 15003ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // If the number presentation has not been set by 15013ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // the ContactInfo, use the one from the 15023ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // connection. 15033ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania 15043ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // TODO: Need a new util method to merge the info 15053ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // from the Connection in a CallerInfo object. 15063ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // Here 'ci' is a new CallerInfo instance read 15073ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // from the DB. It has lost all the connection 15083ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // info preset before the query (see PhoneUtils 15093ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // line 1334). We should have a method to merge 15103ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // back into this new instance the info from the 15113ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // connection object not set by the DB. If the 15123ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // Connection already has a CallerInfo instance in 15133ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // userData, then we could use this instance to 15143ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // fill 'ci' in. The same routine could be used in 15153ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania // PhoneUtils. 15163ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania if (0 == ci.numberPresentation) { 15173ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania ci.numberPresentation = conn.getNumberPresentation(); 15183ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania } 1519e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai } else { 15203ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania CallerInfo newCi = getCallerInfo(null, conn); 1521e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai if (newCi != null) { 1522e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai newCi.phoneNumber = ci.phoneNumber; // To get formatted phone number 15233ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania ci = newCi; 152464824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania } 1525e2c9e16a099b6a120db0a589ad1959b8787b9f9bAbhishek Pillai } 15263ba1cd466a39eb22addb6f6fe3c7b0f3e7916330Nicolas Catania conn.setUserData(ci); 1527b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1528b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project }; 1529b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1530b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1531b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1532b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns a single "name" for the specified given a CallerInfo object. 1533b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * If the name is null, return defaultString as the default value, usually 1534b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * context.getString(R.string.unknown). 1535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static String getCompactNameFromCallerInfo(CallerInfo ci, Context context) { 1537b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("getCompactNameFromCallerInfo: info = " + ci); 1538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project String compactName = null; 1540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (ci != null) { 1541a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania if (TextUtils.isEmpty(ci.name)) { 1542a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // Perform any modifications for special CNAP cases to 1543a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // the phone number being displayed, if applicable. 1544a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania compactName = modifyForSpecialCnapCases(context, ci, ci.phoneNumber, 1545a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania ci.numberPresentation); 1546a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania } else { 1547a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania // Don't call modifyForSpecialCnapCases on regular name. See b/2160795. 1548a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania compactName = ci.name; 1549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1551de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman 15520fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if ((compactName == null) || (TextUtils.isEmpty(compactName))) { 1553de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // If we're still null/empty here, then check if we have a presentation 1554de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // string that takes precedence that we could return, otherwise display 1555de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // "unknown" string. 1556de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (ci != null && ci.numberPresentation == Connection.PRESENTATION_RESTRICTED) { 1557de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.private_num); 1558de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } else if (ci != null && ci.numberPresentation == Connection.PRESENTATION_PAYPHONE) { 1559de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.payphone); 1560de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } else { 1561de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman compactName = context.getString(R.string.unknown); 1562de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman } 1563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1564de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (DBG) log("getCompactNameFromCallerInfo: compactName=" + compactName); 1565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return compactName; 1566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Returns true if the specified Call is a "conference call", meaning 1570b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * that it owns more than one Connection object. This information is 1571b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * used to trigger certain UI changes that appear when a conference 1572b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * call is active (like displaying the label "Conference call", and 1573b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown * enabling the "Manage conference" UI.) 1574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Watch out: This method simply checks the number of Connections, 1576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * *not* their states. So if a Call has (for example) one ACTIVE 1577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * connection and one DISCONNECTED connection, this method will return 1578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * true (which is unintuitive, since the Call isn't *really* a 1579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * conference call any more.) 1580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if the specified call has more than one connection (in any state.) 1582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1583b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean isConferenceCall(Call call) { 1584b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // CDMA phones don't have the same concept of "conference call" as 1585b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // GSM phones do; there's no special "conference call" state of 1586b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // the UI or a "manage conference" function. (Instead, when 1587b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // you're in a 3-way call, all we can do is display the "generic" 1588b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown // state of the UI.) So as far as the in-call UI is concerned, 15890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // Conference corresponds to generic display. 15900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 1591b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan int phoneType = call.getPhone().getPhoneType(); 159279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 159339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai CdmaPhoneCallState.PhoneCallState state = app.cdmaPhoneCallState.getCurrentCallState(); 159439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai if ((state == CdmaPhoneCallState.PhoneCallState.CONF_CALL) 159539a84144262f12df44861d746788b9de92259e4fAbhishek Pillai || ((state == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 159639a84144262f12df44861d746788b9de92259e4fAbhishek Pillai && !app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing())) { 15970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return true; 15980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 1599b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } else { 16000fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville List<Connection> connections = call.getConnections(); 16010fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (connections != null && connections.size() > 1) { 16020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return true; 16030fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 1604b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // TODO: We may still want to change the semantics of this method 1608b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // to say that a given call is only really a conference call if 1609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the number of ACTIVE connections, not the total number of 1610b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // connections, is greater than one. (See warning comment in the 1611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // javadoc above.) 1612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Here's an implementation of that: 1613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (connections == null) { 1614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return false; 1615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1616b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // int numActiveConnections = 0; 1617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // for (Connection conn : connections) { 1618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (DBG) log(" - CONN: " + conn + ", state = " + conn.getState()); 1619b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (conn.getState() == Call.State.ACTIVE) numActiveConnections++; 1620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if (numActiveConnections > 1) { 1621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return true; 1622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // } 1624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // return false; 1625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Launch the Dialer to start a new call. 1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This is just a wrapper around the ACTION_DIAL intent. 1630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 16318343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void startNewCall(final CallManager cm) { 1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Sanity-check that this is OK given the current state of the phone. 16338343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (!okToAddCall(cm)) { 1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Log.w(LOG_TAG, "startNewCall: can't add a new call in the current state"); 16358343169cc89621d46dce86449f5ee1ff5d3a4919John Wang dumpCallManager(); 1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return; 1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // if applicable, mute the call while we're showing the add call UI. 16408343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (cm.hasActiveFgCall()) { 16418343169cc89621d46dce86449f5ee1ff5d3a4919John Wang setMuteInternal(cm.getActiveFgCall().getPhone(), true); 1642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Inform the phone app that this mute state was NOT done 1643b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // voluntarily by the User. 1644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp.getInstance().setRestoreMuteOnInCallResume(true); 1645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project Intent intent = new Intent(Intent.ACTION_DIAL); 1648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 1649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // when we request the dialer come up, we also want to inform 1651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // it that we're going through the "add call" option from the 1652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // InCallScreen / PhoneUtils. 1653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project intent.putExtra(ADD_CALL_MODE_KEY, true); 1654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp.getInstance().startActivity(intent); 1656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1658425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent static void turnOnSpeaker(Context context, boolean flag, boolean store) { 16596b0efb615a5b1a65984192384c88965fa7dd06a0David Brown if (DBG) log("turnOnSpeaker(flag=" + flag + ", store=" + store + ")..."); 1660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project audioManager.setSpeakerphoneOn(flag); 1663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // record the speaker-enable value 1664425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent if (store) { 1665425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent sIsSpeakerEnabled = flag; 1666425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent } 1667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (flag) { 1668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project NotificationMgr.getDefault().notifySpeakerphone(); 1669b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1670b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project NotificationMgr.getDefault().cancelSpeakerphone(); 1671b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1672b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // We also need to make a fresh call to PhoneApp.updateWakeState() 1674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // any time the speaker state changes, since the screen timeout is 1675b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // sometimes different depending on whether or not the speaker is 1676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // in use. 1677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project PhoneApp app = PhoneApp.getInstance(); 1678b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project app.updateWakeState(); 1679d3744ff481f7d96669740b015a39d7441208152bAbhishek Pillai 1680d3744ff481f7d96669740b015a39d7441208152bAbhishek Pillai // Update the Proximity sensor based on speaker state 1681d3744ff481f7d96669740b015a39d7441208152bAbhishek Pillai app.updateProximitySensorMode(app.phone.getState()); 1682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1685b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Restore the speaker mode, called after a wired headset disconnect 1686b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * event. 1687b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1688b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static void restoreSpeakerMode(Context context) { 1689b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("restoreSpeakerMode, restoring to: " + sIsSpeakerEnabled); 1690b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1691b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // change the mode if needed. 1692b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (isSpeakerOn(context) != sIsSpeakerEnabled) { 1693425b8e3c9846d5e0e76466604b35cad8856d79deEric Laurent turnOnSpeaker(context, sIsSpeakerEnabled, false); 1694b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1695b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1696b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1697b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project static boolean isSpeakerOn(Context context) { 1698b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1699b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return audioManager.isSpeakerphoneOn(); 1700b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1701b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1702055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1703055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static void turnOnNoiseSuppression(Context context, boolean flag, boolean store) { 1704055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("turnOnNoiseSuppression: " + flag); 1705055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1706055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1707055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1708055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return; 1709055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1710055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1711055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (flag) { 1712055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent audioManager.setParameters("noise_suppression=auto"); 1713055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } else { 1714055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent audioManager.setParameters("noise_suppression=off"); 1715055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1716055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1717055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // record the speaker-enable value 1718055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (store) { 1719055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent sIsNoiseSuppressionEnabled = flag; 1720055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1721055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1722055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // TODO: implement and manage ICON 1723055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1724055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1725055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1726055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static void restoreNoiseSuppression(Context context) { 1727055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("restoreNoiseSuppression, restoring to: " + sIsNoiseSuppressionEnabled); 1728055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1729055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1730055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return; 1731055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1732055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1733055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent // change the mode if needed. 1734055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (isNoiseSuppressionOn(context) != sIsNoiseSuppressionEnabled) { 1735055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent turnOnNoiseSuppression(context, sIsNoiseSuppressionEnabled, false); 1736055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1737055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1738055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1739055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent static boolean isNoiseSuppressionOn(Context context) { 1740055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1741055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (!context.getResources().getBoolean(R.bool.has_in_call_noise_suppression)) { 1742055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return false; 1743055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1744055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1745055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1746055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent String noiseSuppression = audioManager.getParameters("noise_suppression"); 1747055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (DBG) log("isNoiseSuppressionOn: " + noiseSuppression); 1748055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent if (noiseSuppression.contains("off")) { 1749055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return false; 1750055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } else { 1751055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent return true; 1752055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1753055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent } 1754055b927f7ee587bc1b1e595b12beaa232ab99ffcEric Laurent 1755b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1756a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1757a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Mute / umute the foreground phone, which has the current foreground call 1758b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1759b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * All muting / unmuting from the in-call UI should go through this 1760b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * wrapper. 1761a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1762a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Wrapper around Phone.setMute() and setMicrophoneMute(). 1763a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * It also updates the connectionMuteTable and mute icon in the status bar. 1764a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * 1765b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1766a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static void setMute(boolean muted) { 1767a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang CallManager cm = PhoneApp.getInstance().mCM; 1768a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // make the call to mute the audio 1770a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMuteInternal(cm.getFgPhone(), muted); 1771a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1773b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // update the foreground connections to match. This includes 1774b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // all the connections on conference calls. 1775a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang for (Connection cn : cm.getActiveFgCall().getConnections()) { 1776b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (sConnectionMuteTable.get(cn) == null) { 1777b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG) log("problem retrieving mute value for this connection."); 1778b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1779b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project sConnectionMuteTable.put(cn, Boolean.valueOf(muted)); 1780b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1781b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1782b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1783b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1784a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Internally used muting function. 1785b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1786a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang private static void setMuteInternal(Phone phone, boolean muted) { 1787a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (DBG) log("setMuteInternal: " + muted); 1788c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi Context context = phone.getContext(); 1789c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi boolean routeToAudioManager = 1790c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi context.getResources().getBoolean(R.bool.send_mic_mute_to_AudioManager); 1791c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi if (routeToAudioManager) { 1792c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi AudioManager audioManager = 1793c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi (AudioManager) phone.getContext().getSystemService(Context.AUDIO_SERVICE); 1794a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (DBG) log("setMicrophoneMute: " + muted); 1795c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi audioManager.setMicrophoneMute(muted); 1796c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } else { 1797c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi phone.setMute(muted); 1798c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } 1799a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang NotificationMgr.getDefault().updateMuteNotification(); 1800b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1801b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1802a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang /** 1803a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * Get the mute state of foreground phone, which has the current 1804a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang * foreground call 1805a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang */ 1806a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang static boolean getMute() { 1807a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang Phone phone = PhoneApp.getInstance().mCM.getFgPhone(); 1808a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang 1809c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi Context context = phone.getContext(); 1810c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi boolean routeToAudioManager = 1811c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi context.getResources().getBoolean(R.bool.send_mic_mute_to_AudioManager); 1812c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi if (routeToAudioManager) { 1813c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi AudioManager audioManager = 1814c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi (AudioManager) phone.getContext().getSystemService(Context.AUDIO_SERVICE); 1815c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi return audioManager.isMicrophoneMute(); 1816c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } else { 1817c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi return phone.getMute(); 1818c8f4017c60f26ee760cd2f597de307e1845cf35aJean-Michel Trivi } 1819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1821a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan /* package */ static void setAudioMode() { 1822a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan setAudioMode(PhoneApp.getInstance().mCM); 1823a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan } 1824a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan 1825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1826a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan * Sets the audio mode per current phone state. 1827b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1828a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan /* package */ static void setAudioMode(CallManager cm) { 1829a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (DBG) Log.d(LOG_TAG, "setAudioMode()..." + cm.getState()); 1830b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1831a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan Context context = PhoneApp.getInstance(); 1832a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan AudioManager audioManager = (AudioManager) 1833a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan context.getSystemService(Context.AUDIO_SERVICE); 1834a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan int modeBefore = audioManager.getMode(); 1835a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan cm.setAudioMode(); 1836a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan int modeAfter = audioManager.getMode(); 1837b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1838a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (modeBefore != modeAfter) { 1839b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Enable stack dump only when actively debugging ("new Throwable()" is expensive!) 1840b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (DBG_SETAUDIOMODE_STACK) Log.d(LOG_TAG, "Stack:", new Throwable("stack dump")); 1841b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } else { 1842a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan if (DBG) Log.d(LOG_TAG, "setAudioMode() no change: " 1843a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan + audioModeToString(modeBefore)); 1844b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1846b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static String audioModeToString(int mode) { 1847b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project switch (mode) { 1848b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_INVALID: return "MODE_INVALID"; 1849b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_CURRENT: return "MODE_CURRENT"; 1850b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_NORMAL: return "MODE_NORMAL"; 1851b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_RINGTONE: return "MODE_RINGTONE"; 1852b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project case AudioManager.MODE_IN_CALL: return "MODE_IN_CALL"; 1853b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project default: return String.valueOf(mode); 1854b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1855b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1856b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1857b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1858b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Handles the wired headset button while in-call. 1859b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1860b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * This is called from the PhoneApp, not from the InCallScreen, 1861b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * since the HEADSETHOOK button means "mute or unmute the current 1862b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * call" *any* time a call is active, even if the user isn't actually 1863b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * on the in-call screen. 1864b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1865b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we consumed the event. 1866b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1867893d0233193b2095293d890a9ad1c73b1dc6a9a2mah /* package */ static boolean handleHeadsetHook(Phone phone, KeyEvent event) { 1868893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook()..." + event.getAction() + " " + event.getRepeatCount()); 1869b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1870b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // If the phone is totally idle, we ignore HEADSETHOOK events 1871b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // (and instead let them fall through to the media player.) 1872b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (phone.getState() == Phone.State.IDLE) { 1873b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1874b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1875b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1876b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Ok, the phone is in use. 1877b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // The headset button button means "Answer" if an incoming call is 1878b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringing. If not, it toggles the mute / unmute state. 1879b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // And in any case we *always* consume this event; this means 1881b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // that the usual mediaplayer-related behavior of the headset 1882b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // button will NEVER happen while the user is on a call. 1883b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1884b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasRingingCall = !phone.getRingingCall().isIdle(); 1885b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasActiveCall = !phone.getForegroundCall().isIdle(); 1886b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle(); 1887b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1888893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (hasRingingCall && 1889893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getRepeatCount() == 0 && 1890893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getAction() == KeyEvent.ACTION_UP) { 18912312eba1a4821fd8f10535038555d12874e6fc67Wink Saville // If an incoming call is ringing, answer it (just like with the 18922312eba1a4821fd8f10535038555d12874e6fc67Wink Saville // CALL button): 189379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 189479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 18958343169cc89621d46dce86449f5ee1ff5d3a4919John Wang answerCall(phone.getRingingCall()); 1896872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 1897872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 18980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (hasActiveCall && hasHoldingCall) { 18990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (DBG) log("handleHeadsetHook: ringing (both lines in use) ==> answer!"); 19008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang answerAndEndActive(PhoneApp.getInstance().mCM, phone.getRingingCall()); 19010fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } else { 19020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville if (DBG) log("handleHeadsetHook: ringing ==> answer!"); 19038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang answerCall(phone.getRingingCall()); // Automatically holds the current active call, 19042312eba1a4821fd8f10535038555d12874e6fc67Wink Saville // if there is one 19050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 190679b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 190779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 19082312eba1a4821fd8f10535038555d12874e6fc67Wink Saville } 19092312eba1a4821fd8f10535038555d12874e6fc67Wink Saville } else { 1910a52f06a12e64113097010cb126a722421c7c9cf3Peng Zhu // No incoming ringing call. 1911893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (event.isLongPress()) { 1912893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: longpress -> hangup"); 19138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang hangup(phone.getRingingCall()); 1914893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } 1915893d0233193b2095293d890a9ad1c73b1dc6a9a2mah else if (event.getAction() == KeyEvent.ACTION_UP && 1916893d0233193b2095293d890a9ad1c73b1dc6a9a2mah event.getRepeatCount() == 0) { 1917893d0233193b2095293d890a9ad1c73b1dc6a9a2mah Connection c = phone.getForegroundCall().getLatestConnection(); 1918893d0233193b2095293d890a9ad1c73b1dc6a9a2mah // If it is NOT an emg #, toggle the mute state. Otherwise, ignore the hook. 1919893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (c != null && !PhoneNumberUtils.isEmergencyNumber(c.getAddress())) { 1920a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang if (getMute()) { 1921893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: UNmuting..."); 1922a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(false); 1923893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } else { 1924893d0233193b2095293d890a9ad1c73b1dc6a9a2mah if (DBG) log("handleHeadsetHook: muting..."); 1925a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang setMute(true); 1926893d0233193b2095293d890a9ad1c73b1dc6a9a2mah } 1927a52f06a12e64113097010cb126a722421c7c9cf3Peng Zhu } 1928b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1929b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1930b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1931b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Even if the InCallScreen is the current activity, there's no 1932b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // need to force it to update, because (1) if we answered a 1933b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // ringing call, the InCallScreen will imminently get a phone 1934b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // state change event (causing an update), and (2) if we muted or 1935b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // unmuted, the setMute() call automagically updates the status 1936b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // bar, and there's no "mute" indication in the InCallScreen 1937b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // itself (other than the menu item, which only ever stays 1938b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // onscreen for a second anyway.) 1939b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // TODO: (2) isn't entirely true anymore. Once we return our result 1940b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // to the PhoneApp, we ask InCallScreen to update its control widgets 1941b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // in case we changed mute or speaker state and phones with touch- 1942b8df8173e1a0ea8ba89cea984176216201c4d5e7Paul Berman // screen [toggle] buttons need to update themselves. 1943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1946b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1948b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Look for ANY connections on the phone that qualify as being 1949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * disconnected. 1950b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we find a connection that is disconnected over 1952b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * all the phone's call objects. 1953b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1954b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static boolean hasDisconnectedConnections(Phone phone) { 1955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return hasDisconnectedConnections(phone.getForegroundCall()) || 1956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hasDisconnectedConnections(phone.getBackgroundCall()) || 1957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project hasDisconnectedConnections(phone.getRingingCall()); 1958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * Iterate over all connections in a call to see if there are any 1962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * that are not alive (disconnected or idle). 1963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * 1964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we find a connection that is disconnected, and 1965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * pending removal via 1966a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville * {@link com.android.internal.telephony.gsm.GsmCall#clearDisconnected()}. 1967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 1968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static final boolean hasDisconnectedConnections(Call call) { 1969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // look through all connections for non-active ones. 1970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project for (Connection c : call.getConnections()) { 1971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project if (!c.isAlive()) { 1972b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return true; 1973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project return false; 1976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 1977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Misc UI policy helper functions 1980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 1981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 1982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 1983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we're allowed to swap calls, given the current 1984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 1985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 19868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToSwapCalls(CallManager cm) { 19878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = cm.getDefaultPhone().getPhoneType(); 198879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 19890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // CDMA: "Swap" is enabled only when the phone reaches a *generic*. 19900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // state by either accepting a Call Waiting or by merging two calls 19910fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 19920fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return (app.cdmaPhoneCallState.getCurrentCallState() 19930fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville == CdmaPhoneCallState.PhoneCallState.CONF_CALL); 1994872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 1995872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 19960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Swap" is available if both lines are in use and there's no 19970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // incoming call. (Actually we need to verify that the active 19980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // call really is in the ACTIVE state and the holding call really 19990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // is in the HOLDING state, since you *can't* actually swap calls 20000fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // when the foreground call is DIALING or ALERTING.) 20018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return !cm.hasActiveRingingCall() 20028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang && (cm.getActiveFgCall().getState() == Call.State.ACTIVE) 20038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang && (cm.getFirstActiveBgCall().getState() == Call.State.HOLDING); 200479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 200579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 20060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2007b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2008b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2009b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2010b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if we're allowed to merge calls, given the current 2011b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 2012b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 20138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToMergeCalls(CallManager cm) { 20148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang int phoneType = cm.getFgPhone().getPhoneType(); 201579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 20160fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // CDMA: "Merge" is enabled only when the user is in a 3Way call. 20170fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 201839a84144262f12df44861d746788b9de92259e4fAbhishek Pillai return ((app.cdmaPhoneCallState.getCurrentCallState() 201939a84144262f12df44861d746788b9de92259e4fAbhishek Pillai == CdmaPhoneCallState.PhoneCallState.THRWAY_ACTIVE) 202039a84144262f12df44861d746788b9de92259e4fAbhishek Pillai && !app.cdmaPhoneCallState.IsThreeWayCallOrigStateDialing()); 2021b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan } else { 20220fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Merge" is available if both lines are in use and there's no 20230fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // incoming call, *and* the current conference isn't already 20240fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // "full". 20258343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // TODO: shall move all okToMerge logic to CallManager 2026b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan return !cm.hasActiveRingingCall() && cm.hasActiveFgCall() 2027b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan && cm.hasActiveBgCall() 2028b045b9344f339170d134cf814357361d96c349cfHung-ying Tyan && cm.canConference(cm.getFirstActiveBgCall()); 20290fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2030b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2031b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2032b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /** 2033b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * @return true if the UI should let you add a new call, given the current 2034b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project * state of the Phone. 2035b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */ 20368343169cc89621d46dce86449f5ee1ff5d3a4919John Wang /* package */ static boolean okToAddCall(CallManager cm) { 20378343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Phone phone = cm.getActiveFgCall().getPhone(); 20388343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 203979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink int phoneType = phone.getPhoneType(); 20408343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final Call.State fgCallState = cm.getActiveFgCall().getState(); 204179b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phoneType == Phone.PHONE_TYPE_CDMA) { 20420fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // CDMA: "Add call" menu item is only enabled when the call is in 204339a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // - ForegroundCall is in ACTIVE state 204439a84144262f12df44861d746788b9de92259e4fAbhishek Pillai // - After 30 seconds of user Ignoring/Missing a Call Waiting call. 20450fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville PhoneApp app = PhoneApp.getInstance(); 204639a84144262f12df44861d746788b9de92259e4fAbhishek Pillai return ((fgCallState == Call.State.ACTIVE) 20470fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && (app.cdmaPhoneCallState.getAddCallMenuStateAfterCallWaiting())); 2048872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan } else if ((phoneType == Phone.PHONE_TYPE_GSM) 2049872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan || (phoneType == Phone.PHONE_TYPE_SIP)) { 20500fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // GSM: "Add call" is available only if ALL of the following are true: 20510fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - There's no incoming ringing call 20520fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - There's < 2 lines in use 20530fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // - The foreground call is ACTIVE or IDLE or DISCONNECTED. 20540fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville // (We mainly need to make sure it *isn't* DIALING or ALERTING.) 20558343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasRingingCall = cm.hasActiveRingingCall(); 20568343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasActiveCall = cm.hasActiveFgCall(); 20578343169cc89621d46dce86449f5ee1ff5d3a4919John Wang final boolean hasHoldingCall = cm.hasActiveBgCall(); 20580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville final boolean allLinesTaken = hasActiveCall && hasHoldingCall; 20590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville 20600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville return !hasRingingCall 20610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && !allLinesTaken 20620fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville && ((fgCallState == Call.State.ACTIVE) 20630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville || (fgCallState == Call.State.IDLE) 20640fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville || (fgCallState == Call.State.DISCONNECTED)); 206579b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink } else { 206679b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink throw new IllegalStateException("Unexpected phone type: " + phoneType); 20670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville } 2068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 207086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu /** 207186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * Based on the input CNAP number string, 207286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * @return _RESTRICTED or _UNKNOWN for all the special CNAP strings. 207386c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu * Otherwise, return CNAP_SPECIAL_CASE_NO. 207486c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu */ 207586c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu private static int checkCnapSpecialCases(String n) { 207686c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (n.equals("PRIVATE") || 207786c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("P") || 207886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("RES")) { 207986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, PRIVATE string: " + n); 208086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return Connection.PRESENTATION_RESTRICTED; 208186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } else if (n.equals("UNAVAILABLE") || 208286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("UNKNOWN") || 208386c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("UNA") || 208486c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu n.equals("U")) { 208586c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, UNKNOWN string: " + n); 208686c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return Connection.PRESENTATION_UNKNOWN; 208786c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } else { 208886c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu if (DBG) log("checkCnapSpecialCases, normal str. number: " + n); 208986c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu return CNAP_SPECIAL_CASE_NO; 209086c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } 209186c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu } 209286c4a92aff88506bc81a7ad6d8a3853cd7fbe597Peng Zhu 2093153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman /** 2094153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * Handles certain "corner cases" for CNAP. When we receive weird phone numbers 2095153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * from the network to indicate different number presentations, convert them to 2096153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * expected number and presentation values within the CallerInfo object. 2097153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @param number number we use to verify if we are in a corner case 2098153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @param presentation presentation value used to verify if we are in a corner case 2099153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman * @return the new String that should be used for the phone number 2100153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman */ 2101153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman /* package */ static String modifyForSpecialCnapCases(Context context, CallerInfo ci, 2102153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman String number, int presentation) { 2103de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Obviously we return number if ci == null, but still return number if 2104de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // number == null, because in these cases the correct string will still be 2105de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // displayed/logged after this function returns based on the presentation value. 21065607afe15a507715078025beff1bd743c883a5ccPaul Berman if (ci == null || number == null) return number; 21075607afe15a507715078025beff1bd743c883a5ccPaul Berman 21085607afe15a507715078025beff1bd743c883a5ccPaul Berman if (DBG) log("modifyForSpecialCnapCases: initially, number=" + number 2109a1449e3a5d5d9d5e0e8982c7098752ce11477680Nicolas Catania + ", presentation=" + presentation + " ci " + ci); 2110153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2111153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // "ABSENT NUMBER" is a possible value we could get from the network as the 2112153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // phone number, so if this happens, change it to "Unknown" in the CallerInfo 2113153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // and fix the presentation to be the same. 2114de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman if (number.equals(context.getString(R.string.absent_num)) 2115de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman && presentation == Connection.PRESENTATION_ALLOWED) { 2116153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.unknown); 2117153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman ci.numberPresentation = Connection.PRESENTATION_UNKNOWN; 2118153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2119153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2120de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // Check for other special "corner cases" for CNAP and fix them similarly. Corner 2121de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // cases only apply if we received an allowed presentation from the network, so check 2122de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // if we think we have an allowed presentation, or if the CallerInfo presentation doesn't 2123de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // match the presentation passed in for verification (meaning we changed it previously 2124de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman // because it's a corner case and we're being called from a different entry point). 2125153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (ci.numberPresentation == Connection.PRESENTATION_ALLOWED 2126de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman || (ci.numberPresentation != presentation 2127de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman && presentation == Connection.PRESENTATION_ALLOWED)) { 2128153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman int cnapSpecialCase = checkCnapSpecialCases(number); 2129153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (cnapSpecialCase != CNAP_SPECIAL_CASE_NO) { 2130153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman // For all special strings, change number & numberPresentation. 2131153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (cnapSpecialCase == Connection.PRESENTATION_RESTRICTED) { 2132153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.private_num); 2133153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } else if (cnapSpecialCase == Connection.PRESENTATION_UNKNOWN) { 2134153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman number = context.getString(R.string.unknown); 2135153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2136153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman if (DBG) log("SpecialCnap: number=" + number 2137153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman + "; presentation now=" + cnapSpecialCase); 2138153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman ci.numberPresentation = cnapSpecialCase; 2139153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2140153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 21415607afe15a507715078025beff1bd743c883a5ccPaul Berman if (DBG) log("modifyForSpecialCnapCases: returning number string=" + number); 2142153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman return number; 2143153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman } 2144153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman 2145b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 21467a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // Support for 3rd party phone service providers. 21477a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // 21487a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 21497a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania /** 2150d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * Check if all the provider's info is present in the intent. 2151d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * @param intent Expected to have the provider's extra. 2152d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * @return true if the intent has all the extras to build the 2153d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania * in-call screen's provider info overlay. 2154d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania */ 2155d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /* package */ static boolean hasPhoneProviderExtras(Intent intent) { 21562cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania if (null == intent) { 21576fac3a6bdab79725a2ca2e3102eccb3f6e9c1ac4Nicolas Catania return false; 21586fac3a6bdab79725a2ca2e3102eccb3f6e9c1ac4Nicolas Catania } 21592cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania final String name = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 21602cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania final String gatewayUri = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI); 21612cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 21625e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return !TextUtils.isEmpty(name) && !TextUtils.isEmpty(gatewayUri); 2163d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania } 2164d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania 2165d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /** 21667a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * Copy all the expected extras set when a 3rd party provider is 21677a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * used from the source intent to the destination one. Checks all 21687a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * the required extras are present, if any is missing, none will 21697a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * be copied. 21707a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param src Intent which may contain the provider's extras. 21717a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania * @param dst Intent where a copy of the extras will be added if applicable. 21727a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania */ 2173d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania /* package */ static void checkAndCopyPhoneProviderExtras(Intent src, Intent dst) { 2174d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania if (!hasPhoneProviderExtras(src)) { 2175f24849566edae03c1123203b4362c688d8fa57a9Nicolas Catania Log.d(LOG_TAG, "checkAndCopyPhoneProviderExtras: some or all extras are missing."); 2176d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania return; 21777a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 2178d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania 2179d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania dst.putExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE, 2180d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania src.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE)); 2181d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania dst.putExtra(InCallScreen.EXTRA_GATEWAY_URI, 2182d94cc5e209bf871e4b6d5e84bcf6bd4e38d8ac65Nicolas Catania src.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI)); 21837a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania } 21847a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania 218562ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania /** 21862cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Get the provider's label from the intent. 21872cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param context to lookup the provider's package name. 21882cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param intent with an extra set to the provider's package name. 21895e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @return The provider's application label. null if an error 21905e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * occurred during the lookup of the package name or the label. 21912cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 21922cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static CharSequence getProviderLabel(Context context, Intent intent) { 21932cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania String packageName = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 21942cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania PackageManager pm = context.getPackageManager(); 21952cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 21962cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania try { 21972cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania ApplicationInfo info = pm.getApplicationInfo(packageName, 0); 21982cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 21992cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return pm.getApplicationLabel(info); 22002cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } catch (PackageManager.NameNotFoundException e) { 22012cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return null; 22022cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22032cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22042cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22052cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 22065e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * Get the provider's icon. 22075e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @param context to lookup the provider's icon. 22085e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @param intent with an extra set to the provider's package name. 22095e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania * @return The provider's application icon. null if an error occured during the icon lookup. 22105e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania */ 22115e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania /* package */ static Drawable getProviderIcon(Context context, Intent intent) { 22125e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania String packageName = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_PROVIDER_PACKAGE); 22135e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania PackageManager pm = context.getPackageManager(); 22145e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania 22155e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania try { 22165e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return pm.getApplicationIcon(packageName); 22175e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } catch (PackageManager.NameNotFoundException e) { 22185e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania return null; 22195e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } 22205e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania } 22215e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania 22225e16b62c17a9ad0457008953e2228d5ee8a406d3Nicolas Catania /** 22232cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Return the gateway uri from the intent. 22242cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param intent With the gateway uri extra. 22252cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @return The gateway URI or null if not found. 22262cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 22272cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static Uri getProviderGatewayUri(Intent intent) { 22282cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania String uri = intent.getStringExtra(InCallScreen.EXTRA_GATEWAY_URI); 22292cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return TextUtils.isEmpty(uri) ? null : Uri.parse(uri); 22302cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22312cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22322cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 22332cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * Return a formatted version of the uri's scheme specific 22342cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * part. E.g for 'tel:12345678', return '1-234-5678'. 22352cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @param uri A 'tel:' URI with the gateway phone number. 22362cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * @return the provider's address (from the gateway uri) formatted 22372cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania * for user display. null if uri was null or its scheme was not 'tel:'. 22382cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania */ 22392cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /* package */ static String formatProviderUri(Uri uri) { 22402cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania if (null != uri) { 22412cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania if ("tel".equals(uri.getScheme())) { 22422cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return PhoneNumberUtils.formatNumber(uri.getSchemeSpecificPart()); 22432cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } else { 22442cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return uri.toString(); 22452cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22462cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22472cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania return null; 22482cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania } 22492cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania 22502cbf80dfbbc28ae24e093fb089973b3e59d4508aNicolas Catania /** 225162ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * Check if a phone number can be route through a 3rd party 225262ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * gateway. The number must be a global phone number in numerical 225362ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * form (1-800-666-SEXY won't work). 225462ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * 225562ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * MMI codes and the like cannot be used as a dial number for the 225662ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * gateway either. 225762ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * 225862ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * @param number To be dialed via a 3rd party gateway. 225962ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania * @return true If the number can be routed through the 3rd party network. 226062ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania */ 226162ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania /* package */ static boolean isRoutableViaGateway(String number) { 226262ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania if (TextUtils.isEmpty(number)) { 226362ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return false; 226462ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 226562ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania number = PhoneNumberUtils.stripSeparators(number); 226662ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania if (!number.equals(PhoneNumberUtils.convertKeypadLettersToDigits(number))) { 226762ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return false; 226862ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 226962ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania number = PhoneNumberUtils.extractNetworkPortion(number); 227062ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania return PhoneNumberUtils.isGlobalPhoneNumber(number); 227162ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania } 227262ce1135ff91e303d80cac0434ed5232edb63c86Nicolas Catania 22732eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu /** 22742eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * This function is called when phone answers or places a call. 22752eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * Check if the phone is in a car dock or desk dock. 22762eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * If yes, turn on the speaker, when no wired or BT headsets are connected. 22772eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu * Otherwise do nothing. 22782eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu */ 22792eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu private static void activateSpeakerIfDocked(Phone phone) { 22802eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu if (DBG) log("activateSpeakerIfDocked()..."); 22812eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 22822eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu if (PhoneApp.mDockState == Intent.EXTRA_DOCK_STATE_DESK || 22832eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu PhoneApp.mDockState == Intent.EXTRA_DOCK_STATE_CAR) { 22847f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown if (DBG) log("activateSpeakerIfDocked(): In a dock -> may need to turn on speaker."); 22852eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu PhoneApp app = PhoneApp.getInstance(); 22862eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu BluetoothHandsfree bthf = app.getBluetoothHandsfree(); 22872eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 22882eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu if (!app.isHeadsetPlugged() && !(bthf != null && bthf.isAudioOn())) { 22892eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu turnOnSpeaker(phone.getContext(), true, true); 22902eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 22912eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 22922eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu } 22932eba6fabd0bedaf2a59da643ce475586b62f0ff9Peng Zhu 2294aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown 2295aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown /** 2296aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown * Returns whether the phone is in ECM ("Emergency Callback Mode") or not. 2297aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown */ 2298aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown /* package */ static boolean isPhoneInEcm(Phone phone) { 22998343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if ((phone != null) && TelephonyCapabilities.supportsEcm(phone)) { 23008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // For phones that support ECM, return true iff PROPERTY_INECM_MODE == "true". 23018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // TODO: There ought to be a better API for this than just 23028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // exposing a system property all the way up to the app layer, 23038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // probably a method like "inEcm()" provided by the telephony 23048343169cc89621d46dce86449f5ee1ff5d3a4919John Wang // layer. 2305aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown String ecmMode = 2306aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE); 2307aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown if (ecmMode != null) { 23088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return ecmMode.equals("true"); 23098343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 23108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 23118343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return false; 23128343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 23138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 2314bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown /** 2315bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * Returns the most appropriate Phone object to handle a call 2316bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * to the specified number. 2317bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * 2318bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param cm the CallManager. 2319bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param scheme the scheme from the data URI that the number originally came from. 2320bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown * @param number the phone number, or SIP address. 2321bbc3b15705e4511da3c8fe3fc105ad99a85e1e0bDavid Brown */ 23222587d9c6437b680911e252efecc73788e876de76Chung-yih Wang public static Phone pickPhoneBasedOnNumber(CallManager cm, 23232587d9c6437b680911e252efecc73788e876de76Chung-yih Wang String scheme, String number, String primarySipUri) { 23242587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (DBG) log("pickPhoneBasedOnNumber: scheme " + scheme 23252587d9c6437b680911e252efecc73788e876de76Chung-yih Wang + ", number " + number + ", sipUri " + primarySipUri); 23262587d9c6437b680911e252efecc73788e876de76Chung-yih Wang 23272587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (primarySipUri != null) { 23282587d9c6437b680911e252efecc73788e876de76Chung-yih Wang Phone phone = getSipPhoneFromUri(cm, primarySipUri); 23292587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (phone != null) return phone; 23302587d9c6437b680911e252efecc73788e876de76Chung-yih Wang } 23312587d9c6437b680911e252efecc73788e876de76Chung-yih Wang return cm.getDefaultPhone(); 23322587d9c6437b680911e252efecc73788e876de76Chung-yih Wang } 23332587d9c6437b680911e252efecc73788e876de76Chung-yih Wang 23342587d9c6437b680911e252efecc73788e876de76Chung-yih Wang public static Phone getSipPhoneFromUri(CallManager cm, String target) { 2335872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan for (Phone phone : cm.getAllPhones()) { 2336872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan if (phone.getPhoneType() == Phone.PHONE_TYPE_SIP) { 2337872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan String sipUri = ((SipPhone) phone).getSipUri(); 23382587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (target.equals(sipUri)) { 23392587d9c6437b680911e252efecc73788e876de76Chung-yih Wang if (DBG) log("- pickPhoneBasedOnNumber:" + 2340872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan "found SipPhone! obj = " + phone + ", " 2341872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan + phone.getClass()); 2342872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan return phone; 23438343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 2344aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2345aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 23462587d9c6437b680911e252efecc73788e876de76Chung-yih Wang return null; 2347aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown } 2348f8396c51f11b1044d236415f2ee88750b4e40e1fJohn Wang 23498343169cc89621d46dce86449f5ee1ff5d3a4919John Wang public static boolean isRealIncomingCall(Call.State state) { 23508343169cc89621d46dce86449f5ee1ff5d3a4919John Wang return (state == Call.State.INCOMING && !PhoneApp.getInstance().mCM.hasActiveFgCall()); 23518343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 23528343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 2353aa3d3cfb32c7350f72771db8756e751eb5c61b1eDavid Brown 23547a2ee085993bc9cae01bf9daa993b1551ed64a7bNicolas Catania // 2355b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // General phone and call state debugging/testing code 2356b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // 2357b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2358b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan private static void dumpStateForCall(Call call, String prefix) { 2359b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan StringBuilder b = new StringBuilder(128); 2360b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(prefix).append(call.getState()); 2361b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" ").append(call.getPhone().getPhoneName()); 2362b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" isAlive ").append(call.getState().isAlive()); 2363b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" isRinging ").append(call.getState().isRinging()); 2364b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" isDialing ").append(call.getState().isDialing()); 2365b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" isIdle ").append(call.isIdle()); 2366b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" hasConnections ").append(call.hasConnections()); 2367b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, b.toString()); 2368b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan } 2369b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2370b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan /* package */ static void dumpCallState() { 2371b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan PhoneApp app = PhoneApp.getInstance(); 2372b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan CallManager cm = app.mCM; 2373b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, "dumpCallState():"); 2374b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, "- Call state = " + cm.getState()); 2375b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2376b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan dumpStateForCall(cm.getActiveFgCall(), " - FG call: "); 2377b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan dumpStateForCall(cm.getFirstActiveBgCall(), " - BG call: "); 2378b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan dumpStateForCall(cm.getFirstActiveRingingCall(), " - RINGING call: "); 2379b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2380b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan final boolean hasRingingCall = cm.hasActiveRingingCall(); 2381b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan final boolean hasActiveCall = cm.hasActiveFgCall(); 2382b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan final boolean hasHoldingCall = cm.hasActiveBgCall(); 2383b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan final boolean allLinesTaken = hasActiveCall && hasHoldingCall; 2384b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan StringBuilder b = new StringBuilder(128); 2385b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" - hasRingingCall ").append(hasRingingCall); 2386b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" hasActiveCall ").append(hasActiveCall); 2387b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" hasHoldingCall ").append(hasHoldingCall); 2388b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan b.append(" allLinesTaken ").append(allLinesTaken); 2389b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, b.toString()); 2390b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2391b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Phone phone = cm.getDefaultPhone(); 2392b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan // On CDMA phones, dump out the CdmaPhoneCallState too: 2393b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 2394b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan if (app.cdmaPhoneCallState != null) { 2395b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, " - CDMA call state: " 2396b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan + app.cdmaPhoneCallState.getCurrentCallState()); 2397b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan } else { 2398b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, " - CDMA device, but null cdmaPhoneCallState!"); 2399b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan } 2400b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan } 2401b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2402b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan // Watch out: the isRinging() call below does NOT tell us anything 2403b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan // about the state of the telephony layer; it merely tells us whether 2404b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan // the Ringer manager is currently playing the ringtone. 2405b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan boolean ringing = app.getRinger().isRinging(); 2406b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan Log.d(LOG_TAG, " - Ringer state: " + ringing); 2407b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan } 2408b5190cc81c5cf5ea7bc8f92734b5824bf0b20854Hung-ying Tyan 2409b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project /* package */ static void dumpCallState(Phone phone) { 24100f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown PhoneApp app = PhoneApp.getInstance(); 24111e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, "dumpCallState():"); 2412b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown Log.d(LOG_TAG, "- Phone: " + phone + ", name = " + phone.getPhoneName() 2413b15bef0ddcb4f744dff92013a9b596f2fcc2a008David Brown + ", state = " + phone.getState()); 2414b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 24151e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown StringBuilder b = new StringBuilder(128); 24161e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24171e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Call call = phone.getForegroundCall(); 24181e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24191e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - FG call: ").append(call.getState()); 24201e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24211e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24221e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24231e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24241e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24251e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 24261e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24271e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown call = phone.getBackgroundCall(); 24281e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24291e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - BG call: ").append(call.getState()); 24301e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24311e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24321e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24331e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24341e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24351e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 24361e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown 24371e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown call = phone.getRingingCall(); 24381e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24391e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - RINGING call: ").append(call.getState()); 24401e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isAlive ").append(call.getState().isAlive()); 24411e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isRinging ").append(call.getState().isRinging()); 24421e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isDialing ").append(call.getState().isDialing()); 24431e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" isIdle ").append(call.isIdle()); 24441e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasConnections ").append(call.hasConnections()); 24451e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 2446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasRingingCall = !phone.getRingingCall().isIdle(); 2449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasActiveCall = !phone.getForegroundCall().isIdle(); 2450b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean hasHoldingCall = !phone.getBackgroundCall().isIdle(); 2451b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project final boolean allLinesTaken = hasActiveCall && hasHoldingCall; 24521e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.setLength(0); 24531e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" - hasRingingCall ").append(hasRingingCall); 24541e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasActiveCall ").append(hasActiveCall); 24551e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" hasHoldingCall ").append(hasHoldingCall); 24561e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown b.append(" allLinesTaken ").append(allLinesTaken); 24571e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, b.toString()); 2458b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 24590f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown // On CDMA phones, dump out the CdmaPhoneCallState too: 246079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) { 24610f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown if (app.cdmaPhoneCallState != null) { 24621e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - CDMA call state: " 24630f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown + app.cdmaPhoneCallState.getCurrentCallState()); 24640f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } else { 24651e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - CDMA device, but null cdmaPhoneCallState!"); 24660f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } 24670f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown } 24680f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown 2469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // Watch out: the isRinging() call below does NOT tell us anything 2470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // about the state of the telephony layer; it merely tells us whether 2471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project // the Ringer manager is currently playing the ringtone. 24720f68bb19e2cca0bb7f70e2fcf16e0747a0036885David Brown boolean ringing = app.getRinger().isRinging(); 24731e8a3579f8e49fd1f1a078d6be6864a6a8bac306David Brown Log.d(LOG_TAG, " - Ringer state: " + ringing); 2474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 2475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project 2476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project private static void log(String msg) { 2477796c70c99bc39295bf685061056f06ab8949c742David Brown Log.d(LOG_TAG, msg); 2478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project } 24798343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 24808343169cc89621d46dce86449f5ee1ff5d3a4919John Wang static void dumpCallManager() { 24818343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Call call; 24828343169cc89621d46dce86449f5ee1ff5d3a4919John Wang CallManager cm = PhoneApp.getInstance().mCM; 24838343169cc89621d46dce86449f5ee1ff5d3a4919John Wang StringBuilder b = new StringBuilder(128); 24848343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 24858343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "############### dumpCallManager() ##############"); 24868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "CallManager: " + cm 24878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang + ", state = " + cm.getState()); 24888343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 24898343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getActiveFgCall(); 24908343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - FG call: ").append(cm.hasActiveFgCall()? "YES ": "NO "); 24918343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 24928343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getActiveFgCallState()); 24938343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(cm.getFgCallConnections()); 24948343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 24958343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 24968343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getFirstActiveBgCall(); 24978343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - BG call: ").append(cm.hasActiveBgCall()? "YES ": "NO "); 24988343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 24998343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getFirstActiveBgCall().getState()); 25008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(cm.getBgCallConnections()); 25018343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25028343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25038343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = cm.getFirstActiveRingingCall(); 25048343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - RINGING call: ").append(cm.hasActiveRingingCall()? "YES ": "NO "); 25058343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(call); 25068343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(cm.getFirstActiveRingingCall().getState()); 25078343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25088343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25098343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25108343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25118343169cc89621d46dce86449f5ee1ff5d3a4919John Wang for (Phone phone : CallManager.getInstance().getAllPhones()) { 25128343169cc89621d46dce86449f5ee1ff5d3a4919John Wang if (phone != null) { 25138343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "Phone: " + phone + ", name = " + phone.getPhoneName() 25148343169cc89621d46dce86449f5ee1ff5d3a4919John Wang + ", state = " + phone.getState()); 25158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25168343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getForegroundCall(); 25178343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - FG call: ").append(call); 25188343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25198343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25208343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25218343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.setLength(0); 25228343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getBackgroundCall(); 25238343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - BG call: ").append(call); 25248343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25258343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25268343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString());b.setLength(0); 25278343169cc89621d46dce86449f5ee1ff5d3a4919John Wang call = phone.getRingingCall(); 25288343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append(" - RINGING call: ").append(call); 25298343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " State: ").append(call.getState()); 25308343169cc89621d46dce86449f5ee1ff5d3a4919John Wang b.append( " Conn: ").append(call.hasConnections()); 25318343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, b.toString()); 25328343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 25338343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 25348343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 25358343169cc89621d46dce86449f5ee1ff5d3a4919John Wang Log.d(LOG_TAG, "############## END dumpCallManager() ###############"); 25368343169cc89621d46dce86449f5ee1ff5d3a4919John Wang } 25378343169cc89621d46dce86449f5ee1ff5d3a4919John Wang 2538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project} 2539