Apply new duplication detection logic for M-Notification.ind am: 77a839f1ef
am: cf5dcfef5a
Change-Id: I66f05f83a35c54e35488d86f44e2286a52abca68
This commit is contained in:
@@ -82,6 +82,7 @@ public class DownloadMmsAction extends Action implements Parcelable {
|
|||||||
private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
|
private static final String KEY_SUB_PHONE_NUMBER = "sub_phone_number";
|
||||||
private static final String KEY_AUTO_DOWNLOAD = "auto_download";
|
private static final String KEY_AUTO_DOWNLOAD = "auto_download";
|
||||||
private static final String KEY_FAILURE_STATUS = "failure_status";
|
private static final String KEY_FAILURE_STATUS = "failure_status";
|
||||||
|
private static final String KEY_EXPIRY = "expiry";
|
||||||
|
|
||||||
// Values we attach to the pending intent that's fired when the message is downloaded.
|
// Values we attach to the pending intent that's fired when the message is downloaded.
|
||||||
// Only applicable when downloading via the platform APIs on L+.
|
// Only applicable when downloading via the platform APIs on L+.
|
||||||
@@ -97,6 +98,7 @@ public class DownloadMmsAction extends Action implements Parcelable {
|
|||||||
public static final String EXTRA_CONVERSATION_ID = "conversation_id";
|
public static final String EXTRA_CONVERSATION_ID = "conversation_id";
|
||||||
public static final String EXTRA_PARTICIPANT_ID = "participant_id";
|
public static final String EXTRA_PARTICIPANT_ID = "participant_id";
|
||||||
public static final String EXTRA_STATUS_IF_FAILED = "status_if_failed";
|
public static final String EXTRA_STATUS_IF_FAILED = "status_if_failed";
|
||||||
|
public static final String EXTRA_EXPIRY = "expiry";
|
||||||
|
|
||||||
private DownloadMmsAction() {
|
private DownloadMmsAction() {
|
||||||
super();
|
super();
|
||||||
@@ -130,6 +132,7 @@ public class DownloadMmsAction extends Action implements Parcelable {
|
|||||||
actionParameters.putString(KEY_TRANSACTION_ID, message.getMmsTransactionId());
|
actionParameters.putString(KEY_TRANSACTION_ID, message.getMmsTransactionId());
|
||||||
actionParameters.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
|
actionParameters.putParcelable(KEY_NOTIFICATION_URI, notificationUri);
|
||||||
actionParameters.putBoolean(KEY_AUTO_DOWNLOAD, isAutoDownload(status));
|
actionParameters.putBoolean(KEY_AUTO_DOWNLOAD, isAutoDownload(status));
|
||||||
|
actionParameters.putLong(KEY_EXPIRY, message.getMmsExpiry());
|
||||||
|
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
if (message.getInDownloadWindow(now)) {
|
if (message.getInDownloadWindow(now)) {
|
||||||
@@ -239,6 +242,7 @@ public class DownloadMmsAction extends Action implements Parcelable {
|
|||||||
final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
|
final String conversationId = actionParameters.getString(KEY_CONVERSATION_ID);
|
||||||
final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
|
final String participantId = actionParameters.getString(KEY_PARTICIPANT_ID);
|
||||||
final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
|
final int statusIfFailed = actionParameters.getInt(KEY_FAILURE_STATUS);
|
||||||
|
final long expiry = actionParameters.getLong(KEY_EXPIRY);
|
||||||
|
|
||||||
final long receivedTimestampRoundedToSecond =
|
final long receivedTimestampRoundedToSecond =
|
||||||
1000 * ((System.currentTimeMillis() + 500) / 1000);
|
1000 * ((System.currentTimeMillis() + 500) / 1000);
|
||||||
@@ -256,7 +260,7 @@ public class DownloadMmsAction extends Action implements Parcelable {
|
|||||||
// Start the download
|
// Start the download
|
||||||
final MmsUtils.StatusPlusUri status = MmsUtils.downloadMmsMessage(context,
|
final MmsUtils.StatusPlusUri status = MmsUtils.downloadMmsMessage(context,
|
||||||
notificationUri, subId, subPhoneNumber, transactionId, contentLocation,
|
notificationUri, subId, subPhoneNumber, transactionId, contentLocation,
|
||||||
autoDownload, receivedTimestampRoundedToSecond / 1000L, extras);
|
autoDownload, receivedTimestampRoundedToSecond / 1000L, expiry / 1000L, extras);
|
||||||
if (status == MmsUtils.STATUS_PENDING) {
|
if (status == MmsUtils.STATUS_PENDING) {
|
||||||
// Async download; no status yet
|
// Async download; no status yet
|
||||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ public class ProcessDownloadedMmsAction extends Action {
|
|||||||
private static final String KEY_CONTENT_LOCATION = "content_location";
|
private static final String KEY_CONTENT_LOCATION = "content_location";
|
||||||
private static final String KEY_AUTO_DOWNLOAD = "auto_download";
|
private static final String KEY_AUTO_DOWNLOAD = "auto_download";
|
||||||
private static final String KEY_RECEIVED_TIMESTAMP = "received_timestamp";
|
private static final String KEY_RECEIVED_TIMESTAMP = "received_timestamp";
|
||||||
|
private static final String KEY_EXPIRY = "expiry";
|
||||||
|
|
||||||
// Set when message downloaded by us (legacy)
|
// Set when message downloaded by us (legacy)
|
||||||
private static final String KEY_STATUS = "status";
|
private static final String KEY_STATUS = "status";
|
||||||
@@ -130,6 +131,7 @@ public class ProcessDownloadedMmsAction extends Action {
|
|||||||
params.putString(KEY_PARTICIPANT_ID, participantId);
|
params.putString(KEY_PARTICIPANT_ID, participantId);
|
||||||
params.putInt(KEY_STATUS_IF_FAILED,
|
params.putInt(KEY_STATUS_IF_FAILED,
|
||||||
extras.getInt(DownloadMmsAction.EXTRA_STATUS_IF_FAILED));
|
extras.getInt(DownloadMmsAction.EXTRA_STATUS_IF_FAILED));
|
||||||
|
params.putLong(KEY_EXPIRY, extras.getLong(DownloadMmsAction.EXTRA_EXPIRY));
|
||||||
action.start();
|
action.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,6 +281,7 @@ public class ProcessDownloadedMmsAction extends Action {
|
|||||||
KEY_AUTO_DOWNLOAD);
|
KEY_AUTO_DOWNLOAD);
|
||||||
final long receivedTimestampInSeconds =
|
final long receivedTimestampInSeconds =
|
||||||
actionParameters.getLong(KEY_RECEIVED_TIMESTAMP);
|
actionParameters.getLong(KEY_RECEIVED_TIMESTAMP);
|
||||||
|
final long expiry = actionParameters.getLong(KEY_EXPIRY);
|
||||||
|
|
||||||
// Inform sync we're adding a message to telephony
|
// Inform sync we're adding a message to telephony
|
||||||
final SyncManager syncManager = DataModel.get().getSyncManager();
|
final SyncManager syncManager = DataModel.get().getSyncManager();
|
||||||
@@ -288,7 +291,7 @@ public class ProcessDownloadedMmsAction extends Action {
|
|||||||
MmsUtils.insertDownloadedMessageAndSendResponse(context,
|
MmsUtils.insertDownloadedMessageAndSendResponse(context,
|
||||||
notificationUri, subId, subPhoneNumber, transactionId,
|
notificationUri, subId, subPhoneNumber, transactionId,
|
||||||
contentLocation, autoDownload, receivedTimestampInSeconds,
|
contentLocation, autoDownload, receivedTimestampInSeconds,
|
||||||
retrieveConf);
|
expiry, retrieveConf);
|
||||||
status = result.status;
|
status = result.status;
|
||||||
rawStatus = result.rawStatus;
|
rawStatus = result.rawStatus;
|
||||||
mmsUri = result.uri;
|
mmsUri = result.uri;
|
||||||
|
|||||||
@@ -540,6 +540,10 @@ public class MessageData implements Parcelable {
|
|||||||
return mSeen;
|
return mSeen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final long getMmsExpiry() {
|
||||||
|
return mMmsExpiry;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For incoming MMS messages this returns the retrieve-status value
|
* For incoming MMS messages this returns the retrieve-status value
|
||||||
* For sent MMS messages this returns the response-status value
|
* For sent MMS messages this returns the response-status value
|
||||||
|
|||||||
@@ -952,7 +952,7 @@ public class MmsUtils {
|
|||||||
// Persist a received MMS message in telephony
|
// Persist a received MMS message in telephony
|
||||||
public static Uri insertReceivedMmsMessage(final Context context,
|
public static Uri insertReceivedMmsMessage(final Context context,
|
||||||
final RetrieveConf retrieveConf, final int subId, final String subPhoneNumber,
|
final RetrieveConf retrieveConf, final int subId, final String subPhoneNumber,
|
||||||
final long receivedTimestampInSeconds, final String contentLocation) {
|
final long receivedTimestampInSeconds, final long expiry, final String transactionId) {
|
||||||
final PduPersister persister = PduPersister.getPduPersister(context);
|
final PduPersister persister = PduPersister.getPduPersister(context);
|
||||||
Uri uri = null;
|
Uri uri = null;
|
||||||
try {
|
try {
|
||||||
@@ -963,12 +963,13 @@ public class MmsUtils {
|
|||||||
subPhoneNumber,
|
subPhoneNumber,
|
||||||
null/*preOpenedFiles*/);
|
null/*preOpenedFiles*/);
|
||||||
|
|
||||||
final ContentValues values = new ContentValues(2);
|
final ContentValues values = new ContentValues(3);
|
||||||
// Update mms table with local time instead of PDU time
|
// Update mms table with local time instead of PDU time
|
||||||
values.put(Mms.DATE, receivedTimestampInSeconds);
|
values.put(Mms.DATE, receivedTimestampInSeconds);
|
||||||
// Also update the content location field from NotificationInd so that
|
// Also update the transaction id and the expiry from NotificationInd so that
|
||||||
// wap push dedup would work even after the wap push is deleted
|
// wap push dedup would work even after the wap push is deleted.
|
||||||
values.put(Mms.CONTENT_LOCATION, contentLocation);
|
values.put(Mms.TRANSACTION_ID, transactionId);
|
||||||
|
values.put(Mms.EXPIRY, expiry);
|
||||||
SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null);
|
SqliteWrapper.update(context, context.getContentResolver(), uri, values, null, null);
|
||||||
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
|
||||||
LogUtil.d(TAG, "MmsUtils: Inserted MMS message into telephony, uri: " + uri);
|
LogUtil.d(TAG, "MmsUtils: Inserted MMS message into telephony, uri: " + uri);
|
||||||
@@ -1843,7 +1844,7 @@ public class MmsUtils {
|
|||||||
public static StatusPlusUri downloadMmsMessage(final Context context, final Uri notificationUri,
|
public static StatusPlusUri downloadMmsMessage(final Context context, final Uri notificationUri,
|
||||||
final int subId, final String subPhoneNumber, final String transactionId,
|
final int subId, final String subPhoneNumber, final String transactionId,
|
||||||
final String contentLocation, final boolean autoDownload,
|
final String contentLocation, final boolean autoDownload,
|
||||||
final long receivedTimestampInSeconds, Bundle extras) {
|
final long receivedTimestampInSeconds, final long expiry, Bundle extras) {
|
||||||
if (TextUtils.isEmpty(contentLocation)) {
|
if (TextUtils.isEmpty(contentLocation)) {
|
||||||
LogUtil.e(TAG, "MmsUtils: Download from empty content location URL");
|
LogUtil.e(TAG, "MmsUtils: Download from empty content location URL");
|
||||||
return new StatusPlusUri(
|
return new StatusPlusUri(
|
||||||
@@ -1894,13 +1895,14 @@ public class MmsUtils {
|
|||||||
extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
|
extras.putBoolean(DownloadMmsAction.EXTRA_AUTO_DOWNLOAD, autoDownload);
|
||||||
extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
|
extras.putLong(DownloadMmsAction.EXTRA_RECEIVED_TIMESTAMP,
|
||||||
receivedTimestampInSeconds);
|
receivedTimestampInSeconds);
|
||||||
|
extras.putLong(DownloadMmsAction.EXTRA_EXPIRY, expiry);
|
||||||
|
|
||||||
MmsSender.downloadMms(context, subId, contentLocation, extras);
|
MmsSender.downloadMms(context, subId, contentLocation, extras);
|
||||||
return STATUS_PENDING; // Download happens asynchronously; no status to return
|
return STATUS_PENDING; // Download happens asynchronously; no status to return
|
||||||
}
|
}
|
||||||
return insertDownloadedMessageAndSendResponse(context, notificationUri, subId,
|
return insertDownloadedMessageAndSendResponse(context, notificationUri, subId,
|
||||||
subPhoneNumber, transactionId, contentLocation, autoDownload,
|
subPhoneNumber, transactionId, contentLocation, autoDownload,
|
||||||
receivedTimestampInSeconds, retrieveConf);
|
receivedTimestampInSeconds, expiry, retrieveConf);
|
||||||
|
|
||||||
} catch (final MmsFailureException e) {
|
} catch (final MmsFailureException e) {
|
||||||
LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
|
LogUtil.e(TAG, "MmsUtils: failed to download message " + notificationUri, e);
|
||||||
@@ -1915,7 +1917,7 @@ public class MmsUtils {
|
|||||||
final Uri notificationUri, final int subId, final String subPhoneNumber,
|
final Uri notificationUri, final int subId, final String subPhoneNumber,
|
||||||
final String transactionId, final String contentLocation,
|
final String transactionId, final String contentLocation,
|
||||||
final boolean autoDownload, final long receivedTimestampInSeconds,
|
final boolean autoDownload, final long receivedTimestampInSeconds,
|
||||||
final RetrieveConf retrieveConf) {
|
final long expiry, final RetrieveConf retrieveConf) {
|
||||||
final byte[] notificationTransactionId = stringToBytes(transactionId, "UTF-8");
|
final byte[] notificationTransactionId = stringToBytes(transactionId, "UTF-8");
|
||||||
Uri messageUri = null;
|
Uri messageUri = null;
|
||||||
int status = MMS_REQUEST_MANUAL_RETRY;
|
int status = MMS_REQUEST_MANUAL_RETRY;
|
||||||
@@ -1954,7 +1956,7 @@ public class MmsUtils {
|
|||||||
|
|
||||||
// Insert downloaded message into telephony
|
// Insert downloaded message into telephony
|
||||||
final Uri inboxUri = MmsUtils.insertReceivedMmsMessage(context, retrieveConf, subId,
|
final Uri inboxUri = MmsUtils.insertReceivedMmsMessage(context, retrieveConf, subId,
|
||||||
subPhoneNumber, receivedTimestampInSeconds, contentLocation);
|
subPhoneNumber, receivedTimestampInSeconds, expiry, transactionId);
|
||||||
messageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, ContentUris.parseId(inboxUri));
|
messageUri = ContentUris.withAppendedId(Mms.CONTENT_URI, ContentUris.parseId(inboxUri));
|
||||||
} else if (status == MMS_REQUEST_AUTO_RETRY) {
|
} else if (status == MMS_REQUEST_AUTO_RETRY) {
|
||||||
// For a retry do nothing
|
// For a retry do nothing
|
||||||
@@ -2171,57 +2173,28 @@ public class MmsUtils {
|
|||||||
uri, values, null, null);
|
uri, values, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection for new dedup algorithm:
|
// Selection for dedup algorithm:
|
||||||
// ((m_type<>130) OR (exp>NOW)) AND (date>NOW-7d) AND (date<NOW+7d) AND (ct_l=xxxxxx)
|
// ((m_type=NOTIFICATION_IND) OR (m_type=RETRIEVE_CONF)) AND (exp>NOW)) AND (t_id=xxxxxx)
|
||||||
// i.e. If it is NotificationInd and not expired or not NotificationInd
|
// i.e. If it is NotificationInd or RetrieveConf and not expired
|
||||||
// AND message is received with +/- 7 days from now
|
// AND transaction id is the input id
|
||||||
// AND content location is the input URL
|
|
||||||
private static final String DUP_NOTIFICATION_QUERY_SELECTION =
|
private static final String DUP_NOTIFICATION_QUERY_SELECTION =
|
||||||
"((" + Mms.MESSAGE_TYPE + "<>?) OR (" + Mms.EXPIRY + ">?)) AND ("
|
"((" + Mms.MESSAGE_TYPE + "=?) OR (" + Mms.MESSAGE_TYPE + "=?)) AND ("
|
||||||
+ Mms.DATE + ">?) AND (" + Mms.DATE + "<?) AND (" + Mms.CONTENT_LOCATION +
|
+ Mms.EXPIRY + ">?) AND (" + Mms.TRANSACTION_ID + "=?)";
|
||||||
"=?)";
|
|
||||||
// Selection for old behavior: only checks NotificationInd and its content location
|
|
||||||
private static final String DUP_NOTIFICATION_QUERY_SELECTION_OLD =
|
|
||||||
"(" + Mms.MESSAGE_TYPE + "=?) AND (" + Mms.CONTENT_LOCATION + "=?)";
|
|
||||||
|
|
||||||
private static final int MAX_RETURN = 32;
|
private static final int MAX_RETURN = 32;
|
||||||
private static String[] getDupNotifications(final Context context, final NotificationInd nInd) {
|
private static String[] getDupNotifications(final Context context, final NotificationInd nInd) {
|
||||||
final byte[] rawLocation = nInd.getContentLocation();
|
final byte[] rawTransactionId = nInd.getTransactionId();
|
||||||
if (rawLocation != null) {
|
if (rawTransactionId != null) {
|
||||||
final String location = new String(rawLocation);
|
// dedup algorithm
|
||||||
// We can not be sure if the content location of an MMS is globally and historically
|
String selection = DUP_NOTIFICATION_QUERY_SELECTION;
|
||||||
// unique. So we limit the dedup time within the last 7 days
|
final long nowSecs = System.currentTimeMillis() / 1000;
|
||||||
// (or configured by gservices remotely). If the same content location shows up after
|
String[] selectionArgs = new String[] {
|
||||||
// that, we will download regardless. Duplicated message is better than no message.
|
Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
|
||||||
String selection;
|
Integer.toString(PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF),
|
||||||
String[] selectionArgs;
|
Long.toString(nowSecs),
|
||||||
final long timeLimit = BugleGservices.get().getLong(
|
new String(rawTransactionId)
|
||||||
BugleGservicesKeys.MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS,
|
};
|
||||||
BugleGservicesKeys.MMS_WAP_PUSH_DEDUP_TIME_LIMIT_SECS_DEFAULT);
|
|
||||||
if (timeLimit > 0) {
|
|
||||||
// New dedup algorithm
|
|
||||||
selection = DUP_NOTIFICATION_QUERY_SELECTION;
|
|
||||||
final long nowSecs = System.currentTimeMillis() / 1000;
|
|
||||||
final long timeLowerBoundSecs = nowSecs - timeLimit;
|
|
||||||
// Need upper bound to protect against clock change so that a message has a time
|
|
||||||
// stamp in the future
|
|
||||||
final long timeUpperBoundSecs = nowSecs + timeLimit;
|
|
||||||
selectionArgs = new String[] {
|
|
||||||
Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
|
|
||||||
Long.toString(nowSecs),
|
|
||||||
Long.toString(timeLowerBoundSecs),
|
|
||||||
Long.toString(timeUpperBoundSecs),
|
|
||||||
location
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// If time limit is 0, we revert back to old behavior in case the new
|
|
||||||
// dedup algorithm behaves badly
|
|
||||||
selection = DUP_NOTIFICATION_QUERY_SELECTION_OLD;
|
|
||||||
selectionArgs = new String[] {
|
|
||||||
Integer.toString(PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND),
|
|
||||||
location
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Cursor cursor = null;
|
Cursor cursor = null;
|
||||||
try {
|
try {
|
||||||
cursor = SqliteWrapper.query(
|
cursor = SqliteWrapper.query(
|
||||||
@@ -2358,7 +2331,7 @@ public class MmsUtils {
|
|||||||
} else {
|
} else {
|
||||||
LogUtil.w(TAG, "Received WAP Push is a dup: " + Joiner.on(',').join(dups));
|
LogUtil.w(TAG, "Received WAP Push is a dup: " + Joiner.on(',').join(dups));
|
||||||
if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
|
if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
|
||||||
LogUtil.w(TAG, "Dup WAP Push url=" + new String(nInd.getContentLocation()));
|
LogUtil.w(TAG, "Dup Transaction Id=" + new String(nInd.getTransactionId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user