Fixed that carrier specific messages were not treated as emergency

Added an emergency flag to other channel managers. The carrier's
specific cell broadcast messages can be marked as emergency or
non-emergency.

bug: 31172048
Change-Id: Ie2f20a166125bbcb8c5f9baadd9d97bca9c4d917
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertDialog.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertDialog.java
index a74a968..19ac02f 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertDialog.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertDialog.java
@@ -270,7 +270,8 @@
 
         // For emergency alerts, keep screen on so the user can read it
         CellBroadcastMessage message = getLatestMessage();
-        if (message != null && message.isEmergencyAlertMessage()) {
+        if (message != null && CellBroadcastAlertService.
+                isEmergencyMessage(this, message)) {
             Log.d(TAG, "onCreate setting screen on timer for emergency alert");
             mScreenOffHandler.startScreenOnTimer();
         }
@@ -285,7 +286,8 @@
     protected void onResume() {
         super.onResume();
         CellBroadcastMessage message = getLatestMessage();
-        if (message != null && message.isEmergencyAlertMessage()) {
+        if (message != null && CellBroadcastAlertService.
+                isEmergencyMessage(this, message)) {
             mAnimationHandler.startIconAnimation();
         }
     }
@@ -349,7 +351,8 @@
      * @param message CB message which is used to update alert text.
      */
     private void updateAlertText(CellBroadcastMessage message) {
-        int titleId = CellBroadcastResources.getDialogTitleResource(message);
+        int titleId = CellBroadcastResources.getDialogTitleResource(
+                getApplicationContext(), message);
         setTitle(titleId);
         ((TextView) findViewById(R.id.alertTitle)).setText(titleId);
         ((TextView) findViewById(R.id.message)).setText(message.getMessageBody());
@@ -437,7 +440,8 @@
         CellBroadcastMessage nextMessage = getLatestMessage();
         if (nextMessage != null) {
             updateAlertText(nextMessage);
-            if (nextMessage.isEmergencyAlertMessage()) {
+            if (CellBroadcastAlertService.isEmergencyMessage(
+                    this, nextMessage)) {
                 mAnimationHandler.startIconAnimation();
             } else {
                 mAnimationHandler.stopIconAnimation();
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
index 1c63f7c..3e46eaf 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
@@ -36,10 +36,12 @@
 import android.telephony.SmsCbEtwsInfo;
 import android.telephony.SmsCbLocation;
 import android.telephony.SmsCbMessage;
+import android.telephony.SubscriptionManager;
 import android.util.Log;
 
 import com.android.cellbroadcastreceiver.CellBroadcastAlertAudio.ToneType;
 import com.android.cellbroadcastreceiver.CellBroadcastOtherChannelsManager.CellBroadcastChannelRange;
+import com.android.internal.telephony.PhoneConstants;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -166,6 +168,12 @@
         }
 
         final CellBroadcastMessage cbm = new CellBroadcastMessage(message);
+        int subId = intent.getExtras().getInt(PhoneConstants.SUBSCRIPTION_KEY);
+        if (SubscriptionManager.isValidSubscriptionId(subId)) {
+            cbm.setSubId(subId);
+        } else {
+            Log.e(TAG, "Invalid subscription id");
+        }
 
         if (!isMessageEnabledByUser(cbm)) {
             Log.d(TAG, "ignoring alert of type " + cbm.getServiceCategory() +
@@ -258,7 +266,7 @@
             return;
         }
 
-        if (cbm.isEmergencyAlertMessage()) {
+        if (isEmergencyMessage(this, cbm)) {
             // start alert sound / vibration / TTS and display full-screen alert
             openEmergencyAlertNotification(cbm);
         } else {
@@ -466,7 +474,7 @@
     static void addToNotificationBar(CellBroadcastMessage message,
                                      ArrayList<CellBroadcastMessage> messageList, Context context,
                                      boolean fromSaveState) {
-        int channelTitleId = CellBroadcastResources.getDialogTitleResource(message);
+        int channelTitleId = CellBroadcastResources.getDialogTitleResource(context, message);
         CharSequence channelName = context.getText(channelTitleId);
         String messageBody = message.getMessageBody();
 
@@ -521,4 +529,41 @@
     public IBinder onBind(Intent intent) {
         return null;    // clients can't bind to this service
     }
+
+    /**
+     * Check if the cell broadcast message is an emergency message or not
+     * @param context Device context
+     * @param cbm Cell broadcast message
+     * @return True if the message is an emergency message, otherwise false.
+     */
+    public static boolean isEmergencyMessage(Context context, CellBroadcastMessage cbm) {
+        boolean isEmergency = false;
+
+        if (cbm == null) {
+            return false;
+        }
+
+        int id = cbm.getServiceCategory();
+        int subId = cbm.getSubId();
+
+        if (cbm.isEmergencyAlertMessage()) {
+            isEmergency = true;
+        } else {
+            ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastOtherChannelsManager.
+                    getInstance().getCellBroadcastChannelRanges(context, subId);
+
+            if (ranges != null) {
+                for (CellBroadcastChannelRange range : ranges) {
+                    if (range.mStartId <= id && range.mEndId >= id) {
+                        isEmergency = range.mIsEmergency;
+                        break;
+                    }
+                }
+            }
+        }
+
+        Log.d(TAG, "isEmergencyMessage: " + isEmergency + ", subId = " + subId + ", " +
+                "message id = " + id);
+        return isEmergency;
+    }
 }
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastListItem.java b/src/com/android/cellbroadcastreceiver/CellBroadcastListItem.java
index 7db5fd2..8a06f8a 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastListItem.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastListItem.java
@@ -38,9 +38,11 @@
     private TextView mChannelView;
     private TextView mMessageView;
     private TextView mDateView;
+    private Context mContext;
 
     public CellBroadcastListItem(Context context, AttributeSet attrs) {
         super(context, attrs);
+        mContext = context;
     }
 
     CellBroadcastMessage getMessage() {
@@ -69,7 +71,7 @@
 
         setBackground(background);
 
-        mChannelView.setText(CellBroadcastResources.getDialogTitleResource(message));
+        mChannelView.setText(CellBroadcastResources.getDialogTitleResource(mContext, message));
         mDateView.setText(message.getDateString(getContext()));
         mMessageView.setText(formatMessage(message));
     }
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManager.java b/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManager.java
index 0b1062b..dbd389b 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManager.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManager.java
@@ -41,7 +41,7 @@
  */
 public class CellBroadcastOtherChannelsManager {
 
-    private static final String TAG = "CellBroadcastChannelsManager";
+    private static final String TAG = "CellBroadcastOtherChannelsManager";
 
     private static CellBroadcastOtherChannelsManager sInstance = null;
 
@@ -56,20 +56,39 @@
      * A range is consisted by starting channel id, ending channel id, and the tone type
      */
     public static class CellBroadcastChannelRange {
+
+        private static final String KEY_TYPE = "type";
+        private static final String KEY_EMERGENCY = "emergency";
+
         public int mStartId;
         public int mEndId;
         public ToneType mToneType;
+        public boolean mIsEmergency;
 
         public CellBroadcastChannelRange(String channelRange) throws Exception {
 
             mToneType = ToneType.CMAS_DEFAULT;
+            mIsEmergency = false;
 
             int colonIndex = channelRange.indexOf(':');
             if (colonIndex != -1){
-                // Parse the tone type
-                String[] tokens = channelRange.substring(colonIndex + 1).trim().split("=");
-                if (tokens.length == 2 && tokens[0].trim().equalsIgnoreCase("type")) {
-                    mToneType = ToneType.valueOf(tokens[1].trim().toUpperCase());
+                // Parse the tone type and emergency flag
+                String[] pairs = channelRange.substring(colonIndex + 1).trim().split(",");
+                for (String pair : pairs) {
+                    pair = pair.trim();
+                    String[] tokens = pair.split("=");
+                    if (tokens.length == 2) {
+                        String key = tokens[0].trim();
+                        String value = tokens[1].trim();
+                        switch (key) {
+                            case KEY_TYPE:
+                                mToneType = ToneType.valueOf(value.toUpperCase());
+                                break;
+                            case KEY_EMERGENCY:
+                                mIsEmergency = value.equalsIgnoreCase("true");
+                                break;
+                        }
+                    }
                 }
                 channelRange = channelRange.substring(0, colonIndex).trim();
             }
@@ -110,6 +129,11 @@
         // Check if the cache already had it.
         if (sChannelRanges.get(subId) == null) {
 
+            if (context == null) {
+                loge("context is null");
+                return null;
+            }
+
             ArrayList<CellBroadcastChannelRange> result = new ArrayList<>();
             String[] ranges;
             CarrierConfigManager configManager =
@@ -123,7 +147,7 @@
                             CarrierConfigManager.KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS);
 
                     if (ranges == null || ranges.length == 0) {
-                        log("No additional channels configured.");
+                        log("No additional channels configured. subId = " + subId);
 
                         // If there is nothing configured, store an empty list in the cache
                         // so we won't look up again next time.
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastResources.java b/src/com/android/cellbroadcastreceiver/CellBroadcastResources.java
index a492679..9c5d5fa 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastResources.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastResources.java
@@ -24,6 +24,9 @@
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.style.StyleSpan;
+import com.android.cellbroadcastreceiver.CellBroadcastOtherChannelsManager.CellBroadcastChannelRange;
+
+import java.util.ArrayList;
 
 /**
  * Returns the string resource ID's for CMAS and ETWS emergency alerts.
@@ -236,7 +239,7 @@
         }
     }
 
-    public static int getDialogTitleResource(CellBroadcastMessage cbm) {
+    public static int getDialogTitleResource(Context context, CellBroadcastMessage cbm) {
         // ETWS warning types
         SmsCbEtwsInfo etwsInfo = cbm.getEtwsWarningInfo();
         if (etwsInfo != null) {
@@ -289,7 +292,29 @@
             }
         }
 
-        if (cbm.isEmergencyAlertMessage()) {
+        if (CellBroadcastAlertService.isEmergencyMessage(context, cbm)) {
+            ArrayList<CellBroadcastChannelRange> ranges = CellBroadcastOtherChannelsManager.
+                    getInstance().getCellBroadcastChannelRanges(context, cbm.getSubId());
+            if (ranges != null) {
+                for (CellBroadcastChannelRange range : ranges) {
+                    if (cbm.getServiceCategory() >= range.mStartId &&
+                            cbm.getServiceCategory() <= range.mEndId) {
+                        // Apply the closest title to the specified tones.
+                        switch (range.mToneType) {
+                            case CMAS_DEFAULT:
+                                return R.string.pws_other_message_identifiers;
+                            case EARTHQUAKE:
+                                return R.string.etws_earthquake_warning;
+                            case TSUNAMI:
+                                return R.string.etws_tsunami_warning;
+                            case ETWS_DEFAULT:
+                            case OTHER:
+                                return R.string.etws_other_emergency_type;
+                        }
+                    }
+                }
+
+            }
             return R.string.pws_other_message_identifiers;
         } else {
             return R.string.cb_other_message_identifiers;
diff --git a/tests/unit/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManagerTest.java b/tests/unit/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManagerTest.java
index c01e657..69aa368 100644
--- a/tests/unit/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManagerTest.java
+++ b/tests/unit/src/com/android/cellbroadcastreceiver/CellBroadcastOtherChannelsManagerTest.java
@@ -28,7 +28,9 @@
 
 import java.util.ArrayList;
 
-import static junit.framework.Assert.assertEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
 /**
  * APN retry manager tests
@@ -55,27 +57,38 @@
         carrierConfigSetStringArray(subId,
                 CarrierConfigManager.KEY_CARRIER_ADDITIONAL_CBS_CHANNELS_STRINGS,
                 new String[]{
-                        "12:type=earthquake",
-                        "456:type=tsunami",
-                        "0xAC00-0xAFED:type=other",
-                        "54-60"});
+                        "12:type=earthquake, emergency=true",
+                        "456:type=tsunami, emergency=true",
+                        "0xAC00-0xAFED:type=other, emergency=false",
+                        "54-60:emergency=true",
+                        "100-200"
+                });
         ArrayList<CellBroadcastChannelRange> list = CellBroadcastOtherChannelsManager.getInstance().
                 getCellBroadcastChannelRanges(mContext, subId);
 
         assertEquals(12, list.get(0).mStartId);
         assertEquals(12, list.get(0).mEndId);
         assertEquals(ToneType.EARTHQUAKE, list.get(0).mToneType);
+        assertTrue(list.get(0).mIsEmergency);
 
         assertEquals(456, list.get(1).mStartId);
         assertEquals(456, list.get(1).mEndId);
         assertEquals(ToneType.TSUNAMI, list.get(1).mToneType);
+        assertTrue(list.get(1).mIsEmergency);
 
         assertEquals(0xAC00, list.get(2).mStartId);
         assertEquals(0xAFED, list.get(2).mEndId);
         assertEquals(ToneType.OTHER, list.get(2).mToneType);
+        assertFalse(list.get(2).mIsEmergency);
 
         assertEquals(54, list.get(3).mStartId);
         assertEquals(60, list.get(3).mEndId);
         assertEquals(ToneType.CMAS_DEFAULT, list.get(3).mToneType);
+        assertTrue(list.get(3).mIsEmergency);
+
+        assertEquals(100, list.get(4).mStartId);
+        assertEquals(200, list.get(4).mEndId);
+        assertEquals(ToneType.CMAS_DEFAULT, list.get(4).mToneType);
+        assertFalse(list.get(4).mIsEmergency);
     }
 }