示例#1
0
    @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);
      }
    }
示例#2
0
 @Override
 public void switchHoldingAndActive() throws CallStateException {
   if (DBG) log("dialInternal: switch fg and bg");
   synchronized (SipPhone.class) {
     mForegroundCall.switchWith(mBackgroundCall);
     if (mBackgroundCall.getState().isAlive()) mBackgroundCall.hold();
     if (mForegroundCall.getState().isAlive()) mForegroundCall.unhold();
   }
 }
示例#3
0
 @Override
 public void conference() throws CallStateException {
   synchronized (SipPhone.class) {
     if ((mForegroundCall.getState() != SipCall.State.ACTIVE)
         || (mForegroundCall.getState() != SipCall.State.ACTIVE)) {
       throw new CallStateException(
           "wrong state to merge calls: fg="
               + mForegroundCall.getState()
               + ", bg="
               + mBackgroundCall.getState());
     }
     if (DBG) log("conference: merge fg & bg");
     mForegroundCall.merge(mBackgroundCall);
   }
 }
示例#4
0
  public boolean canTake(Object incomingCall) {
    // FIXME: Is synchronizing on the class necessary, should we use a mLockObj?
    // Also there are many things not synchronized, of course
    // this may be true of CdmaPhone and GsmPhone too!!!
    synchronized (SipPhone.class) {
      if (!(incomingCall instanceof SipAudioCall)) {
        if (DBG) log("canTake: ret=false, not a SipAudioCall");
        return false;
      }
      if (mRingingCall.getState().isAlive()) {
        if (DBG) log("canTake: ret=false, ringingCall not alive");
        return false;
      }

      // FIXME: is it true that we cannot take any incoming call if
      // both foreground and background are active
      if (mForegroundCall.getState().isAlive() && mBackgroundCall.getState().isAlive()) {
        if (DBG) {
          log("canTake: ret=false," + " foreground and background both alive");
        }
        return false;
      }

      try {
        SipAudioCall sipAudioCall = (SipAudioCall) incomingCall;
        if (DBG) log("canTake: taking call from: " + sipAudioCall.getPeerProfile().getUriString());
        String localUri = sipAudioCall.getLocalProfile().getUriString();
        if (localUri.equals(mProfile.getUriString())) {
          boolean makeCallWait = mForegroundCall.getState().isAlive();
          mRingingCall.initIncomingCall(sipAudioCall, makeCallWait);
          if (sipAudioCall.getState() != SipSession.State.INCOMING_CALL) {
            // Peer cancelled the call!
            if (DBG) log("    canTake: call cancelled !!");
            mRingingCall.reset();
          }
          return true;
        }
      } catch (Exception e) {
        // Peer may cancel the call at any time during the time we hook
        // up ringingCall with sipAudioCall. Clean up ringingCall when
        // that happens.
        if (DBG) log("    canTake: exception e=" + e);
        mRingingCall.reset();
      }
      if (DBG) log("canTake: NOT taking !!");
      return false;
    }
  }
示例#5
0
 @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());
   }
 }
示例#6
0
 @Override
 public void acceptCall() throws CallStateException {
   synchronized (SipPhone.class) {
     if ((mRingingCall.getState() == Call.State.INCOMING)
         || (mRingingCall.getState() == Call.State.WAITING)) {
       if (DBG) log("acceptCall: accepting");
       // Always unmute when answering a new call
       mRingingCall.setMute(false);
       mRingingCall.acceptCall();
     } else {
       if (DBG) {
         log("acceptCall:" + " throw CallStateException(\"phone not ringing\")");
       }
       throw new CallStateException("phone not ringing");
     }
   }
 }
示例#7
0
 @Override
 public void sendDtmf(char c) {
   if (!PhoneNumberUtils.is12Key(c)) {
     loge("sendDtmf called with invalid character '" + c + "'");
   } else if (mForegroundCall.getState().isAlive()) {
     synchronized (SipPhone.class) {
       mForegroundCall.sendDtmf(c);
     }
   }
 }
示例#8
0
 @Override
 public void rejectCall() throws CallStateException {
   synchronized (SipPhone.class) {
     if (mRingingCall.getState().isRinging()) {
       if (DBG) log("rejectCall: rejecting");
       mRingingCall.rejectCall();
     } else {
       if (DBG) {
         log("rejectCall:" + " throw CallStateException(\"phone not ringing\")");
       }
       throw new CallStateException("phone not ringing");
     }
   }
 }
示例#9
0
  private Connection dialInternal(String dialString) throws CallStateException {
    if (DBG) log("dialInternal: dialString=" + (VDBG ? dialString : "xxxxxx"));
    clearDisconnected();

    if (!canDial()) {
      throw new CallStateException("dialInternal: cannot dial in current state");
    }
    if (mForegroundCall.getState() == SipCall.State.ACTIVE) {
      switchHoldingAndActive();
    }
    if (mForegroundCall.getState() != SipCall.State.IDLE) {
      // we should have failed in !canDial() above before we get here
      throw new CallStateException("cannot dial in current state");
    }

    mForegroundCall.setMute(false);
    try {
      Connection c = mForegroundCall.dial(dialString);
      return c;
    } catch (SipException e) {
      loge("dialInternal: ", e);
      throw new CallStateException("dial error: " + e);
    }
  }
示例#10
0
 @Override
 public boolean getMute() {
   return (mForegroundCall.getState().isAlive()
       ? mForegroundCall.getMute()
       : mBackgroundCall.getMute());
 }