private void handleMessage(
      MasterSecret masterSecret, TextSecureEnvelope envelope, Optional<Long> smsMessageId) {
    try {
      AxolotlStore axolotlStore = new TextSecureAxolotlStore(context, masterSecret);
      TextSecureAddress localAddress =
          new TextSecureAddress(TextSecurePreferences.getLocalNumber(context));
      TextSecureSMPCipher cipher = new TextSecureSMPCipher(localAddress, axolotlStore);

      TextSecureSMPMessage message = cipher.decrypt(envelope);

      Log.d(TAG, "handleMessage() isSMPMessage: " + message.isSMPMessage());

      if (message.isEndSession())
        handleEndSessionMessage(masterSecret, envelope, message, smsMessageId);
      else if (message.isGroupUpdate())
        handleGroupMessage(masterSecret, envelope, message, smsMessageId);
      else if (message.getAttachments().isPresent())
        handleMediaMessage(masterSecret, envelope, message, smsMessageId);

      // TODO: handleSMPMessage
      else if (message.isSMPMessage()) handleSMPMessage(masterSecret, envelope, message);
      else handleTextMessage(masterSecret, envelope, message, smsMessageId);

      if (envelope.isPreKeyWhisperMessage()) {
        ApplicationContext.getInstance(context).getJobManager().add(new RefreshPreKeysJob(context));
      }
    } catch (InvalidVersionException e) {
      Log.w(TAG, e);
      handleInvalidVersionMessage(masterSecret, envelope, smsMessageId);
    } catch (InvalidMessageException
        | InvalidKeyIdException
        | InvalidKeyException
        | MmsException e) {
      Log.w(TAG, e);
      handleCorruptMessage(masterSecret, envelope, smsMessageId);
    } catch (NoSessionException e) {
      Log.w(TAG, e);
      handleNoSessionMessage(masterSecret, envelope, smsMessageId);
    } catch (LegacyMessageException e) {
      Log.w(TAG, e);
      handleLegacyMessage(masterSecret, envelope, smsMessageId);
    } catch (DuplicateMessageException e) {
      Log.w(TAG, e);
      handleDuplicateMessage(masterSecret, envelope, smsMessageId);
    } catch (UntrustedIdentityException e) {
      Log.w(TAG, e);
      handleUntrustedIdentityMessage(masterSecret, envelope, smsMessageId);
    }
  }
  private void handleMediaMessage(
      MasterSecret masterSecret,
      TextSecureEnvelope envelope,
      TextSecureMessage message,
      Optional<Long> smsMessageId)
      throws MmsException {
    Pair<Long, Long> messageAndThreadId;

    if (message.getSyncContext().isPresent()) {
      messageAndThreadId = insertSyncMediaMessage(masterSecret, envelope, message);
    } else {
      messageAndThreadId = insertStandardMediaMessage(masterSecret, envelope, message);
    }

    ApplicationContext.getInstance(context)
        .getJobManager()
        .add(new AttachmentDownloadJob(context, messageAndThreadId.first));

    if (smsMessageId.isPresent()) {
      DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
    }

    MessageNotifier.updateNotification(context, masterSecret, messageAndThreadId.second);
  }