public static void updateSendFailedNotification(Context context) {
   if (getUndeliveredMessageCount(context, null) < 1) {
     cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID);
   } else {
     notifySendFailed(context); // rebuild and adjust the message count if necessary.
   }
 }
  /**
   * Checks to see if there are any "unseen" messages or delivery reports. Shows the most recent
   * notification if there is one.
   *
   * @param context the context to use
   * @param isNew if notify a new message comes, it should be true, otherwise, false.
   */
  public static void blockingUpdateNewMessageIndicator(
      Context context, boolean isNew, boolean isStatusMessage) {
    SortedSet<MmsSmsNotificationInfo> accumulator =
        new TreeSet<MmsSmsNotificationInfo>(INFO_COMPARATOR);
    MmsSmsDeliveryInfo delivery = null;
    Set<Long> threads = new HashSet<Long>(4);

    int count = 0;
    count +=
        accumulateNotificationInfo(accumulator, getMmsNewMessageNotificationInfo(context, threads));
    count +=
        accumulateNotificationInfo(accumulator, getSmsNewMessageNotificationInfo(context, threads));

    cancelNotification(context, NOTIFICATION_ID);
    if (!accumulator.isEmpty()) {
      if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
        Log.d(TAG, "blockingUpdateNewMessageIndicator: count=" + count + ", isNew=" + isNew);
      }
      accumulator.first().deliver(context, isNew, count, threads.size());
    }

    // And deals with delivery reports (which use Toasts). It's safe to call in a worker
    // thread because the toast will eventually get posted to a handler.
    delivery = getSmsNewDeliveryInfo(context);
    if (delivery != null) {
      delivery.deliver(context, isStatusMessage);
    }
  }
 /** If all the undelivered messages belong to "threadId", cancel the notification. */
 public static void updateSendFailedNotificationForThread(Context context, long threadId) {
   long[] msgThreadId = {0, 0};
   if (getUndeliveredMessageCount(context, msgThreadId) > 0
       && msgThreadId[0] == threadId
       && msgThreadId[1] != 0) {
     cancelNotification(context, MESSAGE_FAILED_NOTIFICATION_ID);
   }
 }
 public static void updateDownloadFailedNotification(Context context) {
   if (getDownloadFailedMessageCount(context) < 1) {
     cancelNotification(context, DOWNLOAD_FAILED_NOTIFICATION_ID);
   }
 }
  @Override
  public void onReceive(Context context, Intent intent) {
    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
      Log.v(TAG, "Intent received: " + intent);
    }
    Xlog.d(MmsApp.LOG_TAG, "onReceive(): intent=" + intent.toString());
    String action = intent.getAction();
    if (action.equals(Mms.Intents.CONTENT_CHANGED_ACTION)) {
      final Intent mIntent = intent;
      new Thread(
              new Runnable() {
                @Override
                public void run() {
                  Uri changed = (Uri) mIntent.getParcelableExtra(Mms.Intents.DELETED_CONTENTS);
                  PduCache.getInstance().purge(changed);
                  Xlog.d(MmsApp.TXN_TAG, "Mms.Intents.CONTENT_CHANGED_ACTION: " + changed);
                }
              })
          .start();
    } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
      String state = intent.getStringExtra(Phone.STATE_KEY);

      if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
        Log.v(TAG, "ANY_DATA_STATE event received: " + state);
      }

      String apnType = intent.getStringExtra(Phone.DATA_APN_TYPE_KEY);

      // if (state.equals("CONNECTED")) {
      if (Phone.APN_TYPE_MMS.equals(apnType)) {
        Xlog.d(
            MmsApp.TXN_TAG,
            "TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED, type is mms.");
        // if the network is not available for mms, keep listening
        ConnectivityManager ConnMgr =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = ConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
        if (ni != null && !ni.isAvailable()) {
          Xlog.d(MmsApp.TXN_TAG, "network is not available for mms, keep listening.");
          return;
        }

        unRegisterForConnectionStateChanges(context);
        // add for gemini
        if (FeatureOption.MTK_GEMINI_SUPPORT == true) {
          // conver slot id to sim id
          SIMInfo si =
              SIMInfo.getSIMInfoBySlot(
                  context, intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, Phone.GEMINI_SIM_1));
          if (null == si) {
            Xlog.e(
                MmsApp.TXN_TAG,
                "System event receiver: SIMInfo is null for slot "
                    + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1));
            return;
          }
          int simId = (int) si.mSimId;
          wakeUpServiceGemini(
              context, simId /*intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY,Phone.GEMINI_SIM_1)*/);
        } else {
          wakeUpService(context);
        }
      }
    } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
      Xlog.d(MmsApp.TXN_TAG, "Intent.ACTION_BOOT_COMPLETED");
      final Context contxt = context;
      new Thread(
              new Runnable() {
                public void run() {
                  setPendingMmsFailed(contxt);
                  setPendingSmsFailed(contxt);
                  setNotificationIndUnstarted(contxt);
                }
              })
          .start();
      // We should check whether there are unread incoming
      // messages in the Inbox and then update the notification icon.
      // Called on the UI thread so don't block.
      MessagingNotification.nonBlockingUpdateNewMessageIndicator(context, false, false);
    } else if (action.equals(Intent.SIM_SETTINGS_INFO_CHANGED)) {
      int simId = (int) intent.getLongExtra("simid", -1);
      MessageUtils.simInfoMap.remove(simId);
      MessageUtils.getSimInfo(context, simId);
    } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
      saveDraft = (OnShutDownListener) ComposeMessageActivity.getComposeContext();
      if (saveDraft != null) {
        saveDraft.onShutDown();
      }
    } else if (action.equals(Intent.ACTION_SMS_DEFAULT_SIM_CHANGED)) {
      Xlog.d(MmsApp.LOG_TAG, "SMS default SIM changed.");
      mSimInforChangedListener =
          (OnSimInforChangedListener) ComposeMessageActivity.getComposeContext();
      if (mSimInforChangedListener != null) {
        mSimInforChangedListener.OnSimInforChanged();
      }
      mSimInforChangedListener = (OnSimInforChangedListener) ConversationList.getContext();
      if (mSimInforChangedListener != null) {
        mSimInforChangedListener.OnSimInforChanged();
      }
    } else if (action.equals(Intent.ACTION_DEVICE_STORAGE_FULL)) {
      MmsConfig.setDeviceStorageFullStatus(true);
    } else if (action.equals(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)) {
      MmsConfig.setDeviceStorageFullStatus(false);
      MessagingNotification.cancelNotification(
          context, SmsRejectedReceiver.SMS_REJECTED_NOTIFICATION_ID);
    }
  }
  @Override
  public void onReceive(Context context, Intent intent) {
    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
      Log.v(TAG, "Intent received: " + intent);
    }
    /// M:
    MmsLog.d(MmsApp.LOG_TAG, "onReceive(): intent=" + intent.toString());
    String action = intent.getAction();
    if (action.equals(Mms.Intents.CONTENT_CHANGED_ACTION)) {
      /// M:Code analyze 003, put in a new thread @{
      final Intent mIntent = intent;
      new Thread(
              new Runnable() {
                @Override
                public void run() {
                  Uri changed = (Uri) mIntent.getParcelableExtra(Mms.Intents.DELETED_CONTENTS);
                  if (changed != null) {
                    MmsApp.getApplication().getPduLoaderManager().removePdu(changed);
                  }
                  MmsLog.d(MmsApp.TXN_TAG, "Mms.Intents.CONTENT_CHANGED_ACTION: " + changed);
                }
              })
          .start();
      /// @}
    } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
      String state = intent.getStringExtra(EncapsulatedPhone.STATE_KEY);

      if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
        Log.v(TAG, "ANY_DATA_STATE event received: " + state);
      }
      /// M:Code analyze 004, modify the logic,if data connection change,unRegister the listener of
      /// connection changed and wake up transaction service,and add gemini logic @{
      String apnType = intent.getStringExtra(EncapsulatedPhone.DATA_APN_TYPE_KEY);

      // if (state.equals("CONNECTED")) {
      if (EncapsulatedPhone.APN_TYPE_MMS.equals(apnType)) {
        MmsLog.d(
            MmsApp.TXN_TAG,
            "TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED, type is mms.");
        // if the network is not available for mms, keep listening
        ConnectivityManager connMgr =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo ni = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS);
        if (ni != null && !ni.isAvailable()) {
          MmsLog.d(MmsApp.TXN_TAG, "network is not available for mms, keep listening.");
          return;
        }

        unRegisterForConnectionStateChanges(context);
        // add for gemini
        if (EncapsulatedFeatureOption.MTK_GEMINI_SUPPORT) {
          // conver slot id to sim id
          SIMInfo si =
              SIMInfo.getSIMInfoBySlot(
                  context,
                  intent.getIntExtra(
                      EncapsulatedPhone.GEMINI_SIM_ID_KEY, EncapsulatedPhone.GEMINI_SIM_1));
          if (null == si) {
            MmsLog.e(
                MmsApp.TXN_TAG,
                "System event receiver: SIMInfo is null for slot "
                    + intent.getIntExtra(EncapsulatedPhone.GEMINI_SIM_ID_KEY, -1));
            return;
          }
          int simId = (int) si.getSimId();
          wakeUpServiceGemini(
              context, simId /*intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY,Phone.GEMINI_SIM_1)*/);
        } else {
          wakeUpService(context);
        }
      }
      /// @}
    } else if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
      /// M:Code analyze 005, mark pending msg failed after boot complete @{
      MmsLog.d(MmsApp.TXN_TAG, "Intent.ACTION_BOOT_COMPLETED");
      final Context contxt = context;
      new Thread(
              new Runnable() {
                public void run() {
                  IpMessageUtils.getIpMessagePlugin(contxt)
                      .getServiceManager(contxt.getApplicationContext())
                      .startIpService();
                  setPendingMmsFailed(contxt);
                  setNotificationIndUnstarted(contxt);
                }
              })
          .start();
      /// @}
      // We should check whether there are unread incoming
      // messages in the Inbox and then update the notification icon.
      // Called on the UI thread so don't block.
      MessagingNotification.nonBlockingUpdateNewMessageIndicator(
          context, MessagingNotification.THREAD_NONE, false);
      /// M: when power off,save the chat setting. {@
      SharedPreferences sp =
          PreferenceManager.getDefaultSharedPreferences(contxt.getApplicationContext());
      final long unSavedthreadId = sp.getLong(ChatPreferenceActivity.CHAT_THREAD_ID, -1l);
      Log.v(TAG, "unSaved chatThreadSetting: " + unSavedthreadId);
      if (unSavedthreadId > 0) {
        final boolean mNotificationEnable =
            sp.getBoolean(ChatPreferenceActivity.ENABLE_NOTIFICATION, false);
        final String mMute = sp.getString(ChatPreferenceActivity.CHAT_MUTE, "0");
        final String mRingtone =
            sp.getString(
                ChatPreferenceActivity.CHAT_RINGTONE, ChatPreferenceActivity.DEFAULT_RINGTONE);
        final boolean mVibrate = sp.getBoolean(ChatPreferenceActivity.CHAT_VIBRATE, false);
        final long mMuteStart = sp.getLong(ChatPreferenceActivity.CHAT_MUTE_START, 0);
        new Thread() {
          public void run() {
            SharedPreferences spChatThreadId =
                PreferenceManager.getDefaultSharedPreferences(contxt.getApplicationContext());
            Uri uri =
                ContentUris.withAppendedId(
                    Uri.parse(ChatPreferenceActivity.CHAT_SETTINGS_URI), unSavedthreadId);
            ContentValues values = new ContentValues();
            values.put(ThreadSettings.NOTIFICATION_ENABLE, mNotificationEnable ? 1 : 0);
            values.put(ThreadSettings.MUTE, Integer.parseInt(mMute));
            values.put(ThreadSettings.MUTE_START, mMuteStart);
            values.put(ThreadSettings.RINGTONE, mRingtone);
            values.put(ThreadSettings.VIBRATE, mVibrate ? 1 : 0);
            contxt.getContentResolver().update(uri, values, null, null);
            SharedPreferences.Editor editor = spChatThreadId.edit();
            editor.putLong(ChatPreferenceActivity.CHAT_THREAD_ID, -1l);
            editor.commit();
            if (MmsConfig.getFolderModeEnabled()) {
              MuteCache.setMuteCache(
                  unSavedthreadId, Long.parseLong(mMute), mMuteStart, mNotificationEnable);
            }
          }
        }.start();
      }
      /// M: @}
      /// M:Code analyze 006,add for listening sim setting info changed @{
    } else if (action.equals(EncapsulatedAction.SIM_SETTINGS_INFO_CHANGED)) {
      int simId = (int) intent.getLongExtra("simid", -1);
      MessageUtils.simInfoMap.remove(simId);
      MessageUtils.getSimInfo(context, simId);
      /// @}
      /// M:Code analyze 001,add for save draft mms when received event of shutdown @{
    } else if (action.equals(Intent.ACTION_SHUTDOWN)) {
      mSaveDraft = (OnShutDownListener) ComposeMessageActivity.getComposeContext();
      if (mSaveDraft != null) {
        mSaveDraft.onShutDown();
      }
      /// @}
      /// M:Code analyze 002,add for listening the changing of sim info @{
    } else if (action.equals(EncapsulatedAction.ACTION_SMS_DEFAULT_SIM_CHANGED)) {
      MmsLog.d(MmsApp.LOG_TAG, "SMS default SIM changed.");
      mSimInforChangedListener =
          (OnSimInforChangedListener) ComposeMessageActivity.getComposeContext();
      if (mSimInforChangedListener != null) {
        mSimInforChangedListener.onSimInforChanged();
      }
      mSimInforChangedListener = (OnSimInforChangedListener) ConversationList.getContext();
      if (mSimInforChangedListener != null) {
        mSimInforChangedListener.onSimInforChanged();
      }
      /// @}
      /// M:Code analyze 007,add for listening device storage full or not @{
    } else if (action.equals(Intent.ACTION_DEVICE_STORAGE_FULL)) {
      MmsConfig.setDeviceStorageFullStatus(true);
    } else if (action.equals(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)) {
      MmsConfig.setDeviceStorageFullStatus(false);
      MessagingNotification.cancelNotification(
          context, SmsRejectedReceiver.SMS_REJECTED_NOTIFICATION_ID);
      /// @}
      /// M: new feature, add default quick_text @{
    } else if (action.equals(Intent.ACTION_LOCALE_CHANGED)) {
      if (MmsConfig.getInitQuickText()) {
        return;
      }
      final Context runContext = context;
      new Thread(
              new Runnable() {
                public void run() {
                  Cursor cursor =
                      runContext
                          .getContentResolver()
                          .query(
                              EncapsulatedTelephony.MmsSms.CONTENT_URI_QUICKTEXT,
                              null,
                              null,
                              null,
                              null);
                  // get delete and add ID in DB, id quick Text array
                  ArrayList<Integer> delAddID = new ArrayList<Integer>();
                  ArrayList<Integer> quickTextID = new ArrayList<Integer>();
                  if (cursor != null) {
                    try {
                      ArrayList<String> preQuickText = MmsConfig.getPreQuickText();
                      while (cursor.moveToNext()) {
                        int id = cursor.getInt(0);
                        String str = cursor.getString(1);
                        for (int i = 0; i < preQuickText.size(); i++) {
                          if (str.equals(preQuickText.get(i))) {
                            delAddID.add(new Integer(id));
                            quickTextID.add(new Integer(i));
                            break;
                          }
                        }
                      }
                    } finally {
                      cursor.close();
                    }
                  }
                  // delete old language default quick text
                  for (Integer i : delAddID) {
                    runContext
                        .getContentResolver()
                        .delete(
                            EncapsulatedTelephony.MmsSms.CONTENT_URI_QUICKTEXT,
                            _ID + "=" + i,
                            null);
                  }

                  // add new language default quick text
                  String[] default_quick_texts =
                      runContext.getResources().getStringArray(R.array.default_quick_texts);
                  for (int i = 0, j = 0; i < delAddID.size() && j < quickTextID.size(); i++, j++) {
                    ContentValues values = new ContentValues();
                    values.put(_ID, delAddID.get(i));
                    values.put("text", default_quick_texts[quickTextID.get(j)]);
                    runContext
                        .getContentResolver()
                        .insert(EncapsulatedTelephony.MmsSms.CONTENT_URI_QUICKTEXT, values);
                  }
                  MmsConfig.setPreQuickText(default_quick_texts);
                }
              })
          .start();
    }
    /// @}
  }