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