am 3a932c80: am 8524c0a3: Enable support for area info cell broadcasts in Brazil.

* commit '3a932c806cfd690a282679d6f9f512eaeb658cdd':
  Enable support for area info cell broadcasts in Brazil.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9b60968..92fda98 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -28,6 +28,7 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
     <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
 
     <application android:name="CellBroadcastReceiverApp"
             android:label="@string/app_label"
@@ -105,6 +106,14 @@
             </intent-filter>
         </receiver>
 
+        <!-- Require sender permission for querying latest area info broadcast -->
+        <receiver android:name="PrivilegedCellBroadcastReceiver"
+            android:permission="android.permission.READ_PHONE_STATE">
+            <intent-filter>
+                 <action android:name="android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO" />
+            </intent-filter>
+        </receiver>
+
         <receiver android:name="CellBroadcastReceiver">
             <intent-filter>
                  <action android:name="android.intent.action.BOOT_COMPLETED" />
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
index 3cc821c..6e1b601 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastAlertService.java
@@ -26,6 +26,7 @@
 import android.content.SharedPreferences;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.UserHandle;
 import android.preference.PreferenceManager;
 import android.provider.Telephony;
 import android.telephony.CellBroadcastMessage;
@@ -52,6 +53,10 @@
     /** Use the same notification ID for non-emergency alerts. */
     static final int NOTIFICATION_ID = 1;
 
+    /** Sticky broadcast for latest area info broadcast received. */
+    static final String CB_AREA_INFO_RECEIVED_ACTION =
+            "android.cellbroadcastreceiver.CB_AREA_INFO_RECEIVED";
+
     /** Container for message ID and geographical scope, for duplicate message detection. */
     private static final class MessageIdAndScope {
         private final int mMessageId;
@@ -245,6 +250,16 @@
             }
         }
 
+        if (message.getServiceCategory() == 50) {
+            // save latest area info broadcast for Settings display and send as broadcast
+            CellBroadcastReceiverApp.setLatestAreaInfo(message);
+            Intent intent = new Intent(CB_AREA_INFO_RECEIVED_ACTION);
+            intent.putExtra("message", message);
+            sendBroadcastAsUser(intent, UserHandle.ALL,
+                    android.Manifest.permission.READ_PHONE_STATE);
+            return false;   // area info broadcasts are displayed in Settings status screen
+        }
+
         return true;    // other broadcast messages are always enabled
     }
 
@@ -339,7 +354,7 @@
                 messageList);
         intent.putExtra(CellBroadcastAlertFullScreen.FROM_NOTIFICATION_EXTRA, true);
 
-        PendingIntent pi = PendingIntent.getActivity(this, 0, intent,
+        PendingIntent pi = PendingIntent.getActivity(this, NOTIFICATION_ID, intent,
                 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
 
         // use default sound/vibration/lights for non-emergency broadcasts
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastConfigService.java b/src/com/android/cellbroadcastreceiver/CellBroadcastConfigService.java
index dd99dc5..3c6eea4 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastConfigService.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastConfigService.java
@@ -17,6 +17,7 @@
 package com.android.cellbroadcastreceiver;
 
 import android.app.IntentService;
+import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
@@ -24,6 +25,7 @@
 import android.preference.PreferenceManager;
 import android.telephony.CellBroadcastMessage;
 import android.telephony.SmsManager;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -133,7 +135,13 @@
                 boolean enableEmergencyAlerts = prefs.getBoolean(
                         CellBroadcastSettings.KEY_ENABLE_EMERGENCY_ALERTS, true);
 
-                boolean enableChannel50Alerts = res.getBoolean(R.bool.show_brazil_settings) &&
+                TelephonyManager tm = (TelephonyManager) getSystemService(
+                        Context.TELEPHONY_SERVICE);
+
+                boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) ||
+                        "br".equals(tm.getSimCountryIso());
+
+                boolean enableChannel50Alerts = enableChannel50Support &&
                         prefs.getBoolean(CellBroadcastSettings.KEY_ENABLE_CHANNEL_50_ALERTS, true);
 
                 SmsManager manager = SmsManager.getDefault();
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastReceiver.java b/src/com/android/cellbroadcastreceiver/CellBroadcastReceiver.java
index 63d0815..3eef633 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastReceiver.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastReceiver.java
@@ -20,10 +20,13 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.preference.PreferenceManager;
 import android.provider.Telephony;
+import android.telephony.CellBroadcastMessage;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
@@ -37,6 +40,9 @@
     private static final String TAG = "CellBroadcastReceiver";
     static final boolean DBG = true;    // STOPSHIP: change to false before ship
 
+    private static final String GET_LATEST_CB_AREA_INFO_ACTION =
+            "android.cellbroadcastreceiver.GET_LATEST_CB_AREA_INFO";
+
     @Override
     public void onReceive(Context context, Intent intent) {
         onReceiveWithPrivilege(context, intent, false);
@@ -83,6 +89,19 @@
             } else {
                 Log.e(TAG, "ignoring unprivileged action received " + action);
             }
+        } else if (GET_LATEST_CB_AREA_INFO_ACTION.equals(action)) {
+            if (privileged) {
+                CellBroadcastMessage message = CellBroadcastReceiverApp.getLatestAreaInfo();
+                if (message != null) {
+                    Intent areaInfoIntent = new Intent(
+                            CellBroadcastAlertService.CB_AREA_INFO_RECEIVED_ACTION);
+                    areaInfoIntent.putExtra("message", message);
+                    context.sendBroadcastAsUser(areaInfoIntent, UserHandle.ALL,
+                            android.Manifest.permission.READ_PHONE_STATE);
+                }
+            } else {
+                Log.e(TAG, "caller missing READ_PHONE_STATE permission, returning");
+            }
         } else {
             Log.w(TAG, "onReceive() unexpected action " + action);
         }
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastReceiverApp.java b/src/com/android/cellbroadcastreceiver/CellBroadcastReceiverApp.java
index 65e8c72..b9e6039 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastReceiverApp.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastReceiverApp.java
@@ -42,6 +42,9 @@
     private static final ArrayList<CellBroadcastMessage> sNewMessageList =
             new ArrayList<CellBroadcastMessage>(4);
 
+    /** Latest area info cell broadcast received. */
+    private static CellBroadcastMessage sLatestAreaInfo;
+
     /** Adds a new unread non-emergency message and returns the current list. */
     static ArrayList<CellBroadcastMessage> addNewMessageToList(CellBroadcastMessage message) {
         sNewMessageList.add(message);
@@ -52,4 +55,14 @@
     static void clearNewMessageList() {
         sNewMessageList.clear();
     }
+
+    /** Saves the latest area info broadcast received. */
+    static void setLatestAreaInfo(CellBroadcastMessage areaInfo) {
+        sLatestAreaInfo = areaInfo;
+    }
+
+    /** Returns the latest area info broadcast received. */
+    static CellBroadcastMessage getLatestAreaInfo() {
+        return sLatestAreaInfo;
+    }
 }
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java b/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
index a7c7482..027ef96 100644
--- a/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
+++ b/src/com/android/cellbroadcastreceiver/CellBroadcastSettings.java
@@ -16,6 +16,7 @@
 
 package com.android.cellbroadcastreceiver;
 
+import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.preference.ListPreference;
@@ -25,6 +26,8 @@
 import android.preference.PreferenceFragment;
 import android.preference.PreferenceScreen;
 import android.provider.Settings;
+import android.telephony.TelephonyManager;
+import android.util.Log;
 
 /**
  * Settings activity for the cell broadcast receiver.
@@ -163,7 +166,14 @@
                         findPreference(KEY_ENABLE_CMAS_SEVERE_THREAT_ALERTS));
                 alertCategory.removePreference(findPreference(KEY_ENABLE_CMAS_AMBER_ALERTS));
             }
-            if (!res.getBoolean(R.bool.show_brazil_settings)) {
+
+            TelephonyManager tm = (TelephonyManager) getActivity().getSystemService(
+                    Context.TELEPHONY_SERVICE);
+
+            boolean enableChannel50Support = res.getBoolean(R.bool.show_brazil_settings) ||
+                    "br".equals(tm.getSimCountryIso());
+
+            if (!enableChannel50Support) {
                 preferenceScreen.removePreference(findPreference(KEY_CATEGORY_BRAZIL_SETTINGS));
             }
             if (!enableDevSettings) {
diff --git a/tests/res/layout/test_buttons.xml b/tests/res/layout/test_buttons.xml
index 96103cb..4486433 100644
--- a/tests/res/layout/test_buttons.xml
+++ b/tests/res/layout/test_buttons.xml
@@ -42,6 +42,23 @@
 
     </LinearLayout>
 
+    <LinearLayout
+      android:layout_width="match_parent"
+      android:layout_height="match_parent"
+      android:orientation="horizontal">
+
+      <TextView android:id="@+id/category_id_label"
+          android:layout_width="wrap_content"
+          android:layout_height="wrap_content"
+          android:text="@string/category_id_label" />
+
+      <EditText android:id="@+id/category_id"
+          android:layout_width="80dp"
+          android:layout_height="wrap_content"
+          android:inputType="number" />
+
+    </LinearLayout>
+
     <CheckBox android:id="@+id/button_delay_broadcast"
         android:text="@string/button_delay_broadcast"
         android:layout_marginLeft="20dp"
diff --git a/tests/res/values/strings.xml b/tests/res/values/strings.xml
index b1b1031..08560ac 100644
--- a/tests/res/values/strings.xml
+++ b/tests/res/values/strings.xml
@@ -40,4 +40,5 @@
     <string name="button_gsm_ucs2_with_language_umts_type">Send UMTS UCS-2 With Language</string>
     <string name="button_delay_broadcast">Delay 5 seconds before sending</string>
     <string name="message_id_label">Message ID:</string>
+    <string name="category_id_label">Category:</string>
 </resources>
diff --git a/tests/src/com/android/cellbroadcastreceiver/tests/SendTestBroadcastActivity.java b/tests/src/com/android/cellbroadcastreceiver/tests/SendTestBroadcastActivity.java
index f47ffd2..ca5a2a0 100644
--- a/tests/src/com/android/cellbroadcastreceiver/tests/SendTestBroadcastActivity.java
+++ b/tests/src/com/android/cellbroadcastreceiver/tests/SendTestBroadcastActivity.java
@@ -72,6 +72,15 @@
     }
 
     /**
+     * Return the value of the category field.
+     * @return the current value of the category text field
+     */
+    private int getCategory() {
+        EditText categoryField = (EditText) findViewById(R.id.category_id);
+        return Integer.parseInt(categoryField.getText().toString());
+    }
+
+    /**
      * Initialization of the Activity after it is first created.  Must at least
      * call {@link android.app.Activity#setContentView(int)} to
      * describe what is to be displayed in the screen.
@@ -85,7 +94,11 @@
         /* Set message ID to a random value from 1-65535. */
         EditText messageIdField = (EditText) findViewById(R.id.message_id);
         messageIdField.setText(String.valueOf(new Random().nextInt(65535) + 1));
-                
+
+        /* When category ID is non-zero, use it for the GSM/UMTS message identifier. */
+        EditText categoryIdField = (EditText) findViewById(R.id.category_id);
+        categoryIdField.setText("0");
+
         /* Send an ETWS normal broadcast message to app. */
         Button etwsNormalTypeButton = (Button) findViewById(R.id.button_etws_normal_type);
         etwsNormalTypeButton.setOnClickListener(new OnClickListener() {
@@ -94,7 +107,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendEtwsMessageNormal(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendEtwsMessageNormal(SendTestBroadcastActivity.this,
+                            getMessageId());
                 }
             }
         });
@@ -107,7 +121,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendEtwsMessageCancel(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendEtwsMessageCancel(SendTestBroadcastActivity.this,
+                            getMessageId());
                 }
             }
         });
@@ -120,7 +135,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendEtwsMessageTest(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendEtwsMessageTest(SendTestBroadcastActivity.this,
+                            getMessageId());
                 }
             }
         });
@@ -203,7 +219,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bit(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bit(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -216,7 +233,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitUmts(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -229,7 +247,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitNoPadding(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitNoPadding(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -243,7 +262,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitNoPaddingUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitNoPaddingUmts(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -257,7 +277,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitMultipageGsm(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitMultipageGsm(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -271,7 +292,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitMultipageUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitMultipageUmts(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -285,7 +307,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitWithLanguage(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitWithLanguage(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -300,7 +323,7 @@
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
                     SendTestMessages.testSendMessage7bitWithLanguageInBody(
-                            SendTestBroadcastActivity.this);
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -314,7 +337,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessage7bitWithLanguageInBodyUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessage7bitWithLanguageInBodyUmts(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -327,7 +351,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessageUcs2(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessageUcs2(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -340,7 +365,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessageUcs2Umts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessageUcs2Umts(SendTestBroadcastActivity.this,
+                            getMessageId(), getCategory());
                 }
             }
         });
@@ -354,7 +380,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessageUcs2MultipageUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessageUcs2MultipageUmts(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -368,7 +395,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessageUcs2WithLanguageInBody(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessageUcs2WithLanguageInBody(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
@@ -382,7 +410,8 @@
                     Message msg = mDelayHandler.obtainMessage(0, this);
                     mDelayHandler.sendMessageDelayed(msg, DELAY_BEFORE_SENDING_MSEC);
                 } else {
-                    SendTestMessages.testSendMessageUcs2WithLanguageUmts(SendTestBroadcastActivity.this);
+                    SendTestMessages.testSendMessageUcs2WithLanguageUmts(
+                            SendTestBroadcastActivity.this, getMessageId(), getCategory());
                 }
             }
         });
diff --git a/tests/src/com/android/cellbroadcastreceiver/tests/SendTestMessages.java b/tests/src/com/android/cellbroadcastreceiver/tests/SendTestMessages.java
index a8496ff..1867118 100644
--- a/tests/src/com/android/cellbroadcastreceiver/tests/SendTestMessages.java
+++ b/tests/src/com/android/cellbroadcastreceiver/tests/SendTestMessages.java
@@ -57,7 +57,7 @@
             "00000000000000000000000000000000000000000000");
 
     private static final byte[] gsm7BitTest = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x40, (byte)0x11, (byte)0x41,
             (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
             (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
             (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
@@ -73,7 +73,7 @@
     };
 
     private static final byte[] gsm7BitTestUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x40,
 
             (byte)0x01,
 
@@ -172,7 +172,7 @@
     };
 
     private static final byte[] gsm7BitTestNoPadding = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x40, (byte)0x11, (byte)0x41,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x40, (byte)0x11, (byte)0x41,
             (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
             (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
             (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
@@ -188,7 +188,7 @@
     };
 
     private static final byte[] gsm7BitTestNoPaddingUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x40,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x40,
 
             (byte)0x01,
 
@@ -211,7 +211,7 @@
     };
 
     private static final byte[] gsm7BitTestWithLanguage = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x04, (byte)0x11, (byte)0x41,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x04, (byte)0x11, (byte)0x41,
             (byte)0xD0, (byte)0x71, (byte)0xDA, (byte)0x04, (byte)0x91, (byte)0xCB, (byte)0xE6,
             (byte)0x70, (byte)0x9D, (byte)0x4D, (byte)0x07, (byte)0x85, (byte)0xD9, (byte)0x70,
             (byte)0x74, (byte)0x58, (byte)0x5C, (byte)0xA6, (byte)0x83, (byte)0xDA, (byte)0xE5,
@@ -227,7 +227,7 @@
     };
 
     private static final byte[] gsm7BitTestWithLanguageInBody = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x10, (byte)0x11, (byte)0x73,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x10, (byte)0x11, (byte)0x73,
             (byte)0x7B, (byte)0x23, (byte)0x08, (byte)0x3A, (byte)0x4E, (byte)0x9B, (byte)0x20,
             (byte)0x72, (byte)0xD9, (byte)0x1C, (byte)0xAE, (byte)0xB3, (byte)0xE9, (byte)0xA0,
             (byte)0x30, (byte)0x1B, (byte)0x8E, (byte)0x0E, (byte)0x8B, (byte)0xCB, (byte)0x74,
@@ -243,7 +243,7 @@
     };
 
     private static final byte[] gsm7BitTestWithLanguageInBodyUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x10,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x10,
 
             (byte)0x01,
 
@@ -266,7 +266,7 @@
     };
 
     private static final byte[] gsmUcs2Test = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x48, (byte)0x11, (byte)0x00,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x48, (byte)0x11, (byte)0x00,
             (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55, (byte)0x00, (byte)0x43,
             (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00, (byte)0x20, (byte)0x00,
             (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73, (byte)0x00, (byte)0x73,
@@ -282,7 +282,7 @@
     };
 
     private static final byte[] gsmUcs2TestUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x48,
 
             (byte)0x01,
 
@@ -305,7 +305,7 @@
     };
 
     private static final byte[] gsmUcs2TestMultipageUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x48,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x48,
 
             (byte)0x02,
 
@@ -345,7 +345,7 @@
     };
 
     private static final byte[] gsmUcs2TestWithLanguageInBody = {
-            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x32, (byte)0x11, (byte)0x11, (byte)0x78,
+            (byte)0xC0, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x11, (byte)0x11, (byte)0x78,
             (byte)0x3C, (byte)0x00, (byte)0x41, (byte)0x00, (byte)0x20, (byte)0x00, (byte)0x55,
             (byte)0x00, (byte)0x43, (byte)0x00, (byte)0x53, (byte)0x00, (byte)0x32, (byte)0x00,
             (byte)0x20, (byte)0x00, (byte)0x6D, (byte)0x00, (byte)0x65, (byte)0x00, (byte)0x73,
@@ -361,7 +361,7 @@
     };
 
     private static final byte[] gsmUcs2TestWithLanguageInBodyUmts = {
-            (byte)0x01, (byte)0x00, (byte)0x32, (byte)0xC0, (byte)0x00, (byte)0x11,
+            (byte)0x01, (byte)0x00, (byte)0x01, (byte)0xC0, (byte)0x00, (byte)0x11,
 
             (byte)0x01,
 
@@ -385,128 +385,161 @@
 
     private static final SmsCbLocation sEmptyLocation = new SmsCbLocation();
 
-    private static SmsCbMessage createFromPdu(byte[] pdu) {
+    private static SmsCbMessage createFromPdu(byte[] pdu, int serialNumber, int category) {
+        byte[][] pdus = new byte[1][];
+        pdus[0] = pdu;
+        return createFromPdus(pdus, serialNumber, category);
+    }
+
+    private static SmsCbMessage createFromPdus(byte[][] pdus, int serialNumber, int category) {
         try {
-            byte[][] pdus = new byte[1][];
-            pdus[0] = pdu;
+            for (byte[] pdu : pdus) {
+                if (pdu.length <= 88) {
+                    // GSM format cell broadcast
+                    Log.d(TAG, "setting GSM serial number to " + serialNumber);
+                    pdu[0] = (byte) ((serialNumber >>> 8) & 0xff);
+                    pdu[1] = (byte) (serialNumber & 0xff);
+                    if (category != 0) {
+                        Log.d(TAG, "setting GSM message identifier to " + category);
+                        pdu[2] = (byte) ((category >>> 8) & 0xff);
+                        pdu[3] = (byte) (category & 0xff);
+                    }
+                } else {
+                    // UMTS format cell broadcast
+                    Log.d(TAG, "setting UMTS serial number to " + serialNumber);
+                    pdu[3] = (byte) ((serialNumber >>> 8) & 0xff);
+                    pdu[4] = (byte) (serialNumber & 0xff);
+                    if (category != 0) {
+                        Log.d(TAG, "setting UMTS message identifier to " + category);
+                        pdu[1] = (byte) ((category >>> 8) & 0xff);
+                        pdu[2] = (byte) (category & 0xff);
+                    }
+                }
+            }
             return GsmSmsCbMessage.createSmsCbMessage(sEmptyLocation, pdus);
         } catch (IllegalArgumentException e) {
             return null;
         }
     }
 
-    private static SmsCbMessage createFromPdus(byte[][] pdus) {
-        try {
-            return GsmSmsCbMessage.createSmsCbMessage(sEmptyLocation, pdus);
-        } catch (IllegalArgumentException e) {
-            return null;
-        }
-    }
-
-    public static void testSendMessage7bit(Activity activity) {
+    public static void testSendMessage7bit(Activity activity, int serialNumber, int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTest));
+        intent.putExtra("message", createFromPdu(gsm7BitTest, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitUmts(Activity activity) {
+    public static void testSendMessage7bitUmts(Activity activity, int serialNumber, int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestUmts));
+        intent.putExtra("message", createFromPdu(gsm7BitTestUmts, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitNoPadding(Activity activity) {
+    public static void testSendMessage7bitNoPadding(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestNoPadding));
+        intent.putExtra("message", createFromPdu(gsm7BitTestNoPadding, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitNoPaddingUmts(Activity activity) {
+    public static void testSendMessage7bitNoPaddingUmts(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestNoPaddingUmts));
+        intent.putExtra("message", createFromPdu(gsm7BitTestNoPaddingUmts, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitMultipageGsm(Activity activity) {
+    public static void testSendMessage7bitMultipageGsm(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
         byte[][] pdus = new byte[2][];
         pdus[0] = gsm7BitTestMultipage1;
         pdus[1] = gsm7BitTestMultipage2;
-        intent.putExtra("message", createFromPdus(pdus));
+        intent.putExtra("message", createFromPdus(pdus, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitMultipageUmts(Activity activity) {
+    public static void testSendMessage7bitMultipageUmts(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestMultipageUmts));
+        intent.putExtra("message", createFromPdu(gsm7BitTestMultipageUmts, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitWithLanguage(Activity activity) {
+    public static void testSendMessage7bitWithLanguage(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguage));
+        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguage, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitWithLanguageInBody(Activity activity) {
+    public static void testSendMessage7bitWithLanguageInBody(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguageInBody));
+        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguageInBody, serialNumber,
+                category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessage7bitWithLanguageInBodyUmts(Activity activity) {
+    public static void testSendMessage7bitWithLanguageInBodyUmts(Activity activity,
+            int serialNumber, int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguageInBodyUmts));
+        intent.putExtra("message", createFromPdu(gsm7BitTestWithLanguageInBodyUmts, serialNumber,
+                category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessageUcs2(Activity activity) {
+    public static void testSendMessageUcs2(Activity activity, int serialNumber, int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsmUcs2Test));
+        intent.putExtra("message", createFromPdu(gsmUcs2Test, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessageUcs2Umts(Activity activity) {
+    public static void testSendMessageUcs2Umts(Activity activity, int serialNumber, int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsmUcs2TestUmts));
+        intent.putExtra("message", createFromPdu(gsmUcs2TestUmts, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessageUcs2MultipageUmts(Activity activity) {
+    public static void testSendMessageUcs2MultipageUmts(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsmUcs2TestMultipageUmts));
+        intent.putExtra("message", createFromPdu(gsmUcs2TestMultipageUmts, serialNumber, category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessageUcs2WithLanguageInBody(Activity activity) {
+    public static void testSendMessageUcs2WithLanguageInBody(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsmUcs2TestWithLanguageInBody));
+        intent.putExtra("message", createFromPdu(gsmUcs2TestWithLanguageInBody, serialNumber,
+                category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendMessageUcs2WithLanguageUmts(Activity activity) {
+    public static void testSendMessageUcs2WithLanguageUmts(Activity activity, int serialNumber,
+            int category) {
         Intent intent = new Intent(Intents.SMS_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(gsmUcs2TestWithLanguageInBodyUmts));
+        intent.putExtra("message", createFromPdu(gsmUcs2TestWithLanguageInBodyUmts, serialNumber,
+                category));
         activity.sendOrderedBroadcast(intent, "android.permission.RECEIVE_SMS");
     }
 
-    public static void testSendEtwsMessageNormal(Activity activity) {
+    public static void testSendEtwsMessageNormal(Activity activity, int serialNumber) {
         Intent intent = new Intent(Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(etwsMessageNormal));
+        intent.putExtra("message", createFromPdu(etwsMessageNormal, serialNumber, 0));
         activity.sendOrderedBroadcast(intent,
                 "android.permission.RECEIVE_EMERGENCY_BROADCAST");
     }
 
-    public static void testSendEtwsMessageCancel(Activity activity) {
+    public static void testSendEtwsMessageCancel(Activity activity, int serialNumber) {
         Intent intent = new Intent(Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(etwsMessageCancel));
+        intent.putExtra("message", createFromPdu(etwsMessageCancel, serialNumber, 0));
         activity.sendOrderedBroadcast(intent,
                 "android.permission.RECEIVE_EMERGENCY_BROADCAST");
     }
 
-    public static void testSendEtwsMessageTest(Activity activity) {
+    public static void testSendEtwsMessageTest(Activity activity, int serialNumber) {
         Intent intent = new Intent(Intents.SMS_EMERGENCY_CB_RECEIVED_ACTION);
-        intent.putExtra("message", createFromPdu(etwsMessageTest));
+        intent.putExtra("message", createFromPdu(etwsMessageTest, serialNumber, 0));
         activity.sendOrderedBroadcast(intent,
                 "android.permission.RECEIVE_EMERGENCY_BROADCAST");
     }