Exemple #1
0
  /**
   * Constructor
   *
   * @param parent IMS service
   * @param invite Initial INVITE request
   */
  public TerminatingOne2OneChatSession(ImsService parent, SipRequest invite) {
    super(parent, PhoneUtils.extractNumberFromUri(SipUtils.getAssertedIdentity(invite)));

    // Set first message
    InstantMessage firstMsg = ChatUtils.getFirstMessage(invite);
    setFirstMesssage(firstMsg);

    // Create dialog path
    createTerminatingDialogPath(invite);

    // Set contribution ID
    String id = ChatUtils.getContributionId(invite);
    setContributionID(id);
    if (RcsSettings.getInstance().isCPMSupported()) {
      if (logger.isActivated()) {
        logger.info("TerminatingFOne2OneSession1  CPMS");
      }
      setConversationID(ChatUtils.getCoversationId(invite));
      setInReplyID(ChatUtils.getInReplyId(invite));
    }

    if (logger.isActivated()) {
      logger.info("TerminatingOne2OneChatSession From: " + ChatUtils.getFromAias(invite));
      logger.info("TerminatingOne2OneChatSession Display name: " + this.getRemoteDisplayName());
    }
    setRemoteDisplayName(this.getRemoteDisplayName());
  }
Exemple #2
0
  /** Interrupt session */
  public void interruptSession() {
    if (logger.isActivated()) {
      logger.info("ABC Interrupt the session");
    }

    try {
      // Unblock semaphore
      synchronized (waitUserAnswer) {
        waitUserAnswer.notifyAll();
      }

      if (!isSessionInterrupted()) {
        if (logger.isActivated()) {
          logger.info("ABC Interrupt the session1");
        }
        // Interrupt thread
        sessionInterrupted = true;
        interrupt();
      }
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Can't interrupt the session correctly", e);
      }
    }
    if (logger.isActivated()) {
      logger.debug("Session has been interrupted");
    }
  }
  /** Background processing */
  public void run() {
    try {
      if (logger.isActivated()) {
        logger.info("Rejoin an existing group chat session");
      }

      // Set setup mode
      String localSetup = createSetupOffer();
      if (logger.isActivated()) {
        logger.debug("Local setup attribute is " + localSetup);
      }

      // Set local port
      int localMsrpPort;
      if ("active".equals(localSetup)) {
        localMsrpPort = 9; // See RFC4145, Page 4
      } else {
        localMsrpPort = getMsrpMgr().getLocalMsrpPort();
      }

      // Build SDP part
      String ipAddress = getDialogPath().getSipStack().getLocalIpAddress();
      String sdp =
          SdpUtils.buildGroupChatSDP(
              ipAddress,
              localMsrpPort,
              getMsrpMgr().getLocalSocketProtocol(),
              getAcceptTypes(),
              getWrappedTypes(),
              localSetup,
              getMsrpMgr().getLocalMsrpPath(),
              SdpUtils.DIRECTION_SENDRECV);

      // Set the local SDP part in the dialog path
      getDialogPath().setLocalContent(sdp);

      // Create an INVITE request
      if (logger.isActivated()) {
        logger.info("Send INVITE");
      }
      SipRequest invite = createInviteRequest(sdp);

      // Set the Authorization header
      getAuthenticationAgent().setAuthorizationHeader(invite);

      // Set initial request in the dialog path
      getDialogPath().setInvite(invite);

      // Send INVITE request
      sendInvite(invite);
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new ChatError(ChatError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }
Exemple #4
0
  /**
   * Receive CANCEL request
   *
   * @param cancel CANCEL request
   */
  public void receiveCancel(SipRequest cancel) {
    if (logger.isActivated()) {
      logger.info("ABC Receive a CANCEL message from the remote");
    }

    if (getDialogPath().isSigEstablished()) {
      if (logger.isActivated()) {
        logger.info(
            "Ignore the received CANCEL message from the remote (session already established)");
      }
      return;
    }

    // Close media session
    closeMediaSession();

    // Update dialog path
    getDialogPath().sessionCancelled();

    // Send a 487 Request terminated
    try {
      if (logger.isActivated()) {
        logger.info("Send 487 Request terminated");
      }
      SipResponse terminatedResp =
          SipMessageFactory.createResponse(
              getDialogPath().getInvite(), getDialogPath().getLocalTag(), 487);
      getImsService().getImsModule().getSipManager().sendSipResponse(terminatedResp);
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Can't send 487 error response", e);
      }
    }

    // Remove the current session
    getImsService().removeSession(this);

    // Set invitation status
    invitationStatus = ImsServiceSession.INVITATION_CANCELED;

    // Unblock semaphore
    synchronized (waitUserAnswer) {
      waitUserAnswer.notifyAll();
    }

    // Notify listeners
    for (int i = 0; i < getListeners().size(); i++) {
      getListeners().get(i).handleSessionTerminatedByRemote();
    }

    // Request capabilities to the remote
    getImsService()
        .getImsModule()
        .getCapabilityService()
        .requestContactCapabilities(getDialogPath().getRemoteParty());
  }
  /**
   * Handle 422 response
   *
   * @param resp 422 response
   */
  private void handle422SessionTooSmall(SipResponse resp) {
    try {
      // 422 response received
      if (logger.isActivated()) {
        logger.info("422 response received");
      }

      // Extract the Min-SE value
      int minExpire = SipUtils.getMinSessionExpirePeriod(resp);
      if (minExpire == -1) {
        if (logger.isActivated()) {
          logger.error("Can't read the Min-SE value");
        }
        handleError(
            new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, "No Min-SE value found"));
        return;
      }

      // Set the min expire value
      getDialogPath().setMinSessionExpireTime(minExpire);

      // Set the expire value
      getDialogPath().setSessionExpireTime(minExpire);

      // Increment the Cseq number of the dialog path
      getDialogPath().incrementCseq();

      // Create a new INVITE with the right expire period
      if (logger.isActivated()) {
        logger.info("Send new INVITE");
      }
      SipRequest invite =
          SipMessageFactory.createInvite(
              getDialogPath(),
              InstantMessagingService.FT_FEATURE_TAGS,
              getDialogPath().getLocalContent());

      // Set the Authorization header
      getAuthenticationAgent().setAuthorizationHeader(invite);

      // Reset initial request in the dialog path
      getDialogPath().setInvite(invite);

      // Send INVITE request
      sendInvite(invite);

    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }
  /**
   * Returns a current session from its unique session ID
   *
   * @return Multimedia session or null if not found
   * @throws ServerApiException
   */
  public IMultimediaSession getSession(String sessionId) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Get multimedia session " + sessionId);
    }

    return sipSessions.get(sessionId);
  }
  /**
   * Data transfer error
   *
   * @param error Error
   */
  public void msrpTransferError(String error) {
    if (isInterrupted()) {
      return;
    }

    if (logger.isActivated()) {
      logger.info("Data transfer error: " + error);
    }

    // Close the media session
    closeMediaSession();

    // Terminate session
    terminateSession();

    // Remove the current session
    getImsService().removeSession(this);

    // Notify listeners
    if (!isInterrupted()) {
      for (int j = 0; j < getListeners().size(); j++) {
        ((FileSharingSessionListener) getListeners().get(j))
            .handleTransferError(
                new FileSharingError(FileSharingError.MEDIA_TRANSFER_FAILED, error));
      }
    }
  }
  /** Stop core */
  public synchronized void stopCore() {
    if (Core.getInstance() == null) {
      // Already stopped
      return;
    }

    if (logger.isActivated()) {
      logger.debug("Stop RCS core service");
    }

    // Update GSMA client API
    GsmaUtils.setClientActivationState(getApplicationContext(), false);

    // Send service intent
    Intent intent = new Intent(ClientApiIntents.SERVICE_STATUS);
    intent.putExtra("status", ClientApiIntents.SERVICE_STATUS_STOPPING);
    getApplicationContext().sendBroadcast(intent);

    // Terminate the core in background
    Core.terminateCore();

    // Close CPU manager
    cpuManager.close();

    // Send service intent
    intent = new Intent(ClientApiIntents.SERVICE_STATUS);
    intent.putExtra("status", ClientApiIntents.SERVICE_STATUS_STOPPED);
    getApplicationContext().sendBroadcast(intent);

    if (logger.isActivated()) {
      logger.info("RCS core service stopped with success");
    }
  }
  /**
   * Sends a message in pager mode to a contact and for a given service. The message may be any type
   * of content. The parameter contact supports the following formats: MSISDN in national or
   * international format, SIP address, SIP-URI or Tel-URI. If the format of the contact is not
   * supported an exception is thrown.
   *
   * @param serviceId Service ID
   * @param contact Contact
   * @param content Message content
   * @return Returns true if sent successfully else returns false
   * @throws ServerApiException
   */
  public boolean sendMessage(String serviceId, String contact, byte[] content)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Send instant message to " + contact);
    }

    // Test IMS connection
    ServerApiUtils.testIms();

    try {
      // Send instant message
      String featureTag =
          FeatureTags.FEATURE_RCSE
              + "=\""
              + FeatureTags.FEATURE_RCSE_EXTENSION
              + "."
              + serviceId
              + "\"";
      return Core.getInstance().getSipService().sendInstantMessage(contact, featureTag, content);
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Unexpected error", e);
      }
      throw new ServerApiException(e.getMessage());
    }
  }
  /**
   * Receive a new video sharing invitation
   *
   * @param session Video sharing session
   */
  public void receiveVideoSharingInvitation(VideoStreamingSession session) {
    if (logger.isActivated()) {
      logger.info("Receive video sharing invitation from " + session.getRemoteContact());
    }

    // Extract number from contact
    String number = PhoneUtils.extractNumberFromUri(session.getRemoteContact());
    VideoContent content = (VideoContent) session.getContent();

    // Update rich call history
    RichCall.getInstance()
        .addCall(
            number,
            session.getSessionID(),
            RichCallData.EVENT_INCOMING,
            content,
            RichCallData.STATUS_STARTED);

    // Add session in the list
    VideoSharingSession sessionApi = new VideoSharingSession(session);
    addVideoSharingSession(sessionApi);

    // Broadcast intent related to the received invitation
    Intent intent = new Intent(RichCallApiIntents.VIDEO_SHARING_INVITATION);
    intent.putExtra("contact", number);
    intent.putExtra("contactDisplayname", session.getRemoteDisplayName());
    intent.putExtra("sessionId", session.getSessionID());
    intent.putExtra("videotype", content.getEncoding());
    intent.putExtra("videowidth", content.getWidth());
    intent.putExtra("videoheight", content.getHeight());
    AndroidFactory.getApplicationContext().sendBroadcast(intent);
  }
Exemple #11
0
  /**
   * Returns a current geoloc sharing from its unique ID
   *
   * @return Geoloc sharing
   * @throws ServerApiException
   */
  public IGeolocSharing getGeolocSharing(String sharingId) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Get geoloc sharing session " + sharingId);
    }

    return gshSessions.get(sharingId);
  }
  /**
   * Returns a current video sharing from its unique ID
   *
   * @return Video sharing or null if not found
   * @throws ServerApiException
   */
  public IVideoSharing getVideoSharing(String sharingId) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Get video sharing session " + sharingId);
    }

    return videoSharingSessions.get(sharingId);
  }
  /**
   * Receive a new geoloc sharing invitation
   *
   * @param session Geoloc sharing session
   */
  public void receiveGeolocSharingInvitation(GeolocTransferSession session) {
    if (logger.isActivated()) {
      logger.info("Receive geoloc sharing invitation from " + session.getRemoteContact());
    }

    // Extract number from contact
    String number = PhoneUtils.extractNumberFromUri(session.getRemoteContact());

    // Update rich call history
    RichCall.getInstance()
        .addCall(
            number,
            session.getSessionID(),
            RichCallData.EVENT_INCOMING,
            session.getContent(),
            RichCallData.STATUS_STARTED);

    // Add session in the list
    GeolocSharingSession sessionApi = new GeolocSharingSession(session);
    addGeolocSharingSession(sessionApi);

    // Broadcast intent related to the received invitation
    Intent intent = new Intent(RichCallApiIntents.GEOLOC_SHARING_INVITATION);
    intent.putExtra("contact", number);
    intent.putExtra("contactDisplayname", session.getRemoteDisplayName());
    intent.putExtra("sessionId", session.getSessionID());
    AndroidFactory.getApplicationContext().sendBroadcast(intent);
  }
  /**
   * Get list of current image sharing sessions with a contact
   *
   * @param contact Contact
   * @return List of sessions
   * @throws ServerApiException
   */
  public List<IBinder> getImageSharingSessionsWith(String contact) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Get image sharing sessions with " + contact);
    }

    // Check permission
    ServerApiUtils.testPermission();

    // Test core availability
    ServerApiUtils.testCore();

    try {
      Vector<ContentSharingSession> list =
          Core.getInstance().getRichcallService().getCShSessions(contact);
      ArrayList<IBinder> result = new ArrayList<IBinder>(list.size());
      for (int i = 0; i < list.size(); i++) {
        ContentSharingSession session = list.elementAt(i);
        IImageSharingSession sessionApi = imageSharingSessions.get(session.getSessionID());
        if (sessionApi != null) {
          result.add(sessionApi.asBinder());
        }
      }
      return result;
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Unexpected error", e);
      }
      throw new ServerApiException(e.getMessage());
    }
  }
Exemple #15
0
  /**
   * Receive a new geoloc sharing invitation
   *
   * @param session Geoloc sharing session
   */
  public void receiveGeolocSharingInvitation(GeolocTransferSession session) {
    if (logger.isActivated()) {
      logger.info("Receive geoloc sharing invitation from " + session.getRemoteContact());
    }

    // Extract number from contact
    String number = PhoneUtils.extractNumberFromUri(session.getRemoteContact());

    // Add session in the list
    GeolocSharingImpl sessionApi = new GeolocSharingImpl(session);
    GeolocSharingServiceImpl.addGeolocSharingSession(sessionApi);

    // Broadcast intent related to the received invitation
    Intent intent = new Intent(GeolocSharingIntent.ACTION_NEW_INVITATION);
    intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
    intent.putExtra(GeolocSharingIntent.EXTRA_CONTACT, number);
    intent.putExtra(GeolocSharingIntent.EXTRA_DISPLAY_NAME, session.getRemoteDisplayName());
    intent.putExtra(GeolocSharingIntent.EXTRA_SHARING_ID, session.getSessionID());
    AndroidFactory.getApplicationContext().sendBroadcast(intent);

    // Notify geoloc sharing invitation listeners
    synchronized (lock) {
      final int N = listeners.beginBroadcast();
      for (int i = 0; i < N; i++) {
        try {
          listeners.getBroadcastItem(i).onNewGeolocSharing(session.getSessionID());
        } catch (Exception e) {
          if (logger.isActivated()) {
            logger.error("Can't notify listener", e);
          }
        }
      }
      listeners.finishBroadcast();
    }
  }
  /**
   * Initiate a pre-recorded video sharing session
   *
   * @param contact Remote contact
   * @param content Video content to share
   * @param player Media player
   * @return CSh session
   * @throws CoreException
   */
  public VideoStreamingSession initiatePreRecordedVideoSharingSession(
      String contact, VideoContent content, IMediaPlayer player) throws CoreException {
    if (logger.isActivated()) {
      logger.info(
          "Initiate a pre-recorded video sharing session with contact "
              + contact
              + ", file "
              + content.toString());
    }

    // Test if call is established
    if (!getImsModule().getCallManager().isCallConnected()) {
      if (logger.isActivated()) {
        logger.debug("Rich call not established: cancel the initiation");
      }
      throw new CoreException("Call not established");
    }

    // Reject if there are already 2 bidirectional sessions with a given contact
    boolean rejectInvitation = false;
    Vector<ContentSharingSession> currentSessions = getCShSessions();
    if (currentSessions.size() >= 2) {
      // Already a bidirectional session
      if (logger.isActivated()) {
        logger.debug("Max sessions reached");
      }
      rejectInvitation = true;
    } else if (currentSessions.size() == 1) {
      ContentSharingSession currentSession = currentSessions.elementAt(0);
      if (!(currentSession instanceof TerminatingVideoStreamingSession)) {
        // Originating session already used
        if (logger.isActivated()) {
          logger.debug("Max originating sessions reached");
        }
        rejectInvitation = true;
      } else if (!PhoneUtils.compareNumbers(contact, currentSession.getRemoteContact())) {
        // Not the same contact
        if (logger.isActivated()) {
          logger.debug("Only bidirectional session with same contact authorized");
        }
        rejectInvitation = true;
      }
    }
    if (rejectInvitation) {
      if (logger.isActivated()) {
        logger.debug("The max number of sharing sessions is achieved: cancel the initiation");
      }
      throw new CoreException("Max content sharing sessions achieved");
    }

    // Create a new session
    OriginatingPreRecordedVideoStreamingSession session =
        new OriginatingPreRecordedVideoStreamingSession(
            this, player, content, PhoneUtils.formatNumberToSipUri(contact));

    // Start the session
    session.startSession();
    return session;
  }
  /** Close API */
  public void close() {
    // Clear list of sessions
    videoSharingSessions.clear();

    if (logger.isActivated()) {
      logger.info("Video sharing service API is closed");
    }
  }
  /**
   * Registers an video sharing invitation listener
   *
   * @param listener New video sharing listener
   * @throws ServerApiException
   */
  public void addNewVideoSharingListener(INewVideoSharingListener listener)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Add an video sharing invitation listener");
    }

    listeners.register(listener);
  }
Exemple #19
0
  /** Close API */
  public void close() {
    // Clear list of sessions
    gshSessions.clear();

    if (logger.isActivated()) {
      logger.info("Geoloc sharing service API is closed");
    }
  }
Exemple #20
0
  /**
   * Unregisters a geoloc sharing invitation listener
   *
   * @param listener New geoloc sharing listener
   * @throws ServerApiException
   */
  public void removeNewGeolocSharingListener(INewGeolocSharingListener listener)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Remove a geoloc sharing invitation listener");
    }

    listeners.unregister(listener);
  }
  /** Close API */
  public void close() {
    // Clear list of sessions
    sipSessions.clear();

    if (logger.isActivated()) {
      logger.info("Multimedia session service API is closed");
    }
  }
Exemple #22
0
  /**
   * Unregisters a listener on service registration events
   *
   * @param listener Service registration listener
   */
  public void removeServiceRegistrationListener(IJoynServiceRegistrationListener listener) {
    synchronized (lock) {
      if (logger.isActivated()) {
        logger.info("Remove a service listener");
      }

      serviceListeners.unregister(listener);
    }
  }
Exemple #23
0
  /**
   * Registers a listener on service registration events
   *
   * @param listener Service registration listener
   */
  public void addServiceRegistrationListener(IJoynServiceRegistrationListener listener) {
    synchronized (lock) {
      if (logger.isActivated()) {
        logger.info("Add a service listener");
      }

      serviceListeners.register(listener);
    }
  }
  /**
   * Receive an image sharing invitation
   *
   * @param invite Initial invite
   */
  public void receiveImageSharingInvitation(SipRequest invite) {
    if (logger.isActivated()) {
      logger.info("Receive an image sharing session invitation");
    }

    // Test if call is established
    if (!getImsModule().getCallManager().isCallConnected()) {
      if (logger.isActivated()) {
        logger.debug("Rich call not established: reject the invitation");
      }
      sendErrorResponse(invite, 606);
      return;
    }

    // Reject if there are already 2 bidirectional sessions with a given contact
    boolean rejectInvitation = false;
    String contact = SipUtils.getAssertedIdentity(invite);
    Vector<ContentSharingSession> currentSessions = getCShSessions();
    if (currentSessions.size() >= 2) {
      // Already a bidirectional session
      if (logger.isActivated()) {
        logger.debug("Max sessions reached");
      }
      rejectInvitation = true;
    } else if (currentSessions.size() == 1) {
      ContentSharingSession currentSession = currentSessions.elementAt(0);
      if (currentSession instanceof TerminatingImageTransferSession) {
        // Terminating session already used
        if (logger.isActivated()) {
          logger.debug("Max terminating sessions reached");
        }
        rejectInvitation = true;
      } else if (!PhoneUtils.compareNumbers(contact, currentSession.getRemoteContact())) {
        // Not the same contact
        if (logger.isActivated()) {
          logger.debug("Only bidirectional session with same contact authorized");
        }
        rejectInvitation = true;
      }
    }
    if (rejectInvitation) {
      if (logger.isActivated()) {
        logger.debug("The max number of sharing sessions is achieved: reject the invitation");
      }
      sendErrorResponse(invite, 486);
      return;
    }

    // Create a new session
    ImageTransferSession session = new TerminatingImageTransferSession(this, invite);

    // Start the session
    session.startSession();

    // Notify listener
    getImsModule().getCore().getListener().handleContentSharingTransferInvitation(session);
  }
  /**
   * Handle 407 Proxy Authentication Required
   *
   * @param resp 407 response
   */
  public void handle407Authentication(SipResponse resp) {
    try {
      if (logger.isActivated()) {
        logger.info("407 response received");
      }

      // Set the remote tag
      getDialogPath().setRemoteTag(resp.getToTag());

      // Update the authentication agent
      getAuthenticationAgent().readProxyAuthenticateHeader(resp);

      // Increment the Cseq number of the dialog path
      getDialogPath().incrementCseq();

      // Create a second INVITE request with the right token
      if (logger.isActivated()) {
        logger.info("Send second INVITE");
      }
      SipRequest invite =
          SipMessageFactory.createInvite(
              getDialogPath(),
              InstantMessagingService.FT_FEATURE_TAGS,
              getDialogPath().getLocalContent());

      // Reset initial request in the dialog path
      getDialogPath().setInvite(invite);

      // Set the Proxy-Authorization header
      getAuthenticationAgent().setProxyAuthorizationHeader(invite);

      // Send INVITE request
      sendInvite(invite);

    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Session initiation has failed", e);
      }

      // Unexpected error
      handleError(new FileSharingError(FileSharingError.UNEXPECTED_EXCEPTION, e.getMessage()));
    }
  }
Exemple #26
0
 /**
  * Is session interrupted
  *
  * @return Boolean
  */
 public boolean isSessionInterrupted() {
   if (sessionInterrupted) {
     if (logger.isActivated()) {
       logger.info("ABC isSessionInterrupted1");
     }
   }
   if (isInterrupted()) {
     if (logger.isActivated()) {
       logger.info("ABC isSessionInterrupted2");
     }
   }
   if (getDialogPath() != null && getDialogPath().isSessionTerminated()) {
     if (logger.isActivated()) {
       logger.info("ABC isSessionInterrupted3");
     }
   }
   return sessionInterrupted
       || isInterrupted()
       || (getDialogPath() != null && getDialogPath().isSessionTerminated());
 }
Exemple #27
0
  /**
   * Shares a geolocation with a contact. An exception if thrown if there is no ongoing CS call. The
   * parameter contact supports the following formats: MSISDN in national or international format,
   * SIP address, SIP-URI or Tel-URI. If the format of the contact is not supported an exception is
   * thrown.
   *
   * @param contact Contact
   * @param geoloc Geolocation info
   * @param listener Geoloc sharing event listener
   * @return Geoloc sharing
   * @throws ServerApiException
   */
  public IGeolocSharing shareGeoloc(String contact, Geoloc geoloc, IGeolocSharingListener listener)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Initiate a geoloc sharing session with " + contact);
    }

    // Test IMS connection
    ServerApiUtils.testIms();

    try {
      // Create a geoloc content
      String msgId = ChatUtils.generateMessageId();
      GeolocPush geolocPush =
          new GeolocPush(
              geoloc.getLabel(),
              geoloc.getLatitude(),
              geoloc.getLongitude(),
              geoloc.getExpiration(),
              geoloc.getAccuracy());
      String geolocDoc =
          ChatUtils.buildGeolocDocument(
              geolocPush, ImsModule.IMS_USER_PROFILE.getPublicUri(), msgId);
      MmContent content =
          new GeolocContent("geoloc.xml", geolocDoc.getBytes().length, geolocDoc.getBytes());

      // Initiate a sharing session
      final GeolocTransferSession session =
          Core.getInstance()
              .getRichcallService()
              .initiateGeolocSharingSession(contact, content, geolocPush);

      // Add session listener
      GeolocSharingImpl sessionApi = new GeolocSharingImpl(session);
      sessionApi.addEventListener(listener);

      // Start the session
      Thread t =
          new Thread() {
            public void run() {
              session.startSession();
            }
          };
      t.start();

      // Add session in the list
      addGeolocSharingSession(sessionApi);
      return sessionApi;
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Unexpected error", e);
      }
      throw new ServerApiException(e.getMessage());
    }
  }
  /**
   * Shares a live video with a contact. The parameter renderer contains the video player provided
   * by the application. An exception if thrown if there is no ongoing CS call. The parameter
   * contact supports the following formats: MSISDN in national or international format, SIP
   * address, SIP-URI or Tel-URI. If the format of the contact is not supported an exception is
   * thrown.
   *
   * @param contact Contact
   * @param player Video player
   * @param listener Video sharing event listener
   * @return Video sharing
   * @throws ServerApiException
   */
  public IVideoSharing shareVideo(
      String contact, IVideoPlayer player, IVideoSharingListener listener)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Initiate a live video session with " + contact);
    }

    // Test IMS connection
    ServerApiUtils.testIms();

    // Test if at least the audio media is configured
    if (player == null) {
      throw new ServerApiException("Missing video player");
    }

    try {
      // Initiate a new session
      final VideoStreamingSession session =
          Core.getInstance().getRichcallService().initiateLiveVideoSharingSession(contact, player);

      // Update rich call history
      RichCallHistory.getInstance()
          .addVideoSharing(
              contact,
              session.getSessionID(),
              VideoSharing.Direction.OUTGOING,
              session.getContent(),
              VideoSharing.State.INITIATED);

      // Add session listener
      VideoSharingImpl sessionApi = new VideoSharingImpl(session);
      sessionApi.addEventListener(listener);

      // Start the session
      Thread t =
          new Thread() {
            public void run() {
              session.startSession();
            }
          };
      t.start();

      // Add session in the list
      addVideoSharingSession(sessionApi);
      return sessionApi;
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Unexpected error", e);
      }
      throw new ServerApiException(e.getMessage());
    }
  }
  /**
   * Set call hold
   *
   * @param state State
   * @throws ServerApiException
   */
  public void setCallHold(boolean state) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Set call hold to " + state);
    }

    // Check permission
    ServerApiUtils.testPermission();

    // Test core availability
    ServerApiUtils.testCore();

    // Update call manager
    Core.getInstance().getImsModule().getCallManager().setCallHold(state);
  }
  /**
   * Get current geoloc sharing session from its session ID
   *
   * @param id Session ID
   * @return Session
   * @throws ServerApiException
   */
  public IGeolocSharingSession getGeolocSharingSession(String id) throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Get geoloc sharing session " + id);
    }

    // Check permission
    ServerApiUtils.testPermission();

    // Test core availability
    ServerApiUtils.testCore();

    // Return a session instance
    return geolocSharingSessions.get(id);
  }