1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.cellbroadcastservice.tests;
18 
19 import android.telephony.CbGeoUtils;
20 import android.telephony.CbGeoUtils.Circle;
21 import android.telephony.CbGeoUtils.Polygon;
22 import android.telephony.SmsCbCmasInfo;
23 import android.telephony.SmsCbEtwsInfo;
24 import android.telephony.SmsCbLocation;
25 import android.telephony.SmsCbMessage;
26 import android.testing.AndroidTestingRunner;
27 import android.testing.TestableLooper;
28 import android.util.Log;
29 
30 import androidx.test.InstrumentationRegistry;
31 
32 import com.android.cellbroadcastservice.GsmSmsCbMessage;
33 import com.android.cellbroadcastservice.R;
34 import com.android.cellbroadcastservice.SmsCbConstants;
35 import com.android.cellbroadcastservice.SmsCbHeader;
36 
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.util.List;
43 import java.util.Random;
44 
45 @RunWith(AndroidTestingRunner.class)
46 @TestableLooper.RunWithLooper
47 public class GsmSmsCbMessageTest extends CellBroadcastServiceTestBase {
48 
49     private static final String TAG = "GsmSmsCbMessageTest";
50 
51     private static final SmsCbLocation TEST_LOCATION = new SmsCbLocation("94040", 1234, 5678);
52 
53 
54     @Before
setUp()55     public void setUp() throws Exception {
56         super.setUp();
57     }
58 
59     @After
tearDown()60     public void tearDown() throws Exception {
61         super.tearDown();
62     }
63 
64     @Test
testGetEtwsPrimaryMessage()65     public void testGetEtwsPrimaryMessage() {
66         String testMessage1 = "Testmessage1";
67         String testMessage2 = "Testmessage2";
68         String testMessage3 = "Testmessage3";
69         String testMessage4 = "Testmessage4";
70         String testMessage5 = "Testmessage5";
71 
72         putResources(R.string.etws_primary_default_message_earthquake, testMessage1);
73         putResources(R.string.etws_primary_default_message_tsunami, testMessage2);
74         putResources(R.string.etws_primary_default_message_earthquake_and_tsunami, testMessage3);
75         putResources(R.string.etws_primary_default_message_test, testMessage4);
76         putResources(R.string.etws_primary_default_message_others, testMessage5);
77 
78         String message = GsmSmsCbMessage.getEtwsPrimaryMessage(mMockedContext,
79                 SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE);
80         Log.d("GsmSmsCbMessageTest", "earthquake message=" + message);
81         assertEquals(testMessage1, message);
82 
83         message = GsmSmsCbMessage.getEtwsPrimaryMessage(mMockedContext,
84                 SmsCbEtwsInfo.ETWS_WARNING_TYPE_TSUNAMI);
85         Log.d("GsmSmsCbMessageTest", "tsunami message=" + message);
86         assertEquals(testMessage2, message);
87 
88         message = GsmSmsCbMessage.getEtwsPrimaryMessage(mMockedContext,
89                 SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE_AND_TSUNAMI);
90         Log.d("GsmSmsCbMessageTest", "earthquake and tsunami message=" + message);
91         assertEquals(testMessage3, message);
92 
93         message = GsmSmsCbMessage.getEtwsPrimaryMessage(mMockedContext,
94                 SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE);
95         Log.d("GsmSmsCbMessageTest", "test message=" + message);
96         assertEquals(testMessage4, message);
97 
98         message = GsmSmsCbMessage.getEtwsPrimaryMessage(mMockedContext,
99                 SmsCbEtwsInfo.ETWS_WARNING_TYPE_OTHER_EMERGENCY);
100         Log.d("GsmSmsCbMessageTest", "others message=" + message);
101         assertEquals(testMessage5, message);
102     }
103 
104     @Test
testCreateMessageFromBinary()105     public void testCreateMessageFromBinary() throws Exception {
106         final byte[] pdu = hexStringToBytes("0111130F6A0101C8329BFD06559BD429E8FE96B3C92C101D9D9"
107                 + "E83D27350B22E1C7EAFF234BDFCADB962AE9A6BCE06A1DCE57B0AD40241C3E73208147B81622E000"
108                 + "0000000000000000000000000000000000000000000000039EA013028B53640A4BF600063204C8FC"
109                 + "D063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E"
110                 + "683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E401"
111                 + "00C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A"
112                 + "4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063204C8FC"
113                 + "D063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E"
114                 + "683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E401"
115                 + "00C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A"
116                 + "4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063204C8FC"
117                 + "D063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E"
118                 + "683CF01215F1E40100C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E401"
119                 + "00C053028B53640A4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A"
120                 + "4BF600063204C8FCD063F341AF67167E683CF01215F1E40100C053028B53640A4BF600063");
121         SmsCbHeader header = new SmsCbHeader(pdu);
122 
123         byte[][] pdus = new byte[1][];
124         pdus[0] = pdu;
125 
126         SmsCbMessage msg = GsmSmsCbMessage.createSmsCbMessage(mMockedContext, header, null, pdus,
127                 0);
128 
129         Log.d(TAG, "msg=" + msg);
130 
131         assertEquals(SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE,
132                 msg.getGeographicalScope());
133         assertEquals(3946, msg.getSerialNumber());
134         assertEquals(SmsCbConstants.MESSAGE_ID_CMAS_ALERT_EXTREME_IMMEDIATE_OBSERVED,
135                 msg.getServiceCategory());
136         assertEquals("en", msg.getLanguageCode());
137         assertEquals("Hello UMTS world, this is IuBC§Write§5.1.5.sl (new) - Page  1/ 1.",
138                 msg.getMessageBody());
139         assertEquals(SmsCbMessage.MESSAGE_PRIORITY_EMERGENCY, msg.getMessagePriority());
140 
141         SmsCbCmasInfo cmasInfo = msg.getCmasWarningInfo();
142         assertEquals(SmsCbCmasInfo.CMAS_CLASS_EXTREME_THREAT, cmasInfo.getMessageClass());
143         assertEquals(SmsCbCmasInfo.CMAS_CATEGORY_UNKNOWN, cmasInfo.getCategory());
144         assertEquals(SmsCbCmasInfo.CMAS_RESPONSE_TYPE_UNKNOWN, cmasInfo.getResponseType());
145         assertEquals(SmsCbCmasInfo.CMAS_URGENCY_IMMEDIATE, cmasInfo.getUrgency());
146         assertEquals(SmsCbCmasInfo.CMAS_CERTAINTY_OBSERVED, cmasInfo.getCertainty());
147 
148         List<CbGeoUtils.Geometry> geometries = msg.getGeometries();
149         for (int i = 0; i < 15; i++) {
150             assertEquals(1546.875, ((Circle) geometries.get(i * 2)).getRadius());
151             assertEquals(37.41462707519531, ((Circle) geometries.get(i * 2)).getCenter().lat);
152             assertEquals(-122.08093643188477, ((Circle) geometries.get(i * 2)).getCenter().lng);
153             assertEquals(11.109967231750488,
154                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(0).lat);
155             assertEquals(22.219934463500977,
156                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(0).lng);
157             assertEquals(33.32998752593994, 44,
158                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(1).lat);
159             assertEquals(44.43995475769043,
160                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(1).lng);
161             assertEquals(55.549964904785156,
162                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(2).lat);
163             assertEquals(-56.560020446777344,
164                     ((Polygon) geometries.get(i * 2 + 1)).getVertices().get(2).lng);
165         }
166     }
167 
168     @Test
testCreateTriggerMessage()169     public void testCreateTriggerMessage() throws Exception {
170         final byte[] pdu = hexStringToBytes("0001113001010010C0111204D2");
171         GsmSmsCbMessage.GeoFencingTriggerMessage triggerMessage =
172                 GsmSmsCbMessage.createGeoFencingTriggerMessage(pdu);
173 
174         Log.d(TAG, "trigger message=" + triggerMessage);
175 
176         assertEquals(1, triggerMessage.type);
177         assertEquals(1, triggerMessage.cbIdentifiers.size());
178         assertEquals(1234, triggerMessage.cbIdentifiers.get(0).serialNumber);
179         assertEquals(SmsCbConstants.MESSAGE_ID_CMAS_ALERT_PRESIDENTIAL_LEVEL,
180                 triggerMessage.cbIdentifiers.get(0).messageIdentifier);
181     }
182 
createFromPdu(byte[] pdu)183     private SmsCbMessage createFromPdu(byte[] pdu) {
184         try {
185             SmsCbHeader header = new SmsCbHeader(pdu);
186             byte[][] pdus = new byte[1][];
187             pdus[0] = pdu;
188             return GsmSmsCbMessage.createSmsCbMessage(InstrumentationRegistry.getContext(), header,
189                     TEST_LOCATION, pdus, /* slotIndex */ 0);
190         } catch (IllegalArgumentException e) {
191             return null;
192         }
193     }
194 
doTestGeographicalScopeValue(byte[] pdu, byte b, int expectedGs)195     private void doTestGeographicalScopeValue(byte[] pdu, byte b, int expectedGs) {
196         pdu[0] = b;
197         SmsCbMessage msg = createFromPdu(pdu);
198 
199         assertEquals("Unexpected geographical scope decoded", expectedGs, msg
200                 .getGeographicalScope());
201     }
202 
203     @Test
testCreateNullPdu()204     public void testCreateNullPdu() {
205         SmsCbMessage msg = createFromPdu(null);
206         assertNull("createFromPdu(byte[] with null pdu should return null", msg);
207     }
208 
209     @Test
testCreateTooShortPdu()210     public void testCreateTooShortPdu() {
211         byte[] pdu = new byte[4];
212         SmsCbMessage msg = createFromPdu(pdu);
213 
214         assertNull("createFromPdu(byte[] with too short pdu should return null", msg);
215     }
216 
217     @Test
testGetGeographicalScope()218     public void testGetGeographicalScope() {
219         byte[] pdu = {
220                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x40, (byte) 0x11,
221                 (byte) 0x41,
222                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
223                 (byte) 0xE6,
224                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
225                 (byte) 0x70,
226                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
227                 (byte) 0xE5,
228                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
229                 (byte) 0x69,
230                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
231                 (byte) 0xE9,
232                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
233                 (byte) 0x75,
234                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
235                 (byte) 0x69,
236                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
237                 (byte) 0x8D,
238                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
239                 (byte) 0x8D,
240                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
241                 (byte) 0x8D,
242                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
243                 (byte) 0x8D,
244                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
245         };
246 
247         doTestGeographicalScopeValue(pdu, (byte) 0x00,
248                 SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE_IMMEDIATE);
249         doTestGeographicalScopeValue(pdu, (byte) 0x40, SmsCbMessage.GEOGRAPHICAL_SCOPE_PLMN_WIDE);
250         doTestGeographicalScopeValue(pdu, (byte) 0x80,
251                 SmsCbMessage.GEOGRAPHICAL_SCOPE_LOCATION_AREA_WIDE);
252         doTestGeographicalScopeValue(pdu, (byte) 0xC0, SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE);
253     }
254 
255     @Test
testGetGeographicalScopeUmts()256     public void testGetGeographicalScopeUmts() {
257         byte[] pdu = {
258                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x40,
259 
260                 (byte) 0x01,
261 
262                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
263                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
264                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
265                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
266                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE, (byte) 0x69, (byte) 0x3A,
267                 (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5, (byte) 0xE9,
268                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
269                 (byte) 0x75, (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93,
270                 (byte) 0xC9, (byte) 0x69, (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
271                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
272                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
273                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
274                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
275                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
276 
277                 (byte) 0x34
278         };
279 
280         SmsCbMessage msg = createFromPdu(pdu);
281 
282         assertEquals("Unexpected geographical scope decoded",
283                 SmsCbMessage.GEOGRAPHICAL_SCOPE_CELL_WIDE, msg.getGeographicalScope());
284     }
285 
286     @Test
testGetMessageBody7Bit()287     public void testGetMessageBody7Bit() {
288         byte[] pdu = {
289                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x40, (byte) 0x11,
290                 (byte) 0x41,
291                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
292                 (byte) 0xE6,
293                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
294                 (byte) 0x70,
295                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
296                 (byte) 0xE5,
297                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
298                 (byte) 0x69,
299                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
300                 (byte) 0xE9,
301                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
302                 (byte) 0x75,
303                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
304                 (byte) 0x69,
305                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
306                 (byte) 0x8D,
307                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
308                 (byte) 0x8D,
309                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
310                 (byte) 0x8D,
311                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
312                 (byte) 0x8D,
313                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
314         };
315         SmsCbMessage msg = createFromPdu(pdu);
316 
317         assertEquals("Unexpected 7-bit string decoded",
318                 "A GSM default alphabet message with carriage return padding",
319                 msg.getMessageBody());
320     }
321 
322     @Test
testGetMessageBody7BitUmts()323     public void testGetMessageBody7BitUmts() {
324         byte[] pdu = {
325                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x40,
326 
327                 (byte) 0x01,
328 
329                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
330                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
331                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
332                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
333                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE, (byte) 0x69, (byte) 0x3A,
334                 (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5, (byte) 0xE9,
335                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
336                 (byte) 0x75, (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93,
337                 (byte) 0xC9, (byte) 0x69, (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
338                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
339                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
340                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
341                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
342                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
343 
344                 (byte) 0x34
345         };
346         SmsCbMessage msg = createFromPdu(pdu);
347 
348         assertEquals("Unexpected 7-bit string decoded",
349                 "A GSM default alphabet message with carriage return padding",
350                 msg.getMessageBody());
351     }
352 
353     @Test
testGetMessageBody7BitMultipageUmts()354     public void testGetMessageBody7BitMultipageUmts() {
355         byte[] pdu = {
356                 (byte) 0x01, (byte) 0x00, (byte) 0x01, (byte) 0xC0, (byte) 0x00, (byte) 0x40,
357 
358                 (byte) 0x02,
359 
360                 (byte) 0xC6, (byte) 0xB4, (byte) 0x7C, (byte) 0x4E, (byte) 0x07, (byte) 0xC1,
361                 (byte) 0xC3, (byte) 0xE7, (byte) 0xF2, (byte) 0xAA, (byte) 0xD1, (byte) 0x68,
362                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
363                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
364                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
365                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
366                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
367                 (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34,
368                 (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68,
369                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
370                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
371                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
372                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
373                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
374 
375                 (byte) 0x0A,
376 
377                 (byte) 0xD3, (byte) 0xF2, (byte) 0xF8, (byte) 0xED, (byte) 0x26, (byte) 0x83,
378                 (byte) 0xE0, (byte) 0xE1, (byte) 0x73, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
379                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
380                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
381                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
382                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
383                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
384                 (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34,
385                 (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68,
386                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
387                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
388                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
389                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
390                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
391 
392                 (byte) 0x0A
393         };
394         SmsCbMessage msg = createFromPdu(pdu);
395 
396         assertEquals("Unexpected multipage 7-bit string decoded",
397                 "First page+Second page",
398                 msg.getMessageBody());
399     }
400 
401     @Test
testGetMessageBody7BitFull()402     public void testGetMessageBody7BitFull() {
403         byte[] pdu = {
404                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x40, (byte) 0x11,
405                 (byte) 0x41,
406                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
407                 (byte) 0xE6,
408                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
409                 (byte) 0x70,
410                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
411                 (byte) 0xE5,
412                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xC4,
413                 (byte) 0xE5,
414                 (byte) 0xB4, (byte) 0xFB, (byte) 0x0C, (byte) 0x2A, (byte) 0xE3, (byte) 0xC3,
415                 (byte) 0x63,
416                 (byte) 0x3A, (byte) 0x3B, (byte) 0x0F, (byte) 0xCA, (byte) 0xCD, (byte) 0x40,
417                 (byte) 0x63,
418                 (byte) 0x74, (byte) 0x58, (byte) 0x1E, (byte) 0x1E, (byte) 0xD3, (byte) 0xCB,
419                 (byte) 0xF2,
420                 (byte) 0x39, (byte) 0x88, (byte) 0xFD, (byte) 0x76, (byte) 0x9F, (byte) 0x59,
421                 (byte) 0xA0,
422                 (byte) 0x76, (byte) 0x39, (byte) 0xEC, (byte) 0x4E, (byte) 0xBB, (byte) 0xCF,
423                 (byte) 0x20,
424                 (byte) 0x3A, (byte) 0xBA, (byte) 0x2C, (byte) 0x2F, (byte) 0x83, (byte) 0xD2,
425                 (byte) 0x73,
426                 (byte) 0x90, (byte) 0xFB, (byte) 0x0D, (byte) 0x82, (byte) 0x87, (byte) 0xC9,
427                 (byte) 0xE4,
428                 (byte) 0xB4, (byte) 0xFB, (byte) 0x1C, (byte) 0x02
429         };
430         SmsCbMessage msg = createFromPdu(pdu);
431 
432         assertEquals(
433                 "Unexpected 7-bit string decoded",
434                 "A GSM default alphabet message being exactly 93 characters long, "
435                         + "meaning there is no padding!",
436                 msg.getMessageBody());
437     }
438 
439     @Test
testGetMessageBody7BitFullUmts()440     public void testGetMessageBody7BitFullUmts() {
441         byte[] pdu = {
442                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x40,
443 
444                 (byte) 0x01,
445 
446                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
447                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
448                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
449                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
450                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xC4, (byte) 0xE5, (byte) 0xB4,
451                 (byte) 0xFB, (byte) 0x0C, (byte) 0x2A, (byte) 0xE3, (byte) 0xC3, (byte) 0x63,
452                 (byte) 0x3A, (byte) 0x3B, (byte) 0x0F, (byte) 0xCA, (byte) 0xCD, (byte) 0x40,
453                 (byte) 0x63, (byte) 0x74, (byte) 0x58, (byte) 0x1E, (byte) 0x1E, (byte) 0xD3,
454                 (byte) 0xCB, (byte) 0xF2, (byte) 0x39, (byte) 0x88, (byte) 0xFD, (byte) 0x76,
455                 (byte) 0x9F, (byte) 0x59, (byte) 0xA0, (byte) 0x76, (byte) 0x39, (byte) 0xEC,
456                 (byte) 0x4E, (byte) 0xBB, (byte) 0xCF, (byte) 0x20, (byte) 0x3A, (byte) 0xBA,
457                 (byte) 0x2C, (byte) 0x2F, (byte) 0x83, (byte) 0xD2, (byte) 0x73, (byte) 0x90,
458                 (byte) 0xFB, (byte) 0x0D, (byte) 0x82, (byte) 0x87, (byte) 0xC9, (byte) 0xE4,
459                 (byte) 0xB4, (byte) 0xFB, (byte) 0x1C, (byte) 0x02,
460 
461                 (byte) 0x52
462         };
463         SmsCbMessage msg = createFromPdu(pdu);
464 
465         assertEquals(
466                 "Unexpected 7-bit string decoded",
467                 "A GSM default alphabet message being exactly 93 characters long, "
468                         + "meaning there is no padding!",
469                 msg.getMessageBody());
470     }
471 
472     @Test
testGetMessageBody7BitWithLanguage()473     public void testGetMessageBody7BitWithLanguage() {
474         byte[] pdu = {
475                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x04, (byte) 0x11,
476                 (byte) 0x41,
477                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
478                 (byte) 0xE6,
479                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
480                 (byte) 0x70,
481                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
482                 (byte) 0xE5,
483                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
484                 (byte) 0x69,
485                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
486                 (byte) 0xE9,
487                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
488                 (byte) 0x75,
489                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
490                 (byte) 0x69,
491                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
492                 (byte) 0x8D,
493                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
494                 (byte) 0x8D,
495                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
496                 (byte) 0x8D,
497                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
498                 (byte) 0x8D,
499                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
500         };
501         SmsCbMessage msg = createFromPdu(pdu);
502 
503         assertEquals("Unexpected 7-bit string decoded",
504                 "A GSM default alphabet message with carriage return padding",
505                 msg.getMessageBody());
506 
507         assertEquals("Unexpected language indicator decoded", "es", msg.getLanguageCode());
508     }
509 
510     @Test
testGetMessageBody7BitWithLanguageInBody()511     public void testGetMessageBody7BitWithLanguageInBody() {
512         byte[] pdu = {
513                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x10, (byte) 0x11,
514                 (byte) 0x73,
515                 (byte) 0x7B, (byte) 0x23, (byte) 0x08, (byte) 0x3A, (byte) 0x4E, (byte) 0x9B,
516                 (byte) 0x20,
517                 (byte) 0x72, (byte) 0xD9, (byte) 0x1C, (byte) 0xAE, (byte) 0xB3, (byte) 0xE9,
518                 (byte) 0xA0,
519                 (byte) 0x30, (byte) 0x1B, (byte) 0x8E, (byte) 0x0E, (byte) 0x8B, (byte) 0xCB,
520                 (byte) 0x74,
521                 (byte) 0x50, (byte) 0xBB, (byte) 0x3C, (byte) 0x9F, (byte) 0x87, (byte) 0xCF,
522                 (byte) 0x65,
523                 (byte) 0xD0, (byte) 0x3D, (byte) 0x4D, (byte) 0x47, (byte) 0x83, (byte) 0xC6,
524                 (byte) 0x61,
525                 (byte) 0xB9, (byte) 0x3C, (byte) 0x1D, (byte) 0x3E, (byte) 0x97, (byte) 0x41,
526                 (byte) 0xF2,
527                 (byte) 0x32, (byte) 0xBD, (byte) 0x2E, (byte) 0x77, (byte) 0x83, (byte) 0xE0,
528                 (byte) 0x61,
529                 (byte) 0x32, (byte) 0x39, (byte) 0xED, (byte) 0x3E, (byte) 0x37, (byte) 0x1A,
530                 (byte) 0x8D,
531                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
532                 (byte) 0x8D,
533                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
534                 (byte) 0x8D,
535                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
536                 (byte) 0x8D,
537                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
538         };
539         SmsCbMessage msg = createFromPdu(pdu);
540 
541         assertEquals("Unexpected 7-bit string decoded",
542                 "A GSM default alphabet message with carriage return padding",
543                 msg.getMessageBody());
544 
545         assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
546     }
547 
548     @Test
testGetMessageBody7BitWithLanguageInBodyUmts()549     public void testGetMessageBody7BitWithLanguageInBodyUmts() {
550         byte[] pdu = {
551                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x10,
552 
553                 (byte) 0x01,
554 
555                 (byte) 0x73, (byte) 0x7B, (byte) 0x23, (byte) 0x08, (byte) 0x3A, (byte) 0x4E,
556                 (byte) 0x9B, (byte) 0x20, (byte) 0x72, (byte) 0xD9, (byte) 0x1C, (byte) 0xAE,
557                 (byte) 0xB3, (byte) 0xE9, (byte) 0xA0, (byte) 0x30, (byte) 0x1B, (byte) 0x8E,
558                 (byte) 0x0E, (byte) 0x8B, (byte) 0xCB, (byte) 0x74, (byte) 0x50, (byte) 0xBB,
559                 (byte) 0x3C, (byte) 0x9F, (byte) 0x87, (byte) 0xCF, (byte) 0x65, (byte) 0xD0,
560                 (byte) 0x3D, (byte) 0x4D, (byte) 0x47, (byte) 0x83, (byte) 0xC6, (byte) 0x61,
561                 (byte) 0xB9, (byte) 0x3C, (byte) 0x1D, (byte) 0x3E, (byte) 0x97, (byte) 0x41,
562                 (byte) 0xF2, (byte) 0x32, (byte) 0xBD, (byte) 0x2E, (byte) 0x77, (byte) 0x83,
563                 (byte) 0xE0, (byte) 0x61, (byte) 0x32, (byte) 0x39, (byte) 0xED, (byte) 0x3E,
564                 (byte) 0x37, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
565                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
566                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
567                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
568                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
569 
570                 (byte) 0x37
571         };
572         SmsCbMessage msg = createFromPdu(pdu);
573 
574         assertEquals("Unexpected 7-bit string decoded",
575                 "A GSM default alphabet message with carriage return padding",
576                 msg.getMessageBody());
577 
578         assertEquals("Unexpected language indicator decoded", "sv", msg.getLanguageCode());
579     }
580 
581     @Test
testGetMessageBodyGsm8Bit()582     public void testGetMessageBodyGsm8Bit() {
583         byte[] pdu = {
584                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x44, (byte) 0x11,
585                 (byte) 0x41, (byte) 0x20, (byte) 0x47, (byte) 0x53, (byte) 0x4D, (byte) 0x20,
586                 (byte) 0x38, (byte) 0x2D, (byte) 0x62, (byte) 0x69, (byte) 0x74, (byte) 0x20,
587                 (byte) 0x6D, (byte) 0x65, (byte) 0x73, (byte) 0x73, (byte) 0x61, (byte) 0x67,
588                 (byte) 0x65, (byte) 0x20, (byte) 0x77, (byte) 0x69, (byte) 0x74, (byte) 0x68,
589                 (byte) 0x20, (byte) 0x63, (byte) 0x61, (byte) 0x72, (byte) 0x72, (byte) 0x69,
590                 (byte) 0x61, (byte) 0x67, (byte) 0x65, (byte) 0x20, (byte) 0x72, (byte) 0x65,
591                 (byte) 0x74, (byte) 0x75, (byte) 0x72, (byte) 0x6E, (byte) 0x20, (byte) 0x70,
592                 (byte) 0x61, (byte) 0x64, (byte) 0x64, (byte) 0x69, (byte) 0x6E, (byte) 0x67,
593                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
594                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
595                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
596                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
597                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
598                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D
599         };
600         SmsCbMessage msg = createFromPdu(pdu);
601 
602         assertEquals("Unexpected 8-bit string decoded",
603                 "A GSM 8-bit message with carriage return padding", msg.getMessageBody());
604     }
605 
606     @Test
testGetMessageBodyUcs2()607     public void testGetMessageBodyUcs2() {
608         byte[] pdu = {
609                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x48, (byte) 0x11,
610                 (byte) 0x00,
611                 (byte) 0x41, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x55, (byte) 0x00,
612                 (byte) 0x43,
613                 (byte) 0x00, (byte) 0x53, (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x20,
614                 (byte) 0x00,
615                 (byte) 0x6D, (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x73, (byte) 0x00,
616                 (byte) 0x73,
617                 (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x65,
618                 (byte) 0x00,
619                 (byte) 0x20, (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x6F, (byte) 0x00,
620                 (byte) 0x6E,
621                 (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x69,
622                 (byte) 0x00,
623                 (byte) 0x6E, (byte) 0x00, (byte) 0x69, (byte) 0x00, (byte) 0x6E, (byte) 0x00,
624                 (byte) 0x67,
625                 (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x20,
626                 (byte) 0x04,
627                 (byte) 0x34, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x63, (byte) 0x00,
628                 (byte) 0x68,
629                 (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x61,
630                 (byte) 0x00,
631                 (byte) 0x63, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x65, (byte) 0x00,
632                 (byte) 0x72,
633                 (byte) 0x00, (byte) 0x0D, (byte) 0x00, (byte) 0x0D
634         };
635         SmsCbMessage msg = createFromPdu(pdu);
636 
637         assertEquals("Unexpected UCS2 string decoded",
638                 "A UCS2 message containing a \u0434 character", msg.getMessageBody());
639     }
640 
641     @Test
testGetMessageBodyUcs2Umts()642     public void testGetMessageBodyUcs2Umts() {
643         byte[] pdu = {
644                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x48,
645 
646                 (byte) 0x01,
647 
648                 (byte) 0x00, (byte) 0x41, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x55,
649                 (byte) 0x00, (byte) 0x43, (byte) 0x00, (byte) 0x53, (byte) 0x00, (byte) 0x32,
650                 (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x6D, (byte) 0x00, (byte) 0x65,
651                 (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x61,
652                 (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x20,
653                 (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x6F, (byte) 0x00, (byte) 0x6E,
654                 (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x69,
655                 (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x69, (byte) 0x00, (byte) 0x6E,
656                 (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x61,
657                 (byte) 0x00, (byte) 0x20, (byte) 0x04, (byte) 0x34, (byte) 0x00, (byte) 0x20,
658                 (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x68, (byte) 0x00, (byte) 0x61,
659                 (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x63,
660                 (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x72,
661                 (byte) 0x00, (byte) 0x0D, (byte) 0x00, (byte) 0x0D,
662 
663                 (byte) 0x4E
664         };
665         SmsCbMessage msg = createFromPdu(pdu);
666 
667         assertEquals("Unexpected UCS2 decoded",
668                 "A UCS2 message containing a \u0434 character", msg.getMessageBody());
669     }
670 
671     @Test
testGetMessageBodyUcs2MultipageUmts()672     public void testGetMessageBodyUcs2MultipageUmts() {
673         byte[] pdu = {
674                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x48,
675 
676                 (byte) 0x02,
677 
678                 (byte) 0x00, (byte) 0x41, (byte) 0x00, (byte) 0x41, (byte) 0x00, (byte) 0x41,
679                 (byte) 0x00, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
680                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
681                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
682                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
683                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
684                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
685                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
686                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
687                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
688                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
689                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
690                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
691                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
692 
693                 (byte) 0x06,
694 
695                 (byte) 0x00, (byte) 0x42, (byte) 0x00, (byte) 0x42, (byte) 0x00, (byte) 0x42,
696                 (byte) 0x00, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
697                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
698                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
699                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
700                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
701                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
702                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
703                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
704                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
705                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
706                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
707                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
708                 (byte) 0x0D, (byte) 0x0D, (byte) 0x0D, (byte) 0x0D,
709 
710                 (byte) 0x06
711         };
712         SmsCbMessage msg = createFromPdu(pdu);
713 
714         assertEquals("Unexpected multipage UCS2 string decoded",
715                 "AAABBB", msg.getMessageBody());
716     }
717 
718     @Test
testGetMessageBodyUcs2WithLanguageInBody()719     public void testGetMessageBodyUcs2WithLanguageInBody() {
720         byte[] pdu = {
721                 (byte) 0xC0, (byte) 0x00, (byte) 0x00, (byte) 0x32, (byte) 0x11, (byte) 0x11,
722                 (byte) 0x78,
723                 (byte) 0x3C, (byte) 0x00, (byte) 0x41, (byte) 0x00, (byte) 0x20, (byte) 0x00,
724                 (byte) 0x55,
725                 (byte) 0x00, (byte) 0x43, (byte) 0x00, (byte) 0x53, (byte) 0x00, (byte) 0x32,
726                 (byte) 0x00,
727                 (byte) 0x20, (byte) 0x00, (byte) 0x6D, (byte) 0x00, (byte) 0x65, (byte) 0x00,
728                 (byte) 0x73,
729                 (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x67,
730                 (byte) 0x00,
731                 (byte) 0x65, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x63, (byte) 0x00,
732                 (byte) 0x6F,
733                 (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x61,
734                 (byte) 0x00,
735                 (byte) 0x69, (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x69, (byte) 0x00,
736                 (byte) 0x6E,
737                 (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x61,
738                 (byte) 0x00,
739                 (byte) 0x20, (byte) 0x04, (byte) 0x34, (byte) 0x00, (byte) 0x20, (byte) 0x00,
740                 (byte) 0x63,
741                 (byte) 0x00, (byte) 0x68, (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x72,
742                 (byte) 0x00,
743                 (byte) 0x61, (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x74, (byte) 0x00,
744                 (byte) 0x65,
745                 (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x0D
746         };
747         SmsCbMessage msg = createFromPdu(pdu);
748 
749         assertEquals("Unexpected UCS2 string decoded",
750                 "A UCS2 message containing a \u0434 character", msg.getMessageBody());
751 
752         assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
753     }
754 
755     @Test
testGetMessageBodyUcs2WithLanguageInBodyUmts()756     public void testGetMessageBodyUcs2WithLanguageInBodyUmts() {
757         byte[] pdu = {
758                 (byte) 0x01, (byte) 0x00, (byte) 0x32, (byte) 0xC0, (byte) 0x00, (byte) 0x11,
759 
760                 (byte) 0x01,
761 
762                 (byte) 0x78, (byte) 0x3C, (byte) 0x00, (byte) 0x41, (byte) 0x00, (byte) 0x20,
763                 (byte) 0x00, (byte) 0x55, (byte) 0x00, (byte) 0x43, (byte) 0x00, (byte) 0x53,
764                 (byte) 0x00, (byte) 0x32, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x6D,
765                 (byte) 0x00, (byte) 0x65, (byte) 0x00, (byte) 0x73, (byte) 0x00, (byte) 0x73,
766                 (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x65,
767                 (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x6F,
768                 (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x61,
769                 (byte) 0x00, (byte) 0x69, (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x69,
770                 (byte) 0x00, (byte) 0x6E, (byte) 0x00, (byte) 0x67, (byte) 0x00, (byte) 0x20,
771                 (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x20, (byte) 0x04, (byte) 0x34,
772                 (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x68,
773                 (byte) 0x00, (byte) 0x61, (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x61,
774                 (byte) 0x00, (byte) 0x63, (byte) 0x00, (byte) 0x74, (byte) 0x00, (byte) 0x65,
775                 (byte) 0x00, (byte) 0x72, (byte) 0x00, (byte) 0x0D,
776 
777                 (byte) 0x50
778         };
779         SmsCbMessage msg = createFromPdu(pdu);
780 
781         assertEquals("Unexpected UCS2 string decoded",
782                 "A UCS2 message containing a \u0434 character", msg.getMessageBody());
783 
784         assertEquals("Unexpected language indicator decoded", "xx", msg.getLanguageCode());
785     }
786 
787     @Test
testGetMessageIdentifier()788     public void testGetMessageIdentifier() {
789         byte[] pdu = {
790                 (byte) 0xC0, (byte) 0x00, (byte) 0x30, (byte) 0x39, (byte) 0x40, (byte) 0x11,
791                 (byte) 0x41,
792                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
793                 (byte) 0xE6,
794                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
795                 (byte) 0x70,
796                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
797                 (byte) 0xE5,
798                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
799                 (byte) 0x69,
800                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
801                 (byte) 0xE9,
802                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
803                 (byte) 0x75,
804                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
805                 (byte) 0x69,
806                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
807                 (byte) 0x8D,
808                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
809                 (byte) 0x8D,
810                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
811                 (byte) 0x8D,
812                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
813                 (byte) 0x8D,
814                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
815         };
816 
817         SmsCbMessage msg = createFromPdu(pdu);
818 
819         assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
820     }
821 
822     @Test
testGetMessageIdentifierUmts()823     public void testGetMessageIdentifierUmts() {
824         byte[] pdu = {
825                 (byte) 0x01, (byte) 0x30, (byte) 0x39, (byte) 0x2A, (byte) 0xA5, (byte) 0x40,
826 
827                 (byte) 0x01,
828 
829                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
830                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
831                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
832                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
833                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE, (byte) 0x69, (byte) 0x3A,
834                 (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5, (byte) 0xE9,
835                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
836                 (byte) 0x75, (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93,
837                 (byte) 0xC9, (byte) 0x69, (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
838                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
839                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
840                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
841                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
842                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
843 
844                 (byte) 0x34
845         };
846 
847         SmsCbMessage msg = createFromPdu(pdu);
848 
849         assertEquals("Unexpected message identifier decoded", 12345, msg.getServiceCategory());
850     }
851 
852     @Test
testGetMessageCode()853     public void testGetMessageCode() {
854         byte[] pdu = {
855                 (byte) 0x2A, (byte) 0xA5, (byte) 0x30, (byte) 0x39, (byte) 0x40, (byte) 0x11,
856                 (byte) 0x41,
857                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
858                 (byte) 0xE6,
859                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
860                 (byte) 0x70,
861                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
862                 (byte) 0xE5,
863                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
864                 (byte) 0x69,
865                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
866                 (byte) 0xE9,
867                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
868                 (byte) 0x75,
869                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
870                 (byte) 0x69,
871                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
872                 (byte) 0x8D,
873                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
874                 (byte) 0x8D,
875                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
876                 (byte) 0x8D,
877                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
878                 (byte) 0x8D,
879                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
880         };
881 
882         SmsCbMessage msg = createFromPdu(pdu);
883         int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
884 
885         assertEquals("Unexpected message code decoded", 682, messageCode);
886     }
887 
888     @Test
testGetMessageCodeUmts()889     public void testGetMessageCodeUmts() {
890         byte[] pdu = {
891                 (byte) 0x01, (byte) 0x30, (byte) 0x39, (byte) 0x2A, (byte) 0xA5, (byte) 0x40,
892 
893                 (byte) 0x01,
894 
895                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
896                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
897                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
898                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
899                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE, (byte) 0x69, (byte) 0x3A,
900                 (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5, (byte) 0xE9,
901                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
902                 (byte) 0x75, (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93,
903                 (byte) 0xC9, (byte) 0x69, (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
904                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
905                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
906                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
907                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
908                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
909 
910                 (byte) 0x34
911         };
912 
913         SmsCbMessage msg = createFromPdu(pdu);
914         int messageCode = (msg.getSerialNumber() & 0x3ff0) >> 4;
915 
916         assertEquals("Unexpected message code decoded", 682, messageCode);
917     }
918 
919     @Test
testGetUpdateNumber()920     public void testGetUpdateNumber() {
921         byte[] pdu = {
922                 (byte) 0x2A, (byte) 0xA5, (byte) 0x30, (byte) 0x39, (byte) 0x40, (byte) 0x11,
923                 (byte) 0x41,
924                 (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91, (byte) 0xCB,
925                 (byte) 0xE6,
926                 (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07, (byte) 0x85, (byte) 0xD9,
927                 (byte) 0x70,
928                 (byte) 0x74, (byte) 0x58, (byte) 0x5C, (byte) 0xA6, (byte) 0x83, (byte) 0xDA,
929                 (byte) 0xE5,
930                 (byte) 0xF9, (byte) 0x3C, (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE,
931                 (byte) 0x69,
932                 (byte) 0x3A, (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5,
933                 (byte) 0xE9,
934                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
935                 (byte) 0x75,
936                 (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93, (byte) 0xC9,
937                 (byte) 0x69,
938                 (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
939                 (byte) 0x8D,
940                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
941                 (byte) 0x8D,
942                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
943                 (byte) 0x8D,
944                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A,
945                 (byte) 0x8D,
946                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00
947         };
948 
949         SmsCbMessage msg = createFromPdu(pdu);
950         int updateNumber = msg.getSerialNumber() & 0x000f;
951 
952         assertEquals("Unexpected update number decoded", 5, updateNumber);
953     }
954 
955     @Test
testGetUpdateNumberUmts()956     public void testGetUpdateNumberUmts() {
957         byte[] pdu = {
958                 (byte) 0x01, (byte) 0x30, (byte) 0x39, (byte) 0x2A, (byte) 0xA5, (byte) 0x40,
959 
960                 (byte) 0x01,
961 
962                 (byte) 0x41, (byte) 0xD0, (byte) 0x71, (byte) 0xDA, (byte) 0x04, (byte) 0x91,
963                 (byte) 0xCB, (byte) 0xE6, (byte) 0x70, (byte) 0x9D, (byte) 0x4D, (byte) 0x07,
964                 (byte) 0x85, (byte) 0xD9, (byte) 0x70, (byte) 0x74, (byte) 0x58, (byte) 0x5C,
965                 (byte) 0xA6, (byte) 0x83, (byte) 0xDA, (byte) 0xE5, (byte) 0xF9, (byte) 0x3C,
966                 (byte) 0x7C, (byte) 0x2E, (byte) 0x83, (byte) 0xEE, (byte) 0x69, (byte) 0x3A,
967                 (byte) 0x1A, (byte) 0x34, (byte) 0x0E, (byte) 0xCB, (byte) 0xE5, (byte) 0xE9,
968                 (byte) 0xF0, (byte) 0xB9, (byte) 0x0C, (byte) 0x92, (byte) 0x97, (byte) 0xE9,
969                 (byte) 0x75, (byte) 0xB9, (byte) 0x1B, (byte) 0x04, (byte) 0x0F, (byte) 0x93,
970                 (byte) 0xC9, (byte) 0x69, (byte) 0xF7, (byte) 0xB9, (byte) 0xD1, (byte) 0x68,
971                 (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3, (byte) 0xD1,
972                 (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46, (byte) 0xA3,
973                 (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D, (byte) 0x46,
974                 (byte) 0xA3, (byte) 0xD1, (byte) 0x68, (byte) 0x34, (byte) 0x1A, (byte) 0x8D,
975                 (byte) 0x46, (byte) 0xA3, (byte) 0xD1, (byte) 0x00,
976 
977                 (byte) 0x34
978         };
979 
980         SmsCbMessage msg = createFromPdu(pdu);
981         int updateNumber = msg.getSerialNumber() & 0x000f;
982 
983         assertEquals("Unexpected update number decoded", 5, updateNumber);
984     }
985 
986     /* ETWS Test message including header */
987     private static final byte[] etwsMessageNormal = hexStringToBytes("000011001101"
988             + "0D0A5BAE57CE770C531790E85C716CBF3044573065B930675730"
989             + "9707767A751F30025F37304463FA308C306B5099304830664E0B30553044FF086C178C615E81FF09"
990             + "0000000000000000000000000000");
991 
992     private static final byte[] etwsMessageCancel = hexStringToBytes("000011001101"
993             + "0D0A5148307B3069002800310030003A0035"
994             + "00320029306E7DCA602557309707901F5831309253D66D883057307E3059FF086C178C615E81FF09"
995             + "00000000000000000000000000000000000000000000");
996 
997     private static final byte[] etwsMessageTest = hexStringToBytes("000011031101"
998             + "0D0A5BAE57CE770C531790E85C716CBF3044"
999             + "573065B9306757309707300263FA308C306B5099304830664E0B30553044FF086C178C615E81FF09"
1000             + "00000000000000000000000000000000000000000000");
1001 
1002     // FIXME: add example of ETWS primary notification PDU
1003 
1004     @Test
testEtwsMessageNormal()1005     public void testEtwsMessageNormal() {
1006         SmsCbMessage msg = createFromPdu(etwsMessageNormal);
1007         Log.d(TAG, msg.toString());
1008         assertEquals("GS mismatch", 0, msg.getGeographicalScope());
1009         assertEquals("serial number mismatch", 0, msg.getSerialNumber());
1010         assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
1011         assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
1012                 msg.getEtwsWarningInfo().getWarningType());
1013     }
1014 
1015     @Test
testEtwsMessageCancel()1016     public void testEtwsMessageCancel() {
1017         SmsCbMessage msg = createFromPdu(etwsMessageCancel);
1018         Log.d(TAG, msg.toString());
1019         assertEquals("GS mismatch", 0, msg.getGeographicalScope());
1020         assertEquals("serial number mismatch", 0, msg.getSerialNumber());
1021         assertEquals("message ID mismatch", 0x1100, msg.getServiceCategory());
1022         assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_EARTHQUAKE,
1023                 msg.getEtwsWarningInfo().getWarningType());
1024     }
1025 
1026     @Test
testEtwsMessageTest()1027     public void testEtwsMessageTest() {
1028         SmsCbMessage msg = createFromPdu(etwsMessageTest);
1029         Log.d(TAG, msg.toString());
1030         assertEquals("GS mismatch", 0, msg.getGeographicalScope());
1031         assertEquals("serial number mismatch", 0, msg.getSerialNumber());
1032         assertEquals("message ID mismatch", 0x1103, msg.getServiceCategory());
1033         assertEquals("warning type mismatch", SmsCbEtwsInfo.ETWS_WARNING_TYPE_TEST_MESSAGE,
1034                 msg.getEtwsWarningInfo().getWarningType());
1035     }
1036 
1037     // Make sure we don't throw an exception if we feed random data to the PDU parser.
1038     @Test
testRandomPdus()1039     public void testRandomPdus() {
1040         Random r = new Random(94040);
1041         for (int run = 0; run < 10000; run++) {
1042             int len = r.nextInt(140);
1043             byte[] data = new byte[len];
1044             for (int i = 0; i < len; i++) {
1045                 data[i] = (byte) r.nextInt(256);
1046             }
1047             try {
1048                 // this should return a SmsCbMessage object or null for invalid data
1049                 SmsCbMessage msg = createFromPdu(data);
1050             } catch (Exception e) {
1051                 Log.d(TAG, "exception thrown", e);
1052                 fail("Exception in decoder at run " + run + " length " + len + ": " + e);
1053             }
1054         }
1055     }
1056 }
1057