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;
}
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();
}
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();
}
Aggregations