Exemple #1
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());
   }
 }
Exemple #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();
   }
 }
Exemple #3
0
 void switchWith(SipCall that) {
   if (SC_DBG) log("switchWith");
   synchronized (SipPhone.class) {
     SipCall tmp = new SipCall();
     tmp.takeOver(this);
     this.takeOver(that);
     that.takeOver(tmp);
   }
 }
Exemple #4
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);
     }
   }
 }
Exemple #5
0
  @Override
  public void clearDisconnected() {
    synchronized (SipPhone.class) {
      mRingingCall.clearDisconnected();
      mForegroundCall.clearDisconnected();
      mBackgroundCall.clearDisconnected();

      updatePhoneState();
      notifyPreciseCallStateChanged();
    }
  }
Exemple #6
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");
     }
   }
 }
Exemple #7
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);
   }
 }
Exemple #8
0
 @Override
 protected void onCallEnded(DisconnectCause cause) {
   if (getDisconnectCause() != DisconnectCause.LOCAL) {
     setDisconnectCause(cause);
   }
   synchronized (SipPhone.class) {
     setState(Call.State.DISCONNECTED);
     SipAudioCall sipAudioCall = mSipAudioCall;
     // FIXME: This goes null and is synchronized, but many uses aren't sync'd
     mSipAudioCall = null;
     String sessionState = (sipAudioCall == null) ? "" : (sipAudioCall.getState() + ", ");
     if (SCN_DBG)
       log(
           "[SipAudioCallAdapter] onCallEnded: "
               + mPeer.getUriString()
               + ": "
               + sessionState
               + "cause: "
               + getDisconnectCause()
               + ", on phone "
               + getPhone());
     if (sipAudioCall != null) {
       sipAudioCall.setListener(null);
       sipAudioCall.close();
     }
     mOwner.onConnectionEnded(SipConnection.this);
   }
 }
Exemple #9
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");
     }
   }
 }
Exemple #10
0
 public void conference(Call that) throws CallStateException {
   synchronized (SipPhone.class) {
     if (!(that instanceof SipCall)) {
       throw new CallStateException(
           "expect " + SipCall.class + ", cannot merge with " + that.getClass());
     }
     mForegroundCall.merge((SipCall) that);
   }
 }
Exemple #11
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);
      }
    }
Exemple #12
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);
    }
  }
Exemple #13
0
 @Override
 public void setEchoSuppressionEnabled(boolean enabled) {
   // TODO: Remove the enabled argument. We should check the speakerphone
   // state with AudioManager instead of keeping a state here so the
   // method with a state argument is redundant. Also rename the method
   // to something like onSpeaerphoneStateChanged(). Echo suppression may
   // not be available on every device.
   synchronized (SipPhone.class) {
     AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
     String echoSuppression = audioManager.getParameters("ec_supported");
     if (echoSuppression.contains("off")) {
       mForegroundCall.setAudioGroupMode();
     }
   }
 }
Exemple #14
0
    void merge(SipCall that) throws CallStateException {
      if (SC_DBG) log("merge:");
      AudioGroup audioGroup = getAudioGroup();

      // copy to an array to avoid concurrent modification as connections
      // in that.connections will be removed in add(SipConnection).
      Connection[] cc = that.mConnections.toArray(new Connection[that.mConnections.size()]);
      for (Connection c : cc) {
        SipConnection conn = (SipConnection) c;
        add(conn);
        if (conn.getState() == Call.State.HOLDING) {
          conn.unhold(audioGroup);
        }
      }
      that.setState(Call.State.IDLE);
    }
Exemple #15
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;
    }
  }
Exemple #16
0
 @Override
 public void setMute(boolean muted) {
   synchronized (SipPhone.class) {
     mForegroundCall.setMute(muted);
   }
 }
Exemple #17
0
 @Override
 protected Phone getPhone() {
   return mOwner.getPhone();
 }
Exemple #18
0
 @Override
 public boolean getMute() {
   return (mForegroundCall.getState().isAlive()
       ? mForegroundCall.getMute()
       : mBackgroundCall.getMute());
 }