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) {