private void processCallStateChange(ImsCall imsCall, ImsPhoneCall.State state, int cause) { if (DBG) log("processCallStateChange " + imsCall + " state=" + state + " cause=" + cause); if (imsCall == null) return; boolean changed = false; ImsPhoneConnection conn = findConnection(imsCall); if (conn == null) { // TODO : what should be done? return; } changed = conn.update(imsCall, state); if (state == ImsPhoneCall.State.DISCONNECTED) { changed = conn.onDisconnect(cause) || changed; // detach the disconnected connections conn.getCall().detach(conn); removeConnection(conn); } if (changed) { if (conn.getCall() == mHandoverCall) return; updatePhoneState(); mPhone.notifyPreciseCallStateChanged(); } }
/* package */ void hangup(ImsPhoneCall call) throws CallStateException { if (DBG) log("hangup call"); if (call.getConnections().size() == 0) { throw new CallStateException("no connections"); } ImsCall imsCall = call.getImsCall(); boolean rejectCall = false; if (call == mRingingCall) { if (Phone.DEBUG_PHONE) log("(ringing) hangup incoming"); rejectCall = true; } else if (call == mForegroundCall) { if (call.isDialingOrAlerting()) { if (Phone.DEBUG_PHONE) { log("(foregnd) hangup dialing or alerting..."); } } else { if (Phone.DEBUG_PHONE) { log("(foregnd) hangup foreground"); } // held call will be resumed by onCallTerminated } } else if (call == mBackgroundCall) { if (Phone.DEBUG_PHONE) { log("(backgnd) hangup waiting or background"); } } else { throw new CallStateException( "ImsPhoneCall " + call + "does not belong to ImsPhoneCallTracker " + this); } call.onHangupLocal(); try { if (imsCall != null) { if (rejectCall) imsCall.reject(ImsReasonInfo.CODE_USER_DECLINE); else imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED); } else if (mPendingMO != null && call == mForegroundCall) { // is holding a foreground call mPendingMO.update(null, ImsPhoneCall.State.DISCONNECTED); mPendingMO.onDisconnect(); removeConnection(mPendingMO); mPendingMO = null; updatePhoneState(); removeMessages(EVENT_DIAL_PENDINGMO); } } catch (ImsException e) { throw new CallStateException(e.getMessage()); } mPhone.notifyPreciseCallStateChanged(); }
@Override public void handleMessage(Message msg) { AsyncResult ar; if (DBG) log("handleMessage what=" + msg.what); switch (msg.what) { case EVENT_HANGUP_PENDINGMO: if (mPendingMO != null) { mPendingMO.onDisconnect(); removeConnection(mPendingMO); mPendingMO = null; } updatePhoneState(); mPhone.notifyPreciseCallStateChanged(); break; case EVENT_RESUME_BACKGROUND: try { resumeWaitingOrHolding(); } catch (CallStateException e) { if (Phone.DEBUG_PHONE) { loge("handleMessage EVENT_RESUME_BACKGROUND exception=" + e); } } break; case EVENT_DIAL_PENDINGMO: dialInternal(mPendingMO, mClirMode, VideoProfile.VideoState.AUDIO_ONLY); break; case EVENT_EXIT_ECM_RESPONSE_CDMA: // no matter the result, we still do the same here if (pendingCallInEcm) { dialInternal(mPendingMO, pendingCallClirMode, pendingCallVideoState); pendingCallInEcm = false; } mPhone.unsetOnEcbModeExitResponse(this); break; } }