Search in sources :

Example 6 with CallStateException

use of com.android.internal.telephony.CallStateException in project XobotOS by xamarin.

the class GsmCallTracker method dial.

/**
     * clirMode is one of the CLIR_ constants
     */
Connection dial(String dialString, int clirMode, UUSInfo uusInfo) throws CallStateException {
    // note that this triggers call state changed notif
    clearDisconnected();
    if (!canDial()) {
        throw new CallStateException("cannot dial in current state");
    }
    // there on hold
    if (foregroundCall.getState() == GsmCall.State.ACTIVE) {
        // this will probably be done by the radio anyway
        // but the dial might fail before this happens
        // and we need to make sure the foreground call is clear
        // for the newly dialed connection
        switchWaitingOrHoldingAndActive();
        // Fake local state so that
        // a) foregroundCall is empty for the newly dialed connection
        // b) hasNonHangupStateChanged remains false in the
        // next poll, so that we don't clear a failed dialing call
        fakeHoldForegroundBeforeDial();
    }
    if (foregroundCall.getState() != GsmCall.State.IDLE) {
        //we should have failed in !canDial() above before we get here
        throw new CallStateException("cannot dial in current state");
    }
    pendingMO = new GsmConnection(phone.getContext(), dialString, this, foregroundCall);
    hangupPendingMO = false;
    if (pendingMO.address == null || pendingMO.address.length() == 0 || pendingMO.address.indexOf(PhoneNumberUtils.WILD) >= 0) {
        // Phone number is invalid
        pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER;
        // handlePollCalls() will notice this call not present
        // and will mark it as dropped.
        pollCallsWhenSafe();
    } else {
        // Always unmute when initiating a new call
        setMute(false);
        cm.dial(pendingMO.address, clirMode, uusInfo, obtainCompleteMessage());
    }
    updatePhoneState();
    phone.notifyPreciseCallStateChanged();
    return pendingMO;
}
Also used : CallStateException(com.android.internal.telephony.CallStateException) GsmConnection(com.android.internal.telephony.gsm.GsmConnection)

Example 7 with CallStateException

use of com.android.internal.telephony.CallStateException in project XobotOS by xamarin.

the class GsmCallTracker method handlePollCalls.

protected void handlePollCalls(AsyncResult ar) {
    List polledCalls;
    if (ar.exception == null) {
        polledCalls = (List) ar.result;
    } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
        // just a dummy empty ArrayList to cause the loop
        // to hang up all the calls
        polledCalls = new ArrayList();
    } else {
        // Radio probably wasn't ready--try again in a bit
        // But don't keep polling if the channel is closed
        pollCallsAfterDelay();
        return;
    }
    //or waiting
    Connection newRinging = null;
    // Any change besides
    boolean hasNonHangupStateChanged = false;
    // a dropped connection
    boolean needsPollDelay = false;
    boolean unknownConnectionAppeared = false;
    for (int i = 0, curDC = 0, dcSize = polledCalls.size(); i < connections.length; i++) {
        GsmConnection conn = connections[i];
        DriverCall dc = null;
        // polledCall list is sparse
        if (curDC < dcSize) {
            dc = (DriverCall) polledCalls.get(curDC);
            if (dc.index == i + 1) {
                curDC++;
            } else {
                dc = null;
            }
        }
        if (DBG_POLL)
            log("poll: conn[i=" + i + "]=" + conn + ", dc=" + dc);
        if (conn == null && dc != null) {
            // Connection appeared in CLCC response that we don't know about
            if (pendingMO != null && pendingMO.compareTo(dc)) {
                if (DBG_POLL)
                    log("poll: pendingMO=" + pendingMO);
                // It's our pending mobile originating call
                connections[i] = pendingMO;
                pendingMO.index = i;
                pendingMO.update(dc);
                pendingMO = null;
                // Someone has already asked to hangup this call
                if (hangupPendingMO) {
                    hangupPendingMO = false;
                    try {
                        if (Phone.DEBUG_PHONE)
                            log("poll: hangupPendingMO, hangup conn " + i);
                        hangup(connections[i]);
                    } catch (CallStateException ex) {
                        Log.e(LOG_TAG, "unexpected error on hangup");
                    }
                    // Wait for hangup and repoll
                    return;
                }
            } else {
                connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
                // it's a ringing call
                if (connections[i].getCall() == ringingCall) {
                    newRinging = connections[i];
                } else {
                    // Something strange happened: a call appeared
                    // which is neither a ringing call or one we created.
                    // Either we've crashed and re-attached to an existing
                    // call, or something else (eg, SIM) initiated the call.
                    Log.i(LOG_TAG, "Phantom call appeared " + dc);
                    // it won't appear as a Missed Call.
                    if (dc.state != DriverCall.State.ALERTING && dc.state != DriverCall.State.DIALING) {
                        connections[i].connectTime = System.currentTimeMillis();
                    }
                    unknownConnectionAppeared = true;
                }
            }
            hasNonHangupStateChanged = true;
        } else if (conn != null && dc == null) {
            // Connection missing in CLCC response that we were
            // tracking.
            droppedDuringPoll.add(conn);
            // Dropped connections are removed from the CallTracker
            // list but kept in the GsmCall list
            connections[i] = null;
        } else if (conn != null && dc != null && !conn.compareTo(dc)) {
            // Connection in CLCC response does not match what
            // we were tracking. Assume dropped call and new call
            droppedDuringPoll.add(conn);
            connections[i] = new GsmConnection(phone.getContext(), dc, this, i);
            if (connections[i].getCall() == ringingCall) {
                newRinging = connections[i];
            }
            // else something strange happened
            hasNonHangupStateChanged = true;
        } else if (conn != null && dc != null) {
            /* implicit conn.compareTo(dc) */
            boolean changed;
            changed = conn.update(dc);
            hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
        }
        if (REPEAT_POLLING) {
            if (dc != null) {
                // FIXME with RIL, we should not need this anymore
                if ((dc.state == DriverCall.State.DIALING) || (dc.state == DriverCall.State.ALERTING) || (dc.state == DriverCall.State.INCOMING) || (dc.state == DriverCall.State.WAITING)) {
                    // Sometimes there's no unsolicited notification
                    // for state transitions
                    needsPollDelay = true;
                }
            }
        }
    }
    // If it does not, we land here
    if (pendingMO != null) {
        Log.d(LOG_TAG, "Pending MO dropped before poll fg state:" + foregroundCall.getState());
        droppedDuringPoll.add(pendingMO);
        pendingMO = null;
        hangupPendingMO = false;
    }
    if (newRinging != null) {
        phone.notifyNewRingingConnection(newRinging);
    }
    // These cases need no "last call fail" reason
    for (int i = droppedDuringPoll.size() - 1; i >= 0; i--) {
        GsmConnection conn = droppedDuringPoll.get(i);
        if (conn.isIncoming() && conn.getConnectTime() == 0) {
            // Missed or rejected call
            Connection.DisconnectCause cause;
            if (conn.cause == Connection.DisconnectCause.LOCAL) {
                cause = Connection.DisconnectCause.INCOMING_REJECTED;
            } else {
                cause = Connection.DisconnectCause.INCOMING_MISSED;
            }
            if (Phone.DEBUG_PHONE) {
                log("missed/rejected call, conn.cause=" + conn.cause);
                log("setting cause to " + cause);
            }
            droppedDuringPoll.remove(i);
            conn.onDisconnect(cause);
        } else if (conn.cause == Connection.DisconnectCause.LOCAL) {
            // Local hangup
            droppedDuringPoll.remove(i);
            conn.onDisconnect(Connection.DisconnectCause.LOCAL);
        } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) {
            droppedDuringPoll.remove(i);
            conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
        }
    }
    // Any non-local disconnects: determine cause
    if (droppedDuringPoll.size() > 0) {
        cm.getLastCallFailCause(obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
    }
    if (needsPollDelay) {
        pollCallsAfterDelay();
    }
    //    we may have switched or held or answered (but not hung up)
    if (newRinging != null || hasNonHangupStateChanged) {
        internalClearDisconnected();
    }
    updatePhoneState();
    if (unknownConnectionAppeared) {
        phone.notifyUnknownConnection();
    }
    if (hasNonHangupStateChanged || newRinging != null) {
        phone.notifyPreciseCallStateChanged();
    }
//dumpState();
}
Also used : DriverCall(com.android.internal.telephony.DriverCall) GsmConnection(com.android.internal.telephony.gsm.GsmConnection) CallStateException(com.android.internal.telephony.CallStateException) ArrayList(java.util.ArrayList) GsmConnection(com.android.internal.telephony.gsm.GsmConnection) Connection(com.android.internal.telephony.Connection) ArrayList(java.util.ArrayList) RegistrantList(android.os.RegistrantList) List(java.util.List)

Example 8 with CallStateException

use of com.android.internal.telephony.CallStateException in project XobotOS by xamarin.

the class CdmaCallTracker method handlePollCalls.

// ***** Overwritten from CallTracker
protected void handlePollCalls(AsyncResult ar) {
    List polledCalls;
    if (ar.exception == null) {
        polledCalls = (List) ar.result;
    } else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
        // just a dummy empty ArrayList to cause the loop
        // to hang up all the calls
        polledCalls = new ArrayList();
    } else {
        // Radio probably wasn't ready--try again in a bit
        // But don't keep polling if the channel is closed
        pollCallsAfterDelay();
        return;
    }
    //or waiting
    Connection newRinging = null;
    // Any change besides
    boolean hasNonHangupStateChanged = false;
    // a dropped connection
    boolean needsPollDelay = false;
    boolean unknownConnectionAppeared = false;
    for (int i = 0, curDC = 0, dcSize = polledCalls.size(); i < connections.length; i++) {
        CdmaConnection conn = connections[i];
        DriverCall dc = null;
        // polledCall list is sparse
        if (curDC < dcSize) {
            dc = (DriverCall) polledCalls.get(curDC);
            if (dc.index == i + 1) {
                curDC++;
            } else {
                dc = null;
            }
        }
        if (DBG_POLL)
            log("poll: conn[i=" + i + "]=" + conn + ", dc=" + dc);
        if (conn == null && dc != null) {
            // Connection appeared in CLCC response that we don't know about
            if (pendingMO != null && pendingMO.compareTo(dc)) {
                if (DBG_POLL)
                    log("poll: pendingMO=" + pendingMO);
                // It's our pending mobile originating call
                connections[i] = pendingMO;
                pendingMO.index = i;
                pendingMO.update(dc);
                pendingMO = null;
                // Someone has already asked to hangup this call
                if (hangupPendingMO) {
                    hangupPendingMO = false;
                    // Re-start Ecm timer when an uncompleted emergency call ends
                    if (mIsEcmTimerCanceled) {
                        handleEcmTimer(phone.RESTART_ECM_TIMER);
                    }
                    try {
                        if (Phone.DEBUG_PHONE)
                            log("poll: hangupPendingMO, hangup conn " + i);
                        hangup(connections[i]);
                    } catch (CallStateException ex) {
                        Log.e(LOG_TAG, "unexpected error on hangup");
                    }
                    // Wait for hangup and repoll
                    return;
                }
            } else {
                if (Phone.DEBUG_PHONE) {
                    log("pendingMo=" + pendingMO + ", dc=" + dc);
                }
                // find if the MT call is a new ring or unknown connection
                newRinging = checkMtFindNewRinging(dc, i);
                if (newRinging == null) {
                    unknownConnectionAppeared = true;
                }
                checkAndEnableDataCallAfterEmergencyCallDropped();
            }
            hasNonHangupStateChanged = true;
        } else if (conn != null && dc == null) {
            // This case means the RIL has no more active call anymore and
            // we need to clean up the foregroundCall and ringingCall.
            // Loop through foreground call connections as
            // it contains the known logical connections.
            int count = foregroundCall.connections.size();
            for (int n = 0; n < count; n++) {
                if (Phone.DEBUG_PHONE)
                    log("adding fgCall cn " + n + " to droppedDuringPoll");
                CdmaConnection cn = (CdmaConnection) foregroundCall.connections.get(n);
                droppedDuringPoll.add(cn);
            }
            count = ringingCall.connections.size();
            // it may contain the known logical connections.
            for (int n = 0; n < count; n++) {
                if (Phone.DEBUG_PHONE)
                    log("adding rgCall cn " + n + " to droppedDuringPoll");
                CdmaConnection cn = (CdmaConnection) ringingCall.connections.get(n);
                droppedDuringPoll.add(cn);
            }
            foregroundCall.setGeneric(false);
            ringingCall.setGeneric(false);
            // Re-start Ecm timer when the connected emergency call ends
            if (mIsEcmTimerCanceled) {
                handleEcmTimer(phone.RESTART_ECM_TIMER);
            }
            // If emergency call is not going through while dialing
            checkAndEnableDataCallAfterEmergencyCallDropped();
            // Dropped connections are removed from the CallTracker
            // list but kept in the Call list
            connections[i] = null;
        } else if (conn != null && dc != null) {
            // Call collision case
            if (conn.isIncoming != dc.isMT) {
                if (dc.isMT == true) {
                    // Mt call takes precedence than Mo,drops Mo
                    droppedDuringPoll.add(conn);
                    // find if the MT call is a new ring or unknown connection
                    newRinging = checkMtFindNewRinging(dc, i);
                    if (newRinging == null) {
                        unknownConnectionAppeared = true;
                    }
                    checkAndEnableDataCallAfterEmergencyCallDropped();
                } else {
                    // Call info stored in conn is not consistent with the call info from dc.
                    // We should follow the rule of MT calls taking precedence over MO calls
                    // when there is conflict, so here we drop the call info from dc and
                    // continue to use the call info from conn, and only take a log.
                    Log.e(LOG_TAG, "Error in RIL, Phantom call appeared " + dc);
                }
            } else {
                boolean changed;
                changed = conn.update(dc);
                hasNonHangupStateChanged = hasNonHangupStateChanged || changed;
            }
        }
        if (REPEAT_POLLING) {
            if (dc != null) {
                // FIXME with RIL, we should not need this anymore
                if ((dc.state == DriverCall.State.DIALING) || (dc.state == DriverCall.State.ALERTING) || (dc.state == DriverCall.State.INCOMING) || (dc.state == DriverCall.State.WAITING)) {
                    // Sometimes there's no unsolicited notification
                    // for state transitions
                    needsPollDelay = true;
                }
            }
        }
    }
    // If it does not, we land here
    if (pendingMO != null) {
        Log.d(LOG_TAG, "Pending MO dropped before poll fg state:" + foregroundCall.getState());
        droppedDuringPoll.add(pendingMO);
        pendingMO = null;
        hangupPendingMO = false;
        if (pendingCallInEcm) {
            pendingCallInEcm = false;
        }
    }
    if (newRinging != null) {
        phone.notifyNewRingingConnection(newRinging);
    }
    // These cases need no "last call fail" reason
    for (int i = droppedDuringPoll.size() - 1; i >= 0; i--) {
        CdmaConnection conn = droppedDuringPoll.get(i);
        if (conn.isIncoming() && conn.getConnectTime() == 0) {
            // Missed or rejected call
            Connection.DisconnectCause cause;
            if (conn.cause == Connection.DisconnectCause.LOCAL) {
                cause = Connection.DisconnectCause.INCOMING_REJECTED;
            } else {
                cause = Connection.DisconnectCause.INCOMING_MISSED;
            }
            if (Phone.DEBUG_PHONE) {
                log("missed/rejected call, conn.cause=" + conn.cause);
                log("setting cause to " + cause);
            }
            droppedDuringPoll.remove(i);
            conn.onDisconnect(cause);
        } else if (conn.cause == Connection.DisconnectCause.LOCAL) {
            // Local hangup
            droppedDuringPoll.remove(i);
            conn.onDisconnect(Connection.DisconnectCause.LOCAL);
        } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) {
            droppedDuringPoll.remove(i);
            conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
        }
    }
    // Any non-local disconnects: determine cause
    if (droppedDuringPoll.size() > 0) {
        cm.getLastCallFailCause(obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
    }
    if (needsPollDelay) {
        pollCallsAfterDelay();
    }
    //    we may have switched or held or answered (but not hung up)
    if (newRinging != null || hasNonHangupStateChanged) {
        internalClearDisconnected();
    }
    updatePhoneState();
    if (unknownConnectionAppeared) {
        phone.notifyUnknownConnection();
    }
    if (hasNonHangupStateChanged || newRinging != null) {
        phone.notifyPreciseCallStateChanged();
    }
//dumpState();
}
Also used : DriverCall(com.android.internal.telephony.DriverCall) CallStateException(com.android.internal.telephony.CallStateException) ArrayList(java.util.ArrayList) Connection(com.android.internal.telephony.Connection) RegistrantList(android.os.RegistrantList) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

CallStateException (com.android.internal.telephony.CallStateException)8 GsmConnection (com.android.internal.telephony.gsm.GsmConnection)4 Connection (com.android.internal.telephony.Connection)3 RegistrantList (android.os.RegistrantList)2 DriverCall (com.android.internal.telephony.DriverCall)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2 SipException (android.net.sip.SipException)1