am 4be1ab16: Update CMAS duplicate message detection for carrier requirement.
* commit '4be1ab169dadd108cceff8f76067cf874bda9d97':
Update CMAS duplicate message detection for carrier requirement.
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
index 07e1bfb..3cc821c 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
@@ -86,7 +86,17 @@
}
/** Cache of received message IDs, for duplicate message detection. */
- private static final HashSet<MessageIdAndScope> sCmasIdList = new HashSet<MessageIdAndScope>(8);
+ private static final HashSet<MessageIdAndScope> sCmasIdSet = new HashSet<MessageIdAndScope>(8);
+
+ /** Maximum number of message IDs to save before removing the oldest message ID. */
+ private static final int MAX_MESSAGE_ID_SIZE = 65535;
+
+ /** List of message IDs received, for removing oldest ID when max message IDs are received. */
+ private static final ArrayList<MessageIdAndScope> sCmasIdList =
+ new ArrayList<MessageIdAndScope>(8);
+
+ /** Index of message ID to replace with new message ID when max message IDs are received. */
+ private static int sCmasIdListIndex = 0;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
@@ -123,11 +133,30 @@
return;
}
- // Set.add() returns false if message ID has already been added
- MessageIdAndScope messageIdAndScope = new MessageIdAndScope(message.getSerialNumber(),
+ // Check for duplicate message IDs according to CMAS carrier requirements. Message IDs
+ // are stored in volatile memory. If the maximum of 65535 messages is reached, the
+ // message ID of the oldest message is deleted from the list.
+ MessageIdAndScope newMessageId = new MessageIdAndScope(message.getSerialNumber(),
message.getLocation());
- if (!sCmasIdList.add(messageIdAndScope)) {
- Log.d(TAG, "ignoring duplicate alert with " + messageIdAndScope);
+
+ // Add the new message ID to the list. It's okay if this is a duplicate message ID,
+ // because the list is only used for removing old message IDs from the hash set.
+ if (sCmasIdList.size() < MAX_MESSAGE_ID_SIZE) {
+ sCmasIdList.add(newMessageId);
+ } else {
+ // Get oldest message ID from the list and replace with the new message ID.
+ MessageIdAndScope oldestId = sCmasIdList.get(sCmasIdListIndex);
+ sCmasIdList.set(sCmasIdListIndex, newMessageId);
+ Log.d(TAG, "message ID limit reached, removing oldest message ID " + oldestId);
+ // Remove oldest message ID from the set.
+ sCmasIdSet.remove(oldestId);
+ if (++sCmasIdListIndex >= MAX_MESSAGE_ID_SIZE) {
+ sCmasIdListIndex = 0;
+ }
+ }
+ // Set.add() returns false if message ID has already been added
+ if (!sCmasIdSet.add(newMessageId)) {
+ Log.d(TAG, "ignoring duplicate alert with " + newMessageId);
return;
}
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java b/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java
index 7460f78..b0a67e5 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java
@@ -181,19 +181,6 @@
throw new UnsupportedOperationException("update not supported");
}
- private static final String QUERY_BY_SERIAL = Telephony.CellBroadcasts.SERIAL_NUMBER + "=?";
-
- private static final String QUERY_BY_SERIAL_PLMN = QUERY_BY_SERIAL + " AND "
- + Telephony.CellBroadcasts.PLMN + "=?";
-
- private static final String QUERY_BY_SERIAL_PLMN_LAC = QUERY_BY_SERIAL_PLMN + " AND "
- + Telephony.CellBroadcasts.LAC + "=?";
-
- private static final String QUERY_BY_SERIAL_PLMN_LAC_CID = QUERY_BY_SERIAL_PLMN_LAC + " AND "
- + Telephony.CellBroadcasts.CID + "=?";
-
- private static final String[] SELECT_ID_COLUMN = {Telephony.CellBroadcasts._ID};
-
/**
* Internal method to insert a new Cell Broadcast into the database and notify observers.
* @param message the message to insert
@@ -203,39 +190,10 @@
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
ContentValues cv = message.getContentValues();
- // Check for existing alert with same serial number and geo scope
- String serial = cv.getAsString(Telephony.CellBroadcasts.SERIAL_NUMBER);
- String plmn = cv.getAsString(Telephony.CellBroadcasts.PLMN);
- String lac = cv.getAsString(Telephony.CellBroadcasts.LAC);
- String cid = cv.getAsString(Telephony.CellBroadcasts.CID);
- String selection;
- String[] selectionArgs;
-
- if (plmn != null) {
- if (lac != null) {
- if (cid != null) {
- selection = QUERY_BY_SERIAL_PLMN_LAC_CID;
- selectionArgs = new String[] {serial, plmn, lac, cid};
- } else {
- selection = QUERY_BY_SERIAL_PLMN_LAC;
- selectionArgs = new String[] {serial, plmn, lac};
- }
- } else {
- selection = QUERY_BY_SERIAL_PLMN;
- selectionArgs = new String[] {serial, plmn};
- }
- } else {
- selection = QUERY_BY_SERIAL;
- selectionArgs = new String[] {serial};
- }
-
- Cursor c = db.query(CellBroadcastDatabaseHelper.TABLE_NAME, SELECT_ID_COLUMN,
- selection, selectionArgs, null, null, null);
-
- if (c.getCount() != 0) {
- Log.d(TAG, "ignoring dup broadcast serial=" + serial + " found " + c.getCount());
- return false;
- }
+ // Note: this method previously queried the database for duplicate message IDs, but this
+ // is not compatible with CMAS carrier requirements and could also cause other emergency
+ // alerts, e.g. ETWS, to not display if the database is filled with old messages.
+ // Use duplicate message ID detection in CellBroadcastAlertService instead of DB query.
long rowId = db.insert(CellBroadcastDatabaseHelper.TABLE_NAME, null, cv);
if (rowId == -1) {