/**
   * Query the DB and return the number of undelivered messages (total for both SMS and MMS)
   *
   * @param context The context
   * @param threadIdResult A container to put the result in, according to the following rules:
   *     threadIdResult[0] contains the thread id of the first message. threadIdResult[1] is nonzero
   *     if the thread ids of all the messages are the same. You can pass in null for
   *     threadIdResult. You can pass in a threadIdResult of size 1 to avoid the comparison of each
   *     thread id.
   */
  private static int getUndeliveredMessageCount(Context context, long[] threadIdResult) {
    Cursor undeliveredCursor =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            UNDELIVERED_URI,
            new String[] {Mms.THREAD_ID},
            "read=0",
            null,
            null);
    if (undeliveredCursor == null) {
      return 0;
    }
    int count = undeliveredCursor.getCount();
    try {
      if (threadIdResult != null && undeliveredCursor.moveToFirst()) {
        threadIdResult[0] = undeliveredCursor.getLong(0);

        if (threadIdResult.length >= 2) {
          // Test to see if all the undelivered messages belong to the same thread.
          long firstId = threadIdResult[0];
          while (undeliveredCursor.moveToNext()) {
            if (undeliveredCursor.getLong(0) != firstId) {
              firstId = 0;
              break;
            }
          }
          threadIdResult[1] = firstId; // non-zero if all ids are the same
        }
      }
    } finally {
      undeliveredCursor.close();
    }
    return count;
  }
Beispiel #2
0
 private static boolean isDuplicateNotification(Context context, NotificationInd nInd) {
   final byte[] rawLocation = nInd.getContentLocation();
   if (rawLocation != null) {
     String location = new String(rawLocation);
     String[] selectionArgs = new String[] {location};
     Cursor cursor = null;
     try {
       cursor =
           SqliteWrapper.query(
               context,
               context.getContentResolver(),
               Telephony.Mms.CONTENT_URI,
               new String[] {Telephony.Mms._ID},
               LOCATION_SELECTION,
               new String[] {
                 Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
                 new String(rawLocation)
               },
               null /*sortOrder*/);
       if (cursor != null && cursor.getCount() > 0) {
         // We already received the same notification before.
         return true;
       }
     } catch (SQLiteException e) {
       Rlog.e(TAG, "failed to query existing notification ind", e);
     } finally {
       if (cursor != null) {
         cursor.close();
       }
     }
   }
   return false;
 }
 private static boolean isDuplicateNotification(Context context, NotificationInd nInd) {
   byte[] rawLocation = nInd.getContentLocation();
   if (rawLocation != null) {
     String location = new String(rawLocation);
     String selection = Mms.CONTENT_LOCATION + " = ?";
     String[] selectionArgs = new String[] {location};
     Cursor cursor =
         SqliteWrapper.query(
             context,
             context.getContentResolver(),
             Mms.CONTENT_URI,
             new String[] {Mms._ID},
             selection,
             selectionArgs,
             null);
     if (cursor != null) {
       try {
         if (cursor.getCount() > 0) {
           cursor.moveToFirst();
           Xlog.d(MmsApp.TXN_TAG, "duplicate, location=" + location + ", id=" + cursor.getLong(0));
           // We already received the same notification before.
           return true;
         }
       } finally {
         cursor.close();
       }
     }
   }
   return false;
 }
  private static final MmsSmsDeliveryInfo getSmsNewDeliveryInfo(Context context) {
    ContentResolver resolver = context.getContentResolver();
    Cursor cursor =
        SqliteWrapper.query(
            context,
            resolver,
            Sms.CONTENT_URI,
            SMS_STATUS_PROJECTION,
            NEW_DELIVERY_SM_CONSTRAINT,
            null,
            Sms.DATE);

    if (cursor == null) return null;

    try {
      if (!cursor.moveToLast()) return null;

      String address = cursor.getString(COLUMN_SMS_ADDRESS);
      long timeMillis = 3000;

      return new MmsSmsDeliveryInfo(
          String.format(context.getString(R.string.delivery_toast_body), address), timeMillis);

    } finally {
      cursor.close();
    }
  }
 private static int getDownloadFailedMessageCount(Context context) {
   // Look for any messages in the MMS Inbox that are of the type
   // NOTIFICATION_IND (i.e. not already downloaded) and in the
   // permanent failure state.  If there are none, cancel any
   // failed download notification.
   Cursor c =
       SqliteWrapper.query(
           context,
           context.getContentResolver(),
           Mms.Inbox.CONTENT_URI,
           null,
           Mms.MESSAGE_TYPE
               + "="
               + String.valueOf(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND)
               + " AND "
               + Mms.STATUS
               + "="
               + String.valueOf(DownloadManager.STATE_PERMANENT_FAILURE),
           null,
           null);
   if (c == null) {
     return 0;
   }
   int count = c.getCount();
   c.close();
   return count;
 }
  private static final MmsSmsNotificationInfo getSmsNewMessageNotificationInfo(
      Context context, Set<Long> threads) {
    ContentResolver resolver = context.getContentResolver();
    Cursor cursor =
        SqliteWrapper.query(
            context,
            resolver,
            Sms.CONTENT_URI,
            SMS_STATUS_PROJECTION,
            NEW_INCOMING_SM_CONSTRAINT,
            null,
            Sms.DATE + " desc");

    if (cursor == null) {
      return null;
    }

    try {
      if (!cursor.moveToFirst()) {
        return null;
      }

      String address = cursor.getString(COLUMN_SMS_ADDRESS);
      String body = cursor.getString(COLUMN_SMS_BODY);
      long threadId = cursor.getLong(COLUMN_THREAD_ID);
      long timeMillis = cursor.getLong(COLUMN_DATE);

      if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
        Log.d(
            TAG,
            "getSmsNewMessageNotificationInfo: count="
                + cursor.getCount()
                + ", first addr="
                + address
                + ", thread_id="
                + threadId);
      }

      MmsSmsNotificationInfo info =
          getNewMessageNotificationInfo(
              address,
              body,
              context,
              R.drawable.stat_notify_sms,
              null,
              threadId,
              timeMillis,
              cursor.getCount());

      threads.add(threadId);
      while (cursor.moveToNext()) {
        threads.add(cursor.getLong(COLUMN_THREAD_ID));
      }

      return info;
    } finally {
      cursor.close();
    }
  }
  /**
   * This method is used if this is a "replace short message" SMS. We find any existing message that
   * matches the incoming message's originating address and protocol identifier. If there is one, we
   * replace its fields with those of the new message. Otherwise, we store the new message as usual.
   *
   * <p>See TS 23.040 9.2.3.9.
   */
  private Uri replaceMessage(Context context, SmsMessage[] msgs, int error) {
    SmsMessage sms = msgs[0];
    ContentValues values = extractContentValues(sms);
    values.put(Sms.ERROR_CODE, error);
    int pduCount = msgs.length;

    if (pduCount == 1) {
      // There is only one part, so grab the body directly.
      values.put(Inbox.BODY, replaceFormFeeds(sms.getDisplayMessageBody()));
    } else {
      // Build up the body from the parts.
      StringBuilder body = new StringBuilder();
      for (int i = 0; i < pduCount; i++) {
        sms = msgs[i];
        if (sms.mWrappedSmsMessage != null) {
          body.append(sms.getDisplayMessageBody());
        }
      }
      values.put(Inbox.BODY, replaceFormFeeds(body.toString()));
    }

    ContentResolver resolver = context.getContentResolver();
    String originatingAddress = sms.getOriginatingAddress();
    int protocolIdentifier = sms.getProtocolIdentifier();
    String selection = Sms.ADDRESS + " = ? AND " + Sms.PROTOCOL + " = ?";
    String[] selectionArgs =
        new String[] {originatingAddress, Integer.toString(protocolIdentifier)};

    Cursor cursor =
        SqliteWrapper.query(
            context,
            resolver,
            Inbox.CONTENT_URI,
            REPLACE_PROJECTION,
            selection,
            selectionArgs,
            null);

    if (cursor != null) {
      try {
        if (cursor.moveToFirst()) {
          long messageId = cursor.getLong(REPLACE_COLUMN_ID);
          Uri messageUri = ContentUris.withAppendedId(Sms.CONTENT_URI, messageId);

          SqliteWrapper.update(context, resolver, messageUri, values, null, null);
          return messageUri;
        }
      } finally {
        cursor.close();
      }
    }
    return storeMessage(context, msgs, error);
  }
  /// M:Code analyze 011,add for setting the mms being downloading when shutdown to unrecognized
  /// after boot complete again,have to manual download @{
  public static void setNotificationIndUnstarted(final Context context) {
    MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted");
    Cursor cursor =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            Mms.CONTENT_URI,
            new String[] {Mms._ID, Mms.STATUS},
            Mms.MESSAGE_TYPE + "=" + PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND,
            null,
            null);
    if (cursor != null) {
      try {
        int count = cursor.getCount();
        MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted: Message Size=" + count);

        if (count == 0) {
          return;
        }

        ContentValues values = null;
        int id = 0;
        int status = 0;
        while (cursor.moveToNext()) {
          id = cursor.getInt(0);
          status = cursor.getInt(1);
          MmsLog.d(
              MmsApp.TXN_TAG, "setNotificationIndUnstarted: MsgId=" + id + "; status=" + status);

          if (DownloadManager.STATE_DOWNLOADING == (status & ~DownloadManager.DEFERRED_MASK)) {
            values = new ContentValues(1);
            values.put(Mms.STATUS, PduHeaders.STATUS_UNRECOGNIZED);
            SqliteWrapper.update(
                context,
                context.getContentResolver(),
                Mms.CONTENT_URI,
                values,
                Mms._ID + "=" + id,
                null);
          }
        }
      } catch (SQLiteDiskIOException e) {
        // Ignore
        MmsLog.e(
            MmsApp.TXN_TAG, "SQLiteDiskIOException caught while set notification ind unstart", e);
      } finally {
        cursor.close();
      }
    } else {
      MmsLog.d(MmsApp.TXN_TAG, "setNotificationIndUnstarted: no pending messages.");
    }
  }
  public static void setPendingSmsFailed(final Context context) {
    Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed");
    Cursor cursor =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            Sms.CONTENT_URI,
            new String[] {Sms._ID},
            Sms.TYPE
                + "="
                + Sms.MESSAGE_TYPE_OUTBOX
                + " OR "
                + Sms.TYPE
                + "="
                + Sms.MESSAGE_TYPE_QUEUED,
            null,
            null);
    if (cursor != null) {
      try {
        int count = cursor.getCount();
        Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: Message Size=" + count);

        if (count == 0) {
          return;
        }

        ContentValues values = null;
        int id = 0;
        while (cursor.moveToNext()) {
          id = cursor.getInt(0);
          Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: MsgId=" + id);
          values = new ContentValues(1);
          values.put(Sms.TYPE, Sms.MESSAGE_TYPE_FAILED);
          SqliteWrapper.update(
              context,
              context.getContentResolver(),
              Sms.CONTENT_URI,
              values,
              Sms._ID + "=" + id,
              null);
        }
      } catch (SQLiteDiskIOException e) {
        Xlog.e(MmsApp.TXN_TAG, "SQLiteDiskIOException caught while set sms failed", e);
      } finally {
        cursor.close();
      }
    } else {
      Xlog.d(MmsApp.TXN_TAG, "setPendingSmsFailed: no pending messages.");
    }
  }
  private static long findThreadId(Context context, GenericPdu pdu, int type) {
    String messageId;

    if (type == MESSAGE_TYPE_DELIVERY_IND) {
      messageId = new String(((DeliveryInd) pdu).getMessageId());
    } else {
      messageId = new String(((ReadOrigInd) pdu).getMessageId());
    }

    StringBuilder sb = new StringBuilder('(');
    sb.append(Mms.MESSAGE_ID);
    sb.append('=');
    sb.append(DatabaseUtils.sqlEscapeString(messageId));
    sb.append(" AND ");
    sb.append(Mms.MESSAGE_TYPE);
    sb.append('=');
    sb.append(PduHeaders.MESSAGE_TYPE_SEND_REQ);
    // TODO ContentResolver.query() appends closing ')' to the selection argument
    // sb.append(')');

    Cursor cursor =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            Mms.CONTENT_URI,
            new String[] {Mms.THREAD_ID},
            sb.toString(),
            null,
            null);
    if (cursor != null) {
      try {
        if ((cursor.getCount() == 1) && cursor.moveToFirst()) {
          return cursor.getLong(0);
        }
      } finally {
        cursor.close();
      }
    }

    return -1;
  }
Beispiel #11
0
 private static long getDeliveryOrReadReportThreadId(Context context, GenericPdu pdu) {
   String messageId;
   if (pdu instanceof DeliveryInd) {
     messageId = new String(((DeliveryInd) pdu).getMessageId());
   } else if (pdu instanceof ReadOrigInd) {
     messageId = new String(((ReadOrigInd) pdu).getMessageId());
   } else {
     Rlog.e(
         TAG,
         "WAP Push data is neither delivery or read report type: "
             + pdu.getClass().getCanonicalName());
     return -1L;
   }
   Cursor cursor = null;
   try {
     cursor =
         SqliteWrapper.query(
             context,
             context.getContentResolver(),
             Telephony.Mms.CONTENT_URI,
             new String[] {Telephony.Mms.THREAD_ID},
             THREAD_ID_SELECTION,
             new String[] {
               DatabaseUtils.sqlEscapeString(messageId),
               Integer.toString(PduHeaders.MESSAGE_TYPE_SEND_REQ)
             },
             null /*sortOrder*/);
     if (cursor != null && cursor.moveToFirst()) {
       return cursor.getLong(0);
     }
   } catch (SQLiteException e) {
     Rlog.e(TAG, "Failed to query delivery or read report thread id", e);
   } finally {
     if (cursor != null) {
       cursor.close();
     }
   }
   return -1L;
 }
  private static final MmsSmsNotificationInfo getMmsNewMessageNotificationInfo(
      Context context, Set<Long> threads) {
    ContentResolver resolver = context.getContentResolver();

    // This query looks like this when logged:
    // I/Database(  147): elapsedTime4Sql|/data/data/com.android.providers.telephony/databases/
    // mmssms.db|0.362 ms|SELECT thread_id, date, _id, sub, sub_cs FROM pdu WHERE ((msg_box=1
    // AND seen=0 AND (m_type=130 OR m_type=132))) ORDER BY date desc

    Cursor cursor =
        SqliteWrapper.query(
            context,
            resolver,
            Mms.CONTENT_URI,
            MMS_STATUS_PROJECTION,
            NEW_INCOMING_MM_CONSTRAINT,
            null,
            Mms.DATE + " desc");

    if (cursor == null) {
      return null;
    }

    try {
      if (!cursor.moveToFirst()) {
        return null;
      }
      long msgId = cursor.getLong(COLUMN_MMS_ID);
      Uri msgUri = Mms.CONTENT_URI.buildUpon().appendPath(Long.toString(msgId)).build();
      String address = AddressUtils.getFrom(context, msgUri);
      String subject =
          getMmsSubject(cursor.getString(COLUMN_SUBJECT), cursor.getInt(COLUMN_SUBJECT_CS));
      long threadId = cursor.getLong(COLUMN_THREAD_ID);
      long timeMillis = cursor.getLong(COLUMN_DATE) * 1000;

      if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
        Log.d(
            TAG,
            "getMmsNewMessageNotificationInfo: count="
                + cursor.getCount()
                + ", first addr = "
                + address
                + ", thread_id="
                + threadId);
      }

      MmsSmsNotificationInfo info =
          getNewMessageNotificationInfo(
              address,
              subject,
              context,
              R.drawable.stat_notify_mms,
              null,
              threadId,
              timeMillis,
              cursor.getCount());

      threads.add(threadId);
      while (cursor.moveToNext()) {
        threads.add(cursor.getLong(COLUMN_THREAD_ID));
      }

      return info;
    } finally {
      cursor.close();
    }
  }
  /**
   * Constructor that uses the default settings of the MMS Client.
   *
   * @param context The context of the MMS Client
   */
  public TransactionSettings(Context context, String apnName) {
    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
      Log.v(TAG, "TransactionSettings: apnName: " + apnName);
    }
    String selection = Telephony.Carriers.CURRENT + " IS NOT NULL";
    String[] selectionArgs = null;
    if (!TextUtils.isEmpty(apnName)) {
      selection += " AND " + Telephony.Carriers.APN + "=?";
      selectionArgs = new String[] {apnName.trim()};
    }

    Cursor cursor =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            Telephony.Carriers.CONTENT_URI,
            APN_PROJECTION,
            selection,
            selectionArgs,
            null);

    if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
      Log.v(
          TAG,
          "TransactionSettings looking for apn: "
              + selection
              + " returned: "
              + (cursor == null ? "null cursor" : (cursor.getCount() + " hits")));
    }

    if (cursor == null) {
      Log.e(TAG, "Apn is not found in Database!");
      return;
    }

    boolean sawValidApn = false;
    try {
      while (cursor.moveToNext() && TextUtils.isEmpty(mServiceCenter)) {
        // Read values from APN settings
        if (isValidApnType(cursor.getString(COLUMN_TYPE), PhoneConstants.APN_TYPE_MMS)) {
          sawValidApn = true;

          String mmsc = cursor.getString(COLUMN_MMSC);
          if (mmsc == null) {
            continue;
          }

          mServiceCenter = NetworkUtils.trimV4AddrZeros(mmsc.trim());
          mProxyAddress = NetworkUtils.trimV4AddrZeros(cursor.getString(COLUMN_MMSPROXY));
          if (isProxySet()) {
            String portString = cursor.getString(COLUMN_MMSPORT);
            try {
              mProxyPort = Integer.parseInt(portString);
            } catch (NumberFormatException e) {
              if (TextUtils.isEmpty(portString)) {
                Log.w(TAG, "mms port not set!");
              } else {
                Log.e(TAG, "Bad port number format: " + portString, e);
              }
            }
          }
        }
      }
    } finally {
      cursor.close();
    }

    Log.v(TAG, "APN setting: MMSC: " + mServiceCenter + " looked for: " + selection);

    if (sawValidApn && TextUtils.isEmpty(mServiceCenter)) {
      Log.e(TAG, "Invalid APN setting: MMSC is empty");
    }
  }
  public static void handleReadReport(
      final Context context,
      final Collection<Long> threadIds,
      final int status,
      final Runnable callback) {
    StringBuilder selectionBuilder =
        new StringBuilder(
            Mms.MESSAGE_TYPE
                + " = "
                + PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF
                + " AND "
                + Mms.READ
                + " = 0"
                + " AND "
                + Mms.READ_REPORT
                + " = "
                + PduHeaders.VALUE_YES);

    String[] selectionArgs = null;
    if (threadIds != null) {
      String threadIdSelection = null;
      StringBuilder buf = new StringBuilder();
      selectionArgs = new String[threadIds.size()];
      int i = 0;

      for (long threadId : threadIds) {
        if (i > 0) {
          buf.append(" OR ");
        }
        buf.append(Mms.THREAD_ID).append("=?");
        selectionArgs[i++] = Long.toString(threadId);
      }
      threadIdSelection = buf.toString();

      selectionBuilder.append(" AND (" + threadIdSelection + ")");
    }

    final Cursor c =
        SqliteWrapper.query(
            context,
            context.getContentResolver(),
            Mms.Inbox.CONTENT_URI,
            new String[] {Mms._ID, Mms.MESSAGE_ID},
            selectionBuilder.toString(),
            selectionArgs,
            null);

    if (c == null) {
      return;
    }

    final Map<String, String> map = new HashMap<String, String>();
    try {
      if (c.getCount() == 0) {
        if (callback != null) {
          callback.run();
        }
        return;
      }

      while (c.moveToNext()) {
        Uri uri = ContentUris.withAppendedId(Mms.CONTENT_URI, c.getLong(0));
        map.put(c.getString(1), AddressUtils.getFrom(context, uri));
      }
    } finally {
      c.close();
    }

    OnClickListener positiveListener =
        new OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            for (final Map.Entry<String, String> entry : map.entrySet()) {
              MmsMessageSender.sendReadRec(context, entry.getValue(), entry.getKey(), status);
            }

            if (callback != null) {
              callback.run();
            }
            dialog.dismiss();
          }
        };

    OnClickListener negativeListener =
        new OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
            if (callback != null) {
              callback.run();
            }
            dialog.dismiss();
          }
        };

    OnCancelListener cancelListener =
        new OnCancelListener() {
          @Override
          public void onCancel(DialogInterface dialog) {
            if (callback != null) {
              callback.run();
            }
            dialog.dismiss();
          }
        };

    confirmReadReportDialog(context, positiveListener, negativeListener, cancelListener);
  }
 /**
  * Load APN settings from system
  *
  * @param context
  * @param apnName the optional APN name to match
  */
 public static ApnSettings load(Context context, String apnName, int subId) throws ApnException {
   if (Log.isLoggable(TAG, Log.VERBOSE)) {
     Log.v(TAG, "ApnSettings: apnName " + apnName);
   }
   // TODO: CURRENT semantics is currently broken in telephony. Revive this when it is fixed.
   // String selection = Telephony.Carriers.CURRENT + " IS NOT NULL";
   String selection = null;
   String[] selectionArgs = null;
   apnName = apnName != null ? apnName.trim() : null;
   if (!TextUtils.isEmpty(apnName)) {
     // selection += " AND " + Telephony.Carriers.APN + "=?";
     selection = Telephony.Carriers.APN + "=?";
     selectionArgs = new String[] {apnName};
   }
   Cursor cursor = null;
   try {
     cursor =
         SqliteWrapper.query(
             context,
             context.getContentResolver(),
             Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "/subId/" + subId),
             APN_PROJECTION,
             selection,
             selectionArgs,
             null /*sortOrder*/);
     if (cursor != null) {
       String mmscUrl = null;
       String proxyAddress = null;
       int proxyPort = -1;
       while (cursor.moveToNext()) {
         // Read values from APN settings
         if (isValidApnType(cursor.getString(COLUMN_TYPE), PhoneConstants.APN_TYPE_MMS)) {
           mmscUrl = trimWithNullCheck(cursor.getString(COLUMN_MMSC));
           if (TextUtils.isEmpty(mmscUrl)) {
             continue;
           }
           mmscUrl = NetworkUtils.trimV4AddrZeros(mmscUrl);
           try {
             new URI(mmscUrl);
           } catch (URISyntaxException e) {
             throw new ApnException("Invalid MMSC url " + mmscUrl);
           }
           proxyAddress = trimWithNullCheck(cursor.getString(COLUMN_MMSPROXY));
           if (!TextUtils.isEmpty(proxyAddress)) {
             proxyAddress = NetworkUtils.trimV4AddrZeros(proxyAddress);
             final String portString = trimWithNullCheck(cursor.getString(COLUMN_MMSPORT));
             if (portString != null) {
               try {
                 proxyPort = Integer.parseInt(portString);
               } catch (NumberFormatException e) {
                 Log.e(TAG, "Invalid port " + portString);
                 throw new ApnException("Invalid port " + portString);
               }
             }
           }
           return new ApnSettings(mmscUrl, proxyAddress, proxyPort, getDebugText(cursor));
         }
       }
     }
   } finally {
     if (cursor != null) {
       cursor.close();
     }
   }
   throw new ApnException("Can not find valid APN");
 }
  /** Does the actual work of rebuilding the draft cache. */
  private synchronized void rebuildCache() {
    if (Log.isLoggable(LogTag.APP, Log.DEBUG)) {
      log("rebuildCache");
    }

    HashSet<Long> oldDraftSet = mDraftSet;
    HashSet<Long> newDraftSet = new HashSet<Long>(oldDraftSet.size());

    Cursor cursor =
        SqliteWrapper.query(
            mContext,
            mContext.getContentResolver(),
            MmsSms.CONTENT_DRAFT_URI,
            DRAFT_PROJECTION,
            null,
            null,
            null);

    if (cursor != null) {
      try {
        if (cursor.moveToFirst()) {
          for (; !cursor.isAfterLast(); cursor.moveToNext()) {
            long threadId = cursor.getLong(COLUMN_DRAFT_THREAD_ID);
            newDraftSet.add(threadId);
            if (Log.isLoggable(LogTag.APP, Log.DEBUG)) {
              log("rebuildCache: add tid=" + threadId);
            }
          }
        }
      } finally {
        cursor.close();
      }
    }
    mDraftSet = newDraftSet;

    if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {
      dump();
    }

    // If nobody's interested in finding out about changes,
    // just bail out early.
    if (mChangeListeners.size() < 1) {
      return;
    }

    // Find out which drafts were removed and added and notify
    // listeners.
    Set<Long> added = new HashSet<Long>(newDraftSet);
    added.removeAll(oldDraftSet);
    Set<Long> removed = new HashSet<Long>(oldDraftSet);
    removed.removeAll(newDraftSet);

    for (OnDraftChangedListener l : mChangeListeners) {
      for (long threadId : added) {
        l.onDraftChanged(threadId, true);
      }
      for (long threadId : removed) {
        l.onDraftChanged(threadId, false);
      }
    }
  }
    @Override
    protected Void doInBackground(Intent... intents) {
      Intent intent = intents[0];
      Xlog.d(
          MmsApp.TXN_TAG,
          "do In Background, slotId=" + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0));
      // Get raw PDU push-data from the message and parse it
      byte[] pushData = intent.getByteArrayExtra("data");
      PduParser parser = new PduParser(pushData);
      GenericPdu pdu = parser.parse();

      if (null == pdu) {
        Log.e(TAG, "Invalid PUSH data");
        return null;
      }

      PduPersister p = PduPersister.getPduPersister(mContext);
      ContentResolver cr = mContext.getContentResolver();
      int type = pdu.getMessageType();
      long threadId = -1;

      try {
        switch (type) {
          case MESSAGE_TYPE_DELIVERY_IND:
            Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_DELIVERY_IND");
          case MESSAGE_TYPE_READ_ORIG_IND:
            {
              if (type == MESSAGE_TYPE_READ_ORIG_IND) {
                Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_READ_ORIG_IND");
              }
              threadId = findThreadId(mContext, pdu, type);
              if (threadId == -1) {
                // The associated SendReq isn't found, therefore skip
                // processing this PDU.
                break;
              }

              Uri uri = p.persist(pdu, Inbox.CONTENT_URI);
              // Update thread ID for ReadOrigInd & DeliveryInd.
              ContentValues values = new ContentValues(1);
              values.put(Mms.THREAD_ID, threadId);
              SqliteWrapper.update(mContext, cr, uri, values, null, null);
              break;
            }
          case MESSAGE_TYPE_NOTIFICATION_IND:
            {
              Xlog.d(MmsApp.TXN_TAG, "type=MESSAGE_TYPE_NOTIFICATION_IND");
              NotificationInd nInd = (NotificationInd) pdu;

              if (MmsConfig.getTransIdEnabled()) {
                byte[] contentLocation = nInd.getContentLocation();
                if ('=' == contentLocation[contentLocation.length - 1]) {
                  byte[] transactionId = nInd.getTransactionId();
                  byte[] contentLocationWithId =
                      new byte[contentLocation.length + transactionId.length];
                  System.arraycopy(
                      contentLocation, 0, contentLocationWithId, 0, contentLocation.length);
                  System.arraycopy(
                      transactionId,
                      0,
                      contentLocationWithId,
                      contentLocation.length,
                      transactionId.length);
                  nInd.setContentLocation(contentLocationWithId);
                }
              }

              if (!isDuplicateNotification(mContext, nInd)) {
                Uri uri = p.persist(pdu, Inbox.CONTENT_URI);
                // add for gemini
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                  // update pdu
                  ContentValues values = new ContentValues(2);
                  SIMInfo si =
                      SIMInfo.getSIMInfoBySlot(
                          mContext, intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1));
                  if (null == si) {
                    Xlog.e(
                        MmsApp.TXN_TAG,
                        "PushReceiver:SIMInfo is null for slot "
                            + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1));
                    break;
                  }
                  values.put(Mms.SIM_ID, si.mSimId);
                  values.put(WapPush.SERVICE_ADDR, intent.getStringExtra(WapPush.SERVICE_ADDR));
                  SqliteWrapper.update(mContext, cr, uri, values, null, null);
                  Xlog.d(
                      MmsApp.TXN_TAG,
                      "save notification slotId="
                          + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0)
                          + "\tsimId="
                          + si.mSimId
                          + "\tsc="
                          + intent.getStringExtra(WapPush.SERVICE_ADDR)
                          + "\taddr="
                          + intent.getStringExtra(WapPush.ADDR));

                  // update pending messages
                  long msgId = 0;
                  Cursor cursor =
                      SqliteWrapper.query(
                          mContext,
                          mContext.getContentResolver(),
                          uri,
                          new String[] {Mms._ID},
                          null,
                          null,
                          null);
                  if (cursor != null && cursor.getCount() == 1 && cursor.moveToFirst()) {
                    try {
                      msgId = cursor.getLong(0);
                      Xlog.d(MmsApp.TXN_TAG, "msg id = " + msgId);
                    } finally {
                      cursor.close();
                    }
                  }

                  Uri.Builder uriBuilder = PendingMessages.CONTENT_URI.buildUpon();
                  uriBuilder.appendQueryParameter("protocol", "mms");
                  uriBuilder.appendQueryParameter("message", String.valueOf(msgId));
                  Cursor pendingCs =
                      SqliteWrapper.query(
                          mContext,
                          mContext.getContentResolver(),
                          uriBuilder.build(),
                          null,
                          null,
                          null,
                          null);
                  if (pendingCs != null) {
                    try {
                      if ((pendingCs.getCount() == 1) && pendingCs.moveToFirst()) {
                        ContentValues valuesforPending = new ContentValues();
                        valuesforPending.put(PendingMessages.SIM_ID, si.mSimId);
                        int columnIndex = pendingCs.getColumnIndexOrThrow(PendingMessages._ID);
                        long id = pendingCs.getLong(columnIndex);
                        SqliteWrapper.update(
                            mContext,
                            mContext.getContentResolver(),
                            PendingMessages.CONTENT_URI,
                            valuesforPending,
                            PendingMessages._ID + "=" + id,
                            null);
                      } else {
                        Xlog.w(
                            MmsApp.TXN_TAG,
                            "can not find message to set pending sim id, msgId=" + msgId);
                      }
                    } finally {
                      pendingCs.close();
                    }
                  }
                } else {
                  ContentValues value = new ContentValues(1);
                  value.put(WapPush.SERVICE_ADDR, intent.getStringExtra(WapPush.SERVICE_ADDR));
                  SqliteWrapper.update(mContext, cr, uri, value, null, null);
                  Xlog.d(
                      MmsApp.TXN_TAG,
                      "save notification,"
                          + "\tsc="
                          + intent.getStringExtra(WapPush.SERVICE_ADDR)
                          + "\taddr="
                          + intent.getStringExtra(WapPush.ADDR));
                }

                // Start service to finish the notification transaction.
                Intent svc = new Intent(mContext, TransactionService.class);
                svc.putExtra(TransactionBundle.URI, uri.toString());
                svc.putExtra(
                    TransactionBundle.TRANSACTION_TYPE, Transaction.NOTIFICATION_TRANSACTION);
                if (FeatureOption.MTK_GEMINI_SUPPORT) {
                  SIMInfo si =
                      SIMInfo.getSIMInfoBySlot(
                          mContext, intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1));
                  if (null == si) {
                    Xlog.e(
                        MmsApp.TXN_TAG,
                        "PushReceiver: SIMInfo is null for slot "
                            + intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, -1));
                    break;
                  }
                  int simId = (int) si.mSimId;
                  svc.putExtra(Phone.GEMINI_SIM_ID_KEY, simId);
                  // svc.putExtra(Phone.GEMINI_SIM_ID_KEY,
                  // intent.getIntExtra(Phone.GEMINI_SIM_ID_KEY, 0));
                }
                mContext.startService(svc);
              } else if (LOCAL_LOGV) {
                Log.v(
                    TAG,
                    "Skip downloading duplicate message: " + new String(nInd.getContentLocation()));
              }
              break;
            }
          default:
            Log.e(TAG, "Received unrecognized PDU.");
        }
      } catch (MmsException e) {
        Log.e(TAG, "Failed to save the data from PUSH: type=" + type, e);
      } catch (RuntimeException e) {
        Log.e(TAG, "Unexpected RuntimeException.", e);
      } finally {
        raisePriority(mContext, false);
        Xlog.d(MmsApp.TXN_TAG, "Normal priority");
      }

      if (LOCAL_LOGV) {
        Log.v(TAG, "PUSH Intent processed.");
      }

      return null;
    }
Beispiel #18
0
  private void initModelFromUri(Uri uri) throws MmsException {
    ContentResolver cr = mContext.getContentResolver();
    Cursor c = SqliteWrapper.query(mContext, cr, uri, null, null, null, null);

    if (c != null) {
      try {
        if (c.moveToFirst()) {
          String path;
          boolean isFromMms = isMmsUri(uri);

          // FIXME We suppose that there should be only two sources
          // of the audio, one is the media store, the other is
          // our MMS database.
          if (isFromMms) {
            path = c.getString(c.getColumnIndexOrThrow(Part._DATA));
            mContentType = c.getString(c.getColumnIndexOrThrow(Part.CONTENT_TYPE));
          } else {
            path = c.getString(c.getColumnIndexOrThrow(Audio.Media.DATA));
            mContentType = c.getString(c.getColumnIndexOrThrow(Audio.Media.MIME_TYPE));
            // Get more extras information which would be useful
            // to the user.
            String album = c.getString(c.getColumnIndexOrThrow("album"));
            if (!TextUtils.isEmpty(album)) {
              mExtras.put("album", album);
            }

            String artist = c.getString(c.getColumnIndexOrThrow("artist"));
            if (!TextUtils.isEmpty(artist)) {
              mExtras.put("artist", artist);
            }
          }
          if (FeatureOption.MTK_DRM_APP) {
            if (MessageUtils.checkUriContainsDrm(mContext, uri)) {
              path += ".dcf";
            }
          }

          mSrc = path.substring(path.lastIndexOf('/') + 1).replace(' ', '_');
          Log.i(TAG, "path: " + path);
          Log.i(TAG, "mSrc: " + mSrc);

          if (TextUtils.isEmpty(mContentType)) {
            throw new MmsException("Type of media is unknown.");
          }

          if (LOCAL_LOGV) {
            Log.v(
                TAG,
                "New AudioModel created:"
                    + " mSrc="
                    + mSrc
                    + " mContentType="
                    + mContentType
                    + " mUri="
                    + uri
                    + " mExtras="
                    + mExtras);
          }
        } else {
          throw new MmsException("Nothing found: " + uri);
        }
      } finally {
        c.close();
      }
    } else {
      throw new MmsException("Bad URI: " + uri);
    }

    initMediaDuration();
  }
  public synchronized void sendFirstQueuedMessage() {
    boolean success = true;
    // get all the queued messages from the database
    final Uri uri = Uri.parse("content://sms/queued");
    ContentResolver resolver = getContentResolver();
    Cursor c =
        SqliteWrapper.query(
            this,
            resolver,
            uri,
            SEND_PROJECTION,
            null,
            null,
            "date ASC"); // date ASC so we send out in
    // same order the user tried
    // to send messages.
    if (c != null) {
      try {
        if (c.moveToFirst()) {
          String msgText = c.getString(SEND_COLUMN_BODY);
          String address = c.getString(SEND_COLUMN_ADDRESS);
          int threadId = c.getInt(SEND_COLUMN_THREAD_ID);
          int status = c.getInt(SEND_COLUMN_STATUS);

          int msgId = c.getInt(SEND_COLUMN_ID);
          Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId);

          SmsMessageSender sender =
              new SmsSingleRecipientSender(
                  this, address, msgText, threadId, status == Sms.STATUS_PENDING, msgUri);

          if (LogTag.DEBUG_SEND
              || LogTag.VERBOSE
              || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
            Log.v(
                TAG,
                "sendFirstQueuedMessage "
                    + msgUri
                    + ", address: "
                    + address
                    + ", threadId: "
                    + threadId);
          }

          try {
            sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);
            ;
            mSending = true;
          } catch (MmsException e) {
            Log.e(TAG, "sendFirstQueuedMessage: failed to send message " + msgUri + ", caught ", e);
            mSending = false;
            messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
            success = false;
            // Sending current message fails. Try to send more pending messages
            // if there is any.
            sendBroadcast(
                new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, this, SmsReceiver.class));
          }
        }
      } finally {
        c.close();
      }
    }
    if (success) {
      // We successfully sent all the messages in the queue. We don't need to
      // be notified of any service changes any longer.
      unRegisterForServiceStateChanges();
    }
  }