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 import static androidx.test.InstrumentationRegistry.getContext; 20 import static androidx.test.InstrumentationRegistry.getInstrumentation; 21 22 import static com.android.compatibility.common.util.BlockedNumberUtil.deleteBlockedNumber; 23 import static com.android.compatibility.common.util.BlockedNumberUtil.insertBlockedNumber; 24 25 import static org.hamcrest.Matchers.anyOf; 26 import static org.hamcrest.Matchers.emptyString; 27 import static org.hamcrest.Matchers.equalTo; 28 import static org.hamcrest.Matchers.greaterThan; 29 import static org.hamcrest.Matchers.startsWith; 30 import static org.junit.Assert.assertEquals; 31 import static org.junit.Assert.assertFalse; 32 import static org.junit.Assert.assertNotEquals; 33 import static org.junit.Assert.assertNotNull; 34 import static org.junit.Assert.assertThat; 35 import static org.junit.Assert.assertTrue; 36 import static org.junit.Assert.fail; 37 import static org.junit.Assume.assumeNoException; 38 import static org.junit.Assume.assumeTrue; 39 40 import android.Manifest; 41 import android.annotation.Nullable; 42 import android.app.AppOpsManager; 43 import android.app.PendingIntent; 44 import android.app.UiAutomation; 45 import android.app.role.RoleManager; 46 import android.content.BroadcastReceiver; 47 import android.content.ComponentName; 48 import android.content.ContentResolver; 49 import android.content.ContentValues; 50 import android.content.Context; 51 import android.content.Intent; 52 import android.content.IntentFilter; 53 import android.content.pm.PackageManager; 54 import android.net.Uri; 55 import android.os.AsyncTask; 56 import android.os.Bundle; 57 import android.os.ParcelFileDescriptor; 58 import android.os.RemoteCallback; 59 import android.os.SystemClock; 60 import android.provider.Telephony; 61 import android.telephony.SmsCbMessage; 62 import android.telephony.SmsManager; 63 import android.telephony.SmsMessage; 64 import android.telephony.SubscriptionManager; 65 import android.telephony.TelephonyManager; 66 import android.telephony.cdma.CdmaSmsCbProgramData; 67 import android.telephony.cts.util.DefaultSmsAppHelper; 68 import android.telephony.cts.util.TelephonyUtils; 69 import android.text.TextUtils; 70 import android.util.Log; 71 72 import androidx.test.InstrumentationRegistry; 73 74 import com.android.compatibility.common.util.ApiTest; 75 import com.android.compatibility.common.util.ShellIdentityUtils; 76 77 import org.junit.After; 78 import org.junit.Before; 79 import org.junit.Test; 80 81 import java.io.BufferedReader; 82 import java.io.FileInputStream; 83 import java.io.IOException; 84 import java.io.InputStream; 85 import java.io.InputStreamReader; 86 import java.nio.charset.StandardCharsets; 87 import java.util.ArrayList; 88 import java.util.Date; 89 import java.util.List; 90 import java.util.concurrent.Callable; 91 import java.util.concurrent.CompletableFuture; 92 import java.util.concurrent.TimeUnit; 93 94 /** 95 * Tests for {@link android.telephony.SmsManager}. 96 * 97 * Structured so tests can be reused to test {@link android.telephony.gsm.SmsManager} 98 */ 99 public class SmsManagerTest { 100 101 private static final String TAG = "SmsManagerTest"; 102 private static final String LONG_TEXT = 103 "This is a very long text. This text should be broken into three " + 104 "separate messages.This is a very long text. This text should be broken into " + 105 "three separate messages.This is a very long text. This text should be broken " + 106 "into three separate messages.This is a very long text. This text should be " + 107 "broken into three separate messages.";; 108 private static final String LONG_TEXT_WITH_32BIT_CHARS = 109 "Long dkkshsh jdjsusj kbsksbdf jfkhcu hhdiwoqiwyrygrvn?*?*!\";:'/,." 110 + "__?9#9292736&4;\"$+$+((]\\[\\℅©℅™^®°¥°¥=¢£}}£∆~¶~÷|√×." 111 + " ⛪⛲ "; 112 113 private static final String SMS_SEND_ACTION = "CTS_SMS_SEND_ACTION"; 114 private static final String SMS_DELIVERY_ACTION = "CTS_SMS_DELIVERY_ACTION"; 115 private static final String DATA_SMS_RECEIVED_ACTION = "android.intent.action.DATA_SMS_RECEIVED"; 116 public static final String SMS_DELIVER_DEFAULT_APP_ACTION = "CTS_SMS_DELIVERY_ACTION_DEFAULT_APP"; 117 public static final String LEGACY_SMS_APP = "android.telephony.cts.sms23"; 118 public static final String MODERN_SMS_APP = "android.telephony.cts.sms"; 119 private static final String SMS_RETRIEVER_APP = "android.telephony.cts.smsretriever"; 120 private static final String SMS_RETRIEVER_ACTION = "CTS_SMS_RETRIEVER_ACTION"; 121 private static final String FINANCIAL_SMS_APP = "android.telephony.cts.financialsms"; 122 123 private TelephonyManager mTelephonyManager; 124 private SubscriptionManager mSubscriptionManager; 125 private String mDestAddr; 126 private String mText; 127 private SmsBroadcastReceiver mSendReceiver; 128 private SmsBroadcastReceiver mDeliveryReceiver; 129 private SmsBroadcastReceiver mDataSmsReceiver; 130 private SmsBroadcastReceiver mSmsDeliverReceiver; 131 private SmsBroadcastReceiver mSmsReceivedReceiver; 132 private SmsBroadcastReceiver mSmsRetrieverReceiver; 133 private PendingIntent mSentIntent; 134 private PendingIntent mDeliveredIntent; 135 private Intent mSendIntent; 136 private Intent mDeliveryIntent; 137 private Context mContext; 138 private Uri mBlockedNumberUri; 139 private boolean mTestAppSetAsDefaultSmsApp; 140 private boolean mDeliveryReportSupported; 141 private static boolean mReceivedDataSms; 142 private static String mReceivedText; 143 @Nullable 144 private String mOriginalDefaultSmsApp; 145 private static boolean sHasShellPermissionIdentity = false; 146 private static long sMessageId = 0L; 147 148 private static final int TIME_OUT = 1000 * 60 * 10; 149 private static final int NO_CALLS_TIMEOUT_MILLIS = 1000; // 1 second 150 151 @Before setUp()152 public void setUp() throws Exception { 153 assumeTrue(getContext().getPackageManager().hasSystemFeature( 154 PackageManager.FEATURE_TELEPHONY_MESSAGING)); 155 156 mContext = getContext(); 157 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 158 mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); 159 mText = "This is a test message"; 160 161 executeWithShellPermissionIdentity(() -> { 162 mDestAddr = mSubscriptionManager.getPhoneNumber(mTelephonyManager.getSubscriptionId()); 163 }); 164 165 // exclude the networks that don't support SMS delivery report 166 String mccmnc = mTelephonyManager.getSimOperator(); 167 mDeliveryReportSupported = !(CarrierCapability.NO_DELIVERY_REPORTS.contains(mccmnc)); 168 169 // register receivers 170 mSendIntent = new Intent(SMS_SEND_ACTION).setPackage(mContext.getPackageName()); 171 mDeliveryIntent = new Intent(SMS_DELIVERY_ACTION).setPackage(mContext.getPackageName()); 172 173 IntentFilter sendIntentFilter = new IntentFilter(SMS_SEND_ACTION); 174 IntentFilter deliveryIntentFilter = new IntentFilter(SMS_DELIVERY_ACTION); 175 IntentFilter dataSmsReceivedIntentFilter = new IntentFilter(DATA_SMS_RECEIVED_ACTION); 176 IntentFilter smsDeliverIntentFilter = new IntentFilter(SMS_DELIVER_DEFAULT_APP_ACTION); 177 IntentFilter smsReceivedIntentFilter = 178 new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION); 179 IntentFilter smsRetrieverIntentFilter = new IntentFilter(SMS_RETRIEVER_ACTION); 180 dataSmsReceivedIntentFilter.addDataScheme("sms"); 181 dataSmsReceivedIntentFilter.addDataAuthority("localhost", "19989"); 182 183 mSendReceiver = new SmsBroadcastReceiver(SMS_SEND_ACTION); 184 mDeliveryReceiver = new SmsBroadcastReceiver(SMS_DELIVERY_ACTION); 185 mDataSmsReceiver = new SmsBroadcastReceiver(DATA_SMS_RECEIVED_ACTION); 186 mSmsDeliverReceiver = new SmsBroadcastReceiver(SMS_DELIVER_DEFAULT_APP_ACTION); 187 mSmsReceivedReceiver = new SmsBroadcastReceiver(Telephony.Sms.Intents.SMS_RECEIVED_ACTION); 188 mSmsRetrieverReceiver = new SmsBroadcastReceiver(SMS_RETRIEVER_ACTION); 189 190 mContext.registerReceiver(mSendReceiver, sendIntentFilter, 191 Context.RECEIVER_EXPORTED_UNAUDITED); 192 mContext.registerReceiver(mDeliveryReceiver, deliveryIntentFilter, 193 Context.RECEIVER_EXPORTED_UNAUDITED); 194 mContext.registerReceiver(mDataSmsReceiver, dataSmsReceivedIntentFilter, 195 Context.RECEIVER_EXPORTED_UNAUDITED); 196 mContext.registerReceiver(mSmsDeliverReceiver, smsDeliverIntentFilter, 197 Context.RECEIVER_EXPORTED_UNAUDITED); 198 mContext.registerReceiver(mSmsReceivedReceiver, smsReceivedIntentFilter); 199 mContext.registerReceiver(mSmsRetrieverReceiver, smsRetrieverIntentFilter, 200 Context.RECEIVER_EXPORTED_UNAUDITED); 201 202 mOriginalDefaultSmsApp = DefaultSmsAppHelper.getDefaultSmsApp(getContext()); 203 DefaultSmsAppHelper.stopBeingDefaultSmsApp(); 204 } 205 206 @After tearDown()207 public void tearDown() throws Exception { 208 if (mBlockedNumberUri != null) { 209 unblockNumber(mBlockedNumberUri); 210 mBlockedNumberUri = null; 211 } 212 if (mTestAppSetAsDefaultSmsApp) { 213 setDefaultSmsApp(false); 214 } 215 216 // unregister receivers 217 if (mSendReceiver != null) { 218 mContext.unregisterReceiver(mSendReceiver); 219 } 220 if (mDeliveryReceiver != null) { 221 mContext.unregisterReceiver(mDeliveryReceiver); 222 } 223 if (mDataSmsReceiver != null) { 224 mContext.unregisterReceiver(mDataSmsReceiver); 225 } 226 if (mSmsDeliverReceiver != null) { 227 mContext.unregisterReceiver(mSmsDeliverReceiver); 228 } 229 if (mSmsReceivedReceiver != null) { 230 mContext.unregisterReceiver(mSmsReceivedReceiver); 231 } 232 if (mSmsRetrieverReceiver != null) { 233 mContext.unregisterReceiver(mSmsRetrieverReceiver); 234 } 235 if (!TextUtils.isEmpty(mOriginalDefaultSmsApp)) { 236 assertTrue(DefaultSmsAppHelper.setDefaultSmsApp(getContext(), mOriginalDefaultSmsApp)); 237 } 238 } 239 240 @Test testDivideMessage()241 public void testDivideMessage() { 242 ArrayList<String> dividedMessages = divideMessage(LONG_TEXT); 243 assertNotNull(dividedMessages); 244 if (TelephonyUtils.isSkt(mTelephonyManager)) { 245 assertTrue(isComplete(dividedMessages, 5, LONG_TEXT) 246 || isComplete(dividedMessages, 3, LONG_TEXT)); 247 } else if (TelephonyUtils.isKt(mTelephonyManager)) { 248 assertTrue(isComplete(dividedMessages, 4, LONG_TEXT) 249 || isComplete(dividedMessages, 3, LONG_TEXT)); 250 } else { 251 assertTrue(isComplete(dividedMessages, 3, LONG_TEXT)); 252 } 253 } 254 255 @Test testDivideUnicodeMessage()256 public void testDivideUnicodeMessage() { 257 ArrayList<String> dividedMessages = divideMessage(LONG_TEXT_WITH_32BIT_CHARS); 258 assertNotNull(dividedMessages); 259 assertTrue(isComplete(dividedMessages, 3, LONG_TEXT_WITH_32BIT_CHARS)); 260 for (String messagePiece : dividedMessages) { 261 assertFalse(Character.isHighSurrogate( 262 messagePiece.charAt(messagePiece.length() - 1))); 263 } 264 } 265 isComplete(List<String> dividedMessages, int numParts, String longText)266 private boolean isComplete(List<String> dividedMessages, int numParts, String longText) { 267 if (dividedMessages.size() != numParts) { 268 return false; 269 } 270 271 String actualMessage = ""; 272 for (int i = 0; i < numParts; i++) { 273 actualMessage += dividedMessages.get(i); 274 } 275 return longText.equals(actualMessage); 276 } 277 278 @Test testSmsRetriever()279 public void testSmsRetriever() throws Exception { 280 assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.", 281 TextUtils.isEmpty(mDestAddr)); 282 283 String mccmnc = mTelephonyManager.getSimOperator(); 284 int carrierId = mTelephonyManager.getSimCarrierId(); 285 assertFalse("[RERUN] Carrier [carrier-id: " + carrierId + "] does not support " 286 + "loop back messages. Use another carrier.", 287 CarrierCapability.UNSUPPORT_LOOP_BACK_MESSAGES.contains(carrierId)); 288 289 init(); 290 291 CompletableFuture<Bundle> callbackResult = new CompletableFuture<>(); 292 293 mContext.startActivity(new Intent() 294 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 295 .setComponent(new ComponentName( 296 SMS_RETRIEVER_APP, SMS_RETRIEVER_APP + ".MainActivity")) 297 .putExtra("callback", new RemoteCallback(callbackResult::complete))); 298 299 300 Bundle bundle = callbackResult.get(200, TimeUnit.SECONDS); 301 String token = bundle.getString("token"); 302 assertThat(bundle.getString("class"), startsWith(SMS_RETRIEVER_APP)); 303 assertNotNull(token); 304 305 String composedText = "testprefix1" + mText + token; 306 sendTextMessage(mDestAddr, composedText, null, null); 307 308 assertTrue("[RERUN] SMS retriever message not received. Check signal.", 309 mSmsRetrieverReceiver.waitForCalls(1, TIME_OUT)); 310 } 311 sendAndReceiveSms(boolean addMessageId, boolean defaultSmsApp)312 private void sendAndReceiveSms(boolean addMessageId, boolean defaultSmsApp) throws Exception { 313 // send single text sms 314 init(); 315 if (addMessageId) { 316 long fakeMessageId = 19812L; 317 sendTextMessageWithMessageId(mDestAddr, 318 String.valueOf(SystemClock.elapsedRealtimeNanos()), mSentIntent, 319 mDeliveredIntent, fakeMessageId); 320 } else { 321 sendTextMessage(mDestAddr, String.valueOf(SystemClock.elapsedRealtimeNanos()), 322 mSentIntent, mDeliveredIntent); 323 } 324 assertTrue("[RERUN] Could not send SMS. Check signal.", 325 mSendReceiver.waitForCalls(1, TIME_OUT)); 326 if (mDeliveryReportSupported) { 327 assertTrue("[RERUN] SMS message delivery notification not received. Check signal.", 328 mDeliveryReceiver.waitForCalls(1, TIME_OUT)); 329 } 330 331 assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT)); 332 // Received SMS should always contain a generated messageId 333 assertNotEquals(0L, sMessageId); 334 335 if (defaultSmsApp) { 336 // default app should receive SMS_DELIVER_ACTION 337 assertTrue(mSmsDeliverReceiver.waitForCalls(1, TIME_OUT)); 338 } else { 339 // non-default app should receive only SMS_RECEIVED_ACTION 340 assertTrue(mSmsDeliverReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 341 } 342 } 343 sendAndReceiveMultipartSms(String mccmnc, boolean addMessageId, boolean defaultSmsApp)344 private void sendAndReceiveMultipartSms(String mccmnc, boolean addMessageId, 345 boolean defaultSmsApp) throws Exception { 346 sMessageId = 0L; 347 int numPartsSent = sendMultipartTextMessageIfSupported(mccmnc, addMessageId); 348 if (numPartsSent > 0) { 349 assertTrue("[RERUN] Could not send multi part SMS. Check signal.", 350 mSendReceiver.waitForCalls(numPartsSent, TIME_OUT)); 351 if (mDeliveryReportSupported) { 352 assertTrue("[RERUN] Multi part SMS message delivery notification not received. " 353 + "Check signal.", mDeliveryReceiver.waitForCalls(numPartsSent, TIME_OUT)); 354 } 355 356 assertTrue(mSmsReceivedReceiver.waitForCalls(1, TIME_OUT)); 357 // Received SMS should contain a generated messageId 358 assertNotEquals(0L, sMessageId); 359 360 if (defaultSmsApp) { 361 // default app should receive SMS_DELIVER_ACTION 362 assertTrue(mSmsDeliverReceiver.waitForCalls(1, TIME_OUT)); 363 } else { 364 // non-default app should receive only SMS_RECEIVED_ACTION 365 assertTrue(mSmsDeliverReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 366 } 367 } else { 368 // This GSM network doesn't support Multipart SMS message. 369 // Skip the test. 370 } 371 } 372 sendDataSms(String mccmnc)373 private void sendDataSms(String mccmnc) throws Exception { 374 if (sendDataMessageIfSupported(mccmnc)) { 375 assertTrue("[RERUN] Could not send data SMS. Check signal.", 376 mSendReceiver.waitForCalls(1, TIME_OUT)); 377 if (mDeliveryReportSupported) { 378 assertTrue("[RERUN] Data SMS message delivery notification not received. " + 379 "Check signal.", mDeliveryReceiver.waitForCalls(1, TIME_OUT)); 380 } 381 mDataSmsReceiver.waitForCalls(1, TIME_OUT); 382 assertTrue("[RERUN] Data SMS message not received. Check signal.", mReceivedDataSms); 383 assertEquals(mReceivedText, mText); 384 } else { 385 // This GSM network doesn't support Data(binary) SMS message. 386 // Skip the test. 387 } 388 } 389 390 @Test(timeout = 10 * 60 * 1000) 391 @ApiTest(apis = { 392 "android.telephony.SmsManager#sendTextMessage", 393 "android.telephony.SmsManager#sendDataMessage", 394 "android.telephony.SmsManager#sendMultipartTextMessage"}) testSendAndReceiveMessages()395 public void testSendAndReceiveMessages() throws Exception { 396 // Test non-default SMS app 397 testSendAndReceiveMessages(false); 398 399 // Test default SMS app 400 DefaultSmsAppHelper.ensureDefaultSmsApp(); 401 testSendAndReceiveMessages(true); 402 DefaultSmsAppHelper.stopBeingDefaultSmsApp(); 403 } 404 testSendAndReceiveMessages(boolean defaultSmsApp)405 private void testSendAndReceiveMessages(boolean defaultSmsApp) throws Exception { 406 assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.", 407 TextUtils.isEmpty(mDestAddr)); 408 409 String mccmnc = mTelephonyManager.getSimOperator(); 410 int carrierId = mTelephonyManager.getSimCarrierId(); 411 assertFalse("[RERUN] Carrier [carrier-id: " + carrierId + "] does not support " 412 + "loop back messages. Use another carrier.", 413 CarrierCapability.UNSUPPORT_LOOP_BACK_MESSAGES.contains(carrierId)); 414 415 // send/receive single text sms with and without messageId 416 sendAndReceiveSms(/* addMessageId= */ true, defaultSmsApp); 417 sendAndReceiveSms(/* addMessageId= */ false, defaultSmsApp); 418 419 420 if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { 421 // TODO: temp workaround, OCTET encoding for EMS not properly supported 422 return; 423 } 424 425 // send/receive data sms 426 sendDataSms(mccmnc); 427 428 // send/receive multi part text sms with and without messageId 429 sendAndReceiveMultipartSms(mccmnc, /* addMessageId= */ true, defaultSmsApp); 430 sendAndReceiveMultipartSms(mccmnc, /* addMessageId= */ false, defaultSmsApp); 431 } 432 433 @Test testSmsBlocking()434 public void testSmsBlocking() throws Exception { 435 assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.", 436 TextUtils.isEmpty(mDestAddr)); 437 438 // disable suppressing blocking. 439 TelephonyUtils.endBlockSuppression(getInstrumentation()); 440 441 String mccmnc = mTelephonyManager.getSimOperator(); 442 // Setting default SMS App is needed to be able to block numbers. 443 setDefaultSmsApp(true); 444 blockNumber(mDestAddr); 445 446 // single-part SMS blocking 447 init(); 448 sendTextMessage(mDestAddr, String.valueOf(SystemClock.elapsedRealtimeNanos()), 449 mSentIntent, mDeliveredIntent); 450 assertTrue("[RERUN] Could not send SMS. Check signal.", 451 mSendReceiver.waitForCalls(1, TIME_OUT)); 452 assertTrue("Expected no messages to be received due to number blocking.", 453 mSmsReceivedReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 454 assertTrue("Expected no messages to be delivered due to number blocking.", 455 mSmsDeliverReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 456 457 // send data sms 458 if (!sendDataMessageIfSupported(mccmnc)) { 459 assertTrue("[RERUN] Could not send data SMS. Check signal.", 460 mSendReceiver.waitForCalls(1, TIME_OUT)); 461 if (mDeliveryReportSupported) { 462 assertTrue("[RERUN] Data SMS message delivery notification not received. " + 463 "Check signal.", mDeliveryReceiver.waitForCalls(1, TIME_OUT)); 464 } 465 assertTrue("Expected no messages to be delivered due to number blocking.", 466 mSmsDeliverReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 467 } else { 468 // This GSM network doesn't support Data(binary) SMS message. 469 // Skip the test. 470 } 471 472 // multi-part SMS blocking 473 int numPartsSent = sendMultipartTextMessageIfSupported(mccmnc, /* addMessageId= */ false); 474 if (numPartsSent > 0) { 475 assertTrue("[RERUN] Could not send multi part SMS. Check signal.", 476 mSendReceiver.waitForCalls(numPartsSent, TIME_OUT)); 477 478 assertTrue("Expected no messages to be received due to number blocking.", 479 mSmsReceivedReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 480 assertTrue("Expected no messages to be delivered due to number blocking.", 481 mSmsDeliverReceiver.verifyNoCalls(NO_CALLS_TIMEOUT_MILLIS)); 482 } else { 483 // This GSM network doesn't support Multipart SMS message. 484 // Skip the test. 485 } 486 } 487 488 @Test testGetSmsMessagesForFinancialAppPermissionRequestedNotGranted()489 public void testGetSmsMessagesForFinancialAppPermissionRequestedNotGranted() throws Exception { 490 CompletableFuture<Bundle> callbackResult = new CompletableFuture<>(); 491 492 mContext.startActivity(new Intent() 493 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 494 .setComponent(new ComponentName(FINANCIAL_SMS_APP, FINANCIAL_SMS_APP + ".MainActivity")) 495 .putExtra("callback", new RemoteCallback(callbackResult::complete))); 496 497 Bundle bundle = callbackResult.get(500, TimeUnit.SECONDS); 498 499 assertThat(bundle.getString("class"), startsWith(FINANCIAL_SMS_APP)); 500 assertThat(bundle.getInt("rowNum"), equalTo(-1)); 501 } 502 503 @Test testGetSmsMessagesForFinancialAppPermissionRequestedGranted()504 public void testGetSmsMessagesForFinancialAppPermissionRequestedGranted() throws Exception { 505 CompletableFuture<Bundle> callbackResult = new CompletableFuture<>(); 506 String ctsPackageName = getInstrumentation().getContext().getPackageName(); 507 508 executeWithShellPermissionIdentity(() -> { 509 setModeForOps(FINANCIAL_SMS_APP, 510 AppOpsManager.MODE_ALLOWED, 511 AppOpsManager.OPSTR_SMS_FINANCIAL_TRANSACTIONS); 512 }); 513 mContext.startActivity(new Intent() 514 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 515 .setComponent(new ComponentName(FINANCIAL_SMS_APP, FINANCIAL_SMS_APP + ".MainActivity")) 516 .putExtra("callback", new RemoteCallback(callbackResult::complete))); 517 518 519 Bundle bundle = callbackResult.get(500, TimeUnit.SECONDS); 520 521 assertThat(bundle.getString("class"), startsWith(FINANCIAL_SMS_APP)); 522 assertThat(bundle.getInt("rowNum"), equalTo(-1)); 523 } 524 525 @Test testSmsNotPersisted_failsWithoutCarrierPermissions()526 public void testSmsNotPersisted_failsWithoutCarrierPermissions() throws Exception { 527 assertFalse("[RERUN] SIM card does not provide phone number. Use a suitable SIM Card.", 528 TextUtils.isEmpty(mDestAddr)); 529 530 try { 531 getSmsManager().sendTextMessageWithoutPersisting(mDestAddr, null /*scAddress */, 532 mDestAddr, mSentIntent, mDeliveredIntent); 533 fail("We should get a SecurityException due to not having carrier privileges"); 534 } catch (SecurityException e) { 535 // Success 536 } 537 } 538 539 @Test testContentProviderAccessRestriction()540 public void testContentProviderAccessRestriction() throws Exception { 541 Uri dummySmsUri = null; 542 Context context = getInstrumentation().getContext(); 543 ContentResolver contentResolver = context.getContentResolver(); 544 int originalWriteSmsMode = -1; 545 String ctsPackageName = context.getPackageName(); 546 try { 547 // Insert some test sms 548 originalWriteSmsMode = context.getSystemService(AppOpsManager.class) 549 .unsafeCheckOpNoThrow(AppOpsManager.OPSTR_WRITE_SMS, 550 getPackageUid(ctsPackageName), ctsPackageName); 551 setModeForOps(ctsPackageName, 552 AppOpsManager.MODE_ALLOWED, AppOpsManager.OPSTR_WRITE_SMS); 553 ContentValues contentValues = new ContentValues(); 554 contentValues.put(Telephony.TextBasedSmsColumns.ADDRESS, "addr"); 555 contentValues.put(Telephony.TextBasedSmsColumns.READ, 1); 556 contentValues.put(Telephony.TextBasedSmsColumns.SUBJECT, "subj"); 557 contentValues.put(Telephony.TextBasedSmsColumns.BODY, "created_at_" 558 + new Date().toString().replace(" ", "_")); 559 560 dummySmsUri = contentResolver.insert(Telephony.Sms.CONTENT_URI, contentValues); 561 assertNotNull("Failed to insert test sms", dummySmsUri); 562 assertNotEquals("Failed to insert test sms", "0", dummySmsUri.getLastPathSegment()); 563 testSmsAccessAboutDefaultApp(LEGACY_SMS_APP); 564 testSmsAccessAboutDefaultApp(MODERN_SMS_APP); 565 } finally { 566 if (dummySmsUri != null && !"/0".equals(dummySmsUri.getLastPathSegment())) { 567 final Uri finalDummySmsUri = dummySmsUri; 568 executeWithShellPermissionIdentity(() -> contentResolver.delete(finalDummySmsUri, 569 null, null)); 570 } 571 if (originalWriteSmsMode >= 0) { 572 int finalOriginalWriteSmsMode = originalWriteSmsMode; 573 executeWithShellPermissionIdentity(() -> 574 setModeForOps(ctsPackageName, 575 finalOriginalWriteSmsMode, AppOpsManager.OPSTR_WRITE_SMS)); 576 } 577 } 578 } 579 testSmsAccessAboutDefaultApp(String pkg)580 private void testSmsAccessAboutDefaultApp(String pkg) 581 throws Exception { 582 String originalSmsApp = getSmsApp(); 583 assertNotEquals(pkg, originalSmsApp); 584 assertCanAccessSms(pkg); 585 try { 586 setSmsApp(pkg); 587 assertCanAccessSms(pkg); 588 } finally { 589 resetReadWriteSmsAppOps(pkg); 590 setSmsApp(originalSmsApp); 591 } 592 } 593 resetReadWriteSmsAppOps(String pkg)594 private void resetReadWriteSmsAppOps(String pkg) throws Exception { 595 setModeForOps(pkg, AppOpsManager.MODE_DEFAULT, 596 AppOpsManager.OPSTR_READ_SMS, AppOpsManager.OPSTR_WRITE_SMS); 597 } 598 setModeForOps(String pkg, int mode, String... ops)599 private void setModeForOps(String pkg, int mode, String... ops) throws Exception { 600 // We cannot reset these app ops to DEFAULT via current API, so we reset them manually here 601 // temporarily as we will rewrite how the default SMS app is setup later. 602 executeWithShellPermissionIdentity(() -> { 603 int uid = getPackageUid(pkg); 604 AppOpsManager appOpsManager = 605 getInstrumentation().getContext().getSystemService(AppOpsManager.class); 606 for (String op : ops) { 607 appOpsManager.setUidMode(op, uid, mode); 608 } 609 }); 610 } 611 getPackageUid(String pkg)612 private int getPackageUid(String pkg) throws PackageManager.NameNotFoundException { 613 return getInstrumentation().getContext().getPackageManager().getPackageUid(pkg, 0); 614 } 615 getSmsApp()616 private String getSmsApp() throws Exception { 617 return executeWithShellPermissionIdentity(() -> getInstrumentation() 618 .getContext() 619 .getSystemService(RoleManager.class) 620 .getRoleHolders(RoleManager.ROLE_SMS) 621 .get(0)); 622 } 623 setSmsApp(String pkg)624 private void setSmsApp(String pkg) throws Exception { 625 executeWithShellPermissionIdentity(() -> { 626 Context context = getInstrumentation().getContext(); 627 RoleManager roleManager = context.getSystemService(RoleManager.class); 628 CompletableFuture<Boolean> result = new CompletableFuture<>(); 629 if (roleManager.getRoleHoldersAsUser(RoleManager.ROLE_SMS, 630 context.getUser()).contains(pkg)) { 631 result.complete(true); 632 } else { 633 roleManager.addRoleHolderAsUser(RoleManager.ROLE_SMS, pkg, 634 RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP, context.getUser(), 635 AsyncTask.THREAD_POOL_EXECUTOR, result::complete); 636 } 637 assertTrue(result.get(5, TimeUnit.SECONDS)); 638 }); 639 } 640 executeWithShellPermissionIdentity(Callable<T> callable)641 private <T> T executeWithShellPermissionIdentity(Callable<T> callable) throws Exception { 642 if (sHasShellPermissionIdentity) { 643 return callable.call(); 644 } 645 UiAutomation uiAutomation = getInstrumentation().getUiAutomation( 646 UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 647 uiAutomation.adoptShellPermissionIdentity(); 648 try { 649 sHasShellPermissionIdentity = true; 650 return callable.call(); 651 } finally { 652 uiAutomation.dropShellPermissionIdentity(); 653 sHasShellPermissionIdentity = false; 654 } 655 } 656 executeWithShellPermissionIdentity(RunnableWithException runnable)657 private void executeWithShellPermissionIdentity(RunnableWithException runnable) 658 throws Exception { 659 executeWithShellPermissionIdentity(() -> { 660 runnable.run(); 661 return null; 662 }); 663 } 664 665 private interface RunnableWithException { run()666 void run() throws Exception; 667 } 668 assertCanAccessSms(String pkg)669 private void assertCanAccessSms(String pkg) throws Exception { 670 CompletableFuture<Bundle> callbackResult = new CompletableFuture<>(); 671 mContext.startActivity(new Intent() 672 .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 673 .setComponent(new ComponentName(pkg, pkg + ".MainActivity")) 674 .putExtra("callback", new RemoteCallback(callbackResult::complete))); 675 676 Bundle bundle = callbackResult.get(20, TimeUnit.SECONDS); 677 678 assertThat(bundle.getString("class"), startsWith(pkg)); 679 assertThat(bundle.getString("exceptionMessage"), anyOf(equalTo(null), emptyString())); 680 assertThat(bundle.getInt("queryCount"), greaterThan(0)); 681 } 682 init()683 private void init() { 684 mSendReceiver.reset(); 685 mDeliveryReceiver.reset(); 686 mDataSmsReceiver.reset(); 687 mSmsDeliverReceiver.reset(); 688 mSmsReceivedReceiver.reset(); 689 mSmsRetrieverReceiver.reset(); 690 mReceivedDataSms = false; 691 sMessageId = 0L; 692 mSentIntent = PendingIntent.getBroadcast(mContext, 0, mSendIntent, 693 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED); 694 mDeliveredIntent = PendingIntent.getBroadcast(mContext, 0, mDeliveryIntent, 695 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE_UNAUDITED); 696 } 697 698 /** 699 * Returns the number of parts sent in the message. If Multi-part SMS is not supported, 700 * returns 0. 701 */ sendMultipartTextMessageIfSupported(String mccmnc, boolean addMessageId)702 private int sendMultipartTextMessageIfSupported(String mccmnc, boolean addMessageId) { 703 int numPartsSent = 0; 704 if (!CarrierCapability.UNSUPPORT_MULTIPART_SMS_MESSAGES.contains(mccmnc)) { 705 init(); 706 ArrayList<String> parts = divideMessage(LONG_TEXT); 707 numPartsSent = parts.size(); 708 ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(); 709 ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(); 710 for (int i = 0; i < numPartsSent; i++) { 711 sentIntents.add(PendingIntent.getBroadcast(mContext, 0, mSendIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED)); 712 deliveryIntents.add(PendingIntent.getBroadcast(mContext, 0, mDeliveryIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED)); 713 } 714 sendMultiPartTextMessage(mDestAddr, parts, sentIntents, deliveryIntents, addMessageId); 715 } 716 return numPartsSent; 717 } 718 sendDataMessageIfSupported(String mccmnc)719 private boolean sendDataMessageIfSupported(String mccmnc) { 720 if (!CarrierCapability.UNSUPPORT_DATA_SMS_MESSAGES.contains(mccmnc)) { 721 byte[] data = mText.getBytes(); 722 short port = 19989; 723 724 init(); 725 sendDataMessage(mDestAddr, port, data, mSentIntent, mDeliveredIntent); 726 return true; 727 } 728 return false; 729 } 730 731 @Test testGetDefault()732 public void testGetDefault() { 733 assertNotNull(getSmsManager()); 734 } 735 736 @Test testGetSetSmscAddress()737 public void testGetSetSmscAddress() { 738 String smsc = null; 739 try { 740 smsc = getSmsManager().getSmscAddress(); 741 fail("SmsManager.getSmscAddress() should throw a SecurityException"); 742 } catch (SecurityException e) { 743 // expected 744 } 745 746 InstrumentationRegistry.getInstrumentation().getUiAutomation() 747 .adoptShellPermissionIdentity("android.permission.READ_PRIVILEGED_PHONE_STATE"); 748 try { 749 smsc = getSmsManager().getSmscAddress(); 750 } catch (SecurityException se) { 751 fail("Caller with READ_PRIVILEGED_PHONE_STATE should be able to call API"); 752 } finally { 753 InstrumentationRegistry.getInstrumentation().getUiAutomation() 754 .dropShellPermissionIdentity(); 755 } 756 757 try { 758 getSmsManager().setSmscAddress(smsc); 759 fail("SmsManager.setSmscAddress() should throw a SecurityException"); 760 } catch (SecurityException e) { 761 // expected 762 } 763 764 InstrumentationRegistry.getInstrumentation().getUiAutomation() 765 .adoptShellPermissionIdentity("android.permission.MODIFY_PHONE_STATE"); 766 try { 767 getSmsManager().setSmscAddress(smsc); 768 } catch (SecurityException se) { 769 fail("Caller with MODIFY_PHONE_STATE should be able to call API"); 770 } finally { 771 InstrumentationRegistry.getInstrumentation().getUiAutomation() 772 .dropShellPermissionIdentity(); 773 } 774 } 775 776 @Test testGetPremiumSmsConsent()777 public void testGetPremiumSmsConsent() { 778 try { 779 getSmsManager().getPremiumSmsConsent("fake package name"); 780 fail("SmsManager.getPremiumSmsConsent() should throw a SecurityException"); 781 } catch (SecurityException e) { 782 // expected 783 } 784 785 InstrumentationRegistry.getInstrumentation().getUiAutomation() 786 .adoptShellPermissionIdentity("android.permission.READ_PRIVILEGED_PHONE_STATE"); 787 try { 788 getSmsManager().getPremiumSmsConsent("fake package name"); 789 fail("Caller with permission but only phone/system uid is allowed"); 790 } catch (SecurityException se) { 791 // expected 792 } finally { 793 InstrumentationRegistry.getInstrumentation().getUiAutomation() 794 .dropShellPermissionIdentity(); 795 } 796 } 797 798 @Test testSetPremiumSmsConsent()799 public void testSetPremiumSmsConsent() { 800 try { 801 getSmsManager().setPremiumSmsConsent("fake package name", 0); 802 fail("SmsManager.setPremiumSmsConsent() should throw a SecurityException"); 803 } catch (SecurityException e) { 804 // expected 805 } 806 807 InstrumentationRegistry.getInstrumentation().getUiAutomation() 808 .adoptShellPermissionIdentity("android.permission.MODIFY_PHONE_STATE"); 809 try { 810 getSmsManager().setPremiumSmsConsent("fake package name", 0); 811 fail("Caller with permission but only phone/system uid is allowed"); 812 } catch (SecurityException se) { 813 // expected 814 } finally { 815 InstrumentationRegistry.getInstrumentation().getUiAutomation() 816 .dropShellPermissionIdentity(); 817 } 818 } 819 820 /** 821 * Verify that SmsManager.getSmsCapacityOnIcc requires Permission. 822 * <p> 823 * Requires Permission: 824 * {@link android.Manifest.permission#READ_PHONE_STATE}. 825 */ 826 @Test testGetSmsCapacityOnIcc()827 public void testGetSmsCapacityOnIcc() { 828 try { 829 getSmsManager().getSmsCapacityOnIcc(); 830 } catch (SecurityException e) { 831 fail("Caller with READ_PHONE_STATE should be able to call API"); 832 } 833 } 834 835 @Test testDisableCellBroadcastRange()836 public void testDisableCellBroadcastRange() { 837 try { 838 int ranType = SmsCbMessage.MESSAGE_FORMAT_3GPP; 839 executeWithShellPermissionIdentity(() -> { 840 getSmsManager().disableCellBroadcastRange( 841 CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT, 842 CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT, 843 ranType); 844 }); 845 } catch (Exception e) { 846 // expected 847 } 848 } 849 850 @Test testEnableCellBroadcastRange()851 public void testEnableCellBroadcastRange() { 852 try { 853 int ranType = SmsCbMessage.MESSAGE_FORMAT_3GPP; 854 executeWithShellPermissionIdentity(() -> { 855 getSmsManager().enableCellBroadcastRange( 856 CdmaSmsCbProgramData.CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT, 857 CdmaSmsCbProgramData.CATEGORY_CMAS_EXTREME_THREAT, 858 ranType); 859 }); 860 } catch (Exception e) { 861 // expected 862 } 863 } 864 865 @Test testResetAllCellBroadcastRanges()866 public void testResetAllCellBroadcastRanges() { 867 try { 868 executeWithShellPermissionIdentity(() -> { 869 getSmsManager().resetAllCellBroadcastRanges(); 870 }); 871 } catch (Exception e) { 872 // expected 873 } 874 } 875 876 @Test testCreateForSubscriptionId()877 public void testCreateForSubscriptionId() { 878 int testSubId = 123; 879 SmsManager smsManager = mContext.getSystemService(SmsManager.class) 880 .createForSubscriptionId(testSubId); 881 assertEquals("getSubscriptionId() should be " + testSubId, testSubId, 882 smsManager.getSubscriptionId()); 883 } 884 885 /** 886 * Verify the API will not throw any exception when READ_PRIVILEGED_PHONE_STATE is granted. 887 */ 888 @Test testGetSmscIdentity()889 public void testGetSmscIdentity() { 890 try { 891 mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_RADIO); 892 } catch (IllegalStateException e) { 893 assumeNoException("Skipping test because Telephony service is null", e); 894 } 895 SmsManager smsManager = getSmsManager(); 896 ShellIdentityUtils.invokeMethodWithShellPermissionsNoReturn(smsManager, 897 SmsManager::getSmscIdentity, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 898 } 899 900 /** 901 * Verify the API will throw the SecurityException or not when no permissions are granted. 902 */ 903 @Test testGetSmscIdentity_Exception()904 public void testGetSmscIdentity_Exception() { 905 try { 906 mTelephonyManager.getHalVersion(TelephonyManager.HAL_SERVICE_RADIO); 907 } catch (IllegalStateException e) { 908 assumeNoException("Skipping test because Telephony service is null", e); 909 } 910 dropShellIdentity(); 911 try { 912 getSmsManager().getSmscIdentity(); 913 fail(); 914 } catch (SecurityException se) { 915 // API will throw SecurityException as no permission is granted to the caller 916 } 917 adoptShellIdentity(); 918 } 919 divideMessage(String text)920 protected ArrayList<String> divideMessage(String text) { 921 return getSmsManager().divideMessage(text); 922 } 923 getSmsManager()924 private android.telephony.SmsManager getSmsManager() { 925 return android.telephony.SmsManager.getDefault(); 926 } 927 sendMultiPartTextMessage(String destAddr, ArrayList<String> parts, ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, boolean addMessageId)928 protected void sendMultiPartTextMessage(String destAddr, ArrayList<String> parts, 929 ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents, 930 boolean addMessageId) { 931 if (addMessageId) { 932 long fakeMessageId = 1278; 933 getSmsManager().sendMultipartTextMessage(destAddr, null, parts, sentIntents, 934 deliveryIntents, fakeMessageId); 935 } else if (mContext.getOpPackageName() != null) { 936 getSmsManager().sendMultipartTextMessage(destAddr, null, parts, sentIntents, 937 deliveryIntents, mContext.getOpPackageName(), mContext.getAttributionTag()); 938 } else { 939 getSmsManager().sendMultipartTextMessage(destAddr, null, parts, sentIntents, 940 deliveryIntents); 941 } 942 } 943 sendDataMessage(String destAddr,short port, byte[] data, PendingIntent sentIntent, PendingIntent deliveredIntent)944 protected void sendDataMessage(String destAddr,short port, byte[] data, PendingIntent sentIntent, PendingIntent deliveredIntent) { 945 getSmsManager().sendDataMessage(destAddr, null, port, data, sentIntent, deliveredIntent); 946 } 947 sendTextMessage(String destAddr, String text, PendingIntent sentIntent, PendingIntent deliveredIntent)948 protected void sendTextMessage(String destAddr, String text, PendingIntent sentIntent, 949 PendingIntent deliveredIntent) { 950 getSmsManager().sendTextMessage(destAddr, null, text, sentIntent, deliveredIntent); 951 } 952 sendTextMessageWithMessageId(String destAddr, String text, PendingIntent sentIntent, PendingIntent deliveredIntent, long messageId)953 protected void sendTextMessageWithMessageId(String destAddr, String text, 954 PendingIntent sentIntent, PendingIntent deliveredIntent, long messageId) { 955 getSmsManager().sendTextMessage(destAddr, null, text, sentIntent, deliveredIntent, 956 messageId); 957 } 958 blockNumber(String number)959 private void blockNumber(String number) { 960 mBlockedNumberUri = insertBlockedNumber(mContext, number); 961 if (mBlockedNumberUri == null) { 962 fail("Failed to insert into blocked number provider."); 963 } 964 } 965 unblockNumber(Uri uri)966 private void unblockNumber(Uri uri) { 967 deleteBlockedNumber(mContext, uri); 968 } 969 setDefaultSmsApp(boolean setToSmsApp)970 private void setDefaultSmsApp(boolean setToSmsApp) 971 throws Exception { 972 String command = String.format( 973 "appops set --user 0 %s WRITE_SMS %s", 974 mContext.getPackageName(), 975 setToSmsApp ? "allow" : "default"); 976 assertTrue("Setting default SMS app failed : " + setToSmsApp, 977 executeShellCommand(command).isEmpty()); 978 mTestAppSetAsDefaultSmsApp = setToSmsApp; 979 } 980 executeShellCommand(String command)981 private String executeShellCommand(String command) 982 throws IOException { 983 ParcelFileDescriptor pfd = 984 getInstrumentation().getUiAutomation().executeShellCommand(command); 985 BufferedReader br = null; 986 try (InputStream in = new FileInputStream(pfd.getFileDescriptor());) { 987 br = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); 988 String str; 989 StringBuilder out = new StringBuilder(); 990 while ((str = br.readLine()) != null) { 991 out.append(str); 992 } 993 return out.toString(); 994 } finally { 995 if (br != null) { 996 br.close(); 997 } 998 } 999 } 1000 1001 private static class SmsBroadcastReceiver extends BroadcastReceiver { 1002 private int mCalls; 1003 private int mExpectedCalls; 1004 private String mAction; 1005 private Object mLock; 1006 SmsBroadcastReceiver(String action)1007 SmsBroadcastReceiver(String action) { 1008 mAction = action; 1009 reset(); 1010 mLock = new Object(); 1011 } 1012 reset()1013 void reset() { 1014 mExpectedCalls = Integer.MAX_VALUE; 1015 mCalls = 0; 1016 } 1017 1018 @Override onReceive(Context context, Intent intent)1019 public void onReceive(Context context, Intent intent) { 1020 if(mAction.equals(DATA_SMS_RECEIVED_ACTION)){ 1021 StringBuilder sb = new StringBuilder(); 1022 Bundle bundle = intent.getExtras(); 1023 if (bundle != null) { 1024 Object[] obj = (Object[]) bundle.get("pdus"); 1025 String format = bundle.getString("format"); 1026 SmsMessage[] message = new SmsMessage[obj.length]; 1027 for (int i = 0; i < obj.length; i++) { 1028 message[i] = SmsMessage.createFromPdu((byte[]) obj[i], format); 1029 } 1030 1031 for (SmsMessage currentMessage : message) { 1032 byte[] binaryContent = currentMessage.getUserData(); 1033 String readableContent = new String(binaryContent); 1034 sb.append(readableContent); 1035 } 1036 } 1037 mReceivedDataSms = true; 1038 mReceivedText=sb.toString(); 1039 } 1040 if (mAction.equals(Telephony.Sms.Intents.SMS_RECEIVED_ACTION)) { 1041 sMessageId = intent.getLongExtra("messageId", 0L); 1042 } 1043 Log.i(TAG, "onReceive " + intent.getAction() + ", mAction " + mAction); 1044 if (intent.getAction().equals(mAction)) { 1045 synchronized (mLock) { 1046 mCalls += 1; 1047 mLock.notify(); 1048 } 1049 } 1050 } 1051 verifyNoCalls(long timeout)1052 public boolean verifyNoCalls(long timeout) throws InterruptedException { 1053 synchronized(mLock) { 1054 mLock.wait(timeout); 1055 return mCalls == 0; 1056 } 1057 } 1058 waitForCalls(int expectedCalls, long timeout)1059 public boolean waitForCalls(int expectedCalls, long timeout) throws InterruptedException { 1060 synchronized(mLock) { 1061 mExpectedCalls = expectedCalls; 1062 long startTime = SystemClock.elapsedRealtime(); 1063 1064 while (mCalls < mExpectedCalls) { 1065 long waitTime = timeout - (SystemClock.elapsedRealtime() - startTime); 1066 if (waitTime > 0) { 1067 mLock.wait(waitTime); 1068 } else { 1069 return false; // timed out 1070 } 1071 } 1072 return true; // success 1073 } 1074 } 1075 } 1076 1077 /** 1078 * Adopts shell permission identity 1079 */ adoptShellIdentity()1080 private static void adoptShellIdentity() { 1081 InstrumentationRegistry.getInstrumentation().getUiAutomation() 1082 .adoptShellPermissionIdentity(); 1083 } 1084 1085 /** 1086 * Drop shell permission identity 1087 */ dropShellIdentity()1088 private static void dropShellIdentity() { 1089 InstrumentationRegistry.getInstrumentation().getUiAutomation() 1090 .dropShellPermissionIdentity(); 1091 } 1092 } 1093