diff options
Diffstat (limited to 'telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java')
-rw-r--r-- | telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java | 230 |
1 files changed, 127 insertions, 103 deletions
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java index d813ecaf9f5b..2485dcb4e5b0 100644 --- a/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java +++ b/telephony/java/com/android/internal/telephony/cdma/CdmaCallTracker.java @@ -37,42 +37,42 @@ import com.android.internal.telephony.*; * {@hide} */ public final class CdmaCallTracker extends CallTracker { - static final String LOG_TAG = "CDMA"; - + static final String LOG_TAG = "CDMA"; + private static final boolean REPEAT_POLLING = false; private static final boolean DBG_POLL = false; //***** Constants - static final int MAX_CONNECTIONS = 7; // only 7 connections allowed in GSM - static final int MAX_CONNECTIONS_PER_CALL = 5; // only 5 connections allowed per call + static final int MAX_CONNECTIONS = 1; // only 1 connection allowed in CDMA + static final int MAX_CONNECTIONS_PER_CALL = 1; // only 1 connection allowed per call //***** Instance Variables - + CdmaConnection connections[] = new CdmaConnection[MAX_CONNECTIONS]; RegistrantList voiceCallEndedRegistrants = new RegistrantList(); RegistrantList voiceCallStartedRegistrants = new RegistrantList(); // connections dropped durin last poll - ArrayList<CdmaConnection> droppedDuringPoll - = new ArrayList<CdmaConnection>(MAX_CONNECTIONS); + ArrayList<CdmaConnection> droppedDuringPoll + = new ArrayList<CdmaConnection>(MAX_CONNECTIONS); - CdmaCall ringingCall = new CdmaCall(this); + CdmaCall ringingCall = new CdmaCall(this); // A call that is ringing or (call) waiting CdmaCall foregroundCall = new CdmaCall(this); CdmaCall backgroundCall = new CdmaCall(this); CdmaConnection pendingMO; boolean hangupPendingMO; - + CDMAPhone phone; - + boolean desiredMute = false; // false = mute off Phone.State state = Phone.State.IDLE; - + // boolean needsPoll; @@ -88,7 +88,34 @@ public final class CdmaCallTracker extends CallTracker { cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null); cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null); } - + + public void dispose() { + cm.unregisterForCallStateChanged(this); + cm.unregisterForOn(this); + cm.unregisterForNotAvailable(this); + + for(CdmaConnection c : connections) { + try { + if(c != null) hangup(c); + } catch (CallStateException ex) { + Log.e(LOG_TAG, "unexpected error on hangup during dispose"); + } + } + + try { + if(pendingMO != null) hangup(pendingMO); + } catch (CallStateException ex) { + Log.e(LOG_TAG, "unexpected error on hangup during dispose"); + } + + clearDisconnected(); + + } + + protected void finalize() { + Log.d(LOG_TAG, "CdmaCallTracker finalized"); + } + //***** Instance Methods //***** Public Methods @@ -96,12 +123,19 @@ public final class CdmaCallTracker extends CallTracker { Registrant r = new Registrant(h, what, obj); voiceCallStartedRegistrants.add(r); } + public void unregisterForVoiceCallStarted(Handler h) { + voiceCallStartedRegistrants.remove(h); + } public void registerForVoiceCallEnded(Handler h, int what, Object obj) { Registrant r = new Registrant(h, what, obj); voiceCallEndedRegistrants.add(r); } + public void unregisterForVoiceCallEnded(Handler h) { + voiceCallEndedRegistrants.remove(h); + } + private void fakeHoldForegroundBeforeDial() { List<Connection> connCopy; @@ -116,7 +150,7 @@ public final class CdmaCallTracker extends CallTracker { conn.fakeHoldBeforeDial(); } } - + /** * clirMode is one of the CLIR_ constants */ @@ -139,13 +173,13 @@ public final class CdmaCallTracker extends CallTracker { // for the newly dialed connection switchWaitingOrHoldingAndActive(); - // Fake local state so that + // 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() != CdmaCall.State.IDLE) { //we should have failed in !canDial() above before we get here throw new CallStateException("cannot dial in current state"); @@ -161,33 +195,33 @@ public final class CdmaCallTracker extends CallTracker { pendingMO.cause = Connection.DisconnectCause.INVALID_NUMBER; // handlePollCalls() will notice this call not present - // and will mark it as dropped. + // and will mark it as dropped. pollCallsWhenSafe(); } else { // Always unmute when initiating a new call setMute(false); - cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); + cm.dial(pendingMO.address, clirMode, obtainCompleteMessage()); } updatePhoneState(); phone.notifyCallStateChanged(); - + return pendingMO; } - + Connection dial (String dialString) throws CallStateException { return dial(dialString, CommandsInterface.CLIR_DEFAULT); } - + void acceptCall () throws CallStateException { // FIXME if SWITCH fails, should retry with ANSWER // in case the active/holding call disappeared and this // is no longer call waiting - + if (ringingCall.getState() == CdmaCall.State.INCOMING) { Log.i("phone", "acceptCall: incoming..."); // Always unmute when answering a new call @@ -218,21 +252,21 @@ public final class CdmaCallTracker extends CallTracker { if (ringingCall.getState() == CdmaCall.State.INCOMING) { throw new CallStateException("cannot be in the incoming state"); } else { - cm.switchWaitingOrHoldingAndActive( - obtainCompleteMessage(EVENT_SWITCH_RESULT)); + cm.sendCDMAFeatureCode("", obtainCompleteMessage(EVENT_SWITCH_RESULT)); } } void conference() throws CallStateException { - cm.conference(obtainCompleteMessage(EVENT_CONFERENCE_RESULT)); + // three way calls in CDMA will be handled by feature codes + Log.e(LOG_TAG, "conference: not possible in CDMA"); } void explicitCallTransfer() throws CallStateException { cm.explicitCallTransfer(obtainCompleteMessage(EVENT_ECT_RESULT)); } - + void clearDisconnected() { internalClearDisconnected(); @@ -241,7 +275,7 @@ public final class CdmaCallTracker extends CallTracker { phone.notifyCallStateChanged(); } - boolean + boolean canConference() { return foregroundCall.getState() == CdmaCall.State.ACTIVE && backgroundCall.getState() == CdmaCall.State.HOLDING @@ -265,21 +299,19 @@ public final class CdmaCallTracker extends CallTracker { boolean canTransfer() { - return foregroundCall.getState() == CdmaCall.State.ACTIVE - && backgroundCall.getState() == CdmaCall.State.HOLDING; + Log.e(LOG_TAG, "canTransfer: not possible in CDMA"); + return false; } - + //***** Private Instance Methods - + private void internalClearDisconnected() { ringingCall.clearDisconnected(); foregroundCall.clearDisconnected(); - backgroundCall.clearDisconnected(); + backgroundCall.clearDisconnected(); } - - - + /** * Obtain a message to use for signalling "invoke getCurrentCalls() when * this operation and all other pending operations are complete @@ -288,7 +320,7 @@ public final class CdmaCallTracker extends CallTracker { obtainCompleteMessage() { return obtainCompleteMessage(EVENT_OPERATION_COMPLETE); } - + /** * Obtain a message to use for signalling "invoke getCurrentCalls() when * this operation and all other pending operations are complete @@ -308,26 +340,26 @@ public final class CdmaCallTracker extends CallTracker { private void operationComplete() { pendingOperations--; - + if (DBG_POLL) log("operationComplete: pendingOperations=" + pendingOperations + ", needsPoll=" + needsPoll); if (pendingOperations == 0 && needsPoll) { lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT); - cm.getCurrentCalls(lastRelevantPoll); + cm.getCurrentCalls(lastRelevantPoll); } else if (pendingOperations < 0) { // this should never happen Log.e(LOG_TAG,"CdmaCallTracker.pendingOperations < 0"); pendingOperations = 0; } } - + private void updatePhoneState() { Phone.State oldState = state; - + if (ringingCall.isRinging()) { state = Phone.State.RINGING; } else if (pendingMO != null || @@ -335,7 +367,7 @@ public final class CdmaCallTracker extends CallTracker { state = Phone.State.OFFHOOK; } else { state = Phone.State.IDLE; - } + } if (state == Phone.State.IDLE && oldState != state) { voiceCallEndedRegistrants.notifyRegistrants( @@ -349,13 +381,13 @@ public final class CdmaCallTracker extends CallTracker { phone.notifyPhoneStateChanged(); } } - + // ***** Overwritten from CallTracker - + protected void handlePollCalls(AsyncResult ar) { List polledCalls; - + if (ar.exception == null) { polledCalls = (List)ar.result; } else if (isCommandExceptionRadioNotAvailable(ar.exception)) { @@ -375,7 +407,7 @@ public final class CdmaCallTracker extends CallTracker { boolean needsPollDelay = false; boolean unknownConnectionAppeared = false; - for (int i = 0, curDC = 0, dcSize = polledCalls.size() + for (int i = 0, curDC = 0, dcSize = polledCalls.size() ; i < connections.length; i++) { CdmaConnection conn = connections[i]; DriverCall dc = null; @@ -432,7 +464,7 @@ public final class CdmaCallTracker extends CallTracker { // 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); // If it's a connected call, set the connect time so that @@ -449,8 +481,8 @@ public final class CdmaCallTracker extends CallTracker { hasNonHangupStateChanged = true; } else if (conn != null && dc == null) { // Connection missing in CLCC response that we were - // tracking. - droppedDuringPoll.add(conn); + // tracking. + droppedDuringPoll.add(conn); // Dropped connections are removed from the CallTracker // list but kept in the Call list connections[i] = null; @@ -458,7 +490,7 @@ public final class CdmaCallTracker extends CallTracker { // Connection in CLCC response does not match what // we were tracking. Assume dropped call and new call - droppedDuringPoll.add(conn); + droppedDuringPoll.add(conn); connections[i] = new CdmaConnection (dc, this, i); if (connections[i].getCall() == ringingCall) { @@ -494,11 +526,11 @@ public final class CdmaCallTracker extends CallTracker { // This is the first poll after an ATD. // We expect the pending call to appear in the list // If it does not, we land here - if (pendingMO != null) { - Log.d(LOG_TAG,"Pending MO dropped before poll fg state:" + if (pendingMO != null) { + Log.d(LOG_TAG,"Pending MO dropped before poll fg state:" + foregroundCall.getState()); - droppedDuringPoll.add(pendingMO); + droppedDuringPoll.add(pendingMO); pendingMO = null; hangupPendingMO = false; } @@ -519,7 +551,7 @@ public final class CdmaCallTracker extends CallTracker { if (conn.cause == Connection.DisconnectCause.LOCAL) { cause = Connection.DisconnectCause.INCOMING_REJECTED; } else { - cause = Connection.DisconnectCause.INCOMING_MISSED; + cause = Connection.DisconnectCause.INCOMING_MISSED; } if (Phone.DEBUG_PHONE) { @@ -532,8 +564,7 @@ public final class CdmaCallTracker extends CallTracker { // Local hangup droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.LOCAL); - } else if (conn.cause == - Connection.DisconnectCause.INVALID_NUMBER) { + } else if (conn.cause == Connection.DisconnectCause.INVALID_NUMBER) { droppedDuringPoll.remove(i); conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER); } @@ -575,7 +606,7 @@ public final class CdmaCallTracker extends CallTracker { /*package*/ void hangup (CdmaConnection conn) throws CallStateException { if (conn.owner != this) { - throw new CallStateException ("CdmaConnection " + conn + throw new CallStateException ("CdmaConnection " + conn + "does not belong to CdmaCallTracker " + this); } @@ -584,14 +615,14 @@ public final class CdmaCallTracker extends CallTracker { // GSM index assigned yet if (Phone.DEBUG_PHONE) log("hangup: set hangupPendingMO to true"); - hangupPendingMO = true; + hangupPendingMO = true; } else { - try { - cm.hangupConnection (conn.getGSMIndex(), obtainCompleteMessage()); + try { + cm.hangupConnection (conn.getCDMAIndex(), obtainCompleteMessage()); } catch (CallStateException ex) { // Ignore "connection not found" // Call may have hung up already - Log.w(LOG_TAG,"CdmaCallTracker WARN: hangup() on absent connection " + Log.w(LOG_TAG,"CdmaCallTracker WARN: hangup() on absent connection " + conn); } } @@ -602,20 +633,20 @@ public final class CdmaCallTracker extends CallTracker { /*package*/ void separate (CdmaConnection conn) throws CallStateException { if (conn.owner != this) { - throw new CallStateException ("CdmaConnection " + conn + throw new CallStateException ("CdmaConnection " + conn + "does not belong to CdmaCallTracker " + this); } try { - cm.separateConnection (conn.getGSMIndex(), + cm.separateConnection (conn.getCDMAIndex(), obtainCompleteMessage(EVENT_SEPARATE_RESULT)); } catch (CallStateException ex) { // Ignore "connection not found" // Call may have hung up already - Log.w(LOG_TAG,"CdmaCallTracker WARN: separate() on absent connection " + Log.w(LOG_TAG,"CdmaCallTracker WARN: separate() on absent connection " + conn); } - } - + } + //***** Called from CDMAPhone /*package*/ void @@ -623,13 +654,13 @@ public final class CdmaCallTracker extends CallTracker { desiredMute = mute; cm.setMute(desiredMute, null); } - + /*package*/ boolean getMute() { return desiredMute; - } + } + - //***** Called from CdmaCall /* package */ void @@ -684,7 +715,7 @@ public final class CdmaCallTracker extends CallTracker { int count = call.connections.size(); for (int i = 0; i < count; i++) { CdmaConnection cn = (CdmaConnection)call.connections.get(i); - if (cn.getGSMIndex() == index) { + if (cn.getCDMAIndex() == index) { cm.hangupConnection(index, obtainCompleteMessage()); return; } @@ -698,27 +729,27 @@ public final class CdmaCallTracker extends CallTracker { int count = call.connections.size(); for (int i = 0; i < count; i++) { CdmaConnection cn = (CdmaConnection)call.connections.get(i); - cm.hangupConnection(cn.getGSMIndex(), obtainCompleteMessage()); + cm.hangupConnection(cn.getCDMAIndex(), obtainCompleteMessage()); } } catch (CallStateException ex) { Log.e(LOG_TAG, "hangupConnectionByIndex caught " + ex); } } - + /* package */ CdmaConnection getConnectionByIndex(CdmaCall call, int index) throws CallStateException { int count = call.connections.size(); for (int i = 0; i < count; i++) { CdmaConnection cn = (CdmaConnection)call.connections.get(i); - if (cn.getGSMIndex() == index) { + if (cn.getCDMAIndex() == index) { return cn; } } return null; } - + private Phone.SuppService getFailedService(int what) { switch (what) { case EVENT_SWITCH_RESULT: @@ -733,16 +764,22 @@ public final class CdmaCallTracker extends CallTracker { return Phone.SuppService.UNKNOWN; } + private void handleRadioNotAvailable() { + // handlePollCalls will clear out its + // call list when it gets the CommandException + // error result from this + pollCallsWhenSafe(); + } + //****** Overridden from Handler - public void + public void handleMessage (Message msg) { AsyncResult ar; - + switch (msg.what) { case EVENT_POLL_CALLS_RESULT:{ - //TODO Remove - Log.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received"); + Log.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received"); ar = (AsyncResult)msg.obj; if(msg == lastRelevantPoll) { @@ -759,25 +796,17 @@ public final class CdmaCallTracker extends CallTracker { ar = (AsyncResult)msg.obj; operationComplete(); break; - -// TODO + case EVENT_SWITCH_RESULT: -// case EVENT_CONFERENCE_RESULT: -// case EVENT_SEPARATE_RESULT: -// case EVENT_ECT_RESULT: - ar = (AsyncResult)msg.obj; - if (ar.exception != null) { - // TODO: will be handles by InCall Supp. Service use case - //phone.notifySuppServiceFailed(getFailedService(msg.what)); - } - operationComplete(); + ar = (AsyncResult)msg.obj; + operationComplete(); break; case EVENT_GET_LAST_CALL_FAIL_CAUSE: int causeCode; ar = (AsyncResult)msg.obj; - operationComplete(); + operationComplete(); if (ar.exception != null) { // An exception occurred...just treat the disconnect @@ -788,7 +817,7 @@ public final class CdmaCallTracker extends CallTracker { } else { causeCode = ((int[])ar.result)[0]; } - + for (int i = 0, s = droppedDuringPoll.size() ; i < s ; i++ ) { @@ -802,31 +831,26 @@ public final class CdmaCallTracker extends CallTracker { phone.notifyCallStateChanged(); droppedDuringPoll.clear(); break; - -// TODO: check if needed -// case EVENT_REPOLL_AFTER_DELAY: + case EVENT_CALL_STATE_CHANGE: - Log.d(LOG_TAG, "Event EVENT_CALL_STATE_CHANGE Received"); //TODO Remove pollCallsWhenSafe(); break; - case EVENT_RADIO_AVAILABLE:{ - Log.d(LOG_TAG, "Event EVENT_RADIO_AVAILABLE Received"); //TODO Remove + case EVENT_RADIO_AVAILABLE: handleRadioAvailable(); - } break; - + case EVENT_RADIO_NOT_AVAILABLE: - Log.d(LOG_TAG, "Event EVENT_RADIO_NOT_AVAILABLE Received"); //TODO Remove - //handleRadioNotAvailable(); //TODO + handleRadioNotAvailable(); break; + default:{ - throw new RuntimeException("unexpected event not handled"); + throw new RuntimeException("unexpected event not handled"); } } } - - private void log(String msg) { + + protected void log(String msg) { Log.d(LOG_TAG, "[CdmaCallTracker] " + msg); } |