1 /*
2  * Copyright (C) 2009 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 android.telephony.cts;
18 
19 
20 import android.app.PendingIntent;
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.pm.PackageManager;
26 import android.os.Bundle;
27 import android.os.SystemClock;
28 import android.telephony.SmsManager;
29 import android.telephony.SmsMessage;
30 import android.telephony.TelephonyManager;
31 import android.test.AndroidTestCase;
32 import android.util.Log;
33 
34 import java.util.ArrayList;
35 import java.util.Arrays;
36 import java.util.List;
37 
38 /**
39  * Tests for {@link android.telephony.SmsManager}.
40  *
41  * Structured so tests can be reused to test {@link android.telephony.gsm.SmsManager}
42  */
43 public class SmsManagerTest extends AndroidTestCase {
44 
45     private static final String TAG = "SmsManagerTest";
46     private static final String LONG_TEXT =
47         "This is a very long text. This text should be broken into three " +
48         "separate messages.This is a very long text. This text should be broken into " +
49         "three separate messages.This is a very long text. This text should be broken " +
50         "into three separate messages.This is a very long text. This text should be " +
51         "broken into three separate messages.";;
52     private static final String LONG_TEXT_WITH_32BIT_CHARS =
53         "Long dkkshsh jdjsusj kbsksbdf jfkhcu hhdiwoqiwyrygrvn?*?*!\";:'/,."
54         + "__?9#9292736&4;\"$+$+((]\\[\\℅©℅™^®°¥°¥=¢£}}£∆~¶~÷|√×."
55         + " ������������������������������⛪⛲ ";
56 
57     private static final String SMS_SEND_ACTION = "CTS_SMS_SEND_ACTION";
58     private static final String SMS_DELIVERY_ACTION = "CTS_SMS_DELIVERY_ACTION";
59     private static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED";
60 
61     // List of network operators that don't support SMS delivery report
62     private static final List<String> NO_DELIVERY_REPORTS =
63             Arrays.asList(
64                     "310410",   // AT&T Mobility
65                     "44010",    // NTT DOCOMO
66                     "45005",    // SKT Mobility
67                     "45002",    // SKT Mobility
68                     "45008",    // KT Mobility
69                     "45006",    // LGT
70                     "311660",   // MetroPCS
71                     "310120",   // Sprint
72                     "44050",    // KDDI
73                     "44051",    // KDDI
74                     "44053",    // KDDI
75                     "44054",    // KDDI
76                     "44070",    // KDDI
77                     "44071",    // KDDI
78                     "44072",    // KDDI
79                     "44073",    // KDDI
80                     "44074",    // KDDI
81                     "44075",    // KDDI
82                     "44076",    // KDDI
83                     "50502",    // OPS
84                     "51502",    // Globe Telecoms
85                     "51503",    // Smart Communications
86                     "51505",    // Sun Cellular
87                     "53001",    // Vodafone New Zealand
88                     "53024",    // NZC
89                     "311870",   // Boost Mobile
90                     "311220",   // USCC
91                     "311225",   // USCC LTE
92                     "311580",   // USCC LTE
93                     "302720",   // Rogers
94                     "30272",    // Rogers
95                     "302370",   // Fido
96                     "30237",    // Fido
97                     "311490",   // Virgin Mobile
98                     "312530",   // Sprint Prepaid
99                     "310000",   // Tracfone
100                     "46003",    // China Telecom
101                     "311230",   // C SPire Wireless + Celluar South
102                     "310600",    // Cellcom
103                     "31000",     // Republic Wireless US
104                     "310026",     // T-Mobile US
105                     "330120", // OpenMobile communication
106                     // Verizon
107                     "310004",
108                     "310012",
109                     "311280",
110                     "311281",
111                     "311282",
112                     "311283",
113                     "311284",
114                     "311285",
115                     "311286",
116                     "311287",
117                     "311288",
118                     "311289",
119                     "311480",
120                     "311481",
121                     "311482",
122                     "311483",
123                     "311484",
124                     "311485",
125                     "311486",
126                     "311487",
127                     "311488",
128                     "311489"
129             );
130 
131     // List of network operators that doesn't support Data(binary) SMS message
132     private static final List<String> UNSUPPORT_DATA_SMS_MESSAGES =
133             Arrays.asList(
134                     "44010",    // NTT DOCOMO
135                     "44020",    // SBM
136                     "44051",    // KDDI
137                     "302720",   // Rogers
138                     "30272",    // Rogers
139                     "302370",   // Fido
140                     "30237",    // Fido
141                     "45008",    // KT
142                     "45005",    // SKT Mobility
143                     "45002",     // SKT Mobility
144                     "45006",    // LGT
145                     // Verizon
146                     "310004",
147                     "310012",
148                     "311280",
149                     "311281",
150                     "311282",
151                     "311283",
152                     "311284",
153                     "311285",
154                     "311286",
155                     "311287",
156                     "311288",
157                     "311289",
158                     "311480",
159                     "311481",
160                     "311482",
161                     "311483",
162                     "311484",
163                     "311485",
164                     "311486",
165                     "311487",
166                     "311488",
167                     "311489"
168             );
169 
170     // List of network operators that doesn't support Maltipart SMS message
171     private static final List<String> UNSUPPORT_MULTIPART_SMS_MESSAGES =
172             Arrays.asList(
173                     "44010",    // NTT DOCOMO
174                     "44020",    // SBM
175                     "44051",    // KDDI
176                     "302720",   // Rogers
177                     "30272",    // Rogers
178                     "302370",   // Fido
179                     "30237",    // Fido
180                     "45006",    // LGT
181                     "45008"     // KT
182             );
183 
184     private TelephonyManager mTelephonyManager;
185     private PackageManager mPackageManager;
186     private String mDestAddr;
187     private String mText;
188     private SmsBroadcastReceiver mSendReceiver;
189     private SmsBroadcastReceiver mDeliveryReceiver;
190     private SmsBroadcastReceiver mDataSmsReceiver;
191     private PendingIntent mSentIntent;
192     private PendingIntent mDeliveredIntent;
193     private Intent mSendIntent;
194     private Intent mDeliveryIntent;
195     private boolean mDeliveryReportSupported;
196     private static boolean mReceivedDataSms;
197     private static String mReceivedText;
198 
199     private static final int TIME_OUT = 1000 * 60 * 5;
200 
201     @Override
setUp()202     protected void setUp() throws Exception {
203         super.setUp();
204         mTelephonyManager =
205             (TelephonyManager) getContext().getSystemService(Context.TELEPHONY_SERVICE);
206         mPackageManager = mContext.getPackageManager();
207         mDestAddr = mTelephonyManager.getLine1Number();
208         mText = "This is a test message";
209 
210         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
211             mDeliveryReportSupported = false;
212         } else {
213             // exclude the networks that don't support SMS delivery report
214             String mccmnc = mTelephonyManager.getSimOperator();
215             mDeliveryReportSupported = !(NO_DELIVERY_REPORTS.contains(mccmnc));
216         }
217     }
218 
testDivideMessage()219     public void testDivideMessage() {
220         ArrayList<String> dividedMessages = divideMessage(LONG_TEXT);
221         assertNotNull(dividedMessages);
222         if (TelephonyUtils.isSkt(mTelephonyManager)) {
223             assertTrue(isComplete(dividedMessages, 5, LONG_TEXT)
224                     || isComplete(dividedMessages, 3, LONG_TEXT));
225         } else if (TelephonyUtils.isKt(mTelephonyManager)) {
226             assertTrue(isComplete(dividedMessages, 4, LONG_TEXT)
227                     || isComplete(dividedMessages, 3, LONG_TEXT));
228         } else {
229             assertTrue(isComplete(dividedMessages, 3, LONG_TEXT));
230         }
231     }
232 
testDivideUnicodeMessage()233     public void testDivideUnicodeMessage() {
234         ArrayList<String> dividedMessages = divideMessage(LONG_TEXT_WITH_32BIT_CHARS);
235         assertNotNull(dividedMessages);
236         assertTrue(isComplete(dividedMessages, 3, LONG_TEXT_WITH_32BIT_CHARS));
237         for (String messagePiece : dividedMessages) {
238             assertFalse(Character.isHighSurrogate(
239                     messagePiece.charAt(messagePiece.length() - 1)));
240         }
241     }
242 
isComplete(List<String> dividedMessages, int numParts, String longText)243     private boolean isComplete(List<String> dividedMessages, int numParts, String longText) {
244         if (dividedMessages.size() != numParts) {
245             return false;
246         }
247 
248         String actualMessage = "";
249         for (int i = 0; i < numParts; i++) {
250             actualMessage += dividedMessages.get(i);
251         }
252         return longText.equals(actualMessage);
253     }
254 
testSendMessages()255     public void testSendMessages() throws InterruptedException {
256         if (!mPackageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
257             return;
258         }
259 
260         String mccmnc = mTelephonyManager.getSimOperator();
261 
262         mSendIntent = new Intent(SMS_SEND_ACTION);
263         mDeliveryIntent = new Intent(SMS_DELIVERY_ACTION);
264 
265         IntentFilter sendIntentFilter = new IntentFilter(SMS_SEND_ACTION);
266         IntentFilter deliveryIntentFilter = new IntentFilter(SMS_DELIVERY_ACTION);
267         IntentFilter dataSmsReceivedIntentFilter = new IntentFilter(DATA_SMS_RECEIVED_ACTION);
268         dataSmsReceivedIntentFilter.addDataScheme("sms");
269         dataSmsReceivedIntentFilter.addDataAuthority("localhost", "19989");
270 
271         mSendReceiver = new SmsBroadcastReceiver(SMS_SEND_ACTION);
272         mDeliveryReceiver = new SmsBroadcastReceiver(SMS_DELIVERY_ACTION);
273         mDataSmsReceiver = new SmsBroadcastReceiver(DATA_SMS_RECEIVED_ACTION);
274 
275         getContext().registerReceiver(mSendReceiver, sendIntentFilter);
276         getContext().registerReceiver(mDeliveryReceiver, deliveryIntentFilter);
277         getContext().registerReceiver(mDataSmsReceiver, dataSmsReceivedIntentFilter);
278 
279         // send single text sms
280         init();
281         sendTextMessage(mDestAddr, mDestAddr, mSentIntent, mDeliveredIntent);
282         assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
283         if (mDeliveryReportSupported) {
284             assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
285         }
286 
287         if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
288             // TODO: temp workaround, OCTET encoding for EMS not properly supported
289             return;
290         }
291 
292         // send data sms
293         if (!UNSUPPORT_DATA_SMS_MESSAGES.contains(mccmnc)) {
294             byte[] data = mText.getBytes();
295             short port = 19989;
296 
297             init();
298             sendDataMessage(mDestAddr, port, data, mSentIntent, mDeliveredIntent);
299             assertTrue(mSendReceiver.waitForCalls(1, TIME_OUT));
300             if (mDeliveryReportSupported) {
301                 assertTrue(mDeliveryReceiver.waitForCalls(1, TIME_OUT));
302             }
303             mDataSmsReceiver.waitForCalls(1, TIME_OUT);
304             assertTrue(mReceivedDataSms);
305             assertEquals(mReceivedText, mText);
306         } else {
307             // This GSM network doesn't support Data(binary) SMS message.
308             // Skip the test.
309         }
310 
311         // send multi parts text sms
312         if (!UNSUPPORT_MULTIPART_SMS_MESSAGES.contains(mccmnc)) {
313             init();
314             ArrayList<String> parts = divideMessage(LONG_TEXT);
315             int numParts = parts.size();
316             ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
317             ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
318             for (int i = 0; i < numParts; i++) {
319                 sentIntents.add(PendingIntent.getBroadcast(getContext(), 0, mSendIntent, 0));
320                 deliveryIntents.add(PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent, 0));
321             }
322             sendMultiPartTextMessage(mDestAddr, parts, sentIntents, deliveryIntents);
323             assertTrue(mSendReceiver.waitForCalls(numParts, TIME_OUT));
324             if (mDeliveryReportSupported) {
325               assertTrue(mDeliveryReceiver.waitForCalls(numParts, TIME_OUT));
326             }
327         } else {
328             // This GSM network doesn't support Multipart SMS message.
329             // Skip the test.
330         }
331     }
332 
init()333     private void init() {
334         mSendReceiver.reset();
335         mDeliveryReceiver.reset();
336         mDataSmsReceiver.reset();
337         mReceivedDataSms = false;
338         mSentIntent = PendingIntent.getBroadcast(getContext(), 0, mSendIntent,
339                 PendingIntent.FLAG_ONE_SHOT);
340         mDeliveredIntent = PendingIntent.getBroadcast(getContext(), 0, mDeliveryIntent,
341                 PendingIntent.FLAG_ONE_SHOT);
342     }
343 
testGetDefault()344     public void testGetDefault() {
345         assertNotNull(getSmsManager());
346     }
347 
divideMessage(String text)348     protected ArrayList<String> divideMessage(String text) {
349         return getSmsManager().divideMessage(text);
350     }
351 
getSmsManager()352     private android.telephony.SmsManager getSmsManager() {
353         return android.telephony.SmsManager.getDefault();
354     }
355 
sendMultiPartTextMessage(String destAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents)356     protected void sendMultiPartTextMessage(String destAddr, ArrayList<String> parts,
357             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
358         getSmsManager().sendMultipartTextMessage(destAddr, null, parts, sentIntents, deliveryIntents);
359     }
360 
sendDataMessage(String destAddr,short port, byte[] data, PendingIntent sentIntent, PendingIntent deliveredIntent)361     protected void sendDataMessage(String destAddr,short port, byte[] data, PendingIntent sentIntent, PendingIntent deliveredIntent) {
362         getSmsManager().sendDataMessage(destAddr, null, port, data, sentIntent, deliveredIntent);
363     }
364 
sendTextMessage(String destAddr, String text, PendingIntent sentIntent, PendingIntent deliveredIntent)365     protected void sendTextMessage(String destAddr, String text, PendingIntent sentIntent, PendingIntent deliveredIntent) {
366         getSmsManager().sendTextMessage(destAddr, null, text, sentIntent, deliveredIntent);
367     }
368 
369     private static class SmsBroadcastReceiver extends BroadcastReceiver {
370         private int mCalls;
371         private int mExpectedCalls;
372         private String mAction;
373         private Object mLock;
374 
SmsBroadcastReceiver(String action)375         SmsBroadcastReceiver(String action) {
376             mAction = action;
377             reset();
378             mLock = new Object();
379         }
380 
reset()381         void reset() {
382             mExpectedCalls = Integer.MAX_VALUE;
383             mCalls = 0;
384         }
385 
386         @Override
onReceive(Context context, Intent intent)387         public void onReceive(Context context, Intent intent) {
388             if(mAction.equals(DATA_SMS_RECEIVED_ACTION)){
389                 StringBuilder sb = new StringBuilder();
390                 Bundle bundle = intent.getExtras();
391                 if (bundle != null) {
392                     Object[] obj = (Object[]) bundle.get("pdus");
393                     String format = bundle.getString("format");
394                     SmsMessage[] message = new SmsMessage[obj.length];
395                     for (int i = 0; i < obj.length; i++) {
396                         message[i] = SmsMessage.createFromPdu((byte[]) obj[i], format);
397                     }
398 
399                     for (SmsMessage currentMessage : message) {
400                         byte[] binaryContent = currentMessage.getUserData();
401                         String readableContent = new String(binaryContent);
402                         sb.append(readableContent);
403                     }
404                 }
405                 mReceivedDataSms = true;
406                 mReceivedText=sb.toString();
407             }
408             Log.i(TAG, "onReceive " + intent.getAction());
409             if (intent.getAction().equals(mAction)) {
410                 synchronized (mLock) {
411                     mCalls += 1;
412                     mLock.notify();
413                 }
414             }
415         }
416 
waitForCalls(int expectedCalls, long timeout)417         public boolean waitForCalls(int expectedCalls, long timeout) throws InterruptedException {
418             synchronized(mLock) {
419                 mExpectedCalls = expectedCalls;
420                 long startTime = SystemClock.elapsedRealtime();
421 
422                 while (mCalls < mExpectedCalls) {
423                     long waitTime = timeout - (SystemClock.elapsedRealtime() - startTime);
424                     if (waitTime > 0) {
425                         mLock.wait(waitTime);
426                     } else {
427                         return false;  // timed out
428                     }
429                 }
430                 return true;  // success
431             }
432         }
433     }
434 }
435