/**
   * Send a text message
   *
   * @param msgId Message-ID
   * @param txt Text message
   */
  public void sendTextMessage(String msgId, String txt) {
    // Send message in CPIM
    String from = ImsModule.IMS_USER_PROFILE.getPublicUri();
    String to = getRemoteContact();
    String content =
        ChatUtils.buildCpimMessage(from, to, StringUtils.encodeUTF8(txt), InstantMessage.MIME_TYPE);

    // Send data
    boolean result = sendDataChunks(msgId, content, CpimMessage.MIME_TYPE);

    // Update rich messaging history
    InstantMessage msg = new InstantMessage(msgId, getRemoteContact(), txt, false, new Date());
    RichMessaging.getInstance().addOutgoingChatMessage(msg, this);

    // Check if message has been sent with success or not
    if (!result) {
      // Update rich messaging history
      RichMessaging.getInstance().markChatMessageFailed(msgId);

      // Notify listeners
      for (int i = 0; i < getListeners().size(); i++) {
        /** M: add server date for delivery status @{ */
        ((ChatSessionListener) getListeners().get(i))
            .handleMessageDeliveryStatus(msgId, ImdnDocument.DELIVERY_STATUS_FAILED, -1L);
        /** @} */
      }
    }
  }
  /**
   * Handle 404 Session Not Found
   *
   * @param resp 404 response
   */
  public void handle404SessionNotFound(SipResponse resp) {
    // Rejoin session has failed, we update the database with status terminated by remote
    RichMessaging.getInstance().addChatSessionTerminationByRemote(this);

    // Notify listener
    handleError(new ChatError(ChatError.SESSION_NOT_FOUND, resp.getReasonPhrase()));
  }
  /**
   * Initiate a geoloc sharing session
   *
   * @param contact Contact
   * @param geoloc Geoloc info
   * @return Geoloc sharing session
   * @throws ServerApiException
   */
  public IGeolocSharingSession initiateGeolocSharing(String contact, GeolocPush geoloc)
      throws ServerApiException {
    if (logger.isActivated()) {
      logger.info("Initiate a geoloc sharing session with " + contact);
    }

    // Check permission
    ServerApiUtils.testPermission();

    // Test IMS connection
    ServerApiUtils.testIms();

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

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

      // Update rich call
      RichCall.getInstance()
          .addCall(
              contact,
              session.getSessionID(),
              RichCallData.EVENT_OUTGOING,
              session.getContent(),
              RichCallData.STATUS_STARTED);

      // Update rich messaging history
      GeolocMessage geolocMsg = new GeolocMessage(null, contact, geoloc, false);
      RichMessaging.getInstance().addOutgoingGeoloc(geolocMsg);

      // Add session in the list
      GeolocSharingSession sessionApi = new GeolocSharingSession(session);
      addGeolocSharingSession(sessionApi);
      return sessionApi;
    } catch (Exception e) {
      if (logger.isActivated()) {
        logger.error("Unexpected error", e);
      }
      throw new ServerApiException(e.getMessage());
    }
  }
  /** Send the file transfer information */
  private void sendFileTransferInfo() {
    // Send File transfer Info
    String mime = CpimMessage.MIME_TYPE;
    String from = ImsModule.IMS_USER_PROFILE.getPublicUri();
    String to = ChatUtils.ANOMYNOUS_URI;
    String msgId = IdGenerator.getIdentifier();

    // Send file info in CPIM message
    String content =
        ChatUtils.buildCpimMessageWithImdn(
            from, to, msgId, fileInfo, FileTransferHttpInfoDocument.MIME_TYPE);

    // Send content
    chatSession.sendDataChunks(ChatUtils.generateMessageId(), content, mime);
    RichMessaging.getInstance()
        .updateFileTransferChatId(getSessionID(), chatSession.getContributionID(), msgId);
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Set layout
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    setContentView(R.layout.messaging_chat_list);

    // Set UI title
    setTitle(getString(R.string.menu_chat_list));

    // Instantiate messaging API
    RichMessaging.createInstance(getApplicationContext());
    messagingApi = new MessagingApi(getApplicationContext());
    messagingApi.addApiEventListener(this);
    messagingApi.connectApi();

    // Set list adapter
    ListView view = (ListView) findViewById(android.R.id.list);
    TextView emptyView = (TextView) findViewById(android.R.id.empty);
    view.setEmptyView(emptyView);
    view.setAdapter(createChatListAdapter());
  }
        public void onClick(View v) {
          if (!isServiceAvailable()) {
            Utils.showMessage(ChatList.this, getString(R.string.label_continue_chat_failed));
            return;
          }

          // Get selected item
          ChatListItemCache cache = (ChatListItemCache) v.getTag();
          if (cache.isGroupChat()) {
            // Group chat
            IChatSession session = isGroupChatActive(cache.chatId);
            if (session != null) {
              // Session already active on the device: just reload it in the UI
              try {
                Intent intent = new Intent(ChatList.this, GroupChatView.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.putExtra("subject", session.getSubject());
                intent.putExtra("sessionId", session.getSessionID());
                startActivity(intent);
              } catch (Exception e) {
                Utils.showMessage(ChatList.this, getString(R.string.label_api_failed));
              }
            } else {
              // Test if the session may be rejoined or not
              int status = RichMessaging.getInstance().getGroupChatStatus(cache.chatId);
              if (status == EventsLogApi.STATUS_TERMINATED_BY_USER) {
                // The session was terminated by user itself: rejoin or restart are not authorized
                Utils.showMessage(ChatList.this, getString(R.string.label_rejoin_unauthorized));
              } else if (status == EventsLogApi.STATUS_TERMINATED_BY_REMOTE) {
                // The session was terminated: only a restart may be done
                restartChat = new RestartChat(ChatList.this, messagingApi, cache.chatId);
                restartChat.start();
              } else {
                // Session terminated on the device: try to rejoin the session
                rejoinChat = new RejoinChat(ChatList.this, messagingApi, cache.chatId);
                rejoinChat.start();
              }
            }
          } else {
            // 1-1 chat
            IChatSession session = isChatSessionActive(cache.sessionId);
            if (session != null) {
              // Session already active on the device: just reload it in the UI
              try {
                Intent intent = new Intent(ChatList.this, OneToOneChatView.class);
                intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                intent.putExtra("contact", session.getRemoteContact());
                intent.putExtra("sessionId", session.getSessionID());
                startActivity(intent);
              } catch (Exception e) {
                Utils.showMessage(ChatList.this, getString(R.string.label_api_failed));
              }
            } else {
              // Session terminated on the device: create a new one on the first message
              Intent intent = new Intent(ChatList.this, OneToOneChatView.class);
              intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
              intent.putExtra("contact", cache.contact);
              startActivity(intent);
            }
          }
        }
  /** Start core */
  public synchronized void startCore() {
    if (Core.getInstance() != null) {
      // Already started
      return;
    }

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

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

      // Terminal version
      if (logger.isActivated()) {
        logger.info("RCS stack release is " + TerminalInfo.getProductVersion());
      }

      // Instantiate the contacts manager
      ContactsManager.createInstance(getApplicationContext());

      // Instantiate the rich messaging history
      RichMessaging.createInstance(getApplicationContext());

      // Instantiate the rich call history
      RichCall.createInstance(getApplicationContext());

      // Instantiate the IP call history
      IPCall.createInstance(getApplicationContext());

      // Create the core
      Core.createCore(this);

      // Start the core
      Core.getInstance().startCore();

      // Create multimedia directory on sdcard
      FileFactory.createDirectory(RcsSettings.getInstance().getPhotoRootDirectory());
      FileFactory.createDirectory(RcsSettings.getInstance().getVideoRootDirectory());
      FileFactory.createDirectory(RcsSettings.getInstance().getFileRootDirectory());

      // Init CPU manager
      cpuManager.init();

      // Register account changed event receiver
      if (accountChangedReceiver == null) {
        accountChangedReceiver = new AccountChangedReceiver();

        // Register account changed broadcast receiver after a timeout of 2s (This is not done
        // immediately, as we do not want to catch
        // the removal of the account (creating and removing accounts is done asynchronously). We
        // can reasonably assume that no
        // RCS account deletion will be done by user during this amount of time, as he just started
        // his service.
        Handler handler = new Handler();
        handler.postDelayed(
            new Runnable() {
              public void run() {
                registerReceiver(
                    accountChangedReceiver,
                    new IntentFilter("android.accounts.LOGIN_ACCOUNTS_CHANGED"));
              }
            },
            2000);
      }

      // Register SMS receiver for network initiated configuration

      if (reconfSMSReceiver == null) {
        reconfSMSReceiver = new HttpsProvisioningSMS(this);
        reconfSMSReceiver.registerSmsProvisioningReceiver(
            Integer.toString(HttpsProvisioningUtils.DEFAULT_SMS_PORT), null, null, null);
      }

      // Show a first notification
      addRcsServiceNotification(false, getString(R.string.rcs_core_loaded));

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

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

      if (logger.isActivated()) {
        logger.info("RCS core service started with success");
      }
    } catch (Exception e) {
      // Unexpected error
      if (logger.isActivated()) {
        logger.error("Can't instanciate the RCS core service", e);
      }

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

      // Show error in notification bar
      addRcsServiceNotification(false, getString(R.string.rcs_core_failed));

      // Exit service
      stopSelf();
    }
  }