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 com.android.internal.telephony.Call;
20b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.CallerInfo;
21b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.CallerInfoAsyncQuery;
220fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Savilleimport com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
230fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Savilleimport com.android.internal.telephony.cdma.SignalToneUtil;
240fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Savilleimport com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaDisplayInfoRec;
250fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Savilleimport com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
26b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Connection;
27b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport com.android.internal.telephony.Phone;
286f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Savilleimport com.android.internal.telephony.PhoneBase;
29170160f6550b2933ff5a6c96c879d074a3ca2f16John Wangimport com.android.internal.telephony.CallManager;
30b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
317f63f08c5c88d604abba447032ed42f4f972f3efDavid Brownimport android.app.ActivityManagerNative;
32b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.content.Context;
33b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.AudioManager;
34b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.media.ToneGenerator;
35b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.AsyncResult;
36b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Handler;
37b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.Message;
387f63f08c5c88d604abba447032ed42f4f972f3efDavid Brownimport android.os.RemoteException;
39b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.os.SystemProperties;
40678d72446de9c185c767206338f5fb199e0cd845Peng Zhuimport android.os.Vibrator;
41b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.provider.CallLog.Calls;
42b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.provider.Settings;
433800ac871d6548790ac6119bb68b9be0640af261David Krauseimport android.telephony.PhoneNumberUtils;
44b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.PhoneStateListener;
45b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.telephony.TelephonyManager;
4640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Cataniaimport android.text.TextUtils;
47cd89106dcd1038666f992cea3cc79e067245187fDan Egnorimport android.util.EventLog;
48b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectimport android.util.Log;
49b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
50b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
51b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project/**
52325cc2ced6f1ff5fb1708abfcc5e9c73ac0cd962David Brown * Phone app module that listens for phone state changes and various other
53325cc2ced6f1ff5fb1708abfcc5e9c73ac0cd962David Brown * events from the telephony layer, and triggers any resulting UI behavior
54325cc2ced6f1ff5fb1708abfcc5e9c73ac0cd962David Brown * (like starting the Ringer and Incoming Call UI, playing in-call tones,
55325cc2ced6f1ff5fb1708abfcc5e9c73ac0cd962David Brown * updating notifications, writing call log entries, etc.)
56b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project */
57b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Projectpublic class CallNotifier extends Handler
58b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        implements CallerInfoAsyncQuery.OnQueryCompleteListener {
59796c70c99bc39295bf685061056f06ab8949c742David Brown    private static final String LOG_TAG = "CallNotifier";
60b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final boolean DBG =
61796c70c99bc39295bf685061056f06ab8949c742David Brown            (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1);
62796c70c99bc39295bf685061056f06ab8949c742David Brown    private static final boolean VDBG = (PhoneApp.DBG_LEVEL >= 2);
63b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
64b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Maximum time we allow the CallerInfo query to run,
65b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // before giving up and falling back to the default ringtone.
66b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int RINGTONE_QUERY_WAIT_TIME = 500;  // msec
67b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
680fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // Timers related to CDMA Call Waiting
690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // 1) For displaying Caller Info
700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // 2) For disabling "Add Call" menu option once User selects Ignore or CW Timeout occures
710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private static final int CALLWAITING_CALLERINFO_DISPLAY_TIME = 20000; // msec
7239a84144262f12df44861d746788b9de92259e4fAbhishek Pillai    private static final int CALLWAITING_ADDCALL_DISABLE_TIME = 30000; // msec
730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // Time to display the  DisplayInfo Record sent by CDMA network
750fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private static final int DISPLAYINFO_NOTIFICATION_TIME = 2000; // msec
760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
77f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    /** The singleton instance. */
78f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    private static CallNotifier sInstance;
79f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown
8077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // Boolean to keep track of whether or not a CDMA Call Waiting call timed out.
8177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    //
8277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // This is CDMA-specific, because with CDMA we *don't* get explicit
8377350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // notification from the telephony layer that a call-waiting call has
8477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // stopped ringing.  Instead, when a call-waiting call first comes in we
8577350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // start a 20-second timer (see CALLWAITING_CALLERINFO_DISPLAY_DONE), and
8677350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // if the timer expires we clean up the call and treat it as a missed call.
8777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    //
8877350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // If this field is true, that means that the current Call Waiting call
8977350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // "timed out" and should be logged in Call Log as a missed call.  If it's
9077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // false when we reach onCdmaCallWaitingReject(), we can assume the user
9177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // explicitly rejected this call-waiting call.
9277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    //
9377350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // This field is reset to false any time a call-waiting call first comes
9477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // in, and after cleaning up a missed call-waiting call.  It's only ever
9577350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // set to true when the CALLWAITING_CALLERINFO_DISPLAY_DONE timer fires.
9677350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    //
9777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // TODO: do we really need a member variable for this?  Don't we always
9877350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // know at the moment we call onCdmaCallWaitingReject() whether this is an
9977350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // explicit rejection or not?
10077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // (Specifically: when we call onCdmaCallWaitingReject() from
10177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // PhoneUtils.hangupRingingCall() that means the user deliberately rejected
10277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // the call, and if we call onCdmaCallWaitingReject() because of a
10377350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // CALLWAITING_CALLERINFO_DISPLAY_DONE event that means that it timed
10477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    // out...)
1050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private boolean mCallWaitingTimeOut = false;
1060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // values used to track the query state
108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int CALLERINFO_QUERY_READY = 0;
109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int CALLERINFO_QUERYING = -1;
110b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // the state of the CallerInfo Query.
112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private int mCallerInfoQueryState;
113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // object used to synchronize access to mCallerInfoQueryState
115b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private Object mCallerInfoQueryStateGuard = new Object();
116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
117b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Event used to indicate a query timeout.
118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT = 100;
119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Events from the Phone object:
121b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int PHONE_STATE_CHANGED = 1;
122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int PHONE_NEW_RINGING_CONNECTION = 2;
123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int PHONE_DISCONNECT = 3;
124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int PHONE_UNKNOWN_CONNECTION_APPEARED = 4;
125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private static final int PHONE_INCOMING_RING = 5;
1260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private static final int PHONE_STATE_DISPLAYINFO = 6;
1270fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private static final int PHONE_STATE_SIGNALINFO = 7;
1280fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private static final int PHONE_CDMA_CALL_WAITING = 8;
1293800ac871d6548790ac6119bb68b9be0640af261David Krause    private static final int PHONE_ENHANCED_VP_ON = 9;
1303800ac871d6548790ac6119bb68b9be0640af261David Krause    private static final int PHONE_ENHANCED_VP_OFF = 10;
13177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int PHONE_RINGBACK_TONE = 11;
13277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int PHONE_RESEND_MUTE = 12;
1333800ac871d6548790ac6119bb68b9be0640af261David Krause
134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    // Events generated internally:
13577350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int PHONE_MWI_CHANGED = 21;
13677350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int PHONE_BATTERY_LOW = 22;
13777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int CALLWAITING_CALLERINFO_DISPLAY_DONE = 23;
13877350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int CALLWAITING_ADDCALL_DISABLE_TIMEOUT = 24;
13977350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int DISPLAYINFO_NOTIFICATION_DONE = 25;
14077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int EVENT_OTA_PROVISION_CHANGE = 26;
14177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private static final int CDMA_CALL_WAITING_REJECT = 27;
142e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown    private static final int UPDATE_IN_CALL_NOTIFICATION = 28;
143eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
144678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    // Emergency call related defines:
145678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private static final int EMERGENCY_TONE_OFF = 0;
146678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private static final int EMERGENCY_TONE_ALERT = 1;
147678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private static final int EMERGENCY_TONE_VIBRATE = 2;
148678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
149b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private PhoneApp mApplication;
150170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang    private CallManager mCM;
151b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private Ringer mRinger;
152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private BluetoothHandsfree mBluetoothHandsfree;
15311aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania    private CallLogAsync mCallLog;
154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private boolean mSilentRingerRequested;
155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1560fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // ToneGenerator instance for playing SignalInfo tones
1570fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private ToneGenerator mSignalInfoToneGenerator;
1580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
1590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    // The tone volume relative to other sounds in the stream SignalInfo
160ed1d155825eb32990fde95eef9d89a7260e4c3f1w    private static final int TONE_RELATIVE_VOLUME_SIGNALINFO = 80;
1610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
1623800ac871d6548790ac6119bb68b9be0640af261David Krause    private Call.State mPreviousCdmaCallState;
16324f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon    private boolean mVoicePrivacyState = false;
1643800ac871d6548790ac6119bb68b9be0640af261David Krause    private boolean mIsCdmaRedialCall = false;
1653800ac871d6548790ac6119bb68b9be0640af261David Krause
166678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    // Emergency call tone and vibrate:
167678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private int mIsEmergencyToneOn;
168678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private int mCurrentEmergencyToneState = EMERGENCY_TONE_OFF;
169678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private EmergencyTonePlayerVibrator mEmergencyTonePlayerVibrator;
170678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
171eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang    // Ringback tone player
17203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent    private InCallTonePlayer mInCallRingbackTonePlayer;
17303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
17403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent    // Call waiting tone player
17503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent    private InCallTonePlayer mCallWaitingTonePlayer;
17603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
17703d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent    // Cached AudioManager
17803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent    private AudioManager mAudioManager;
179eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
180f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    /**
181f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown     * Initialize the singleton CallNotifier instance.
182f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown     * This is only done once, at startup, from PhoneApp.onCreate().
183f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown     */
184f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    /* package */ static CallNotifier init(PhoneApp app, Phone phone, Ringer ringer,
185f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown                                           BluetoothHandsfree btMgr, CallLogAsync callLog) {
186f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown        synchronized (CallNotifier.class) {
187f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown            if (sInstance == null) {
188f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown                sInstance = new CallNotifier(app, phone, ringer, btMgr, callLog);
189f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown            } else {
190f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown                Log.wtf(LOG_TAG, "init() called multiple times!  sInstance = " + sInstance);
191f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown            }
192f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown            return sInstance;
193f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown        }
194f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    }
195f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown
196f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    /** Private constructor; @see init() */
197f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown    private CallNotifier(PhoneApp app, Phone phone, Ringer ringer,
198f0c4d0e94b7fa915bcfacd28ee432f8b3846511aDavid Brown                         BluetoothHandsfree btMgr, CallLogAsync callLog) {
199b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mApplication = app;
200170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM = app.mCM;
20111aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania        mCallLog = callLog;
20279b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink
203872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        mAudioManager = (AudioManager) mApplication.getSystemService(Context.AUDIO_SERVICE);
20403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
20524f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        registerForNotifications();
20624f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon
20724f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        // Instantiate the ToneGenerator for SignalInfo and CallWaiting
20824f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        // TODO: We probably don't need the mSignalInfoToneGenerator instance
20924f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        // around forever. Need to change it so as to create a ToneGenerator instance only
21024f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        // when a tone is being played and releases it after its done playing.
21124f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        try {
21224f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon            mSignalInfoToneGenerator = new ToneGenerator(AudioManager.STREAM_VOICE_CALL,
21324f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                    TONE_RELATIVE_VOLUME_SIGNALINFO);
21424f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        } catch (RuntimeException e) {
21524f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon            Log.w(LOG_TAG, "CallNotifier: Exception caught while creating " +
21624f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                    "mSignalInfoToneGenerator: " + e);
21724f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon            mSignalInfoToneGenerator = null;
218eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        }
219eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mRinger = ringer;
221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mBluetoothHandsfree = btMgr;
222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        TelephonyManager telephonyManager = (TelephonyManager)app.getSystemService(
224b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                Context.TELEPHONY_SERVICE);
225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        telephonyManager.listen(mPhoneStateListener,
226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                | PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR);
228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    @Override
231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    public void handleMessage(Message msg) {
232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        switch (msg.what) {
233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_NEW_RINGING_CONNECTION:
2344158ed3e7bdff5212a5542e662240ea0063664b2David Brown                log("RINGING... (new)");
235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onNewRingingConnection((AsyncResult) msg.obj);
236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mSilentRingerRequested = false;
237b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_INCOMING_RING:
240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // repeat the ring when requested by the RIL, and when the user has NOT
241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // specifically requested silence.
2426f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                if (msg.obj != null && ((AsyncResult) msg.obj).result != null) {
2436f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                    PhoneBase pb =  (PhoneBase)((AsyncResult)msg.obj).result;
2446f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville
2456f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                    if ((pb.getState() == Phone.State.RINGING)
2466f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                            && (mSilentRingerRequested == false)) {
2476f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                        if (DBG) log("RINGING... (PHONE_INCOMING_RING event)");
2486f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                        mRinger.ring();
2496f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                    } else {
2506f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                        if (DBG) log("RING before NEW_RING, skipping");
2516f9f8d7224cd9c66513f987fc71edb61a30a2c2eWink Saville                    }
252b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
253b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
2540fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
255b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_STATE_CHANGED:
256b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onPhoneStateChanged((AsyncResult) msg.obj);
257b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
258b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
259b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_DISCONNECT:
260b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("DISCONNECT");
261b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onDisconnect((AsyncResult) msg.obj);
262b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
263b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
264b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_UNKNOWN_CONNECTION_APPEARED:
265b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onUnknownConnectionAppeared((AsyncResult) msg.obj);
266b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
267b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
268b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT:
269b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // CallerInfo query is taking too long!  But we can't wait
270b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // any more, so start ringing NOW even if it means we won't
271b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // use the correct custom ringtone.
272796c70c99bc39295bf685061056f06ab8949c742David Brown                Log.w(LOG_TAG, "CallerInfo query took too long; manually starting ringer");
273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // In this case we call onCustomRingQueryComplete(), just
275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // like if the query had completed normally.  (But we're
276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // going to get the default ringtone, since we never got
277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // the chance to call Ringer.setCustomRingtoneUri()).
278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onCustomRingQueryComplete();
279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
280b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_MWI_CHANGED:
282872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                onMwiChanged(mApplication.phone.getMessageWaitingIndicator());
283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            case PHONE_BATTERY_LOW:
286b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onBatteryLow();
287b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                break;
288b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
2890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case PHONE_CDMA_CALL_WAITING:
2900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if (DBG) log("Received PHONE_CDMA_CALL_WAITING event");
2910fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                onCdmaCallWaiting((AsyncResult) msg.obj);
2920fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
2930fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
29477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown            case CDMA_CALL_WAITING_REJECT:
29577350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown                Log.i(LOG_TAG, "Received CDMA_CALL_WAITING_REJECT event");
29677350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown                onCdmaCallWaitingReject();
29777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown                break;
29877350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown
2990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case CALLWAITING_CALLERINFO_DISPLAY_DONE:
30077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown                Log.i(LOG_TAG, "Received CALLWAITING_CALLERINFO_DISPLAY_DONE event");
3010fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                mCallWaitingTimeOut = true;
3020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                onCdmaCallWaitingReject();
3030fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
3040fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
3050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case CALLWAITING_ADDCALL_DISABLE_TIMEOUT:
3060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if (DBG) log("Received CALLWAITING_ADDCALL_DISABLE_TIMEOUT event ...");
3070fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // Set the mAddCallMenuStateAfterCW state to true
3080fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                mApplication.cdmaPhoneCallState.setAddCallMenuStateAfterCallWaiting(true);
30975e3711d82d0c98444f6c438437cad41d862fca6David Brown                mApplication.updateInCallScreen();
3100fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
3110fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
3120fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case PHONE_STATE_DISPLAYINFO:
3130fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if (DBG) log("Received PHONE_STATE_DISPLAYINFO event");
3140fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                onDisplayInfo((AsyncResult) msg.obj);
3150fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
3160fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
3170fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case PHONE_STATE_SIGNALINFO:
3180fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if (DBG) log("Received PHONE_STATE_SIGNALINFO event");
3190fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                onSignalInfo((AsyncResult) msg.obj);
3200fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
3210fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
3220fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            case DISPLAYINFO_NOTIFICATION_DONE:
3230fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if (DBG) log("Received Display Info notification done event ...");
3240fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                CdmaDisplayInfo.dismissDisplayInfoRecord();
3250fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                break;
3260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
327af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville            case EVENT_OTA_PROVISION_CHANGE:
328211ff4c5c95f63f845b953f0020dfb516c01fcadDavid Brown                if (DBG) log("EVENT_OTA_PROVISION_CHANGE...");
329211ff4c5c95f63f845b953f0020dfb516c01fcadDavid Brown                mApplication.handleOtaspEvent(msg);
330af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                break;
331af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville
3323800ac871d6548790ac6119bb68b9be0640af261David Krause            case PHONE_ENHANCED_VP_ON:
3333800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("PHONE_ENHANCED_VP_ON...");
33424f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                if (!mVoicePrivacyState) {
3353800ac871d6548790ac6119bb68b9be0640af261David Krause                    int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
3363800ac871d6548790ac6119bb68b9be0640af261David Krause                    new InCallTonePlayer(toneToPlay).start();
33724f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                    mVoicePrivacyState = true;
338b3e1e0012986738034dab1e0625cde8095c61542Peng Zhu                    // Update the VP icon:
33949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown                    if (DBG) log("- updating notification for VP state...");
340df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown                    mApplication.notificationMgr.updateInCallNotification();
3413800ac871d6548790ac6119bb68b9be0640af261David Krause                }
3423800ac871d6548790ac6119bb68b9be0640af261David Krause                break;
3433800ac871d6548790ac6119bb68b9be0640af261David Krause
3443800ac871d6548790ac6119bb68b9be0640af261David Krause            case PHONE_ENHANCED_VP_OFF:
3453800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("PHONE_ENHANCED_VP_OFF...");
34624f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                if (mVoicePrivacyState) {
3473800ac871d6548790ac6119bb68b9be0640af261David Krause                    int toneToPlay = InCallTonePlayer.TONE_VOICE_PRIVACY;
3483800ac871d6548790ac6119bb68b9be0640af261David Krause                    new InCallTonePlayer(toneToPlay).start();
34924f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon                    mVoicePrivacyState = false;
350b3e1e0012986738034dab1e0625cde8095c61542Peng Zhu                    // Update the VP icon:
35149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown                    if (DBG) log("- updating notification for VP state...");
352df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown                    mApplication.notificationMgr.updateInCallNotification();
3533800ac871d6548790ac6119bb68b9be0640af261David Krause                }
3543800ac871d6548790ac6119bb68b9be0640af261David Krause                break;
3553800ac871d6548790ac6119bb68b9be0640af261David Krause
356eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            case PHONE_RINGBACK_TONE:
357eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                onRingbackTone((AsyncResult) msg.obj);
358eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                break;
359eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
3605bf2817fb998e6d7c7b50103733bfe8710d63916John Wang            case PHONE_RESEND_MUTE:
3615bf2817fb998e6d7c7b50103733bfe8710d63916John Wang                onResendMute();
3625bf2817fb998e6d7c7b50103733bfe8710d63916John Wang                break;
3635bf2817fb998e6d7c7b50103733bfe8710d63916John Wang
364e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            case UPDATE_IN_CALL_NOTIFICATION:
365df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown                mApplication.notificationMgr.updateInCallNotification();
366e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown                break;
367e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown
368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            default:
369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // super.handleMessage(msg);
370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
374b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        @Override
375b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public void onMessageWaitingIndicatorChanged(boolean mwi) {
376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            onMwiChanged(mwi);
377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        @Override
380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public void onCallForwardingIndicatorChanged(boolean cfi) {
381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            onCfiChanged(cfi);
382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    };
384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
385d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown    /**
386d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * Handles a "new ringing connection" event from the telephony layer.
387d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     */
388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onNewRingingConnection(AsyncResult r) {
389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Connection c = (Connection) r.result;
3904158ed3e7bdff5212a5542e662240ea0063664b2David Brown        log("onNewRingingConnection(): state = " + mCM.getState() + ", conn = { " + c + " }");
3918343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Call ringing = c.getCall();
3928343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        Phone phone = ringing.getPhone();
393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
394d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // Check for a few cases where we totally ignore incoming calls.
395d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        if (ignoreAllIncomingCalls(phone)) {
396d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // Immediately reject the call, without even indicating to the user
397d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // that an incoming call occurred.  (This will generally send the
398d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // caller straight to voicemail, just as if we *had* shown the
399d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // incoming-call UI and the user had declined the call.)
4008343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            PhoneUtils.hangupRingingCall(ringing);
401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            return;
402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
40449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (c == null) {
40549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            Log.w(LOG_TAG, "CallNotifier.onNewRingingConnection(): null connection!");
40649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // Should never happen, but if it does just bail out and do nothing.
40749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            return;
40849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        }
40905fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu
41049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (!c.isRinging()) {
41149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            Log.i(LOG_TAG, "CallNotifier.onNewRingingConnection(): connection not ringing!");
41249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // This is a very strange case: an incoming call that stopped
41349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // ringing almost instantly after the onNewRingingConnection()
41449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // event.  There's nothing we can do here, so just bail out
41549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // without doing anything.  (But presumably we'll log it in
41649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // the call log when the disconnect event comes in...)
41749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            return;
41849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        }
41949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
42049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // Stop any signalInfo tone being played on receiving a Call
4219537852545bf97d9e4d903c1eb2b528adc22dbc8David Brown        stopSignalInfoTone();
42249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
42349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        Call.State state = c.getState();
42449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // State will be either INCOMING or WAITING.
42549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (VDBG) log("- connection is ringing!  state = " + state);
42649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // if (DBG) PhoneUtils.dumpCallState(mPhone);
42749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
42849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // No need to do any service state checks here (like for
42949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // "emergency mode"), since in those states the SIM won't let
43049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // us get incoming connections in the first place.
43149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
43249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // TODO: Consider sending out a serialized broadcast Intent here
43349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // (maybe "ACTION_NEW_INCOMING_CALL"), *before* starting the
43449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // ringer and going to the in-call UI.  The intent should contain
43549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // the caller-id info for the current connection, and say whether
43649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // it would be a "call waiting" call or a regular ringing call.
43749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // If anybody consumed the broadcast, we'd bail out without
43849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // ringing or bringing up the in-call UI.
43949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        //
44049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // This would give 3rd party apps a chance to listen for (and
44149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // intercept) new ringing connections.  An app could reject the
44249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // incoming call by consuming the broadcast and doing nothing, or
44349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // it could "pick up" the call (without any action by the user!)
44475e3711d82d0c98444f6c438437cad41d862fca6David Brown        // via some future TelephonyManager API.
44549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        //
44675e3711d82d0c98444f6c438437cad41d862fca6David Brown        // See bug 1312336 for more details.
44749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // We'd need to protect this with a new "intercept incoming calls"
44849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // system permission.
44949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
45049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // Obtain a partial wake lock to make sure the CPU doesn't go to
45149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // sleep before we finish bringing up the InCallScreen.
45249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // (This will be upgraded soon to a full wake lock; see
45349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // showIncomingCall().)
45449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (VDBG) log("Holding wake lock on new incoming connection.");
45549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        mApplication.requestWakeState(PhoneApp.WakeState.PARTIAL);
45649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown
45749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // - don't ring for call waiting connections
45849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // - do this before showing the incoming call panel
4598343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        if (PhoneUtils.isRealIncomingCall(state)) {
46049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            startIncomingCallQuery(c);
46149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        } else {
46249c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (VDBG) log("- starting call waiting tone...");
46349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (mCallWaitingTonePlayer == null) {
46449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown                mCallWaitingTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_CALL_WAITING);
46549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown                mCallWaitingTonePlayer.start();
466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
46749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // in this case, just fall through like before, and call
46849c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            // showIncomingCall().
46949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (DBG) log("- showing incoming call (this is a WAITING call)...");
47049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            showIncomingCall();
471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
47349c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // Note we *don't* post a status bar notification here, since
47449c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // we're not necessarily ready to actually show the incoming call
47549c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // to the user.  (For calls in the INCOMING state, at least, we
47649c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // still need to run a caller-id query, and we may not even ring
47749c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // at all if the "send directly to voicemail" flag is set.)
4784f76ebacc88f5c69608a7a4f258887fe2036c55dDavid Brown        //
47949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // Instead, we update the notification (and potentially launch the
48049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // InCallScreen) from the showIncomingCall() method, which runs
48149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        // when the caller-id query completes or times out.
4824f76ebacc88f5c69608a7a4f258887fe2036c55dDavid Brown
483796c70c99bc39295bf685061056f06ab8949c742David Brown        if (VDBG) log("- onNewRingingConnection() done.");
484b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
486b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
487d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * Determines whether or not we're allowed to present incoming calls to the
488d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * user, based on the capabilities and/or current state of the device.
489d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     *
490d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * If this method returns true, that means we should immediately reject the
491d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * current incoming call, without even indicating to the user that an
492d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * incoming call occurred.
493d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     *
494d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * (We only reject incoming calls in a few cases, like during an OTASP call
495d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * when we can't interrupt the user, or if the device hasn't completed the
496d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * SetupWizard yet.  We also don't allow incoming calls on non-voice-capable
497d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * devices.  But note that we *always* allow incoming calls while in ECM.)
498d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     *
499d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * @return true if we're *not* allowed to present an incoming call to
500d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     * the user.
501d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown     */
502d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown    private boolean ignoreAllIncomingCalls(Phone phone) {
503d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // Incoming calls are totally ignored on non-voice-capable devices.
504d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        if (!PhoneApp.sVoiceCapable) {
505d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // ...but still log a warning, since we shouldn't have gotten this
506d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // event in the first place!  (Incoming calls *should* be blocked at
507d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            // the telephony layer on non-voice-capable capable devices.)
508d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            Log.w(LOG_TAG, "Got onNewRingingConnection() on non-voice-capable device! Ignoring...");
509d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            return true;
510d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        }
511d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
512d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // In ECM (emergency callback mode), we ALWAYS allow incoming calls
513d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // to get through to the user.  (Note that ECM is applicable only to
514d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // voice-capable CDMA devices).
515d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        if (PhoneUtils.isPhoneInEcm(phone)) {
516d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            if (DBG) log("Incoming call while in ECM: always allow...");
517d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            return false;
518d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        }
519d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
520d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // Incoming calls are totally ignored if the device isn't provisioned yet.
521d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        boolean provisioned = Settings.Secure.getInt(mApplication.getContentResolver(),
522d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
523d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        if (!provisioned) {
524d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            Log.i(LOG_TAG, "Ignoring incoming call: not provisioned");
525d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            return true;
526d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        }
527d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
528d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // Incoming calls are totally ignored if an OTASP call is active.
529d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        if (TelephonyCapabilities.supportsOtasp(phone)) {
530d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            boolean activateState = (mApplication.cdmaOtaScreenState.otaScreenState
531d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                    == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_ACTIVATION);
532d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            boolean dialogState = (mApplication.cdmaOtaScreenState.otaScreenState
533d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                    == OtaUtils.CdmaOtaScreenState.OtaScreenState.OTA_STATUS_SUCCESS_FAILURE_DLG);
534d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            boolean spcState = mApplication.cdmaOtaProvisionData.inOtaSpcState;
535d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
536d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            if (spcState) {
537d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                Log.i(LOG_TAG, "Ignoring incoming call: OTA call is active");
538d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                return true;
539d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            } else if (activateState || dialogState) {
540d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                // We *are* allowed to receive incoming calls at this point.
541d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                // But clear out any residual OTASP UI first.
542d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                // TODO: It's an MVC violation to twiddle the OTA UI state here;
543d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                // we should instead provide a higher-level API via OtaUtils.
544d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                if (dialogState) mApplication.dismissOtaDialogs();
545d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                mApplication.clearOtaState();
546d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                mApplication.clearInCallScreenMode();
547d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown                return false;
548d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown            }
549d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        }
550d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
551d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        // Normal case: allow this call to be presented to the user.
552d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown        return false;
553d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown    }
554d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown
555d250d5b223cfc053702b6ec06d90c79abd8ae8ffDavid Brown    /**
556b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Helper method to manage the start of incoming call queries
557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
558b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void startIncomingCallQuery(Connection c) {
559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // TODO: cache the custom ringer object so that subsequent
560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // calls will not need to do this query work.  We can keep
561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // the MRU ringtones in memory.  We'll still need to hit
562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // the database to get the callerinfo to act as a key,
563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // but at least we can save the time required for the
564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Media player setup.  The only issue with this is that
565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // we may need to keep an eye on the resources the Media
566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // player uses to keep these ringtones around.
567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // make sure we're in a state where we can be ready to
569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // query a ringtone uri.
570b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        boolean shouldStartQuery = false;
571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        synchronized (mCallerInfoQueryStateGuard) {
572b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (mCallerInfoQueryState == CALLERINFO_QUERY_READY) {
573b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallerInfoQueryState = CALLERINFO_QUERYING;
574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                shouldStartQuery = true;
575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
576b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
577b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (shouldStartQuery) {
578b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // create a custom ringer using the default ringer first
579b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mRinger.setCustomRingtoneUri(Settings.System.DEFAULT_RINGTONE_URI);
580b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
581b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // query the callerinfo to try to get the ringer.
582b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            PhoneUtils.CallerInfoToken cit = PhoneUtils.startGetCallerInfo(
583872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    mApplication, c, this, this);
584b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
585b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // if this has already been queried then just ring, otherwise
586b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // we wait for the alloted time before ringing.
587b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (cit.isFinal) {
588796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("- CallerInfo already up to date, using available data");
589b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onQueryComplete(0, this, cit.currentInfo);
590b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
591796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("- Starting query, posting timeout message.");
592b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                sendEmptyMessageDelayed(RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT,
593b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        RINGTONE_QUERY_WAIT_TIME);
594b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
5957f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            // The call to showIncomingCall() will happen after the
5967f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            // queries are complete (or time out).
597b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        } else {
598b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // This should never happen; its the case where an incoming call
599b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // arrives at the same time that the query is still being run,
600b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // and before the timeout window has closed.
601cd89106dcd1038666f992cea3cc79e067245187fDan Egnor            EventLog.writeEvent(EventLogTags.PHONE_UI_MULTIPLE_QUERY);
602b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
603b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // In this case, just log the request and ring.
604796c70c99bc39295bf685061056f06ab8949c742David Brown            if (VDBG) log("RINGING... (request to ring arrived while query is running)");
605b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mRinger.ring();
606b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
607b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // in this case, just fall through like before, and call
6087f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            // showIncomingCall().
60949c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (DBG) log("- showing incoming call (couldn't start query)...");
6107f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            showIncomingCall();
611b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
612b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
613b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
614b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
615b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Performs the final steps of the onNewRingingConnection sequence:
6167f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * starts the ringer, and brings up the "incoming call" UI.
617b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
618b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Normally, this is called when the CallerInfo query completes (see
619b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * onQueryComplete()).  In this case, onQueryComplete() has already
620b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * configured the Ringer object to use the custom ringtone (if there
621b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * is one) for this caller.  So we just tell the Ringer to start, and
622b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * proceed to the InCallScreen.
623b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
624b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * But this method can *also* be called if the
625b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * RINGTONE_QUERY_WAIT_TIME timeout expires, which means that the
626b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * CallerInfo query is taking too long.  In that case, we log a
627b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * warning but otherwise we behave the same as in the normal case.
628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * (We still tell the Ringer to start, but it's going to use the
629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * default ringtone.)
630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onCustomRingQueryComplete() {
632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        boolean isQueryExecutionTimeExpired = false;
633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        synchronized (mCallerInfoQueryStateGuard) {
634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (mCallerInfoQueryState == CALLERINFO_QUERYING) {
635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mCallerInfoQueryState = CALLERINFO_QUERY_READY;
636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                isQueryExecutionTimeExpired = true;
637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (isQueryExecutionTimeExpired) {
640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // There may be a problem with the query here, since the
641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // default ringtone is playing instead of the custom one.
642796c70c99bc39295bf685061056f06ab8949c742David Brown            Log.w(LOG_TAG, "CallerInfo query took too long; falling back to default ringtone");
643cd89106dcd1038666f992cea3cc79e067245187fDan Egnor            EventLog.writeEvent(EventLogTags.PHONE_UI_RINGER_QUERY_ELAPSED);
644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Make sure we still have an incoming call!
647b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        //
648b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // (It's possible for the incoming call to have been disconnected
649b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // while we were running the query.  In that case we better not
650b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // start the ringer here, since there won't be any future
651b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // DISCONNECT event to stop it!)
652b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        //
653b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Note we don't have to worry about the incoming call going away
654b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // *after* this check but before we call mRinger.ring() below,
655b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // since in that case we *will* still get a DISCONNECT message sent
656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // to our handler.  (And we will correctly stop the ringer when we
657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // process that event.)
658170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        if (mCM.getState() != Phone.State.RINGING) {
659796c70c99bc39295bf685061056f06ab8949c742David Brown            Log.i(LOG_TAG, "onCustomRingQueryComplete: No incoming call! Bailing out...");
660b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Don't start the ringer *or* bring up the "incoming call" UI.
661b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Just bail out.
662b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            return;
663b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
664b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
665b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Ring, either with the queried ringtone or default one.
666796c70c99bc39295bf685061056f06ab8949c742David Brown        if (VDBG) log("RINGING... (onCustomRingQueryComplete)");
667b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mRinger.ring();
668b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
6697f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // ...and display the incoming call to the user:
67049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (DBG) log("- showing incoming call (custom ring query complete)...");
6717f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        showIncomingCall();
672b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
673b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
674b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onUnknownConnectionAppeared(AsyncResult r) {
675170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        Phone.State state = mCM.getState();
676b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
677b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (state == Phone.State.OFFHOOK) {
6787f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            // basically do onPhoneStateChanged + display the incoming call UI
679b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            onPhoneStateChanged(r);
68049c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (DBG) log("- showing incoming call (unknown connection appeared)...");
6817f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            showIncomingCall();
682b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
683b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
684b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
6857f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown    /**
6867f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * Informs the user about a new incoming call.
6877f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *
6887f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * In most cases this means "bring up the full-screen incoming call
6897f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * UI".  However, if an immersive activity is running, the system
6907f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * NotificationManager will instead pop up a small notification window
6917f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * on top of the activity.
6927f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *
6937f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * Watch out: be sure to call this method only once per incoming call,
6947f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * or otherwise we may end up launching the InCallScreen multiple
6957f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * times (which can lead to slow responsiveness and/or visible
6967f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * glitches.)
6977f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *
6987f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * Note this method handles only the onscreen UI for incoming calls;
6997f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * the ringer and/or vibrator are started separately (see the various
7007f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * calls to Ringer.ring() in this class.)
7017f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *
7020fcb3901bf032e722385489bd6488fef49371f16David Brown     * @see NotificationMgr.updateNotificationAndLaunchIncomingCallUi()
7037f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     */
7047f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown    private void showIncomingCall() {
7054158ed3e7bdff5212a5542e662240ea0063664b2David Brown        log("showIncomingCall()...  phone state = " + mCM.getState());
7067f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7077f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // Before bringing up the "incoming call" UI, force any system
7087f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // dialogs (like "recent tasks" or the power dialog) to close first.
7097f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        try {
7107f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            ActivityManagerNative.getDefault().closeSystemDialogs("call");
7117f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        } catch (RemoteException e) {
7127f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        }
7137f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7147f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // Go directly to the in-call screen.
7157f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // (No need to do anything special if we're already on the in-call
7167f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // screen; it'll notice the phone state change and update itself.)
7177f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7187f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // But first, grab a full wake lock.  We do this here, before we
7197f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // even fire off the InCallScreen intent, to make sure the
7207f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // ActivityManager doesn't try to pause the InCallScreen as soon
7217f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // as it comes up.  (See bug 1648751.)
7227f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        //
7237f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // And since the InCallScreen isn't visible yet (we haven't even
7247f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // fired off the intent yet), we DON'T want the screen to actually
7257f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // come on right now.  So *before* acquiring the wake lock we need
7267f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // to call preventScreenOn(), which tells the PowerManager that
7277f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // the screen should stay off even if someone's holding a full
7287f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // wake lock.  (This prevents any flicker during the "incoming
7297f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // call" sequence.  The corresponding preventScreenOn(false) call
7307f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // will come from the InCallScreen when it's finally ready to be
7317f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // displayed.)
7327f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        //
7337f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // TODO: this is all a temporary workaround.  The real fix is to add
7347f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // an Activity attribute saying "this Activity wants to wake up the
7357f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // phone when it's displayed"; that way the ActivityManager could
7367f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // manage the wake locks *and* arrange for the screen to come on at
7377f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // the exact moment that the InCallScreen is ready to be displayed.
7387f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // (See bug 1648751.)
7397f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        //
7407f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // TODO: also, we should probably *not* do any of this if the
7417f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // screen is already on(!)
7427f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7437f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        mApplication.preventScreenOn(true);
7447f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        mApplication.requestWakeState(PhoneApp.WakeState.FULL);
7457f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7460fcb3901bf032e722385489bd6488fef49371f16David Brown        // Post the "incoming call" notification *and* include the
7470fcb3901bf032e722385489bd6488fef49371f16David Brown        // fullScreenIntent that'll launch the incoming-call UI.
7480fcb3901bf032e722385489bd6488fef49371f16David Brown        // (This will usually take us straight to the incoming call
7490fcb3901bf032e722385489bd6488fef49371f16David Brown        // screen, but if an immersive activity is running it'll just
7500fcb3901bf032e722385489bd6488fef49371f16David Brown        // appear as a notification.)
75149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown        if (DBG) log("- updating notification from showIncomingCall()...");
752df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown        mApplication.notificationMgr.updateNotificationAndLaunchIncomingCallUi();
7537f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown    }
7547f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown
7557f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown    /**
7567f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * Updates the phone UI in response to phone state changes.
7577f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *
7587f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * Watch out: certain state changes are actually handled by their own
7597f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     * specific methods:
7607f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *   - see onNewRingingConnection() for new incoming calls
7617f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     *   - see onDisconnect() for calls being hung up or disconnected
7627f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown     */
763b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onPhoneStateChanged(AsyncResult r) {
764170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        Phone.State state = mCM.getState();
765f0f6d973992a988c0fc801ba80f826c8edf02c03David Brown        if (VDBG) log("onPhoneStateChanged: state = " + state);
766b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
767b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Turn status bar notifications on or off depending upon the state
768b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // of the phone.  Notification Alerts (audible or vibrating) should
769b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // be on if and only if the phone is IDLE.
770df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown        mApplication.notificationMgr.statusBarHelper
771b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                .enableNotificationAlerts(state == Phone.State.IDLE);
772b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
773872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        Phone fgPhone = mCM.getFgPhone();
774872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        if (fgPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
775872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            if ((fgPhone.getForegroundCall().getState() == Call.State.ACTIVE)
7763800ac871d6548790ac6119bb68b9be0640af261David Krause                    && ((mPreviousCdmaCallState == Call.State.DIALING)
7773800ac871d6548790ac6119bb68b9be0640af261David Krause                    ||  (mPreviousCdmaCallState == Call.State.ALERTING))) {
7783800ac871d6548790ac6119bb68b9be0640af261David Krause                if (mIsCdmaRedialCall) {
7793800ac871d6548790ac6119bb68b9be0640af261David Krause                    int toneToPlay = InCallTonePlayer.TONE_REDIAL;
7803800ac871d6548790ac6119bb68b9be0640af261David Krause                    new InCallTonePlayer(toneToPlay).start();
7813800ac871d6548790ac6119bb68b9be0640af261David Krause                }
7823bd6c8e98772c43c237e9752b33e54f3ce13fb85BinaPatel                // Stop any signal info tone when call moves to ACTIVE state
7833bd6c8e98772c43c237e9752b33e54f3ce13fb85BinaPatel                stopSignalInfoTone();
7843800ac871d6548790ac6119bb68b9be0640af261David Krause            }
785872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            mPreviousCdmaCallState = fgPhone.getForegroundCall().getState();
7863800ac871d6548790ac6119bb68b9be0640af261David Krause        }
7873800ac871d6548790ac6119bb68b9be0640af261David Krause
7888bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        // Have the PhoneApp recompute its mShowBluetoothIndication
7898bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project        // flag based on the (new) telephony state.
7904b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        // There's no need to force a UI update since we update the
7914b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        // in-call notification ourselves (below), and the InCallScreen
7924b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        // listens for phone state changes itself.
7934b8337277ec2e375c3536b97c40e6617a7b12990The Android Open Source Project        mApplication.updateBluetoothIndication(false);
7948bb467d9a1106dedd79e42166c7b6e9fc9a897a7The Android Open Source Project
79558de0c5d10bbf48f6316a12495cd1c176a11a6feDavid Brown        // Update the proximity sensor mode (on devices that have a
79658de0c5d10bbf48f6316a12495cd1c176a11a6feDavid Brown        // proximity sensor).
797445c9030dc93750a8209ace086ea3820ee33f0b1Mike Lockwood        mApplication.updatePhoneState(state);
79858de0c5d10bbf48f6316a12495cd1c176a11a6feDavid Brown
799b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (state == Phone.State.OFFHOOK) {
80003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            // stop call waiting tone if needed when answering
80103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            if (mCallWaitingTonePlayer != null) {
80203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mCallWaitingTonePlayer.stopTone();
80303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mCallWaitingTonePlayer = null;
80403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            }
80503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
806796c70c99bc39295bf685061056f06ab8949c742David Brown            if (VDBG) log("onPhoneStateChanged: OFF HOOK");
807a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan            // make sure audio is in in-call mode now
808a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan            PhoneUtils.setAudioMode(mCM);
809b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
810b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // if the call screen is showing, let it handle the event,
811b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // otherwise handle it here.
812b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (!mApplication.isShowingCallScreen()) {
813b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mApplication.setScreenTimeout(PhoneApp.ScreenTimeoutDuration.DEFAULT);
814b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mApplication.requestWakeState(PhoneApp.WakeState.SLEEP);
815b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
816b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
817b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Since we're now in-call, the Ringer should definitely *not*
818b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // be ringing any more.  (This is just a sanity-check; we
819b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // already stopped the ringer explicitly back in
820b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // PhoneUtils.answerCall(), before the call to phone.acceptCall().)
821b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // TODO: Confirm that this call really *is* unnecessary, and if so,
822b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // remove it!
823b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (DBG) log("stopRing()... (OFFHOOK state)");
824b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mRinger.stopRing();
825b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
826e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // Post a request to update the "in-call" status bar icon.
827e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //
828e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // We don't call NotificationMgr.updateInCallNotification()
829e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // directly here, for two reasons:
830e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // (1) a single phone state change might actually trigger multiple
831e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   onPhoneStateChanged() callbacks, so this prevents redundant
832e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   updates of the notification.
833e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // (2) we suppress the status bar icon while the in-call UI is
834e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   visible (see updateInCallNotification()).  But when launching
835e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   an outgoing call the phone actually goes OFFHOOK slightly
836e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   *before* the InCallScreen comes up, so the delay here avoids a
837e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            //   brief flicker of the icon at that point.
838e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown
839e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            if (DBG) log("- posting UPDATE_IN_CALL_NOTIFICATION request...");
840e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            // Remove any previous requests in the queue
841e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            removeMessages(UPDATE_IN_CALL_NOTIFICATION);
842e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            final int IN_CALL_NOTIFICATION_UPDATE_DELAY = 1000;  // msec
843e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown            sendEmptyMessageDelayed(UPDATE_IN_CALL_NOTIFICATION,
844e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown                                    IN_CALL_NOTIFICATION_UPDATE_DELAY);
845b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
846678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
847872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        if (fgPhone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
848872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            Connection c = fgPhone.getForegroundCall().getLatestConnection();
8491ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia            if ((c != null) && (PhoneNumberUtils.isLocalEmergencyNumber(c.getAddress(),
8501ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia                                                                        mApplication))) {
851678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                if (VDBG) log("onPhoneStateChanged: it is an emergency call.");
852872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                Call.State callState = fgPhone.getForegroundCall().getState();
853678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                if (mEmergencyTonePlayerVibrator == null) {
854678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mEmergencyTonePlayerVibrator = new EmergencyTonePlayerVibrator();
855678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                }
856678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
857678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                if (callState == Call.State.DIALING || callState == Call.State.ALERTING) {
858678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mIsEmergencyToneOn = Settings.System.getInt(
859872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                            mApplication.getContentResolver(),
860678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                            Settings.System.EMERGENCY_TONE, EMERGENCY_TONE_OFF);
861678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    if (mIsEmergencyToneOn != EMERGENCY_TONE_OFF &&
862678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        mCurrentEmergencyToneState == EMERGENCY_TONE_OFF) {
863678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        if (mEmergencyTonePlayerVibrator != null) {
864678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                            mEmergencyTonePlayerVibrator.start();
865678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        }
866678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    }
867678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                } else if (callState == Call.State.ACTIVE) {
868678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    if (mCurrentEmergencyToneState != EMERGENCY_TONE_OFF) {
869678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        if (mEmergencyTonePlayerVibrator != null) {
870678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                            mEmergencyTonePlayerVibrator.stop();
871678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        }
872678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    }
873678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                }
874678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            }
875678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        }
876eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
877872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        if ((fgPhone.getPhoneType() == Phone.PHONE_TYPE_GSM)
878872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                || (fgPhone.getPhoneType() == Phone.PHONE_TYPE_SIP)) {
879170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang            Call.State callState = mCM.getActiveFgCallState();
880eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            if (!callState.isDialing()) {
881eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                // If call get activated or disconnected before the ringback
882eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                // tone stops, we have to stop it to prevent disturbing.
88303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                if (mInCallRingbackTonePlayer != null) {
88403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    mInCallRingbackTonePlayer.stopTone();
88503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    mInCallRingbackTonePlayer = null;
886eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                }
887eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            }
888eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        }
889b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
890b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
891a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville    void updateCallNotifierRegistrationsAfterRadioTechnologyChange() {
89287258b2b589c3afea4b89b840251012378e0d3b4David Brown        if (DBG) Log.d(LOG_TAG, "updateCallNotifierRegistrationsAfterRadioTechnologyChange...");
89387258b2b589c3afea4b89b840251012378e0d3b4David Brown        // Unregister all events from the old obsolete phone
894170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForNewRingingConnection(this);
895170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForPreciseCallStateChanged(this);
896170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForDisconnect(this);
897170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForUnknownConnection(this);
898170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForIncomingRing(this);
899170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForCallWaiting(this);
900170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForDisplayInfo(this);
901170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForSignalInfo(this);
902170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForCdmaOtaStatusChange(this);
903170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForRingbackTone(this);
904170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForResendIncallMute(this);
9050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
90687258b2b589c3afea4b89b840251012378e0d3b4David Brown        // Release the ToneGenerator used for playing SignalInfo and CallWaiting
9070fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (mSignalInfoToneGenerator != null) {
9080fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mSignalInfoToneGenerator.release();
9090fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
910a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville
911eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        // Clear ringback tone player
912eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        mInCallRingbackTonePlayer = null;
913eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
91403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        // Clear call waiting tone player
91503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        mCallWaitingTonePlayer = null;
91603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
917170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForInCallVoicePrivacyOn(this);
918170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.unregisterForInCallVoicePrivacyOff(this);
9193800ac871d6548790ac6119bb68b9be0640af261David Krause
92087258b2b589c3afea4b89b840251012378e0d3b4David Brown        // Register all events new to the new active phone
92124f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        registerForNotifications();
92224f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon    }
92324f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon
92424f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon    private void registerForNotifications() {
925170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForNewRingingConnection(this, PHONE_NEW_RINGING_CONNECTION, null);
926170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForPreciseCallStateChanged(this, PHONE_STATE_CHANGED, null);
927170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForDisconnect(this, PHONE_DISCONNECT, null);
928170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForUnknownConnection(this, PHONE_UNKNOWN_CONNECTION_APPEARED, null);
929170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForIncomingRing(this, PHONE_INCOMING_RING, null);
93034b17481486fc41e99627d68dda9b5c075b4cc8eJohn Wang        mCM.registerForCdmaOtaStatusChange(this, EVENT_OTA_PROVISION_CHANGE, null);
931170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForCallWaiting(this, PHONE_CDMA_CALL_WAITING, null);
932170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForDisplayInfo(this, PHONE_STATE_DISPLAYINFO, null);
933170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForSignalInfo(this, PHONE_STATE_SIGNALINFO, null);
934170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForInCallVoicePrivacyOn(this, PHONE_ENHANCED_VP_ON, null);
935170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForInCallVoicePrivacyOff(this, PHONE_ENHANCED_VP_OFF, null);
936170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForRingbackTone(this, PHONE_RINGBACK_TONE, null);
937170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        mCM.registerForResendIncallMute(this, PHONE_RESEND_MUTE, null);
938a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville    }
939a69de9f9a2e99fe08f0009bb218b95ed7985c575Wink Saville
940b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
941b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Implemented for CallerInfoAsyncQuery.OnQueryCompleteListener interface.
942b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * refreshes the CallCard data when it called.  If called with this
943b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * class itself, it is assumed that we have been waiting for the ringtone
944b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * and direct to voicemail settings to update.
945b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
94605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu    public void onQueryComplete(int token, Object cookie, CallerInfo ci) {
947b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (cookie instanceof Long) {
948796c70c99bc39295bf685061056f06ab8949c742David Brown            if (VDBG) log("CallerInfo query complete, posting missed call notification");
949b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
950df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown            mApplication.notificationMgr.notifyMissedCall(ci.name, ci.phoneNumber,
951b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    ci.phoneLabel, ((Long) cookie).longValue());
95205fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu        } else if (cookie instanceof CallNotifier) {
9534f76ebacc88f5c69608a7a4f258887fe2036c55dDavid Brown            if (VDBG) log("CallerInfo query complete (for CallNotifier), "
9544f76ebacc88f5c69608a7a4f258887fe2036c55dDavid Brown                          + "updating state for incoming call..");
955b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
956b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // get rid of the timeout messages
957b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            removeMessages(RINGER_CUSTOM_RINGTONE_QUERY_TIMEOUT);
958b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
959b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            boolean isQueryExecutionTimeOK = false;
960b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            synchronized (mCallerInfoQueryStateGuard) {
961b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (mCallerInfoQueryState == CALLERINFO_QUERYING) {
962b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    mCallerInfoQueryState = CALLERINFO_QUERY_READY;
963b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    isQueryExecutionTimeOK = true;
964b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
965b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
966b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            //if we're in the right state
967b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (isQueryExecutionTimeOK) {
968b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
969b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // send directly to voicemail.
970b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (ci.shouldSendToVoicemail) {
971b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("send to voicemail flag detected. hanging up.");
972872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    PhoneUtils.hangupRingingCall(mCM.getFirstActiveRingingCall());
973b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    return;
974b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
975b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
976b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // set the ringtone uri to prepare for the ring.
977b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (ci.contactRingtoneUri != null) {
978b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    if (DBG) log("custom ringtone found, setting up ringer.");
979b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    Ringer r = ((CallNotifier) cookie).mRinger;
980b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    r.setCustomRingtoneUri(ci.contactRingtoneUri);
981b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
982b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // ring, and other post-ring actions.
983b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                onCustomRingQueryComplete();
984b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
985b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
986b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
987b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
988b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onDisconnect(AsyncResult r) {
989170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        if (VDBG) log("onDisconnect()...  CallManager state: " + mCM.getState());
9903800ac871d6548790ac6119bb68b9be0640af261David Krause
99124f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        mVoicePrivacyState = false;
992872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        Connection c = (Connection) r.result;
993cf8455a03fe74cc46b2b5d1cc2ceb0c7a48d28e7David Brown        if (c != null) {
9944158ed3e7bdff5212a5542e662240ea0063664b2David Brown            log("onDisconnect: cause = " + c.getDisconnectCause()
995cf8455a03fe74cc46b2b5d1cc2ceb0c7a48d28e7David Brown                  + ", incoming = " + c.isIncoming()
996cf8455a03fe74cc46b2b5d1cc2ceb0c7a48d28e7David Brown                  + ", date = " + c.getCreateTime());
997cf8455a03fe74cc46b2b5d1cc2ceb0c7a48d28e7David Brown        } else {
998cf8455a03fe74cc46b2b5d1cc2ceb0c7a48d28e7David Brown            Log.w(LOG_TAG, "onDisconnect: null connection");
999872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        }
1000872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan
10013800ac871d6548790ac6119bb68b9be0640af261David Krause        int autoretrySetting = 0;
1002872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        if ((c != null) && (c.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA)) {
1003872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            autoretrySetting = android.provider.Settings.System.getInt(mApplication.
10043800ac871d6548790ac6119bb68b9be0640af261David Krause                    getContentResolver(),android.provider.Settings.System.CALL_AUTO_RETRY, 0);
10053800ac871d6548790ac6119bb68b9be0640af261David Krause        }
10063800ac871d6548790ac6119bb68b9be0640af261David Krause
100724f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        // Stop any signalInfo tone being played when a call gets ended
100824f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        stopSignalInfoTone();
100991fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai
1010feac731f603c89ca88c294814f067dfe4b9b5f79David Brown        if ((c != null) && (c.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA)) {
101191fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai            // Resetting the CdmaPhoneCallState members
101291fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai            mApplication.cdmaPhoneCallState.resetCdmaPhoneCallState();
101391fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai
101491fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai            // Remove Call waiting timers
101591fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai            removeMessages(CALLWAITING_CALLERINFO_DISPLAY_DONE);
101691fc9257191eadb9f2d0a7792ad78cf51f2f36dfAbhishek Pillai            removeMessages(CALLWAITING_ADDCALL_DISABLE_TIMEOUT);
10170fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
10180fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
1019b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Stop the ringer if it was ringing (for an incoming call that
1020b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // either disconnected by itself, or was rejected by the user.)
1021b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        //
1022b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // TODO: We technically *shouldn't* stop the ringer if the
1023b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // foreground or background call disconnects while an incoming call
1024b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // is still ringing, but that's a really rare corner case.
1025b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // It's safest to just unconditionally stop the ringer here.
1026cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai
1027cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        // CDMA: For Call collision cases i.e. when the user makes an out going call
1028cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        // and at the same time receives an Incoming Call, the Incoming Call is given
1029cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        // higher preference. At this time framework sends a disconnect for the Out going
1030cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        // call connection hence we should *not* be stopping the ringer being played for
1031cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        // the Incoming Call
1032872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        Call ringingCall = mCM.getFirstActiveRingingCall();
1033872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        if (ringingCall.getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) {
1034872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            if (PhoneUtils.isRealIncomingCall(ringingCall.getState())) {
1035cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai                // Also we need to take off the "In Call" icon from the Notification
1036cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai                // area as the Out going Call never got connected
1037e08c8e4cbee3b2434f9222394ac0dafd13009effDavid Brown                if (DBG) log("cancelCallInProgressNotifications()... (onDisconnect)");
1038df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown                mApplication.notificationMgr.cancelCallInProgressNotifications();
1039cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai            } else {
1040cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai                if (DBG) log("stopRing()... (onDisconnect)");
1041cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai                mRinger.stopRing();
1042cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai            }
1043cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        } else { // GSM
1044cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai            if (DBG) log("stopRing()... (onDisconnect)");
1045cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai            mRinger.stopRing();
1046cbab175f33bad5c132c14c6f5a10d4cdd7111d70Abhishek Pillai        }
1047b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
104803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        // stop call waiting tone if needed when disconnecting
104903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        if (mCallWaitingTonePlayer != null) {
105003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            mCallWaitingTonePlayer.stopTone();
105103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            mCallWaitingTonePlayer = null;
105203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        }
105303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
1054b154630235935e1aab2a41eff9ed794d40084a02David Brown        // If this is the end of an OTASP call, pass it on to the PhoneApp.
105502a86291ed297ab1700daf004f515ee9614689abHung-ying Tyan        if (c != null && TelephonyCapabilities.supportsOtasp(c.getCall().getPhone())) {
1056b154630235935e1aab2a41eff9ed794d40084a02David Brown            final String number = c.getAddress();
105702a86291ed297ab1700daf004f515ee9614689abHung-ying Tyan            if (c.getCall().getPhone().isOtaSpNumber(number)) {
1058b154630235935e1aab2a41eff9ed794d40084a02David Brown                if (DBG) log("onDisconnect: this was an OTASP call!");
1059b154630235935e1aab2a41eff9ed794d40084a02David Brown                mApplication.handleOtaspDisconnect();
1060b154630235935e1aab2a41eff9ed794d40084a02David Brown            }
1061b154630235935e1aab2a41eff9ed794d40084a02David Brown        }
1062b154630235935e1aab2a41eff9ed794d40084a02David Brown
1063b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // Check for the various tones we might need to play (thru the
1064b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // earpiece) after a call disconnects.
1065b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        int toneToPlay = InCallTonePlayer.TONE_NONE;
1066b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1067b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // The "Busy" or "Congestion" tone is the highest priority:
1068b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (c != null) {
1069b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            Connection.DisconnectCause cause = c.getDisconnectCause();
1070b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (cause == Connection.DisconnectCause.BUSY) {
1071b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("- need to play BUSY tone!");
1072b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                toneToPlay = InCallTonePlayer.TONE_BUSY;
1073b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else if (cause == Connection.DisconnectCause.CONGESTION) {
1074b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (DBG) log("- need to play CONGESTION tone!");
1075b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                toneToPlay = InCallTonePlayer.TONE_CONGESTION;
1076af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville            } else if (((cause == Connection.DisconnectCause.NORMAL)
1077af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    || (cause == Connection.DisconnectCause.LOCAL))
1078af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    && (mApplication.isOtaCallInActiveState())) {
1079af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                if (DBG) log("- need to play OTA_CALL_END tone!");
1080af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                toneToPlay = InCallTonePlayer.TONE_OTA_CALL_END;
10813800ac871d6548790ac6119bb68b9be0640af261David Krause            } else if (cause == Connection.DisconnectCause.CDMA_REORDER) {
10823800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("- need to play CDMA_REORDER tone!");
10833800ac871d6548790ac6119bb68b9be0640af261David Krause                toneToPlay = InCallTonePlayer.TONE_REORDER;
10843800ac871d6548790ac6119bb68b9be0640af261David Krause            } else if (cause == Connection.DisconnectCause.CDMA_INTERCEPT) {
10853800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("- need to play CDMA_INTERCEPT tone!");
10863800ac871d6548790ac6119bb68b9be0640af261David Krause                toneToPlay = InCallTonePlayer.TONE_INTERCEPT;
10873800ac871d6548790ac6119bb68b9be0640af261David Krause            } else if (cause == Connection.DisconnectCause.CDMA_DROP) {
10883800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("- need to play CDMA_DROP tone!");
10893800ac871d6548790ac6119bb68b9be0640af261David Krause                toneToPlay = InCallTonePlayer.TONE_CDMA_DROP;
10903800ac871d6548790ac6119bb68b9be0640af261David Krause            } else if (cause == Connection.DisconnectCause.OUT_OF_SERVICE) {
10913800ac871d6548790ac6119bb68b9be0640af261David Krause                if (DBG) log("- need to play OUT OF SERVICE tone!");
10923800ac871d6548790ac6119bb68b9be0640af261David Krause                toneToPlay = InCallTonePlayer.TONE_OUT_OF_SERVICE;
10939eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla            } else if (cause == Connection.DisconnectCause.UNOBTAINABLE_NUMBER) {
10949eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                if (DBG) log("- need to play TONE_UNOBTAINABLE_NUMBER tone!");
10959eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                toneToPlay = InCallTonePlayer.TONE_UNOBTAINABLE_NUMBER;
1096eae268799f7ca0ad09d5d24093d84bc93c1ab050Peng Zhu            } else if (cause == Connection.DisconnectCause.ERROR_UNSPECIFIED) {
1097eae268799f7ca0ad09d5d24093d84bc93c1ab050Peng Zhu                if (DBG) log("- DisconnectCause is ERROR_UNSPECIFIED: play TONE_CALL_ENDED!");
1098eae268799f7ca0ad09d5d24093d84bc93c1ab050Peng Zhu                toneToPlay = InCallTonePlayer.TONE_CALL_ENDED;
1099b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1100b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1101b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1102b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // If we don't need to play BUSY or CONGESTION, then play the
1103b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // "call ended" tone if this was a "regular disconnect" (i.e. a
1104b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // normal call where one end or the other hung up) *and* this
1105b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // disconnect event caused the phone to become idle.  (In other
1106b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // words, we *don't* play the sound if one call hangs up but
1107b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // there's still an active call on the other line.)
1108b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // TODO: We may eventually want to disable this via a preference.
1109b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if ((toneToPlay == InCallTonePlayer.TONE_NONE)
1110170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang            && (mCM.getState() == Phone.State.IDLE)
1111b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            && (c != null)) {
1112b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            Connection.DisconnectCause cause = c.getDisconnectCause();
1113b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if ((cause == Connection.DisconnectCause.NORMAL)  // remote hangup
1114b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                || (cause == Connection.DisconnectCause.LOCAL)) {  // local hangup
1115796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("- need to play CALL_ENDED tone!");
1116b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                toneToPlay = InCallTonePlayer.TONE_CALL_ENDED;
11173800ac871d6548790ac6119bb68b9be0640af261David Krause                mIsCdmaRedialCall = false;
1118b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1119b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1120b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1121170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        if (mCM.getState() == Phone.State.IDLE) {
1122b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Don't reset the audio mode or bluetooth/speakerphone state
1123b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // if we still need to let the user hear a tone through the earpiece.
1124b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (toneToPlay == InCallTonePlayer.TONE_NONE) {
1125b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                resetAudioStateAfterDisconnect();
1126b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1127b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1128df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown            mApplication.notificationMgr.cancelCallInProgressNotifications();
1129b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1130b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // If the InCallScreen is *not* in the foreground, forcibly
1131b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // dismiss it to make sure it won't still be in the activity
1132b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // history.  (But if it *is* in the foreground, don't mess
1133b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // with it; it needs to be visible, displaying the "Call
1134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // ended" state.)
1135b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (!mApplication.isShowingCallScreen()) {
1136796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("onDisconnect: force InCallScreen to finish()");
1137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                mApplication.dismissCallScreen();
11386d6523c51e68ddfd1140713ddd9cb279499e9f4fJoe Onorato            } else {
11396d6523c51e68ddfd1140713ddd9cb279499e9f4fJoe Onorato                if (VDBG) log("onDisconnect: In call screen. Set short timeout.");
11406d6523c51e68ddfd1140713ddd9cb279499e9f4fJoe Onorato                mApplication.clearUserActivityTimeout();
1141b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1142b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1143b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1144b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (c != null) {
114540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            final String number = c.getAddress();
1146b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            final long date = c.getCreateTime();
1147b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            final long duration = c.getDurationMillis();
1148b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            final Connection.DisconnectCause cause = c.getDisconnectCause();
1149872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            final Phone phone = c.getCall().getPhone();
11501ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia            final boolean isEmergencyNumber =
11511ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia                    PhoneNumberUtils.isLocalEmergencyNumber(number, mApplication);
1152b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Set the "type" to be displayed in the call log (see constants in CallLog.Calls)
1153b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            final int callLogType;
1154b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (c.isIncoming()) {
1155b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                callLogType = (cause == Connection.DisconnectCause.INCOMING_MISSED ?
115611aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                               Calls.MISSED_TYPE : Calls.INCOMING_TYPE);
1157b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
115811aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                callLogType = Calls.OUTGOING_TYPE;
1159b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1160796c70c99bc39295bf685061056f06ab8949c742David Brown            if (VDBG) log("- callLogType: " + callLogType + ", UserData: " + c.getUserData());
1161b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
116240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
1163b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            {
116440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                final CallerInfo ci = getCallerInfoFromConnection(c);  // May be null.
116540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                final String logNumber = getLogNumber(c, ci);
116640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
11676323823dec8d1fde89c7450e57a9ffe733a0b053Wink Saville                if (DBG) log("- onDisconnect(): logNumber set to: " + /*logNumber*/ "xxxxxxx");
1168b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
116940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                // TODO: In getLogNumber we use the presentation from
117040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                // the connection for the CNAP. Should we use the one
117140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                // below instead? (comes from caller info)
1172153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman
1173153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman                // For international calls, 011 needs to be logged as +
117440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                final int presentation = getPresentation(c, ci);
1175153e79d8d413b1ccd4abf55a8dbe4e266aa92799Paul Berman
1176872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                if (phone.getPhoneType() == Phone.PHONE_TYPE_CDMA) {
11771ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia                    if ((isEmergencyNumber)
1178678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                            && (mCurrentEmergencyToneState != EMERGENCY_TONE_OFF)) {
1179678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        if (mEmergencyTonePlayerVibrator != null) {
1180678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                            mEmergencyTonePlayerVibrator.stop();
1181678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                        }
1182678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    }
1183678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                }
118440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
118535e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // On some devices, to avoid accidental redialing of
118635e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // emergency numbers, we *never* log emergency calls to
118735e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // the Call Log.  (This behavior is set on a per-product
118835e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // basis, based on carrier requirements.)
118935e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                final boolean okToLogEmergencyNumber =
119035e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                        mApplication.getResources().getBoolean(
119135e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                                R.bool.allow_emergency_numbers_in_call_log);
119235e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown
119335e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // Don't call isOtaSpNumber() on phones that don't support OTASP.
11941b4455031a45a9b87cf66b3384ce59287500a448Hung-ying Tyan                final boolean isOtaspNumber = TelephonyCapabilities.supportsOtasp(phone)
1195872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                        && phone.isOtaSpNumber(number);
119674cae90ddb7fe8ce9bc0bc56e4c1fe4daf98e2d1Nicolas Catania
119735e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // Don't log emergency numbers if the device doesn't allow it,
119835e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                // and never log OTASP calls.
119935e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                final boolean okToLogThisCall =
120035e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                        (!isEmergencyNumber || okToLogEmergencyNumber)
120135e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                        && !isOtaspNumber;
120235e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown
120335e980f12cef04fc5c72b1ee87556503ceeeb21eDavid Brown                if (okToLogThisCall) {
120411aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                    CallLogAsync.AddCallArgs args =
120511aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                            new CallLogAsync.AddCallArgs(
1206872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                                mApplication, ci, logNumber, presentation,
120711aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                                callLogType, date, duration);
120811aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                    mCallLog.addCall(args);
120940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                }
1210b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1211b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
121211aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania            if (callLogType == Calls.MISSED_TYPE) {
1213b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Show the "Missed call" notification.
1214b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // (Note we *don't* do this if this was an incoming call that
1215b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // the user deliberately rejected.)
1216c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                showMissedCallNotification(c, date);
1217b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1218b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1219b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Possibly play a "post-disconnect tone" thru the earpiece.
1220b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // We do this here, rather than from the InCallScreen
1221b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // activity, since we need to do this even if you're not in
1222b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // the Phone UI at the moment the connection ends.
1223b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (toneToPlay != InCallTonePlayer.TONE_NONE) {
1224796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("- starting post-disconnect tone (" + toneToPlay + ")...");
1225b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                new InCallTonePlayer(toneToPlay).start();
1226b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1227b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // TODO: alternatively, we could start an InCallTonePlayer
1228b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // here with an "unlimited" tone length,
1229b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // and manually stop it later when this connection truly goes
1230b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // away.  (The real connection over the network was closed as soon
1231b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // as we got the BUSY message.  But our telephony layer keeps the
1232b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // connection open for a few extra seconds so we can show the
1233b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // "busy" indication to the user.  We could stop the busy tone
1234b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // when *that* connection's "disconnect" event comes in.)
1235b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1236b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1237170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang            if (mCM.getState() == Phone.State.IDLE) {
1238b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // Release screen wake locks if the in-call screen is not
1239b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // showing. Otherwise, let the in-call screen handle this because
1240b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // it needs to show the call ended screen for a couple of
1241b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // seconds.
1242b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (!mApplication.isShowingCallScreen()) {
1243796c70c99bc39295bf685061056f06ab8949c742David Brown                    if (VDBG) log("- NOT showing in-call screen; releasing wake locks!");
1244b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    mApplication.setScreenTimeout(PhoneApp.ScreenTimeoutDuration.DEFAULT);
1245b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    mApplication.requestWakeState(PhoneApp.WakeState.SLEEP);
1246b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
1247796c70c99bc39295bf685061056f06ab8949c742David Brown                    if (VDBG) log("- still showing in-call screen; not releasing wake locks.");
1248b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1249b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } else {
1250796c70c99bc39295bf685061056f06ab8949c742David Brown                if (VDBG) log("- phone still in use; not releasing wake locks.");
1251b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
12523800ac871d6548790ac6119bb68b9be0640af261David Krause
12533800ac871d6548790ac6119bb68b9be0640af261David Krause            if (((mPreviousCdmaCallState == Call.State.DIALING)
12543800ac871d6548790ac6119bb68b9be0640af261David Krause                    || (mPreviousCdmaCallState == Call.State.ALERTING))
12551ca2b2b333a7c22b728d648d3592ee064762dd00Shaopeng Jia                    && (!isEmergencyNumber)
12563800ac871d6548790ac6119bb68b9be0640af261David Krause                    && (cause != Connection.DisconnectCause.INCOMING_MISSED )
12573800ac871d6548790ac6119bb68b9be0640af261David Krause                    && (cause != Connection.DisconnectCause.NORMAL)
12583800ac871d6548790ac6119bb68b9be0640af261David Krause                    && (cause != Connection.DisconnectCause.LOCAL)
12593800ac871d6548790ac6119bb68b9be0640af261David Krause                    && (cause != Connection.DisconnectCause.INCOMING_REJECTED)) {
12603800ac871d6548790ac6119bb68b9be0640af261David Krause                if (!mIsCdmaRedialCall) {
12613800ac871d6548790ac6119bb68b9be0640af261David Krause                    if (autoretrySetting == InCallScreen.AUTO_RETRY_ON) {
12623800ac871d6548790ac6119bb68b9be0640af261David Krause                        // TODO: (Moto): The contact reference data may need to be stored and use
12633800ac871d6548790ac6119bb68b9be0640af261David Krause                        // here when redialing a call. For now, pass in NULL as the URI parameter.
12641b4455031a45a9b87cf66b3384ce59287500a448Hung-ying Tyan                        PhoneUtils.placeCall(mApplication, phone, number, null, false, null);
12653800ac871d6548790ac6119bb68b9be0640af261David Krause                        mIsCdmaRedialCall = true;
12663800ac871d6548790ac6119bb68b9be0640af261David Krause                    } else {
12673800ac871d6548790ac6119bb68b9be0640af261David Krause                        mIsCdmaRedialCall = false;
12683800ac871d6548790ac6119bb68b9be0640af261David Krause                    }
12693800ac871d6548790ac6119bb68b9be0640af261David Krause                } else {
12703800ac871d6548790ac6119bb68b9be0640af261David Krause                    mIsCdmaRedialCall = false;
12713800ac871d6548790ac6119bb68b9be0640af261David Krause                }
12723800ac871d6548790ac6119bb68b9be0640af261David Krause            }
1273b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1274b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1275b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1276b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1277b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Resets the audio mode and speaker state when a call ends.
1278b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1279b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void resetAudioStateAfterDisconnect() {
1280796c70c99bc39295bf685061056f06ab8949c742David Brown        if (VDBG) log("resetAudioStateAfterDisconnect()...");
1281b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1282b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (mBluetoothHandsfree != null) {
1283b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mBluetoothHandsfree.audioOff();
1284b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1285b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
12864a8cbde060e7876a5560346215c11078a9efc90eEric Laurent        // call turnOnSpeaker() with state=false and store=true even if speaker
12874a8cbde060e7876a5560346215c11078a9efc90eEric Laurent        // is already off to reset user requested speaker state.
1288872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan        PhoneUtils.turnOnSpeaker(mApplication, false, true);
1289b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1290a4b443115c1442c9d65ba58fcb667b0e025993deHung-ying Tyan        PhoneUtils.setAudioMode(mCM);
1291b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1292b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1293b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onMwiChanged(boolean visible) {
1294796c70c99bc39295bf685061056f06ab8949c742David Brown        if (VDBG) log("onMwiChanged(): " + visible);
1295feac731f603c89ca88c294814f067dfe4b9b5f79David Brown
1296feac731f603c89ca88c294814f067dfe4b9b5f79David Brown        // "Voicemail" is meaningless on non-voice-capable devices,
1297feac731f603c89ca88c294814f067dfe4b9b5f79David Brown        // so ignore MWI events.
1298feac731f603c89ca88c294814f067dfe4b9b5f79David Brown        if (!PhoneApp.sVoiceCapable) {
1299feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            // ...but still log a warning, since we shouldn't have gotten this
1300feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            // event in the first place!
1301feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            // (PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR events
1302feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            // *should* be blocked at the telephony layer on non-voice-capable
1303feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            // capable devices.)
1304feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            Log.w(LOG_TAG, "Got onMwiChanged() on non-voice-capable device! Ignoring...");
1305feac731f603c89ca88c294814f067dfe4b9b5f79David Brown            return;
1306feac731f603c89ca88c294814f067dfe4b9b5f79David Brown        }
1307feac731f603c89ca88c294814f067dfe4b9b5f79David Brown
1308df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown        mApplication.notificationMgr.updateMwi(visible);
1309b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1310b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1311b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1312b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Posts a delayed PHONE_MWI_CHANGED event, to schedule a "retry" for a
1313b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * failed NotificationMgr.updateMwi() call.
1314b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1315b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /* package */ void sendMwiChangedDelayed(long delayMillis) {
1316b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Message message = Message.obtain(this, PHONE_MWI_CHANGED);
1317b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        sendMessageDelayed(message, delayMillis);
1318b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1319b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1320b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onCfiChanged(boolean visible) {
1321796c70c99bc39295bf685061056f06ab8949c742David Brown        if (VDBG) log("onCfiChanged(): " + visible);
1322df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown        mApplication.notificationMgr.updateCfi(visible);
1323b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1324b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1325b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1326b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Indicates whether or not this ringer is ringing.
1327b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1328b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    boolean isRinging() {
1329b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        return mRinger.isRinging();
1330b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1331b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1332b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1333b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Stops the current ring, and tells the notifier that future
1334b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * ring requests should be ignored.
1335b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1336b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    void silenceRinger() {
1337b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mSilentRingerRequested = true;
1338b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("stopRing()... (silenceRinger)");
1339b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        mRinger.stopRing();
1340b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1341b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1342b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
134311544975bb29ede282333209e945a75430b221a8David Brown     * Restarts the ringer after having previously silenced it.
134411544975bb29ede282333209e945a75430b221a8David Brown     *
134511544975bb29ede282333209e945a75430b221a8David Brown     * (This is a no-op if the ringer is actually still ringing, or if the
134611544975bb29ede282333209e945a75430b221a8David Brown     * incoming ringing call no longer exists.)
134711544975bb29ede282333209e945a75430b221a8David Brown     */
134811544975bb29ede282333209e945a75430b221a8David Brown    /* package */ void restartRinger() {
134911544975bb29ede282333209e945a75430b221a8David Brown        if (DBG) log("restartRinger()...");
135011544975bb29ede282333209e945a75430b221a8David Brown        if (isRinging()) return;  // Already ringing; no need to restart.
135111544975bb29ede282333209e945a75430b221a8David Brown
135211544975bb29ede282333209e945a75430b221a8David Brown        final Call ringingCall = mCM.getFirstActiveRingingCall();
135311544975bb29ede282333209e945a75430b221a8David Brown        // Don't check ringingCall.isRinging() here, since that'll be true
135411544975bb29ede282333209e945a75430b221a8David Brown        // for the WAITING state also.  We only allow the ringer for
135511544975bb29ede282333209e945a75430b221a8David Brown        // regular INCOMING calls.
135611544975bb29ede282333209e945a75430b221a8David Brown        if (DBG) log("- ringingCall state: " + ringingCall.getState());
135711544975bb29ede282333209e945a75430b221a8David Brown        if (ringingCall.getState() == Call.State.INCOMING) {
135811544975bb29ede282333209e945a75430b221a8David Brown            mRinger.ring();
135911544975bb29ede282333209e945a75430b221a8David Brown        }
136011544975bb29ede282333209e945a75430b221a8David Brown    }
136111544975bb29ede282333209e945a75430b221a8David Brown
136211544975bb29ede282333209e945a75430b221a8David Brown    /**
1363b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Posts a PHONE_BATTERY_LOW event, causing us to play a warning
1364b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * tone if the user is in-call.
1365b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1366b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /* package */ void sendBatteryLow() {
1367b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        Message message = Message.obtain(this, PHONE_BATTERY_LOW);
1368b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        sendMessage(message);
1369b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1370b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1371b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void onBatteryLow() {
1372b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        if (DBG) log("onBatteryLow()...");
1373b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
13743e2bc7b4724cf015d5ef06dfd33553a290a55f9bDaniel Sandler        // A "low battery" warning tone is now played by
13753e2bc7b4724cf015d5ef06dfd33553a290a55f9bDaniel Sandler        // StatusBarPolicy.updateBattery().
1376b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1377b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1378b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1379b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    /**
1380b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Helper class to play tones through the earpiece (or speaker / BT)
1381b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * during a call, using the ToneGenerator.
1382b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1383b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * To use, just instantiate a new InCallTonePlayer
1384b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * (passing in the TONE_* constant for the tone you want)
1385b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * and start() it.
1386b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     *
1387b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * When we're done playing the tone, if the phone is idle at that
1388b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * point, we'll reset the audio routing and speaker state.
1389b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * (That means that for tones that get played *after* a call
1390b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * disconnects, like "busy" or "congestion" or "call ended", you
1391b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * should NOT call resetAudioStateAfterDisconnect() yourself.
1392b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * Instead, just start the InCallTonePlayer, which will automatically
1393b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * defer the resetAudioStateAfterDisconnect() call until the tone
1394b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     * finishes playing.)
1395b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project     */
1396b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private class InCallTonePlayer extends Thread {
1397b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        private int mToneId;
139803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        private int mState;
1399b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // The possible tones we can play.
1400b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_NONE = 0;
1401b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_CALL_WAITING = 1;
1402b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_BUSY = 2;
1403b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_CONGESTION = 3;
1404b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_BATTERY_LOW = 4;
1405b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public static final int TONE_CALL_ENDED = 5;
14063800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_VOICE_PRIVACY = 6;
14073800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_REORDER = 7;
14083800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_INTERCEPT = 8;
14093800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_CDMA_DROP = 9;
14103800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_OUT_OF_SERVICE = 10;
14113800ac871d6548790ac6119bb68b9be0640af261David Krause        public static final int TONE_REDIAL = 11;
1412af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville        public static final int TONE_OTA_CALL_END = 12;
141303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        public static final int TONE_RING_BACK = 13;
1414975d455b9bf32f2c07527ffa96aafecf042a68d8The Android Open Source Project        public static final int TONE_UNOBTAINABLE_NUMBER = 14;
1415b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1416b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        // The tone volume relative to other sounds in the stream
14173dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent        private static final int TONE_RELATIVE_VOLUME_EMERGENCY = 100;
1418b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        private static final int TONE_RELATIVE_VOLUME_HIPRI = 80;
1419b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        private static final int TONE_RELATIVE_VOLUME_LOPRI = 50;
1420b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1421421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman        // Buffer time (in msec) to add on to tone timeout value.
1422421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman        // Needed mainly when the timeout value for a tone is the
1423421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman        // exact duration of the tone itself.
1424421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman        private static final int TONE_TIMEOUT_BUFFER = 20;
1425421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman
142603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        // The tone state
142703d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        private static final int TONE_OFF = 0;
142803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        private static final int TONE_ON = 1;
142903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        private static final int TONE_STOPPED = 2;
143003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
1431b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        InCallTonePlayer(int toneId) {
1432b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            super();
1433b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            mToneId = toneId;
143403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            mState = TONE_OFF;
1435b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
1436b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1437b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        @Override
1438b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        public void run() {
143904a4162d2c47e63f27d8a6d0a4efd945f2c8052fDavid Brown            log("InCallTonePlayer.run(toneId = " + mToneId + ")...");
1440b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
14413800ac871d6548790ac6119bb68b9be0640af261David Krause            int toneType = 0;  // passed to ToneGenerator.startTone()
1442b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            int toneVolume;  // passed to the ToneGenerator constructor
1443b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            int toneLengthMillis;
1444872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            int phoneType = mCM.getFgPhone().getPhoneType();
14453800ac871d6548790ac6119bb68b9be0640af261David Krause
1446b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            switch (mToneId) {
1447b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case TONE_CALL_WAITING:
1448b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneType = ToneGenerator.TONE_SUP_CALL_WAITING;
1449b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
145003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    // Call waiting tone is stopped by stopTone() method
145103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    toneLengthMillis = Integer.MAX_VALUE - TONE_TIMEOUT_BUFFER;
1452b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1453b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case TONE_BUSY:
145479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                    if (phoneType == Phone.PHONE_TYPE_CDMA) {
14553800ac871d6548790ac6119bb68b9be0640af261David Krause                        toneType = ToneGenerator.TONE_CDMA_NETWORK_BUSY_ONE_SHOT;
14563800ac871d6548790ac6119bb68b9be0640af261David Krause                        toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
1457421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                        toneLengthMillis = 1000;
1458872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    } else if ((phoneType == Phone.PHONE_TYPE_GSM)
1459872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                            || (phoneType == Phone.PHONE_TYPE_SIP)) {
14603800ac871d6548790ac6119bb68b9be0640af261David Krause                        toneType = ToneGenerator.TONE_SUP_BUSY;
14613800ac871d6548790ac6119bb68b9be0640af261David Krause                        toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
14623800ac871d6548790ac6119bb68b9be0640af261David Krause                        toneLengthMillis = 4000;
146379b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                    } else {
146479b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                        throw new IllegalStateException("Unexpected phone type: " + phoneType);
14653800ac871d6548790ac6119bb68b9be0640af261David Krause                    }
1466b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1467b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case TONE_CONGESTION:
1468b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneType = ToneGenerator.TONE_SUP_CONGESTION;
1469b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1470b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneLengthMillis = 4000;
1471b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1472b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case TONE_BATTERY_LOW:
1473b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // For now, use ToneGenerator.TONE_PROP_ACK (two quick
1474b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // beeps).  TODO: is there some other ToneGenerator
1475b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // tone that would be more appropriate here?  Or
1476b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    // should we consider adding a new custom tone?
1477b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneType = ToneGenerator.TONE_PROP_ACK;
1478b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1479b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneLengthMillis = 1000;
1480b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1481b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                case TONE_CALL_ENDED:
1482b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    toneType = ToneGenerator.TONE_PROP_PROMPT;
1483520c34f2281e3ef6f2293606b4fe99b0fcb2afabPeng Zhu                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1484421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                    toneLengthMillis = 200;
1485b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    break;
1486af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                 case TONE_OTA_CALL_END:
1487af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    if (mApplication.cdmaOtaConfigData.otaPlaySuccessFailureTone ==
1488af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                            OtaUtils.OTA_PLAY_SUCCESS_FAILURE_TONE_ON) {
1489af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                        toneType = ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD;
1490814d369bd1ee21f0b9f8cd2209e3f61ed15329e7Charulata R Pardhanani                        toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1491421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                        toneLengthMillis = 750;
1492af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    } else {
1493af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                        toneType = ToneGenerator.TONE_PROP_PROMPT;
1494520c34f2281e3ef6f2293606b4fe99b0fcb2afabPeng Zhu                        toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1495421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                        toneLengthMillis = 200;
1496af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    }
1497af684393e2c6d0c051b9d5a189c2cd1de2506831Wink Saville                    break;
14983800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_VOICE_PRIVACY:
14993800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneType = ToneGenerator.TONE_CDMA_ALERT_NETWORK_LITE;
15001c3518a5cf9b39dbc462a1ab8c1e5390cd5c8f04Peng Zhu                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
15013800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneLengthMillis = 5000;
15023800ac871d6548790ac6119bb68b9be0640af261David Krause                    break;
15033800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_REORDER:
1504b3ea9d2c99efb837b2b4d0c54a91b36ca05aa43aShruthi N.K                    toneType = ToneGenerator.TONE_CDMA_REORDER;
1505b3ea9d2c99efb837b2b4d0c54a91b36ca05aa43aShruthi N.K                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
1506421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                    toneLengthMillis = 4000;
15073800ac871d6548790ac6119bb68b9be0640af261David Krause                    break;
15083800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_INTERCEPT:
15093800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneType = ToneGenerator.TONE_CDMA_ABBR_INTERCEPT;
15103800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
1511421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                    toneLengthMillis = 500;
15123800ac871d6548790ac6119bb68b9be0640af261David Krause                    break;
15133800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_CDMA_DROP:
15143800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_OUT_OF_SERVICE:
15153800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneType = ToneGenerator.TONE_CDMA_CALLDROP_LITE;
15163800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
1517421475c4fe1b2388ce84be8d85f61a639ee3e253Paul Berman                    toneLengthMillis = 375;
15183800ac871d6548790ac6119bb68b9be0640af261David Krause                    break;
15193800ac871d6548790ac6119bb68b9be0640af261David Krause                case TONE_REDIAL:
15203800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneType = ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE;
1521e1c85a5471a4a80c1bff9a3bfe0e18a4d0e59b92Peng Zhu                    toneVolume = TONE_RELATIVE_VOLUME_LOPRI;
15223800ac871d6548790ac6119bb68b9be0640af261David Krause                    toneLengthMillis = 5000;
15233800ac871d6548790ac6119bb68b9be0640af261David Krause                    break;
152403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                case TONE_RING_BACK:
152503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    toneType = ToneGenerator.TONE_SUP_RINGTONE;
152603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
152703d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    // Call ring back tone is stopped by stopTone() method
152803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    toneLengthMillis = Integer.MAX_VALUE - TONE_TIMEOUT_BUFFER;
152903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    break;
15309eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                case TONE_UNOBTAINABLE_NUMBER:
15319eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    toneType = ToneGenerator.TONE_SUP_ERROR;
15329eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    toneVolume = TONE_RELATIVE_VOLUME_HIPRI;
15339eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    toneLengthMillis = 4000;
15349eb2ffdf7b4752c7199eba6a3b88f63edc4a0ac8Naveen Kalla                    break;
1535b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                default:
1536b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    throw new IllegalArgumentException("Bad toneId: " + mToneId);
1537b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1538b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1539b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // If the mToneGenerator creation fails, just continue without it.  It is
1540b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // a local audio signal, and is not as important.
1541b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            ToneGenerator toneGenerator;
1542b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            try {
1543b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                int stream;
1544b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                if (mBluetoothHandsfree != null) {
1545b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    stream = mBluetoothHandsfree.isAudioOn() ? AudioManager.STREAM_BLUETOOTH_SCO:
1546b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                        AudioManager.STREAM_VOICE_CALL;
1547b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                } else {
1548b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                    stream = AudioManager.STREAM_VOICE_CALL;
1549b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                }
1550b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                toneGenerator = new ToneGenerator(stream, toneVolume);
1551b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                // if (DBG) log("- created toneGenerator: " + toneGenerator);
1552b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            } catch (RuntimeException e) {
1553796c70c99bc39295bf685061056f06ab8949c742David Brown                Log.w(LOG_TAG,
1554796c70c99bc39295bf685061056f06ab8949c742David Brown                      "InCallTonePlayer: Exception caught while creating ToneGenerator: " + e);
1555b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                toneGenerator = null;
1556b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1557b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1558b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Using the ToneGenerator (with the CALL_WAITING / BUSY /
1559b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // CONGESTION tones at least), the ToneGenerator itself knows
1560b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // the right pattern of tones to play; we do NOT need to
1561b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // manually start/stop each individual tone, or manually
1562b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // insert the correct delay between tones.  (We just start it
1563b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // and let it run for however long we want the tone pattern to
1564b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // continue.)
1565b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            //
1566b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // TODO: When we stop the ToneGenerator in the middle of a
1567b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // "tone pattern", it sounds bad if we cut if off while the
1568b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // tone is actually playing.  Consider adding API to the
1569b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // ToneGenerator to say "stop at the next silent part of the
1570b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // pattern", or simply "play the pattern N times and then
1571b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // stop."
15723800ac871d6548790ac6119bb68b9be0640af261David Krause            boolean needToStopTone = true;
15737fe7f7e57aaa38290c37ab48867d34a279d198f3w            boolean okToPlayTone = false;
1574b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1575b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            if (toneGenerator != null) {
157603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                int ringerMode = mAudioManager.getRingerMode();
157779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                if (phoneType == Phone.PHONE_TYPE_CDMA) {
15787fe7f7e57aaa38290c37ab48867d34a279d198f3w                    if (toneType == ToneGenerator.TONE_CDMA_ALERT_CALL_GUARD) {
157979b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                        if ((ringerMode != AudioManager.RINGER_MODE_SILENT) &&
158079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                                (ringerMode != AudioManager.RINGER_MODE_VIBRATE)) {
15817fe7f7e57aaa38290c37ab48867d34a279d198f3w                            if (DBG) log("- InCallTonePlayer: start playing call tone=" + toneType);
15827fe7f7e57aaa38290c37ab48867d34a279d198f3w                            okToPlayTone = true;
15837fe7f7e57aaa38290c37ab48867d34a279d198f3w                            needToStopTone = false;
15847fe7f7e57aaa38290c37ab48867d34a279d198f3w                        }
15857fe7f7e57aaa38290c37ab48867d34a279d198f3w                    } else if ((toneType == ToneGenerator.TONE_CDMA_NETWORK_BUSY_ONE_SHOT) ||
1586b3ea9d2c99efb837b2b4d0c54a91b36ca05aa43aShruthi N.K                            (toneType == ToneGenerator.TONE_CDMA_REORDER) ||
15877fe7f7e57aaa38290c37ab48867d34a279d198f3w                            (toneType == ToneGenerator.TONE_CDMA_ABBR_REORDER) ||
15887fe7f7e57aaa38290c37ab48867d34a279d198f3w                            (toneType == ToneGenerator.TONE_CDMA_ABBR_INTERCEPT) ||
15897fe7f7e57aaa38290c37ab48867d34a279d198f3w                            (toneType == ToneGenerator.TONE_CDMA_CALLDROP_LITE)) {
159079b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                        if (ringerMode != AudioManager.RINGER_MODE_SILENT) {
15917fe7f7e57aaa38290c37ab48867d34a279d198f3w                            if (DBG) log("InCallTonePlayer:playing call fail tone:" + toneType);
15927fe7f7e57aaa38290c37ab48867d34a279d198f3w                            okToPlayTone = true;
15937fe7f7e57aaa38290c37ab48867d34a279d198f3w                            needToStopTone = false;
15947fe7f7e57aaa38290c37ab48867d34a279d198f3w                        }
15957fe7f7e57aaa38290c37ab48867d34a279d198f3w                    } else if ((toneType == ToneGenerator.TONE_CDMA_ALERT_AUTOREDIAL_LITE) ||
15967fe7f7e57aaa38290c37ab48867d34a279d198f3w                               (toneType == ToneGenerator.TONE_CDMA_ALERT_NETWORK_LITE)) {
159779b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                        if ((ringerMode != AudioManager.RINGER_MODE_SILENT) &&
159879b9f6e30e8402b103f1ec3ed9dda1fcad2b1cd5Tammo Spalink                                (ringerMode != AudioManager.RINGER_MODE_VIBRATE)) {
15997fe7f7e57aaa38290c37ab48867d34a279d198f3w                            if (DBG) log("InCallTonePlayer:playing tone for toneType=" + toneType);
16007fe7f7e57aaa38290c37ab48867d34a279d198f3w                            okToPlayTone = true;
16017fe7f7e57aaa38290c37ab48867d34a279d198f3w                            needToStopTone = false;
16027fe7f7e57aaa38290c37ab48867d34a279d198f3w                        }
1603520c34f2281e3ef6f2293606b4fe99b0fcb2afabPeng Zhu                    } else { // For the rest of the tones, always OK to play.
1604520c34f2281e3ef6f2293606b4fe99b0fcb2afabPeng Zhu                        okToPlayTone = true;
16053800ac871d6548790ac6119bb68b9be0640af261David Krause                    }
1606520c34f2281e3ef6f2293606b4fe99b0fcb2afabPeng Zhu                } else {  // Not "CDMA"
16077fe7f7e57aaa38290c37ab48867d34a279d198f3w                    okToPlayTone = true;
16083800ac871d6548790ac6119bb68b9be0640af261David Krause                }
1609b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
161003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                synchronized (this) {
161103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    if (okToPlayTone && mState != TONE_STOPPED) {
161203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        mState = TONE_ON;
161303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        toneGenerator.startTone(toneType);
161403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        try {
161503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                            wait(toneLengthMillis + TONE_TIMEOUT_BUFFER);
161603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        } catch  (InterruptedException e) {
161703d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                            Log.w(LOG_TAG,
161803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                                  "InCallTonePlayer stopped: " + e);
161903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        }
162003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        if (needToStopTone) {
162103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                            toneGenerator.stopTone();
162203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                        }
16233800ac871d6548790ac6119bb68b9be0640af261David Krause                    }
162403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    // if (DBG) log("- InCallTonePlayer: done playing.");
162503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    toneGenerator.release();
162603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    mState = TONE_OFF;
16273800ac871d6548790ac6119bb68b9be0640af261David Krause                }
1628b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1629b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
1630b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // Finally, do the same cleanup we otherwise would have done
1631b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // in onDisconnect().
1632b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            //
1633b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // (But watch out: do NOT do this if the phone is in use,
1634b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // since some of our tones get played *during* a call (like
1635b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // CALL_WAITING and BATTERY_LOW) and we definitely *don't*
1636b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // want to reset the audio mode / speaker / bluetooth after
1637b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // playing those!
1638b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // This call is really here for use with tones that get played
1639b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // *after* a call disconnects, like "busy" or "congestion" or
1640b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // "call ended", where the phone has already become idle but
1641b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // we need to defer the resetAudioStateAfterDisconnect() call
1642b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            // till the tone finishes playing.)
1643170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang            if (mCM.getState() == Phone.State.IDLE) {
1644b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project                resetAudioStateAfterDisconnect();
1645b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project            }
1646b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project        }
164703d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent
164803d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        public void stopTone() {
164903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            synchronized (this) {
165003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                if (mState == TONE_ON) {
165103d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                    notify();
165203d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                }
165303d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mState = TONE_STOPPED;
165403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            }
165503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent        }
1656b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
1657b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
16580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    /**
16590fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * Displays a notification when the phone receives a DisplayInfo record.
16600fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     */
16610fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private void onDisplayInfo(AsyncResult r) {
16620fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Extract the DisplayInfo String from the message
16630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        CdmaDisplayInfoRec displayInfoRec = (CdmaDisplayInfoRec)(r.result);
16640fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16650fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (displayInfoRec != null) {
16660fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            String displayInfo = displayInfoRec.alpha;
16670fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            if (DBG) log("onDisplayInfo: displayInfo=" + displayInfo);
16680fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            CdmaDisplayInfo.displayInfoRecord(mApplication, displayInfo);
16690fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            // start a 2 second timer
16710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            sendEmptyMessageDelayed(DISPLAYINFO_NOTIFICATION_DONE,
16720fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    DISPLAYINFO_NOTIFICATION_TIME);
16730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
16740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    }
16750fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    /**
16770fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * Helper class to play SignalInfo tones using the ToneGenerator.
16780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     *
16790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * To use, just instantiate a new SignalInfoTonePlayer
16800fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * (passing in the ToneID constant for the tone you want)
16810fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * and start() it.
16820fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     */
16830fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private class SignalInfoTonePlayer extends Thread {
16840fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        private int mToneId;
16850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        SignalInfoTonePlayer(int toneId) {
16870fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            super();
16880fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mToneId = toneId;
16890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
16900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16910fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        @Override
16920fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        public void run() {
169304a4162d2c47e63f27d8a6d0a4efd945f2c8052fDavid Brown            log("SignalInfoTonePlayer.run(toneId = " + mToneId + ")...");
16940fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16950fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            if (mSignalInfoToneGenerator != null) {
16960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                //First stop any ongoing SignalInfo tone
16970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                mSignalInfoToneGenerator.stopTone();
16980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
16990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                //Start playing the new tone if its a valid tone
17000fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                mSignalInfoToneGenerator.startTone(mToneId);
17010fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            }
17020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
17030fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    }
17040fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    /**
17060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * Plays a tone when the phone receives a SignalInfo record.
17070fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     */
17080fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private void onSignalInfo(AsyncResult r) {
1709a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang        // Signal Info are totally ignored on non-voice-capable devices.
1710a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang        if (!PhoneApp.sVoiceCapable) {
1711a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang            Log.w(LOG_TAG, "Got onSignalInfo() on non-voice-capable device! Ignoring...");
1712a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang            return;
1713a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang        }
1714a0a3e4d52f8d39a6a8c1341144a1e6c522db0055John Wang
17158343169cc89621d46dce86449f5ee1ff5d3a4919John Wang        if (PhoneUtils.isRealIncomingCall(mCM.getFirstActiveRingingCall().getState())) {
171605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            // Do not start any new SignalInfo tone when Call state is INCOMING
171705fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            // and stop any previous SignalInfo tone which is being played
171805fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            stopSignalInfoTone();
171905fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu        } else {
172005fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            // Extract the SignalInfo String from the message
172105fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            CdmaSignalInfoRec signalInfoRec = (CdmaSignalInfoRec)(r.result);
172205fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            // Only proceed if a Signal info is present.
172305fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu            if (signalInfoRec != null) {
172405fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                boolean isPresent = signalInfoRec.isPresent;
172505fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                if (DBG) log("onSignalInfo: isPresent=" + isPresent);
172605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                if (isPresent) {// if tone is valid
172705fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    int uSignalType = signalInfoRec.signalType;
172805fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    int uAlertPitch = signalInfoRec.alertPitch;
172905fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    int uSignal = signalInfoRec.signal;
173005fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu
173105fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    if (DBG) log("onSignalInfo: uSignalType=" + uSignalType + ", uAlertPitch=" +
173205fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                            uAlertPitch + ", uSignal=" + uSignal);
173305fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    //Map the Signal to a ToneGenerator ToneID only if Signal info is present
173405fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    int toneID = SignalToneUtil.getAudioToneFromSignalInfo
173505fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                            (uSignalType, uAlertPitch, uSignal);
173605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu
173705fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    //Create the SignalInfo tone player and pass the ToneID
173805fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                    new SignalInfoTonePlayer(toneID).start();
173905fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu                }
17400fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            }
17410fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
17420fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    }
17430fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17440fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    /**
174505fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu     * Stops a SignalInfo tone in the following condition
174605fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu     * 1 - On receiving a New Ringing Call
174705fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu     * 2 - On disconnecting a call
174805fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu     * 3 - On answering a Call Waiting Call
174905fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu     */
175005fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu    /* package */ void stopSignalInfoTone() {
175105fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu        if (DBG) log("stopSignalInfoTone: Stopping SignalInfo tone player");
175205fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu        new SignalInfoTonePlayer(ToneGenerator.TONE_CDMA_SIGNAL_OFF).start();
175305fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu    }
175405fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu
175505fb729f41a3f7e06891d0c73c04be4be933a89cPeng Zhu    /**
17560fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * Plays a Call waiting tone if it is present in the second incoming call.
17570fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     */
17580fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    private void onCdmaCallWaiting(AsyncResult r) {
17591c48fc89c22508154ac6a682dc39c8f827e0c634w        // Remove any previous Call waiting timers in the queue
17601c48fc89c22508154ac6a682dc39c8f827e0c634w        removeMessages(CALLWAITING_CALLERINFO_DISPLAY_DONE);
17611c48fc89c22508154ac6a682dc39c8f827e0c634w        removeMessages(CALLWAITING_ADDCALL_DISABLE_TIMEOUT);
17621c48fc89c22508154ac6a682dc39c8f827e0c634w
17631c48fc89c22508154ac6a682dc39c8f827e0c634w        // Set the Phone Call State to SINGLE_ACTIVE as there is only one connection
17641c48fc89c22508154ac6a682dc39c8f827e0c634w        // else we would not have received Call waiting
17651c48fc89c22508154ac6a682dc39c8f827e0c634w        mApplication.cdmaPhoneCallState.setCurrentCallState(
17661c48fc89c22508154ac6a682dc39c8f827e0c634w                CdmaPhoneCallState.PhoneCallState.SINGLE_ACTIVE);
17671c48fc89c22508154ac6a682dc39c8f827e0c634w
17687f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // Display the incoming call to the user if the InCallScreen isn't
17697f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown        // already in the foreground.
17700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (!mApplication.isShowingCallScreen()) {
177149c2f55d9544b3262b82ff956cc84c06cfed7f41David Brown            if (DBG) log("- showing incoming call (CDMA call waiting)...");
17727f63f08c5c88d604abba447032ed42f4f972f3efDavid Brown            showIncomingCall();
17730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
17740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17750fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Start timer for CW display
17760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        mCallWaitingTimeOut = false;
17770fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        sendEmptyMessageDelayed(CALLWAITING_CALLERINFO_DISPLAY_DONE,
17780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                CALLWAITING_CALLERINFO_DISPLAY_TIME);
17790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17800fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Set the mAddCallMenuStateAfterCW state to false
17810fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        mApplication.cdmaPhoneCallState.setAddCallMenuStateAfterCallWaiting(false);
17820fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17830fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Start the timer for disabling "Add Call" menu option
17840fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        sendEmptyMessageDelayed(CALLWAITING_ADDCALL_DISABLE_TIMEOUT,
17850fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                CALLWAITING_ADDCALL_DISABLE_TIME);
17860fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
17870fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Extract the Call waiting information
17880fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        CdmaCallWaitingNotification infoCW = (CdmaCallWaitingNotification) r.result;
17890fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        int isPresent = infoCW.isPresent;
17900fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (DBG) log("onCdmaCallWaiting: isPresent=" + isPresent);
17910fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (isPresent == 1 ) {//'1' if tone is valid
17920fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            int uSignalType = infoCW.signalType;
17930fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            int uAlertPitch = infoCW.alertPitch;
17940fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            int uSignal = infoCW.signal;
17950fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            if (DBG) log("onCdmaCallWaiting: uSignalType=" + uSignalType + ", uAlertPitch="
17960fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    + uAlertPitch + ", uSignal=" + uSignal);
17970fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            //Map the Signal to a ToneGenerator ToneID only if Signal info is present
17980fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            int toneID =
17990fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                SignalToneUtil.getAudioToneFromSignalInfo(uSignalType, uAlertPitch, uSignal);
18000fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18010fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            //Create the SignalInfo tone player and pass the ToneID
18020fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            new SignalInfoTonePlayer(toneID).start();
18030fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
18040fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    }
18050fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18060fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    /**
180777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * Posts a event causing us to clean up after rejecting (or timing-out) a
180877350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * CDMA call-waiting call.
180977350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     *
181077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * This method is safe to call from any thread.
181177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * @see onCdmaCallWaitingReject()
181277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     */
181377350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    /* package */ void sendCdmaCallWaitingReject() {
181477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown        sendEmptyMessage(CDMA_CALL_WAITING_REJECT);
181577350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    }
181677350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown
181777350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    /**
18180fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * Performs Call logging based on Timeout or Ignore Call Waiting Call for CDMA,
18190fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     * and finally calls Hangup on the Call Waiting connection.
182077350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     *
182177350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * This method should be called only from the UI thread.
182277350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown     * @see sendCdmaCallWaitingReject()
18230fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville     */
182477350aabae2f056ede7d0df806a9e5a3c22daf7aDavid Brown    private void onCdmaCallWaitingReject() {
1825170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang        final Call ringingCall = mCM.getFirstActiveRingingCall();
18260fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18270fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        // Call waiting timeout scenario
18280fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        if (ringingCall.getState() == Call.State.WAITING) {
18290fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            // Code for perform Call logging and missed call notification
18300fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            Connection c = ringingCall.getLatestConnection();
18310fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18320fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            if (c != null) {
1833de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                String number = c.getAddress();
1834de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                int presentation = c.getNumberPresentation();
1835c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                final long date = c.getCreateTime();
1836c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                final long duration = c.getDurationMillis();
1837c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                final int callLogType = mCallWaitingTimeOut ?
183811aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                        Calls.MISSED_TYPE : Calls.INCOMING_TYPE;
18390fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18400fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // get the callerinfo object and then log the call with it.
18410fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                Object o = c.getUserData();
1842c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                final CallerInfo ci;
18430fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                if ((o == null) || (o instanceof CallerInfo)) {
18440fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    ci = (CallerInfo) o;
18450fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                } else {
18460fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
18470fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                }
18480fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
1849de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                // Do final CNAP modifications of logNumber prior to logging [mimicking
1850de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                // onDisconnect()]
1851de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                final String logNumber = PhoneUtils.modifyForSpecialCnapCases(
1852872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                        mApplication, ci, number, presentation);
1853de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                final int newPresentation = (ci != null) ? ci.numberPresentation : presentation;
1854de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                if (DBG) log("- onCdmaCallWaitingReject(): logNumber set to: " + logNumber
1855de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                        + ", newPresentation value is: " + newPresentation);
1856de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman
185711aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                CallLogAsync.AddCallArgs args =
185811aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                        new CallLogAsync.AddCallArgs(
1859872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                            mApplication, ci, logNumber, presentation,
186011aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                            callLogType, date, duration);
186111aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania
186211aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                mCallLog.addCall(args);
18630fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
186411aceea577d724e61056a646ef6ac8c6430613eeNicolas Catania                if (callLogType == Calls.MISSED_TYPE) {
18650fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                    // Add missed call notification
1866c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                    showMissedCallNotification(c, date);
18671c48fc89c22508154ac6a682dc39c8f827e0c634w                } else {
18681c48fc89c22508154ac6a682dc39c8f827e0c634w                    // Remove Call waiting 20 second display timer in the queue
18691c48fc89c22508154ac6a682dc39c8f827e0c634w                    removeMessages(CALLWAITING_CALLERINFO_DISPLAY_DONE);
18700fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                }
18710fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18720fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                // Hangup the RingingCall connection for CW
18730fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville                PhoneUtils.hangup(c);
18740fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            }
18750fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville
18760fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            //Reset the mCallWaitingTimeOut boolean
18770fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville            mCallWaitingTimeOut = false;
18780fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville        }
18790fb2b4b8eff811fd3243aefdf536e7ba2b10f4e9Wink Saville    }
1880b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project
18813800ac871d6548790ac6119bb68b9be0640af261David Krause    /**
18823800ac871d6548790ac6119bb68b9be0640af261David Krause     * Return the private variable mPreviousCdmaCallState.
18833800ac871d6548790ac6119bb68b9be0640af261David Krause     */
18843800ac871d6548790ac6119bb68b9be0640af261David Krause    /* package */ Call.State getPreviousCdmaCallState() {
18853800ac871d6548790ac6119bb68b9be0640af261David Krause        return mPreviousCdmaCallState;
18863800ac871d6548790ac6119bb68b9be0640af261David Krause    }
18873800ac871d6548790ac6119bb68b9be0640af261David Krause
18883800ac871d6548790ac6119bb68b9be0640af261David Krause    /**
188924f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon     * Return the private variable mVoicePrivacyState.
18903800ac871d6548790ac6119bb68b9be0640af261David Krause     */
189124f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon    /* package */ boolean getVoicePrivacyState() {
189224f2ad06f72bda5d06281ff082598aad60f74a66Martin Hibdon        return mVoicePrivacyState;
18933800ac871d6548790ac6119bb68b9be0640af261David Krause    }
18943800ac871d6548790ac6119bb68b9be0640af261David Krause
18953800ac871d6548790ac6119bb68b9be0640af261David Krause    /**
18963800ac871d6548790ac6119bb68b9be0640af261David Krause     * Return the private variable mIsCdmaRedialCall.
18973800ac871d6548790ac6119bb68b9be0640af261David Krause     */
18983800ac871d6548790ac6119bb68b9be0640af261David Krause    /* package */ boolean getIsCdmaRedialCall() {
18993800ac871d6548790ac6119bb68b9be0640af261David Krause        return mIsCdmaRedialCall;
19003800ac871d6548790ac6119bb68b9be0640af261David Krause    }
19013800ac871d6548790ac6119bb68b9be0640af261David Krause
190280e7149ffe1f9cd99cc6c161717ff1780232d907Wink Saville    /**
1903c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman     * Helper function used to show a missed call notification.
1904c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman     */
1905c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman    private void showMissedCallNotification(Connection c, final long date) {
1906c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman        PhoneUtils.CallerInfoToken info =
1907c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            PhoneUtils.startGetCallerInfo(mApplication, c, this, Long.valueOf(date));
1908c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman        if (info != null) {
1909c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            // at this point, we've requested to start a query, but it makes no
1910c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            // sense to log this missed call until the query comes back.
1911c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            if (VDBG) log("showMissedCallNotification: Querying for CallerInfo on missed call...");
1912c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            if (info.isFinal) {
1913c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                // it seems that the query we have actually is up to date.
1914c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                // send the notification then.
1915c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                CallerInfo ci = info.currentInfo;
1916de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman
1917de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                // Check number presentation value; if we have a non-allowed presentation,
1918de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                // then display an appropriate presentation string instead as the missed
1919de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                // call.
1920de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                String name = ci.name;
1921de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                String number = ci.phoneNumber;
1922de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                if (ci.numberPresentation == Connection.PRESENTATION_RESTRICTED) {
1923872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    name = mApplication.getString(R.string.private_num);
1924de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                } else if (ci.numberPresentation != Connection.PRESENTATION_ALLOWED) {
1925872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    name = mApplication.getString(R.string.unknown);
1926de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                } else {
1927872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                    number = PhoneUtils.modifyForSpecialCnapCases(mApplication,
1928de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                            ci, number, ci.numberPresentation);
1929de0d16c814b5e7f6c75d00025dc331f64703de1cPaul Berman                }
1930df266ade99188365d4a52f89a6d26b549c2aaf9aDavid Brown                mApplication.notificationMgr.notifyMissedCall(name, number,
1931c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman                        ci.phoneLabel, date);
1932c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            }
1933c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman        } else {
1934c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            // getCallerInfo() can return null in rare cases, like if we weren't
1935c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            // able to get a valid phone number out of the specified Connection.
1936c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman            Log.w(LOG_TAG, "showMissedCallNotification: got null CallerInfo for Connection " + c);
1937c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman        }
1938c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman    }
1939c9eddc4caa45b1e39b964a60c4edab9ae6f689cfPaul Berman
1940678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    /**
1941678d72446de9c185c767206338f5fb199e0cd845Peng Zhu     *  Inner class to handle emergency call tone and vibrator
1942678d72446de9c185c767206338f5fb199e0cd845Peng Zhu     */
1943678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    private class EmergencyTonePlayerVibrator {
1944678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private final int EMG_VIBRATE_LENGTH = 1000;  // ms.
1945678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private final int EMG_VIBRATE_PAUSE  = 1000;  // ms.
1946678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private final long[] mVibratePattern =
1947678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                new long[] { EMG_VIBRATE_LENGTH, EMG_VIBRATE_PAUSE };
1948678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1949678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private ToneGenerator mToneGenerator;
1950678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private Vibrator mEmgVibrator;
19513dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent        private int mInCallVolume;
1952678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1953678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        /**
1954678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         * constructor
1955678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         */
1956678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        public EmergencyTonePlayerVibrator() {
1957678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        }
1958678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1959678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        /**
1960678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         * Start the emergency tone or vibrator.
1961678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         */
1962678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private void start() {
1963678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            if (VDBG) log("call startEmergencyToneOrVibrate.");
1964678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            int ringerMode = mAudioManager.getRingerMode();
1965678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1966678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            if ((mIsEmergencyToneOn == EMERGENCY_TONE_ALERT) &&
1967678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    (ringerMode == AudioManager.RINGER_MODE_NORMAL)) {
196804a4162d2c47e63f27d8a6d0a4efd945f2c8052fDavid Brown                log("EmergencyTonePlayerVibrator.start(): emergency tone...");
1969678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                mToneGenerator = new ToneGenerator (AudioManager.STREAM_VOICE_CALL,
19703dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                        InCallTonePlayer.TONE_RELATIVE_VOLUME_EMERGENCY);
1971678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                if (mToneGenerator != null) {
19723dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                    mInCallVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
19733dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                    mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
19743dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                            mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL),
19753dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                            0);
1976678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mToneGenerator.startTone(ToneGenerator.TONE_CDMA_EMERGENCY_RINGBACK);
1977678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mCurrentEmergencyToneState = EMERGENCY_TONE_ALERT;
1978678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                }
1979678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            } else if (mIsEmergencyToneOn == EMERGENCY_TONE_VIBRATE) {
198004a4162d2c47e63f27d8a6d0a4efd945f2c8052fDavid Brown                log("EmergencyTonePlayerVibrator.start(): emergency vibrate...");
1981678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                mEmgVibrator = new Vibrator();
1982678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                if (mEmgVibrator != null) {
1983678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mEmgVibrator.vibrate(mVibratePattern, 0);
1984678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    mCurrentEmergencyToneState = EMERGENCY_TONE_VIBRATE;
1985678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                }
1986678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            }
1987678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        }
1988678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1989678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        /**
1990678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         * If the emergency tone is active, stop the tone or vibrator accordingly.
1991678d72446de9c185c767206338f5fb199e0cd845Peng Zhu         */
1992678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        private void stop() {
1993678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            if (VDBG) log("call stopEmergencyToneOrVibrate.");
1994678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
1995678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            if ((mCurrentEmergencyToneState == EMERGENCY_TONE_ALERT)
1996678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    && (mToneGenerator != null)) {
1997678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                mToneGenerator.stopTone();
1998678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                mToneGenerator.release();
19993dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                mAudioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL,
20003dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                        mInCallVolume,
20013dee774b27d7992f6cb51cde9b1b2d379d0e1169Eric Laurent                        0);
2002678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            } else if ((mCurrentEmergencyToneState == EMERGENCY_TONE_VIBRATE)
2003678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                    && (mEmgVibrator != null)) {
2004678d72446de9c185c767206338f5fb199e0cd845Peng Zhu                mEmgVibrator.cancel();
2005678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            }
2006678d72446de9c185c767206338f5fb199e0cd845Peng Zhu            mCurrentEmergencyToneState = EMERGENCY_TONE_OFF;
2007678d72446de9c185c767206338f5fb199e0cd845Peng Zhu        }
2008678d72446de9c185c767206338f5fb199e0cd845Peng Zhu    }
2009678d72446de9c185c767206338f5fb199e0cd845Peng Zhu
2010eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang    private void onRingbackTone(AsyncResult r) {
2011eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        boolean playTone = (Boolean)(r.result);
2012eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
2013eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        if (playTone == true) {
2014eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            // Only play when foreground call is in DIALING or ALERTING.
201503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            // to prevent a late coming playtone after ALERTING.
2016eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            // Don't play ringback tone if it is in play, otherwise it will cut
2017eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            // the current tone and replay it
2018170160f6550b2933ff5a6c96c879d074a3ca2f16John Wang            if (mCM.getActiveFgCallState().isDialing() &&
201903d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mInCallRingbackTonePlayer == null) {
202003d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mInCallRingbackTonePlayer = new InCallTonePlayer(InCallTonePlayer.TONE_RING_BACK);
2021eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang                mInCallRingbackTonePlayer.start();
2022eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            }
2023eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        } else {
202403d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent            if (mInCallRingbackTonePlayer != null) {
202503d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mInCallRingbackTonePlayer.stopTone();
202603d3877ce3396d533761216f3a0dce0ec71d1410Eric Laurent                mInCallRingbackTonePlayer = null;
2027eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang            }
2028eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang        }
2029eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang    }
2030eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang
2031eee76740ccf80cf2e4c3885dad7f7b544003bcdcjohnwang    /**
20325bf2817fb998e6d7c7b50103733bfe8710d63916John Wang     * Toggle mute and unmute requests while keeping the same mute state
20335bf2817fb998e6d7c7b50103733bfe8710d63916John Wang     */
20345bf2817fb998e6d7c7b50103733bfe8710d63916John Wang    private void onResendMute() {
2035a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang        boolean muteState = PhoneUtils.getMute();
2036a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang        PhoneUtils.setMute(!muteState);
2037a50e10e2efadac960987eaadc0938c6f92d3ee90John Wang        PhoneUtils.setMute(muteState);
20385bf2817fb998e6d7c7b50103733bfe8710d63916John Wang    }
20395bf2817fb998e6d7c7b50103733bfe8710d63916John Wang
20405bf2817fb998e6d7c7b50103733bfe8710d63916John Wang    /**
204140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * Retrieve the phone number from the caller info or the connection.
204240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     *
204340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * For incoming call the number is in the Connection object. For
204440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * outgoing call we use the CallerInfo phoneNumber field if
204540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * present. All the processing should have been done already (CDMA vs GSM numbers).
204640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     *
204740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * If CallerInfo is missing the phone number, get it from the connection.
204840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * Apply the Call Name Presentation (CNAP) transform in the connection on the number.
204940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     *
205040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @param conn The phone connection.
205140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @param info The CallerInfo. Maybe null.
205240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @return the phone number.
205340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     */
205440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    private String getLogNumber(Connection conn, CallerInfo callerInfo) {
205540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        String number = null;
205640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
205740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        if (conn.isIncoming()) {
205840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            number = conn.getAddress();
205940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        } else {
206064824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            // For emergency and voicemail calls,
206164824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            // CallerInfo.phoneNumber does *not* contain a valid phone
206264824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            // number.  Instead it contains an I18N'd string such as
206364824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            // "Emergency Number" or "Voice Mail" so we get the number
206464824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            // from the connection.
206564824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            if (null == callerInfo || TextUtils.isEmpty(callerInfo.phoneNumber) ||
206664824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania                callerInfo.isEmergencyNumber() || callerInfo.isVoiceMailNumber()) {
2067872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan                if (conn.getCall().getPhone().getPhoneType() == Phone.PHONE_TYPE_CDMA) {
206840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                    // In cdma getAddress() is not always equals to getOrigDialString().
206940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                    number = conn.getOrigDialString();
207040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                } else {
207140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                    number = conn.getAddress();
207240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                }
207364824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania            } else {
207464824003c89a7758240425f5c9f8d29cb00e4a65Nicolas Catania                number = callerInfo.phoneNumber;
207540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            }
207640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        }
207740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
207840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        if (null == number) {
207940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            return null;
208040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        } else {
208140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            int presentation = conn.getNumberPresentation();
208240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
208340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            // Do final CNAP modifications.
2084872a3a7af50ce6a4efb180336614bddefe102ac5Hung-ying Tyan            number = PhoneUtils.modifyForSpecialCnapCases(mApplication, callerInfo,
208504a7ee829585973c667ca688a41f65897eaad452Nicolas Catania                                                          number, presentation);
20868343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            if (!PhoneNumberUtils.isUriNumber(number)) {
20878343169cc89621d46dce86449f5ee1ff5d3a4919John Wang                number = PhoneNumberUtils.stripSeparators(number);
20888343169cc89621d46dce86449f5ee1ff5d3a4919John Wang            }
208904a7ee829585973c667ca688a41f65897eaad452Nicolas Catania            if (VDBG) log("getLogNumber: " + number);
209004a7ee829585973c667ca688a41f65897eaad452Nicolas Catania            return number;
209140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        }
209240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    }
209340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
209440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    /**
209540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * Get the caller info.
209640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     *
209740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @param conn The phone connection.
209840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @return The CallerInfo associated with the connection. Maybe null.
209940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     */
210040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    private CallerInfo getCallerInfoFromConnection(Connection conn) {
210140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        CallerInfo ci = null;
210240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        Object o = conn.getUserData();
210340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
210440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        if ((o == null) || (o instanceof CallerInfo)) {
210540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            ci = (CallerInfo) o;
210640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        } else {
210740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            ci = ((PhoneUtils.CallerInfoToken) o).currentInfo;
210840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        }
210940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        return ci;
211040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    }
211140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
211240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    /**
211340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * Get the presentation from the callerinfo if not null otherwise,
211440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * get it from the connection.
211540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     *
211640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @param conn The phone connection.
211740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @param info The CallerInfo. Maybe null.
211840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     * @return The presentation to use in the logs.
211940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania     */
212040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    private int getPresentation(Connection conn, CallerInfo callerInfo) {
212140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        int presentation;
212240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
212340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        if (null == callerInfo) {
212440e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            presentation = conn.getNumberPresentation();
212540e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        } else {
212640e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            presentation = callerInfo.numberPresentation;
212740e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania            if (DBG) log("- getPresentation(): ignoring connection's presentation: " +
212840e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania                         conn.getNumberPresentation());
212940e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        }
213040e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        if (DBG) log("- getPresentation: presentation: " + presentation);
213140e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania        return presentation;
213240e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania    }
213340e46378d410065b7d3a5f3f2c1666c45e678689Nicolas Catania
2134b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    private void log(String msg) {
2135796c70c99bc39295bf685061056f06ab8949c742David Brown        Log.d(LOG_TAG, msg);
2136b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project    }
2137b16363f5fc191b769e88c364243e34b92eb22688The Android Open Source Project}
2138