10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2006 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.gsm;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Registrant;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.RegistrantList;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.PhoneNumberUtils;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.ServiceState;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.TelephonyManager;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.telephony.gsm.GsmCellLocation;
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.EventLog;
300825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log;
310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CallStateException;
330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CallTracker;
340825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandsInterface;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.Connection;
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.DriverCall;
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.EventLogTags;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.Phone;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.PhoneConstants;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.TelephonyProperties;
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.UUSInfo;
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.gsm.CallFailCause;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.gsm.GSMPhone;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.gsm.GsmCall;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.gsm.GsmConnection;
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.FileDescriptor;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.PrintWriter;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList;
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic final class GsmCallTracker extends CallTracker {
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String LOG_TAG = "GSM";
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final boolean REPEAT_POLLING = false;
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final boolean DBG_POLL = false;
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constants
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Variables
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmConnection connections[] = new GsmConnection[MAX_CONNECTIONS];
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RegistrantList voiceCallEndedRegistrants = new RegistrantList();
690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RegistrantList voiceCallStartedRegistrants = new RegistrantList();
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // connections dropped during last poll
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ArrayList<GsmConnection> droppedDuringPoll
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        = new ArrayList<GsmConnection>(MAX_CONNECTIONS);
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCall ringingCall = new GsmCall(this);
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // A call that is ringing or (call) waiting
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCall foregroundCall = new GsmCall(this);
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCall backgroundCall = new GsmCall(this);
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmConnection pendingMO;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean hangupPendingMO;
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GSMPhone phone;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean desiredMute = false;    // false = mute off
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    PhoneConstants.State state = PhoneConstants.State.IDLE;
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Events
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Constructors
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmCallTracker (GSMPhone phone) {
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.phone = phone;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm = phone.mCM;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //Unregister for all events
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForCallStateChanged(this);
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForOn(this);
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.unregisterForNotAvailable(this);
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for(GsmConnection c : connections) {
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if(c != null) hangup(c);
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (CallStateException ex) {
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if(pendingMO != null) hangup(pendingMO);
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (CallStateException ex) {
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        clearDisconnected();
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void finalize() {
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.d(LOG_TAG, "GsmCallTracker finalized");
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Instance Methods
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Public Methods
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Registrant r = new Registrant(h, what, obj);
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        voiceCallStartedRegistrants.add(r);
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void unregisterForVoiceCallStarted(Handler h) {
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        voiceCallStartedRegistrants.remove(h);
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Registrant r = new Registrant(h, what, obj);
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        voiceCallEndedRegistrants.add(r);
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void unregisterForVoiceCallEnded(Handler h) {
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        voiceCallEndedRegistrants.remove(h);
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    fakeHoldForegroundBeforeDial() {
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List<Connection> connCopy;
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // We need to make a copy here, since fakeHoldBeforeDial()
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // modifies the lists, and we don't want to reverse the order
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        connCopy = (List<Connection>) foregroundCall.connections.clone();
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = connCopy.size() ; i < s ; i++) {
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmConnection conn = (GsmConnection)connCopy.get(i);
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            conn.fakeHoldBeforeDial();
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * clirMode is one of the CLIR_ constants
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    synchronized Connection
1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    dial (String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException {
1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // note that this triggers call state changed notif
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        clearDisconnected();
1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!canDial()) {
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("cannot dial in current state");
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // The new call must be assigned to the foreground call.
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // That call must be idle, so place anything that's
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // there on hold
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (foregroundCall.getState() == GsmCall.State.ACTIVE) {
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // this will probably be done by the radio anyway
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // but the dial might fail before this happens
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // and we need to make sure the foreground call is clear
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // for the newly dialed connection
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switchWaitingOrHoldingAndActive();
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Fake local state so that
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // a) foregroundCall is empty for the newly dialed connection
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // b) hasNonHangupStateChanged remains false in the
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // next poll, so that we don't clear a failed dialing call
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            fakeHoldForegroundBeforeDial();
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (foregroundCall.getState() != GsmCall.State.IDLE) {
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            //we should have failed in !canDial() above before we get here
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("cannot dial in current state");
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pendingMO = new GsmConnection(phone.getContext(), checkForTestEmergencyNumber(dialString),
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                this, foregroundCall);
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        hangupPendingMO = false;
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (pendingMO.address == null || pendingMO.address.length() == 0
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            || pendingMO.address.indexOf(PhoneNumberUtils.WILD) >= 0
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ) {
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Phone number is invalid
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER;
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // handlePollCalls() will notice this call not present
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // and will mark it as dropped.
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pollCallsWhenSafe();
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Always unmute when initiating a new call
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setMute(false);
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage());
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        updatePhoneState();
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.notifyPreciseCallStateChanged();
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return pendingMO;
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Connection
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    dial(String dialString) throws CallStateException {
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return dial(dialString, CommandsInterface.CLIR_DEFAULT, null);
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Connection
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    dial(String dialString, UUSInfo uusInfo) throws CallStateException {
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return dial(dialString, CommandsInterface.CLIR_DEFAULT, uusInfo);
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Connection
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    dial(String dialString, int clirMode) throws CallStateException {
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return dial(dialString, clirMode, null);
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    acceptCall () throws CallStateException {
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // FIXME if SWITCH fails, should retry with ANSWER
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // in case the active/holding call disappeared and this
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // is no longer call waiting
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ringingCall.getState() == GsmCall.State.INCOMING) {
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i("phone", "acceptCall: incoming...");
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Always unmute when answering a new call
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setMute(false);
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.acceptCall(obtainCompleteMessage());
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (ringingCall.getState() == GsmCall.State.WAITING) {
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            setMute(false);
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switchWaitingOrHoldingAndActive();
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("phone not ringing");
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    rejectCall () throws CallStateException {
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // AT+CHLD=0 means "release held or UDUB"
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // so if the phone isn't ringing, this could hang up held
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ringingCall.getState().isRinging()) {
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.rejectCall(obtainCompleteMessage());
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("phone not ringing");
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    switchWaitingOrHoldingAndActive() throws CallStateException {
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Should we bother with this check?
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ringingCall.getState() == GsmCall.State.INCOMING) {
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("cannot be in the incoming state");
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.switchWaitingOrHoldingAndActive(
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    obtainCompleteMessage(EVENT_SWITCH_RESULT));
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    conference() throws CallStateException {
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    explicitCallTransfer() throws CallStateException {
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    clearDisconnected() {
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        internalClearDisconnected();
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        updatePhoneState();
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.notifyPreciseCallStateChanged();
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    canConference() {
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return foregroundCall.getState() == GsmCall.State.ACTIVE
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && backgroundCall.getState() == GsmCall.State.HOLDING
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && !backgroundCall.isFull()
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && !foregroundCall.isFull();
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    canDial() {
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean ret;
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int serviceState = phone.getServiceState().getState();
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String disableCall = SystemProperties.get(
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ret = (serviceState != ServiceState.STATE_POWER_OFF)
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && pendingMO == null
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && !ringingCall.isRinging()
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && !disableCall.equals("true")
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && (!foregroundCall.getState().isAlive()
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    || !backgroundCall.getState().isAlive());
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return ret;
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    boolean
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    canTransfer() {
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return foregroundCall.getState() == GsmCall.State.ACTIVE
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                && backgroundCall.getState() == GsmCall.State.HOLDING;
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Private Instance Methods
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    internalClearDisconnected() {
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ringingCall.clearDisconnected();
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        foregroundCall.clearDisconnected();
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        backgroundCall.clearDisconnected();
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Obtain a message to use for signalling "invoke getCurrentCalls() when
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * this operation and all other pending operations are complete
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Message
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    obtainCompleteMessage() {
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Obtain a message to use for signalling "invoke getCurrentCalls() when
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * this operation and all other pending operations are complete
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Message
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    obtainCompleteMessage(int what) {
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pendingOperations++;
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        lastRelevantPoll = null;
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        needsPoll = true;
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG_POLL) log("obtainCompleteMessage: pendingOperations=" +
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pendingOperations + ", needsPoll=" + needsPoll);
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return obtainMessage(what);
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    operationComplete() {
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pendingOperations--;
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (DBG_POLL) log("operationComplete: pendingOperations=" +
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pendingOperations + ", needsPoll=" + needsPoll);
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (pendingOperations == 0 && needsPoll) {
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.getCurrentCalls(lastRelevantPoll);
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (pendingOperations < 0) {
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // this should never happen
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG,"GsmCallTracker.pendingOperations < 0");
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pendingOperations = 0;
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    updatePhoneState() {
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PhoneConstants.State oldState = state;
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ringingCall.isRinging()) {
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = PhoneConstants.State.RINGING;
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (pendingMO != null ||
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                !(foregroundCall.isIdle() && backgroundCall.isIdle())) {
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = PhoneConstants.State.OFFHOOK;
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            state = PhoneConstants.State.IDLE;
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (state == PhoneConstants.State.IDLE && oldState != state) {
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            voiceCallEndedRegistrants.notifyRegistrants(
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                new AsyncResult(null, null, null));
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (oldState == PhoneConstants.State.IDLE && oldState != state) {
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            voiceCallStartedRegistrants.notifyRegistrants (
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    new AsyncResult(null, null, null));
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (state != oldState) {
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyPhoneStateChanged();
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected synchronized void
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    handlePollCalls(AsyncResult ar) {
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List polledCalls;
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (ar.exception == null) {
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            polledCalls = (List)ar.result;
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // just a dummy empty ArrayList to cause the loop
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // to hang up all the calls
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            polledCalls = new ArrayList();
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Radio probably wasn't ready--try again in a bit
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // But don't keep polling if the channel is closed
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pollCallsAfterDelay();
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Connection newRinging = null; //or waiting
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean hasNonHangupStateChanged = false;   // Any change besides
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                                    // a dropped connection
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean needsPollDelay = false;
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean unknownConnectionAppeared = false;
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, curDC = 0, dcSize = polledCalls.size()
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ; i < connections.length; i++) {
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmConnection conn = connections[i];
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            DriverCall dc = null;
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // polledCall list is sparse
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (curDC < dcSize) {
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                dc = (DriverCall) polledCalls.get(curDC);
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (dc.index == i+1) {
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    curDC++;
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    dc = null;
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (DBG_POLL) log("poll: conn[i=" + i + "]=" +
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    conn+", dc=" + dc);
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (conn == null && dc != null) {
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Connection appeared in CLCC response that we don't know about
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (pendingMO != null && pendingMO.compareTo(dc)) {
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (DBG_POLL) log("poll: pendingMO=" + pendingMO);
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // It's our pending mobile originating call
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    connections[i] = pendingMO;
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    pendingMO.index = i;
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    pendingMO.update(dc);
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    pendingMO = null;
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // Someone has already asked to hangup this call
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (hangupPendingMO) {
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        hangupPendingMO = false;
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        try {
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            if (Phone.DEBUG_PHONE) log(
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    "poll: hangupPendingMO, hangup conn " + i);
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            hangup(connections[i]);
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        } catch (CallStateException ex) {
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            Log.e(LOG_TAG, "unexpected error on hangup");
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Do not continue processing this poll
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Wait for hangup and repoll
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        return;
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // it's a ringing call
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (connections[i].getCall() == ringingCall) {
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        newRinging = connections[i];
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } else {
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Something strange happened: a call appeared
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // which is neither a ringing call or one we created.
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Either we've crashed and re-attached to an existing
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // call, or something else (eg, SIM) initiated the call.
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        Log.i(LOG_TAG,"Phantom call appeared " + dc);
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // If it's a connected call, set the connect time so that
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // it's non-zero.  It may not be accurate, but at least
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // it won't appear as a Missed Call.
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        if (dc.state != DriverCall.State.ALERTING
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                && dc.state != DriverCall.State.DIALING) {
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            connections[i].connectTime = System.currentTimeMillis();
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        }
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        unknownConnectionAppeared = true;
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hasNonHangupStateChanged = true;
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (conn != null && dc == null) {
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Connection missing in CLCC response that we were
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // tracking.
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.add(conn);
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Dropped connections are removed from the CallTracker
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // list but kept in the GsmCall list
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                connections[i] = null;
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (conn != null && dc != null && !conn.compareTo(dc)) {
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Connection in CLCC response does not match what
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // we were tracking. Assume dropped call and new call
5170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.add(conn);
5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                connections[i] = new GsmConnection (phone.getContext(), dc, this, i);
5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (connections[i].getCall() == ringingCall) {
5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    newRinging = connections[i];
5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } // else something strange happened
5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hasNonHangupStateChanged = true;
5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */
5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                boolean changed;
5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                changed = conn.update(dc);
5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (REPEAT_POLLING) {
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (dc != null) {
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // FIXME with RIL, we should not need this anymore
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if ((dc.state == DriverCall.State.DIALING
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            /*&& cm.getOption(cm.OPTION_POLL_DIALING)*/)
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        || (dc.state == DriverCall.State.ALERTING
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            /*&& cm.getOption(cm.OPTION_POLL_ALERTING)*/)
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        || (dc.state == DriverCall.State.INCOMING
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            /*&& cm.getOption(cm.OPTION_POLL_INCOMING)*/)
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        || (dc.state == DriverCall.State.WAITING
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            /*&& cm.getOption(cm.OPTION_POLL_WAITING)*/)
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ) {
5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // Sometimes there's no unsolicited notification
5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        // for state transitions
5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        needsPollDelay = true;
5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // This is the first poll after an ATD.
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // We expect the pending call to appear in the list
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // If it does not, we land here
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (pendingMO != null) {
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.d(LOG_TAG,"Pending MO dropped before poll fg state:"
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            + foregroundCall.getState());
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            droppedDuringPoll.add(pendingMO);
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pendingMO = null;
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            hangupPendingMO = false;
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (newRinging != null) {
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyNewRingingConnection(newRinging);
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // clear the "local hangup" and "missed/rejected call"
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // cases from the "dropped during poll" list
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // These cases need no "last call fail" reason
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmConnection conn = droppedDuringPoll.get(i);
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (conn.isIncoming() && conn.getConnectTime() == 0) {
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Missed or rejected call
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Connection.DisconnectCause cause;
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (conn.cause == Connection.DisconnectCause.LOCAL) {
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    cause = Connection.DisconnectCause.INCOMING_REJECTED;
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    cause = Connection.DisconnectCause.INCOMING_MISSED;
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (Phone.DEBUG_PHONE) {
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    log("missed/rejected call, conn.cause=" + conn.cause);
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    log("setting cause to " + cause);
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.remove(i);
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                conn.onDisconnect(cause);
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (conn.cause == Connection.DisconnectCause.LOCAL) {
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Local hangup
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.remove(i);
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                conn.onDisconnect(Connection.DisconnectCause.LOCAL);
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if (conn.cause ==
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Connection.DisconnectCause.INVALID_NUMBER) {
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.remove(i);
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Any non-local disconnects: determine cause
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (droppedDuringPoll.size() > 0) {
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.getLastCallFailCause(
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (needsPollDelay) {
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pollCallsAfterDelay();
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Cases when we can no longer keep disconnected Connection's
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // with their previous calls
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // 1) the phone has started to ring
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // 2) A Call/Connection object has changed state...
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //    we may have switched or held or answered (but not hung up)
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (newRinging != null || hasNonHangupStateChanged) {
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            internalClearDisconnected();
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        updatePhoneState();
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (unknownConnectionAppeared) {
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyUnknownConnection();
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (hasNonHangupStateChanged || newRinging != null) {
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            phone.notifyPreciseCallStateChanged();
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //dumpState();
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    handleRadioNotAvailable() {
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // handlePollCalls will clear out its
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // call list when it gets the CommandException
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // error result from this
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pollCallsWhenSafe();
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    dumpState() {
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List l;
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.i(LOG_TAG,"Phone State:" + state);
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.i(LOG_TAG,"Ringing call: " + ringingCall.toString());
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        l = ringingCall.getConnections();
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = l.size(); i < s; i++) {
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i(LOG_TAG,l.get(i).toString());
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.i(LOG_TAG,"Foreground call: " + foregroundCall.toString());
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        l = foregroundCall.getConnections();
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = l.size(); i < s; i++) {
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i(LOG_TAG,l.get(i).toString());
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.i(LOG_TAG,"Background call: " + backgroundCall.toString());
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        l = backgroundCall.getConnections();
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0, s = l.size(); i < s; i++) {
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.i(LOG_TAG,l.get(i).toString());
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Called from GsmConnection
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /*package*/ void
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    hangup (GsmConnection conn) throws CallStateException {
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (conn.owner != this) {
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException ("GsmConnection " + conn
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    + "does not belong to GsmCallTracker " + this);
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (conn == pendingMO) {
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // We're hanging up an outgoing call that doesn't have it's
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // GSM index assigned yet
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (Phone.DEBUG_PHONE) log("hangup: set hangupPendingMO to true");
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            hangupPendingMO = true;
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.hangupConnection (conn.getGSMIndex(), obtainCompleteMessage());
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (CallStateException ex) {
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Ignore "connection not found"
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Call may have hung up already
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Log.w(LOG_TAG,"GsmCallTracker WARN: hangup() on absent connection "
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                + conn);
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        conn.onHangupLocal();
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /*package*/ void
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    separate (GsmConnection conn) throws CallStateException {
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (conn.owner != this) {
7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException ("GsmConnection " + conn
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                    + "does not belong to GsmCallTracker " + this);
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.separateConnection (conn.getGSMIndex(),
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                obtainCompleteMessage(EVENT_SEPARATE_RESULT));
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (CallStateException ex) {
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Ignore "connection not found"
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // Call may have hung up already
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.w(LOG_TAG,"GsmCallTracker WARN: separate() on absent connection "
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                          + conn);
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Called from GSMPhone
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /*package*/ void
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    setMute(boolean mute) {
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        desiredMute = mute;
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.setMute(desiredMute, null);
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /*package*/ boolean
7230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    getMute() {
7240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return desiredMute;
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //***** Called from GsmCall
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* package */ void
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    hangup (GsmCall call) throws CallStateException {
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (call.getConnections().size() == 0) {
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new CallStateException("no connections in call");
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (call == ringingCall) {
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (Phone.DEBUG_PHONE) log("(ringing) hangup waiting or background");
7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cm.hangupWaitingOrBackground(obtainCompleteMessage());
7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (call == foregroundCall) {
7400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (call.isDialingOrAlerting()) {
7410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (Phone.DEBUG_PHONE) {
7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    log("(foregnd) hangup dialing or alerting...");
7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hangup((GsmConnection)(call.getConnections().get(0)));
7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hangupForegroundResumeBackground();
7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else if (call == backgroundCall) {
7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (ringingCall.isRinging()) {
7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (Phone.DEBUG_PHONE) {
7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    log("hangup all conns in background call");
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hangupAllConnections(call);
7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
7550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                hangupWaitingOrBackground();
7560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
7580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new RuntimeException ("GsmCall " + call +
7590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    "does not belong to GsmCallTracker " + this);
7600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        call.onHangupLocal();
7630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        phone.notifyPreciseCallStateChanged();
7640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* package */
7670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void hangupWaitingOrBackground() {
7680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (Phone.DEBUG_PHONE) log("hangupWaitingOrBackground");
7690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.hangupWaitingOrBackground(obtainCompleteMessage());
7700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* package */
7730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void hangupForegroundResumeBackground() {
7740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (Phone.DEBUG_PHONE) log("hangupForegroundResumeBackground");
7750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        cm.hangupForegroundResumeBackground(obtainCompleteMessage());
7760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void hangupConnectionByIndex(GsmCall call, int index)
7790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throws CallStateException {
7800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int count = call.connections.size();
7810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < count; i++) {
7820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmConnection cn = (GsmConnection)call.connections.get(i);
7830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (cn.getGSMIndex() == index) {
7840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.hangupConnection(index, obtainCompleteMessage());
7850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
7860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        throw new CallStateException("no gsm index found");
7900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    void hangupAllConnections(GsmCall call) throws CallStateException{
7930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
7940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int count = call.connections.size();
7950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            for (int i = 0; i < count; i++) {
7960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                GsmConnection cn = (GsmConnection)call.connections.get(i);
7970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
7980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (CallStateException ex) {
8000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            Log.e(LOG_TAG, "hangupConnectionByIndex caught " + ex);
8010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* package */
8050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    GsmConnection getConnectionByIndex(GsmCall call, int index)
8060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throws CallStateException {
8070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int count = call.connections.size();
8080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for (int i = 0; i < count; i++) {
8090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            GsmConnection cn = (GsmConnection)call.connections.get(i);
8100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (cn.getGSMIndex() == index) {
8110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return cn;
8120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
8130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return null;
8160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Phone.SuppService getFailedService(int what) {
8190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (what) {
8200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SWITCH_RESULT:
8210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return Phone.SuppService.SWITCH;
8220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_CONFERENCE_RESULT:
8230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return Phone.SuppService.CONFERENCE;
8240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SEPARATE_RESULT:
8250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return Phone.SuppService.SEPARATE;
8260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_ECT_RESULT:
8270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return Phone.SuppService.TRANSFER;
8280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
8290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return Phone.SuppService.UNKNOWN;
8300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
8310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    //****** Overridden from Handler
8330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void
8350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    handleMessage (Message msg) {
8360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        AsyncResult ar;
8370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
8390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_POLL_CALLS_RESULT:
8400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult)msg.obj;
8410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (msg == lastRelevantPoll) {
8430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (DBG_POLL) log(
8440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
8450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    needsPoll = false;
8460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    lastRelevantPoll = null;
8470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    handlePollCalls((AsyncResult)msg.obj);
8480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
8490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
8500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_OPERATION_COMPLETE:
8520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult)msg.obj;
8530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                operationComplete();
8540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
8550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SWITCH_RESULT:
8570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_CONFERENCE_RESULT:
8580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_SEPARATE_RESULT:
8590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_ECT_RESULT:
8600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult)msg.obj;
8610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception != null) {
8620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    phone.notifySuppServiceFailed(getFailedService(msg.what));
8630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
8640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                operationComplete();
8650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
8660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_GET_LAST_CALL_FAIL_CAUSE:
8680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                int causeCode;
8690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ar = (AsyncResult)msg.obj;
8700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                operationComplete();
8720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar.exception != null) {
8740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // An exception occurred...just treat the disconnect
8750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // cause as "normal"
8760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode = CallFailCause.NORMAL_CLEARING;
8770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    Log.i(LOG_TAG,
8780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            "Exception during getLastCallFailCause, assuming normal disconnect");
8790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
8800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode = ((int[])ar.result)[0];
8810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
8820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Log the causeCode if its not normal
8830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL ||
8840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.TEMPORARY_FAILURE ||
8850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.SWITCHING_CONGESTION ||
8860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.CHANNEL_NOT_AVAIL ||
8870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.QOS_NOT_AVAIL ||
8880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.BEARER_NOT_AVAIL ||
8890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    causeCode == CallFailCause.ERROR_UNSPECIFIED) {
8900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
8910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    EventLog.writeEvent(EventLogTags.CALL_DROP,
8920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            causeCode, loc != null ? loc.getCid() : -1,
8930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            TelephonyManager.getDefault().getNetworkType());
8940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
8950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
8960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                for (int i = 0, s =  droppedDuringPoll.size()
8970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        ; i < s ; i++
8980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ) {
8990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    GsmConnection conn = droppedDuringPoll.get(i);
9000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    conn.onRemoteDisconnect(causeCode);
9020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
9030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                updatePhoneState();
9050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                phone.notifyPreciseCallStateChanged();
9070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                droppedDuringPoll.clear();
9080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
9090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_REPOLL_AFTER_DELAY:
9110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_CALL_STATE_CHANGE:
9120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                pollCallsWhenSafe();
9130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
9140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RADIO_AVAILABLE:
9160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handleRadioAvailable();
9170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
9180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case EVENT_RADIO_NOT_AVAILABLE:
9200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handleRadioNotAvailable();
9210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
9220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void log(String msg) {
9260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Log.d(LOG_TAG, "[GsmCallTracker] " + msg);
9270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
9290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
9300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
9310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println("GsmCallTracker extends:");
9320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        super.dump(fd, pw, args);
9330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println("connections: length=" + connections.length);
9340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for(int i=0; i < connections.length; i++) {
9350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pw.printf("  connections[%d]=%s\n", i, connections[i]);
9360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" voiceCallEndedRegistrants=" + voiceCallEndedRegistrants);
9380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" voiceCallStartedRegistrants=" + voiceCallStartedRegistrants);
9390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" droppedDuringPoll: size=" + droppedDuringPoll.size());
9400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        for(int i = 0; i < droppedDuringPoll.size(); i++) {
9410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            pw.printf( "  droppedDuringPoll[%d]=%s\n", i, droppedDuringPoll.get(i));
9420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
9430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" ringingCall=" + ringingCall);
9440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" foregroundCall=" + foregroundCall);
9450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" backgroundCall=" + backgroundCall);
9460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" pendingMO=" + pendingMO);
9470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" hangupPendingMO=" + hangupPendingMO);
9480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" phone=" + phone);
9490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" desiredMute=" + desiredMute);
9500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        pw.println(" state=" + state);
9510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
9520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
953