@Override public void separate() throws CallStateException { synchronized (SipPhone.class) { SipCall call = (getPhone() == SipPhone.this) ? (SipCall) getBackgroundCall() : (SipCall) getForegroundCall(); if (call.getState() != Call.State.IDLE) { throw new CallStateException( "cannot put conn back to a call in non-idle state: " + call.getState()); } if (SCN_DBG) log("separate: conn=" + mPeer.getUriString() + " from " + mOwner + " back to " + call); // separate the AudioGroup and connection from the original call Phone originalPhone = getPhone(); AudioGroup audioGroup = call.getAudioGroup(); // may be null call.add(this); mSipAudioCall.setAudioGroup(audioGroup); // put the original call to bg; and the separated call becomes // fg if it was in bg originalPhone.switchHoldingAndActive(); // start audio and notify the phone app of the state change call = (SipCall) getForegroundCall(); mSipAudioCall.startAudio(); call.onConnectionStateChanged(this); } }
@Override public void onChanged(SipAudioCall call) { synchronized (SipPhone.class) { Call.State newState = getCallStateFrom(call); if (mState == newState) return; if (newState == Call.State.INCOMING) { setState(mOwner.getState()); // INCOMING or WAITING } else { if (mOwner == mRingingCall) { if (mRingingCall.getState() == Call.State.WAITING) { try { switchHoldingAndActive(); } catch (CallStateException e) { // disconnect the call. onCallEnded(DisconnectCause.LOCAL); return; } } mForegroundCall.switchWith(mRingingCall); } setState(newState); } mOwner.onConnectionStateChanged(SipConnection.this); if (SCN_DBG) log( "onChanged: " + mPeer.getUriString() + ": " + mState + " on phone " + getPhone()); } }