19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.internal.telephony.gsm;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1918e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.AsyncResult;
2018e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.Handler;
2118e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.Message;
2218e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.Registrant;
2318e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.RegistrantList;
2418e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.os.SystemProperties;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.PhoneNumberUtils;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.ServiceState;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.telephony.TelephonyManager;
2818e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport android.telephony.gsm.GsmCellLocation;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.CallStateException;
3304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.CallTracker;
3404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.CommandsInterface;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.telephony.Connection;
3604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.DriverCall;
3718e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport com.android.internal.telephony.EventLogTags;
3818e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport com.android.internal.telephony.Phone;
3918e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport com.android.internal.telephony.TelephonyProperties;
4024440cf8a9431291bdcaa77b418e6c4715932507Naveen Kallaimport com.android.internal.telephony.UUSInfo;
4104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.gsm.CallFailCause;
4218e939623556928f73fcc7511c85a537929a4a7eDan Egnorimport com.android.internal.telephony.gsm.GSMPhone;
4304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.gsm.GsmCall;
4404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport com.android.internal.telephony.gsm.GsmConnection;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4630ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Savilleimport java.io.FileDescriptor;
4730ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Savilleimport java.io.PrintWriter;
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
4904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savilleimport java.util.ArrayList;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@hide}
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
5404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Savillepublic final class GsmCallTracker extends CallTracker {
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final String LOG_TAG = "GSM";
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean REPEAT_POLLING = false;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final boolean DBG_POLL = false;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Constants
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MAX_CONNECTIONS = 7;   // only 7 connections allowed in GSM
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Instance Variables
6604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmConnection connections[] = new GsmConnection[MAX_CONNECTIONS];
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RegistrantList voiceCallEndedRegistrants = new RegistrantList();
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    RegistrantList voiceCallStartedRegistrants = new RegistrantList();
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
71390de220248d05ccb9dc10a197700ad3c1595937Jake Hamby    // connections dropped during last poll
7204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    ArrayList<GsmConnection> droppedDuringPoll
7304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        = new ArrayList<GsmConnection>(MAX_CONNECTIONS);
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmCall ringingCall = new GsmCall(this);
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // A call that is ringing or (call) waiting
7704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmCall foregroundCall = new GsmCall(this);
7804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmCall backgroundCall = new GsmCall(this);
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmConnection pendingMO;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean hangupPendingMO;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    GSMPhone phone;
8404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean desiredMute = false;    // false = mute off
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Phone.State state = Phone.State.IDLE;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Events
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Constructors
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmCallTracker (GSMPhone phone) {
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this.phone = phone;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm = phone.mCM;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public void dispose() {
10704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        //Unregister for all events
10804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        cm.unregisterForCallStateChanged(this);
10904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        cm.unregisterForOn(this);
11004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        cm.unregisterForNotAvailable(this);
11104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
11204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        for(GsmConnection c : connections) {
11304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            try {
11404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                if(c != null) hangup(c);
11504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            } catch (CallStateException ex) {
11604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                Log.e(LOG_TAG, "unexpected error on hangup during dispose");
11704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            }
11804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        }
11904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
12004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        try {
12104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            if(pendingMO != null) hangup(pendingMO);
12204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        } catch (CallStateException ex) {
12304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            Log.e(LOG_TAG, "unexpected error on hangup during dispose");
12404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        }
12504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
12604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        clearDisconnected();
12704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    }
12804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
12904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    protected void finalize() {
13004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        Log.d(LOG_TAG, "GsmCallTracker finalized");
13104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    }
13204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Instance Methods
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Public Methods
13604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public void registerForVoiceCallStarted(Handler h, int what, Object obj) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Registrant r = new Registrant(h, what, obj);
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        voiceCallStartedRegistrants.add(r);
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public void unregisterForVoiceCallStarted(Handler h) {
14204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        voiceCallStartedRegistrants.remove(h);
14304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    }
14404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
14504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public void registerForVoiceCallEnded(Handler h, int what, Object obj) {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Registrant r = new Registrant(h, what, obj);
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        voiceCallEndedRegistrants.add(r);
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    public void unregisterForVoiceCallEnded(Handler h) {
15104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        voiceCallEndedRegistrants.remove(h);
15204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    }
15304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
15504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    fakeHoldForegroundBeforeDial() {
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List<Connection> connCopy;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We need to make a copy here, since fakeHoldBeforeDial()
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // modifies the lists, and we don't want to reverse the order
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        connCopy = (List<Connection>) foregroundCall.connections.clone();
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0, s = connCopy.size() ; i < s ; i++) {
16304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            GsmConnection conn = (GsmConnection)connCopy.get(i);
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            conn.fakeHoldBeforeDial();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * clirMode is one of the CLIR_ constants
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1720593c68a986152cd6c21cd92dca43a81c4060fd7John Wang    synchronized Connection
17324440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    dial (String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // note that this triggers call state changed notif
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearDisconnected();
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!canDial()) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("cannot dial in current state");
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // The new call must be assigned to the foreground call.
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // That call must be idle, so place anything that's
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // there on hold
18404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        if (foregroundCall.getState() == GsmCall.State.ACTIVE) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // this will probably be done by the radio anyway
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // but the dial might fail before this happens
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // and we need to make sure the foreground call is clear
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // for the newly dialed connection
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switchWaitingOrHoldingAndActive();
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Fake local state so that
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // a) foregroundCall is empty for the newly dialed connection
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // b) hasNonHangupStateChanged remains false in the
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // next poll, so that we don't clear a failed dialing call
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            fakeHoldForegroundBeforeDial();
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        if (foregroundCall.getState() != GsmCall.State.IDLE) {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            //we should have failed in !canDial() above before we get here
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("cannot dial in current state");
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2037c20c4607c4402589ce4800a0c49127876dbc6bdWink Saville        pendingMO = new GsmConnection(phone.getContext(), checkForTestEmergencyNumber(dialString),
2047c20c4607c4402589ce4800a0c49127876dbc6bdWink Saville                this, foregroundCall);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        hangupPendingMO = false;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pendingMO.address == null || pendingMO.address.length() == 0
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            || pendingMO.address.indexOf(PhoneNumberUtils.WILD) >= 0
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ) {
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Phone number is invalid
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // handlePollCalls() will notice this call not present
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // and will mark it as dropped.
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pollCallsWhenSafe();
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Always unmute when initiating a new call
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setMute(false);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22024440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla            cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage());
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePhoneState();
2241c42769339d8fe98ecb2698c64e7dc6672e3d59dJaikumar Ganesh        phone.notifyPreciseCallStateChanged();
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return pendingMO;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
22924440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    Connection
23024440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    dial(String dialString) throws CallStateException {
23124440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla        return dial(dialString, CommandsInterface.CLIR_DEFAULT, null);
23224440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    }
23324440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla
23424440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    Connection
23524440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    dial(String dialString, UUSInfo uusInfo) throws CallStateException {
23624440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla        return dial(dialString, CommandsInterface.CLIR_DEFAULT, uusInfo);
23724440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Connection
24024440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla    dial(String dialString, int clirMode) throws CallStateException {
24124440cf8a9431291bdcaa77b418e6c4715932507Naveen Kalla        return dial(dialString, clirMode, null);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
24504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    acceptCall () throws CallStateException {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // FIXME if SWITCH fails, should retry with ANSWER
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // in case the active/holding call disappeared and this
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // is no longer call waiting
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        if (ringingCall.getState() == GsmCall.State.INCOMING) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i("phone", "acceptCall: incoming...");
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Always unmute when answering a new call
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setMute(false);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.acceptCall(obtainCompleteMessage());
25504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        } else if (ringingCall.getState() == GsmCall.State.WAITING) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            setMute(false);
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switchWaitingOrHoldingAndActive();
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("phone not ringing");
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
26404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    rejectCall () throws CallStateException {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // AT+CHLD=0 means "release held or UDUB"
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so if the phone isn't ringing, this could hang up held
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ringingCall.getState().isRinging()) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.rejectCall(obtainCompleteMessage());
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("phone not ringing");
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    switchWaitingOrHoldingAndActive() throws CallStateException {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Should we bother with this check?
27704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        if (ringingCall.getState() == GsmCall.State.INCOMING) {
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("cannot be in the incoming state");
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.switchWaitingOrHoldingAndActive(
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    obtainCompleteMessage(EVENT_SWITCH_RESULT));
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
28604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    conference() throws CallStateException {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT));
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
29104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    explicitCallTransfer() throws CallStateException {
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT));
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void
29604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    clearDisconnected() {
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        internalClearDisconnected();
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePhoneState();
3001c42769339d8fe98ecb2698c64e7dc6672e3d59dJaikumar Ganesh        phone.notifyPreciseCallStateChanged();
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean
30404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    canConference() {
30504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        return foregroundCall.getState() == GsmCall.State.ACTIVE
30604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                && backgroundCall.getState() == GsmCall.State.HOLDING
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && !backgroundCall.isFull()
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && !foregroundCall.isFull();
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean
31204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    canDial() {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean ret;
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int serviceState = phone.getServiceState().getState();
315597f2b7022db1368831251d776f42b98d10ba2cdjohnwang        String disableCall = SystemProperties.get(
316597f2b7022db1368831251d776f42b98d10ba2cdjohnwang                TelephonyProperties.PROPERTY_DISABLE_CALL, "false");
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
318597f2b7022db1368831251d776f42b98d10ba2cdjohnwang        ret = (serviceState != ServiceState.STATE_POWER_OFF)
319597f2b7022db1368831251d776f42b98d10ba2cdjohnwang                && pendingMO == null
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && !ringingCall.isRinging()
321597f2b7022db1368831251d776f42b98d10ba2cdjohnwang                && !disableCall.equals("true")
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (!foregroundCall.getState().isAlive()
323597f2b7022db1368831251d776f42b98d10ba2cdjohnwang                    || !backgroundCall.getState().isAlive());
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean
32904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    canTransfer() {
33004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        return foregroundCall.getState() == GsmCall.State.ACTIVE
33104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                && backgroundCall.getState() == GsmCall.State.HOLDING;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Private Instance Methods
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
33704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    internalClearDisconnected() {
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ringingCall.clearDisconnected();
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        foregroundCall.clearDisconnected();
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        backgroundCall.clearDisconnected();
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtain a message to use for signalling "invoke getCurrentCalls() when
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this operation and all other pending operations are complete
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Message
34804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    obtainCompleteMessage() {
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Obtain a message to use for signalling "invoke getCurrentCalls() when
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * this operation and all other pending operations are complete
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Message
35704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    obtainCompleteMessage(int what) {
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pendingOperations++;
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        lastRelevantPoll = null;
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        needsPoll = true;
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG_POLL) log("obtainCompleteMessage: pendingOperations=" +
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pendingOperations + ", needsPoll=" + needsPoll);
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return obtainMessage(what);
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
36904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    operationComplete() {
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pendingOperations--;
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DBG_POLL) log("operationComplete: pendingOperations=" +
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pendingOperations + ", needsPoll=" + needsPoll);
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pendingOperations == 0 && needsPoll) {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.getCurrentCalls(lastRelevantPoll);
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pendingOperations < 0) {
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // this should never happen
38004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            Log.e(LOG_TAG,"GsmCallTracker.pendingOperations < 0");
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pendingOperations = 0;
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
38604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    updatePhoneState() {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Phone.State oldState = state;
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ringingCall.isRinging()) {
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            state = Phone.State.RINGING;
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (pendingMO != null ||
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                !(foregroundCall.isIdle() && backgroundCall.isIdle())) {
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            state = Phone.State.OFFHOOK;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            state = Phone.State.IDLE;
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state == Phone.State.IDLE && oldState != state) {
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            voiceCallEndedRegistrants.notifyRegistrants(
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new AsyncResult(null, null, null));
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (oldState == Phone.State.IDLE && oldState != state) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            voiceCallStartedRegistrants.notifyRegistrants (
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new AsyncResult(null, null, null));
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (state != oldState) {
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            phone.notifyPhoneStateChanged();
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4110593c68a986152cd6c21cd92dca43a81c4060fd7John Wang    protected synchronized void
41204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    handlePollCalls(AsyncResult ar) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List polledCalls;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (ar.exception == null) {
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            polledCalls = (List)ar.result;
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // just a dummy empty ArrayList to cause the loop
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to hang up all the calls
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            polledCalls = new ArrayList();
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Radio probably wasn't ready--try again in a bit
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // But don't keep polling if the channel is closed
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pollCallsAfterDelay();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Connection newRinging = null; //or waiting
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean hasNonHangupStateChanged = false;   // Any change besides
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                                    // a dropped connection
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean needsPollDelay = false;
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean unknownConnectionAppeared = false;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0, curDC = 0, dcSize = polledCalls.size()
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ; i < connections.length; i++) {
43604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            GsmConnection conn = connections[i];
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            DriverCall dc = null;
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // polledCall list is sparse
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (curDC < dcSize) {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                dc = (DriverCall) polledCalls.get(curDC);
4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (dc.index == i+1) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    curDC++;
4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    dc = null;
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DBG_POLL) log("poll: conn[i=" + i + "]=" +
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    conn+", dc=" + dc);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (conn == null && dc != null) {
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Connection appeared in CLCC response that we don't know about
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (pendingMO != null && pendingMO.compareTo(dc)) {
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DBG_POLL) log("poll: pendingMO=" + pendingMO);
4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // It's our pending mobile originating call
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    connections[i] = pendingMO;
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pendingMO.index = i;
4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pendingMO.update(dc);
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    pendingMO = null;
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Someone has already asked to hangup this call
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (hangupPendingMO) {
4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        hangupPendingMO = false;
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        try {
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (Phone.DEBUG_PHONE) log(
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                    "poll: hangupPendingMO, hangup conn " + i);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            hangup(connections[i]);
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } catch (CallStateException ex) {
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            Log.e(LOG_TAG, "unexpected error on hangup");
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do not continue processing this poll
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Wait for hangup and repoll
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        return;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
48104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                    connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // it's a ringing call
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (connections[i].getCall() == ringingCall) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        newRinging = connections[i];
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Something strange happened: a call appeared
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // which is neither a ringing call or one we created.
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Either we've crashed and re-attached to an existing
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // call, or something else (eg, SIM) initiated the call.
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Log.i(LOG_TAG,"Phantom call appeared " + dc);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // If it's a connected call, set the connect time so that
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // it's non-zero.  It may not be accurate, but at least
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // it won't appear as a Missed Call.
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (dc.state != DriverCall.State.ALERTING
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                && dc.state != DriverCall.State.DIALING) {
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            connections[i].connectTime = System.currentTimeMillis();
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        unknownConnectionAppeared = true;
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasNonHangupStateChanged = true;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (conn != null && dc == null) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Connection missing in CLCC response that we were
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // tracking.
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.add(conn);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Dropped connections are removed from the CallTracker
51104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                // list but kept in the GsmCall list
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                connections[i] = null;
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (conn != null && dc != null && !conn.compareTo(dc)) {
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Connection in CLCC response does not match what
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // we were tracking. Assume dropped call and new call
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.add(conn);
51804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                connections[i] = new GsmConnection (phone.getContext(), dc, this, i);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (connections[i].getCall() == ringingCall) {
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    newRinging = connections[i];
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } // else something strange happened
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasNonHangupStateChanged = true;
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (conn != null && dc != null) { /* implicit conn.compareTo(dc) */
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed;
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                changed = conn.update(dc);
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (REPEAT_POLLING) {
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (dc != null) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // FIXME with RIL, we should not need this anymore
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if ((dc.state == DriverCall.State.DIALING
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            /*&& cm.getOption(cm.OPTION_POLL_DIALING)*/)
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || (dc.state == DriverCall.State.ALERTING
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            /*&& cm.getOption(cm.OPTION_POLL_ALERTING)*/)
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || (dc.state == DriverCall.State.INCOMING
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            /*&& cm.getOption(cm.OPTION_POLL_INCOMING)*/)
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || (dc.state == DriverCall.State.WAITING
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            /*&& cm.getOption(cm.OPTION_POLL_WAITING)*/)
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Sometimes there's no unsolicited notification
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // for state transitions
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        needsPollDelay = true;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // This is the first poll after an ATD.
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // We expect the pending call to appear in the list
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If it does not, we land here
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (pendingMO != null) {
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.d(LOG_TAG,"Pending MO dropped before poll fg state:"
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + foregroundCall.getState());
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            droppedDuringPoll.add(pendingMO);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pendingMO = null;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hangupPendingMO = false;
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newRinging != null) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            phone.notifyNewRingingConnection(newRinging);
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // clear the "local hangup" and "missed/rejected call"
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // cases from the "dropped during poll" list
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // These cases need no "last call fail" reason
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) {
57004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            GsmConnection conn = droppedDuringPoll.get(i);
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (conn.isIncoming() && conn.getConnectTime() == 0) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Missed or rejected call
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Connection.DisconnectCause cause;
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (conn.cause == Connection.DisconnectCause.LOCAL) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cause = Connection.DisconnectCause.INCOMING_REJECTED;
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    cause = Connection.DisconnectCause.INCOMING_MISSED;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Phone.DEBUG_PHONE) {
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log("missed/rejected call, conn.cause=" + conn.cause);
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log("setting cause to " + cause);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.remove(i);
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                conn.onDisconnect(cause);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (conn.cause == Connection.DisconnectCause.LOCAL) {
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Local hangup
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.remove(i);
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                conn.onDisconnect(Connection.DisconnectCause.LOCAL);
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (conn.cause ==
59204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                Connection.DisconnectCause.INVALID_NUMBER) {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.remove(i);
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Any non-local disconnects: determine cause
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (droppedDuringPoll.size() > 0) {
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.getLastCallFailCause(
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (needsPollDelay) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pollCallsAfterDelay();
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Cases when we can no longer keep disconnected Connection's
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // with their previous calls
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 1) the phone has started to ring
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // 2) A Call/Connection object has changed state...
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    we may have switched or held or answered (but not hung up)
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (newRinging != null || hasNonHangupStateChanged) {
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            internalClearDisconnected();
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        updatePhoneState();
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (unknownConnectionAppeared) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            phone.notifyUnknownConnection();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (hasNonHangupStateChanged || newRinging != null) {
6241c42769339d8fe98ecb2698c64e7dc6672e3d59dJaikumar Ganesh            phone.notifyPreciseCallStateChanged();
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //dumpState();
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
63104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    handleRadioNotAvailable() {
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // handlePollCalls will clear out its
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // call list when it gets the CommandException
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // error result from this
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        pollCallsWhenSafe();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void
63904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    dumpState() {
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        List l;
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.i(LOG_TAG,"Phone State:" + state);
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.i(LOG_TAG,"Ringing call: " + ringingCall.toString());
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        l = ringingCall.getConnections();
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0, s = l.size(); i < s; i++) {
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i(LOG_TAG,l.get(i).toString());
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.i(LOG_TAG,"Foreground call: " + foregroundCall.toString());
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        l = foregroundCall.getConnections();
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0, s = l.size(); i < s; i++) {
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i(LOG_TAG,l.get(i).toString());
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Log.i(LOG_TAG,"Background call: " + backgroundCall.toString());
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        l = backgroundCall.getConnections();
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0, s = l.size(); i < s; i++) {
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i(LOG_TAG,l.get(i).toString());
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
66704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    //***** Called from GsmConnection
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ void
67004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    hangup (GsmConnection conn) throws CallStateException {
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (conn.owner != this) {
67204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            throw new CallStateException ("GsmConnection " + conn
67304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                                    + "does not belong to GsmCallTracker " + this);
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (conn == pendingMO) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // We're hanging up an outgoing call that doesn't have it's
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // GSM index assigned yet
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Phone.DEBUG_PHONE) log("hangup: set hangupPendingMO to true");
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            hangupPendingMO = true;
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cm.hangupConnection (conn.getGSMIndex(), obtainCompleteMessage());
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (CallStateException ex) {
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Ignore "connection not found"
6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Call may have hung up already
68804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                Log.w(LOG_TAG,"GsmCallTracker WARN: hangup() on absent connection "
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                + conn);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        conn.onHangupLocal();
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ void
69704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    separate (GsmConnection conn) throws CallStateException {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (conn.owner != this) {
69904e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            throw new CallStateException ("GsmConnection " + conn
70004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                                    + "does not belong to GsmCallTracker " + this);
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.separateConnection (conn.getGSMIndex(),
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                obtainCompleteMessage(EVENT_SEPARATE_RESULT));
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (CallStateException ex) {
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Ignore "connection not found"
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Call may have hung up already
70804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            Log.w(LOG_TAG,"GsmCallTracker WARN: separate() on absent connection "
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                          + conn);
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //***** Called from GSMPhone
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ void
71604e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    setMute(boolean mute) {
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        desiredMute = mute;
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.setMute(desiredMute, null);
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*package*/ boolean
72204e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    getMute() {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return desiredMute;
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
72704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    //***** Called from GsmCall
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */ void
73004e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    hangup (GsmCall call) throws CallStateException {
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (call.getConnections().size() == 0) {
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new CallStateException("no connections in call");
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (call == ringingCall) {
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (Phone.DEBUG_PHONE) log("(ringing) hangup waiting or background");
7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cm.hangupWaitingOrBackground(obtainCompleteMessage());
7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (call == foregroundCall) {
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (call.isDialingOrAlerting()) {
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Phone.DEBUG_PHONE) {
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log("(foregnd) hangup dialing or alerting...");
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
74304e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                hangup((GsmConnection)(call.getConnections().get(0)));
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hangupForegroundResumeBackground();
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (call == backgroundCall) {
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ringingCall.isRinging()) {
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (Phone.DEBUG_PHONE) {
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    log("hangup all conns in background call");
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hangupAllConnections(call);
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                hangupWaitingOrBackground();
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
75704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            throw new RuntimeException ("GsmCall " + call +
75804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                    "does not belong to GsmCallTracker " + this);
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        call.onHangupLocal();
762e7a9201edbb4d18f12d00ba1b80e2481a5cb446fjsh        phone.notifyPreciseCallStateChanged();
7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hangupWaitingOrBackground() {
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Phone.DEBUG_PHONE) log("hangupWaitingOrBackground");
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.hangupWaitingOrBackground(obtainCompleteMessage());
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hangupForegroundResumeBackground() {
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (Phone.DEBUG_PHONE) log("hangupForegroundResumeBackground");
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        cm.hangupForegroundResumeBackground(obtainCompleteMessage());
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
77704e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    void hangupConnectionByIndex(GsmCall call, int index)
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws CallStateException {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = call.connections.size();
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < count; i++) {
78104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            GsmConnection cn = (GsmConnection)call.connections.get(i);
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cn.getGSMIndex() == index) {
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cm.hangupConnection(index, obtainCompleteMessage());
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        throw new CallStateException("no gsm index found");
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
79104e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    void hangupAllConnections(GsmCall call) throws CallStateException{
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int count = call.connections.size();
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i = 0; i < count; i++) {
79504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                GsmConnection cn = (GsmConnection)call.connections.get(i);
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage());
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (CallStateException ex) {
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.e(LOG_TAG, "hangupConnectionByIndex caught " + ex);
8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /* package */
80404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    GsmConnection getConnectionByIndex(GsmCall call, int index)
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws CallStateException {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = call.connections.size();
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < count; i++) {
80804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville            GsmConnection cn = (GsmConnection)call.connections.get(i);
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cn.getGSMIndex() == index) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return cn;
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Phone.SuppService getFailedService(int what) {
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (what) {
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_SWITCH_RESULT:
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return Phone.SuppService.SWITCH;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_CONFERENCE_RESULT:
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return Phone.SuppService.CONFERENCE;
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_SEPARATE_RESULT:
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return Phone.SuppService.SEPARATE;
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_ECT_RESULT:
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return Phone.SuppService.TRANSFER;
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return Phone.SuppService.UNKNOWN;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //****** Overridden from Handler
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void
83404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    handleMessage (Message msg) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AsyncResult ar;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_POLL_CALLS_RESULT:
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ar = (AsyncResult)msg.obj;
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (msg == lastRelevantPoll) {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DBG_POLL) log(
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    needsPoll = false;
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    lastRelevantPoll = null;
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    handlePollCalls((AsyncResult)msg.obj);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_OPERATION_COMPLETE:
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ar = (AsyncResult)msg.obj;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                operationComplete();
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_SWITCH_RESULT:
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_CONFERENCE_RESULT:
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_SEPARATE_RESULT:
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_ECT_RESULT:
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ar = (AsyncResult)msg.obj;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ar.exception != null) {
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    phone.notifySuppServiceFailed(getFailedService(msg.what));
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                operationComplete();
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_GET_LAST_CALL_FAIL_CAUSE:
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int causeCode;
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ar = (AsyncResult)msg.obj;
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                operationComplete();
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (ar.exception != null) {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // An exception occurred...just treat the disconnect
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // cause as "normal"
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode = CallFailCause.NORMAL_CLEARING;
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Log.i(LOG_TAG,
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "Exception during getLastCallFailCause, assuming normal disconnect");
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode = ((int[])ar.result)[0];
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Log the causeCode if its not normal
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (causeCode == CallFailCause.NO_CIRCUIT_AVAIL ||
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.TEMPORARY_FAILURE ||
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.SWITCHING_CONGESTION ||
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.CHANNEL_NOT_AVAIL ||
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.QOS_NOT_AVAIL ||
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.BEARER_NOT_AVAIL ||
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    causeCode == CallFailCause.ERROR_UNSPECIFIED) {
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    GsmCellLocation loc = ((GsmCellLocation)phone.getCellLocation());
89018e939623556928f73fcc7511c85a537929a4a7eDan Egnor                    EventLog.writeEvent(EventLogTags.CALL_DROP,
89162136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                            causeCode, loc != null ? loc.getCid() : -1,
89262136d3e1c1262fc31a1f77f6d6acbd75e5ea81dDan Egnor                            TelephonyManager.getDefault().getNetworkType());
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i = 0, s =  droppedDuringPoll.size()
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        ; i < s ; i++
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ) {
89804e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville                    GsmConnection conn = droppedDuringPoll.get(i);
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    conn.onRemoteDisconnect(causeCode);
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                updatePhoneState();
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9051c42769339d8fe98ecb2698c64e7dc6672e3d59dJaikumar Ganesh                phone.notifyPreciseCallStateChanged();
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                droppedDuringPoll.clear();
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_REPOLL_AFTER_DELAY:
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_CALL_STATE_CHANGE:
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                pollCallsWhenSafe();
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_RADIO_AVAILABLE:
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleRadioAvailable();
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case EVENT_RADIO_NOT_AVAILABLE:
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleRadioNotAvailable();
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            break;
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
92404e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville    protected void log(String msg) {
92504e71b3db84fd5f7fc4eefb49a33154ea91ec9fcWink Saville        Log.d(LOG_TAG, "[GsmCallTracker] " + msg);
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
92730ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville
92830ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville    @Override
92930ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
93030ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println("GsmCallTracker extends:");
93130ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        super.dump(fd, pw, args);
93230ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println("connections: length=" + connections.length);
93330ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        for(int i=0; i < connections.length; i++) {
93430ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville            pw.printf("  connections[%d]=%s\n", i, connections[i]);
93530ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        }
93630ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" voiceCallEndedRegistrants=" + voiceCallEndedRegistrants);
93730ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" voiceCallStartedRegistrants=" + voiceCallStartedRegistrants);
93830ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" droppedDuringPoll: size=" + droppedDuringPoll.size());
93930ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        for(int i = 0; i < droppedDuringPoll.size(); i++) {
94030ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville            pw.printf( "  droppedDuringPoll[%d]=%s\n", i, droppedDuringPoll.get(i));
94130ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        }
94230ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" ringingCall=" + ringingCall);
94330ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" foregroundCall=" + foregroundCall);
94430ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" backgroundCall=" + backgroundCall);
94530ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" pendingMO=" + pendingMO);
94630ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" hangupPendingMO=" + hangupPendingMO);
94730ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" phone=" + phone);
94830ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" desiredMute=" + desiredMute);
94930ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville        pw.println(" state=" + state);
95030ccade7f9432b8212807b9ddc8cc69a4a8fc854Wink Saville    }
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
952