Loading src/java/com/android/internal/telephony/SMSDispatcher.java +92 −46 Original line number Diff line number Diff line Loading @@ -355,45 +355,60 @@ public abstract class SMSDispatcher extends Handler { */ protected abstract class SmsSender extends Handler { private static final int EVENT_TIMEOUT = 1; protected final SmsTracker mTracker; // Initialized in sendSmsByCarrierApp protected volatile SmsSenderCallback mSenderCallback; protected volatile CarrierMessagingCallback mSenderCallback; protected final CarrierMessagingServiceWrapper mCarrierMessagingServiceWrapper = new CarrierMessagingServiceWrapper(); private String mCarrierPackageName; protected SmsSender(SmsTracker tracker) { protected SmsSender() { super(Looper.getMainLooper()); mTracker = tracker; } /** * Bind to carrierPackageName to send message through it */ public void sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback) { CarrierMessagingCallback senderCallback) { mCarrierPackageName = carrierPackageName; mSenderCallback = senderCallback; if (!mCarrierMessagingServiceWrapper.bindToCarrierMessagingService( mContext, carrierPackageName, runnable -> runnable.run(), ()->onServiceReady())) { Rlog.e(TAG, "bindService() for carrier messaging service failed"); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } else { Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); sendMessageDelayed(obtainMessage(EVENT_TIMEOUT), mCarrierMessagingTimeout); } } /** * Callback received from mCarrierPackageName on binding to it is done */ public abstract void onServiceReady(); /** * Method to call message send callback with passed in result and default parameters */ public abstract void onSendComplete(@CarrierMessagingService.SendResult int result); /** * Used to get the SmsTracker for single part messages */ public abstract SmsTracker getSmsTracker(); /** * Used to get the SmsTrackers for multi part messages */ public abstract SmsTracker[] getSmsTrackers(); @Override public void handleMessage(Message msg) { if (msg.what == EVENT_TIMEOUT) { logWithLocalLog("handleMessage: did not receive response from " + mCarrierPackageName + " for " + mCarrierMessagingTimeout + " ms"); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } else { logWithLocalLog("handleMessage: received unexpected message " + msg.what); } Loading @@ -413,8 +428,10 @@ public abstract class SMSDispatcher extends Handler { * Use the carrier messaging service to send a text SMS. */ protected final class TextSmsSender extends SmsSender { private final SmsTracker mTracker; public TextSmsSender(SmsTracker tracker) { super(tracker); super(); mTracker = tracker; } @Override Loading @@ -435,24 +452,38 @@ public abstract class SMSDispatcher extends Handler { mSenderCallback); } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e.getMessage()); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } else { mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */); } @Override public SmsTracker getSmsTracker() { return mTracker; } @Override public SmsTracker[] getSmsTrackers() { Rlog.e(TAG, "getSmsTrackers: Unexpected call for TextSmsSender"); return null; } } /** * Use the carrier messaging service to send a data SMS. */ protected final class DataSmsSender extends SmsSender { private final SmsTracker mTracker; public DataSmsSender(SmsTracker tracker) { super(tracker); super(); mTracker = tracker; } @Override Loading @@ -476,16 +507,28 @@ public abstract class SMSDispatcher extends Handler { } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e + " " + SmsController.formatCrossStackMessageId(mTracker.mMessageId)); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } else { mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */); } @Override public SmsTracker getSmsTracker() { return mTracker; } @Override public SmsTracker[] getSmsTrackers() { Rlog.e(TAG, "getSmsTrackers: Unexpected call for DataSmsSender"); return null; } } /** Loading @@ -507,7 +550,7 @@ public abstract class SMSDispatcher extends Handler { final long identity = Binder.clearCallingIdentity(); try { mSmsSender.mCarrierMessagingServiceWrapper.disconnect(); processSendSmsResponse(mSmsSender.mTracker, result, messageRef); processSendSmsResponse(mSmsSender.getSmsTracker(), result, messageRef); mSmsSender.removeTimeout(); } finally { Binder.restoreCallingIdentity(identity); Loading Loading @@ -579,15 +622,12 @@ public abstract class SMSDispatcher extends Handler { /** * Use the carrier messaging service to send a multipart text SMS. */ private final class MultipartSmsSender { private final class MultipartSmsSender extends SmsSender { private final List<String> mParts; public final SmsTracker[] mTrackers; // Initialized in sendSmsByCarrierApp private volatile MultipartSmsSenderCallback mSenderCallback; private final CarrierMessagingServiceWrapper mCarrierMessagingServiceWrapper = new CarrierMessagingServiceWrapper(); MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) { super(); mParts = parts; mTrackers = trackers; } Loading @@ -595,20 +635,11 @@ public abstract class SMSDispatcher extends Handler { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void sendSmsByCarrierApp(String carrierPackageName, MultipartSmsSenderCallback senderCallback) { mSenderCallback = senderCallback; if (!mCarrierMessagingServiceWrapper.bindToCarrierMessagingService( mContext, carrierPackageName, runnable -> runnable.run(), ()->onServiceReady())) { Rlog.e(TAG, "bindService() for carrier messaging service failed"); mSenderCallback.onSendMultipartSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null /* messageRefs */); } else { Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); } super.sendSmsByCarrierApp(carrierPackageName, senderCallback); } private void onServiceReady() { @Override public void onServiceReady() { boolean statusReportRequested = false; for (SmsTracker tracker : mTrackers) { if (tracker.mDeliveryIntent != null) { Loading @@ -629,10 +660,24 @@ public abstract class SMSDispatcher extends Handler { mSenderCallback); } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e); mSenderCallback.onSendMultipartSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null /* messageRefs */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendMultipartSmsComplete(result, null /* messageRefs */); } @Override public SmsTracker getSmsTracker() { Rlog.e(TAG, "getSmsTracker: Unexpected call for MultipartSmsSender"); return null; } @Override public SmsTracker[] getSmsTrackers() { return mTrackers; } } Loading @@ -657,6 +702,7 @@ public abstract class SMSDispatcher extends Handler { */ @Override public void onSendMultipartSmsComplete(int result, int[] messageRefs) { mSmsSender.removeTimeout(); mSmsSender.mCarrierMessagingServiceWrapper.disconnect(); if (mSmsSender.mTrackers == null) { Loading tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +2 −1 Original line number Diff line number Diff line Loading @@ -1146,7 +1146,8 @@ public class SimulatedCommands extends BaseCommands */ @Override public void sendSMSExpectMore (String smscPDU, String pdu, Message result) { unimplemented(result); SimulatedCommandsVerifier.getInstance().sendSMSExpectMore(smscPDU, pdu, result); resultSuccess(result, new SmsResponse(0 /*messageRef*/, null, SmsResponse.NO_ERROR_CODE)); } @Override Loading tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java +93 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,7 @@ public class GsmSmsDispatcherTest extends TelephonyTest { throws RemoteException { when(stub.queryLocalInterface(anyString())).thenReturn(stub); when(stub.asBinder()).thenReturn(stub); // for single part doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Loading @@ -360,6 +361,21 @@ public class GsmSmsDispatcherTest extends TelephonyTest { }).when(stub).sendTextSms( anyString(), anyInt(), anyString(), anyInt(), any(ICarrierMessagingCallback.class)); // for multi part doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ICarrierMessagingCallback callback = (ICarrierMessagingCallback) args[4]; if (callOnFilterComplete) { callback.onSendMultipartSmsComplete(result, null); } return null; } }).when(stub).sendMultipartTextSms( any(), anyInt(), anyString(), anyInt(), any(ICarrierMessagingCallback.class)); } @Test Loading Loading @@ -417,4 +433,81 @@ public class GsmSmsDispatcherTest extends TelephonyTest { processAllMessages(); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } private void sendMultipartTextSms(boolean withSentIntents) { // initiate parameters for a multipart sms ArrayList<String> parts = new ArrayList<>(); parts.add("segment1"); parts.add("segment2"); ArrayList<PendingIntent> sentIntents = new ArrayList<>(); PendingIntent sentIntent1 = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0, new Intent(TEST_INTENT), PendingIntent.FLAG_MUTABLE); PendingIntent sentIntent2 = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0, new Intent(TEST_INTENT), PendingIntent.FLAG_MUTABLE); sentIntents.add(sentIntent1); sentIntents.add(sentIntent2); mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts, withSentIntents ? sentIntents : null, null, null, null, false, -1, false, -1, 0L); } @Test @SmallTest public void testSendMultipartSmsByCarrierApp() throws Exception { mockCarrierApp(); mockCarrierAppStubResults(CarrierMessagingService.SEND_STATUS_OK, mICarrierAppMessagingService, true); registerTestIntentReceiver(); // send SMS and check sentIntent mReceivedTestIntent = false; sendMultipartTextSms(true); processAllMessages(); synchronized (mLock) { if (!mReceivedTestIntent) { // long wait since sometimes broadcasts can take a long time if the system is loaded mLock.wait(60000); } assertEquals(true, mReceivedTestIntent); int resultCode = mTestReceiver.getResultCode(); assertTrue("Unexpected result code: " + resultCode, resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK); verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(), any(Message.class)); } } @Test @SmallTest public void testSendMultipartSmsByCarrierAppNoResponse() throws Exception { mockCarrierApp(); // do not mock result, instead reduce the timeout for test mGsmSmsDispatcher.mCarrierMessagingTimeout = 100; sendMultipartTextSms(false); // wait for timeout waitForMs(150); verify(mSimulatedCommandsVerifier).sendSMSExpectMore(anyString(), anyString(), any(Message.class)); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } @Test @SmallTest public void testSendMultipartSmsByCarrierAppBindingFailed() throws Exception { mContextFixture.mockBindingFailureForPackage(CARRIER_APP_PACKAGE_NAME); // mock presence of carrier app, but do not create a mock service to make binding fail mockUiccWithCarrierApp(); sendMultipartTextSms(false); processAllMessages(); verify(mSimulatedCommandsVerifier).sendSMSExpectMore(anyString(), anyString(), any(Message.class)); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } } Loading
src/java/com/android/internal/telephony/SMSDispatcher.java +92 −46 Original line number Diff line number Diff line Loading @@ -355,45 +355,60 @@ public abstract class SMSDispatcher extends Handler { */ protected abstract class SmsSender extends Handler { private static final int EVENT_TIMEOUT = 1; protected final SmsTracker mTracker; // Initialized in sendSmsByCarrierApp protected volatile SmsSenderCallback mSenderCallback; protected volatile CarrierMessagingCallback mSenderCallback; protected final CarrierMessagingServiceWrapper mCarrierMessagingServiceWrapper = new CarrierMessagingServiceWrapper(); private String mCarrierPackageName; protected SmsSender(SmsTracker tracker) { protected SmsSender() { super(Looper.getMainLooper()); mTracker = tracker; } /** * Bind to carrierPackageName to send message through it */ public void sendSmsByCarrierApp(String carrierPackageName, SmsSenderCallback senderCallback) { CarrierMessagingCallback senderCallback) { mCarrierPackageName = carrierPackageName; mSenderCallback = senderCallback; if (!mCarrierMessagingServiceWrapper.bindToCarrierMessagingService( mContext, carrierPackageName, runnable -> runnable.run(), ()->onServiceReady())) { Rlog.e(TAG, "bindService() for carrier messaging service failed"); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } else { Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); sendMessageDelayed(obtainMessage(EVENT_TIMEOUT), mCarrierMessagingTimeout); } } /** * Callback received from mCarrierPackageName on binding to it is done */ public abstract void onServiceReady(); /** * Method to call message send callback with passed in result and default parameters */ public abstract void onSendComplete(@CarrierMessagingService.SendResult int result); /** * Used to get the SmsTracker for single part messages */ public abstract SmsTracker getSmsTracker(); /** * Used to get the SmsTrackers for multi part messages */ public abstract SmsTracker[] getSmsTrackers(); @Override public void handleMessage(Message msg) { if (msg.what == EVENT_TIMEOUT) { logWithLocalLog("handleMessage: did not receive response from " + mCarrierPackageName + " for " + mCarrierMessagingTimeout + " ms"); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } else { logWithLocalLog("handleMessage: received unexpected message " + msg.what); } Loading @@ -413,8 +428,10 @@ public abstract class SMSDispatcher extends Handler { * Use the carrier messaging service to send a text SMS. */ protected final class TextSmsSender extends SmsSender { private final SmsTracker mTracker; public TextSmsSender(SmsTracker tracker) { super(tracker); super(); mTracker = tracker; } @Override Loading @@ -435,24 +452,38 @@ public abstract class SMSDispatcher extends Handler { mSenderCallback); } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e.getMessage()); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } else { mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */); } @Override public SmsTracker getSmsTracker() { return mTracker; } @Override public SmsTracker[] getSmsTrackers() { Rlog.e(TAG, "getSmsTrackers: Unexpected call for TextSmsSender"); return null; } } /** * Use the carrier messaging service to send a data SMS. */ protected final class DataSmsSender extends SmsSender { private final SmsTracker mTracker; public DataSmsSender(SmsTracker tracker) { super(tracker); super(); mTracker = tracker; } @Override Loading @@ -476,16 +507,28 @@ public abstract class SMSDispatcher extends Handler { } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e + " " + SmsController.formatCrossStackMessageId(mTracker.mMessageId)); mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } else { mSenderCallback.onSendSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, 0 /* messageRef */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendSmsComplete(result, 0 /* messageRef */); } @Override public SmsTracker getSmsTracker() { return mTracker; } @Override public SmsTracker[] getSmsTrackers() { Rlog.e(TAG, "getSmsTrackers: Unexpected call for DataSmsSender"); return null; } } /** Loading @@ -507,7 +550,7 @@ public abstract class SMSDispatcher extends Handler { final long identity = Binder.clearCallingIdentity(); try { mSmsSender.mCarrierMessagingServiceWrapper.disconnect(); processSendSmsResponse(mSmsSender.mTracker, result, messageRef); processSendSmsResponse(mSmsSender.getSmsTracker(), result, messageRef); mSmsSender.removeTimeout(); } finally { Binder.restoreCallingIdentity(identity); Loading Loading @@ -579,15 +622,12 @@ public abstract class SMSDispatcher extends Handler { /** * Use the carrier messaging service to send a multipart text SMS. */ private final class MultipartSmsSender { private final class MultipartSmsSender extends SmsSender { private final List<String> mParts; public final SmsTracker[] mTrackers; // Initialized in sendSmsByCarrierApp private volatile MultipartSmsSenderCallback mSenderCallback; private final CarrierMessagingServiceWrapper mCarrierMessagingServiceWrapper = new CarrierMessagingServiceWrapper(); MultipartSmsSender(ArrayList<String> parts, SmsTracker[] trackers) { super(); mParts = parts; mTrackers = trackers; } Loading @@ -595,20 +635,11 @@ public abstract class SMSDispatcher extends Handler { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) void sendSmsByCarrierApp(String carrierPackageName, MultipartSmsSenderCallback senderCallback) { mSenderCallback = senderCallback; if (!mCarrierMessagingServiceWrapper.bindToCarrierMessagingService( mContext, carrierPackageName, runnable -> runnable.run(), ()->onServiceReady())) { Rlog.e(TAG, "bindService() for carrier messaging service failed"); mSenderCallback.onSendMultipartSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null /* messageRefs */); } else { Rlog.d(TAG, "bindService() for carrier messaging service succeeded"); } super.sendSmsByCarrierApp(carrierPackageName, senderCallback); } private void onServiceReady() { @Override public void onServiceReady() { boolean statusReportRequested = false; for (SmsTracker tracker : mTrackers) { if (tracker.mDeliveryIntent != null) { Loading @@ -629,10 +660,24 @@ public abstract class SMSDispatcher extends Handler { mSenderCallback); } catch (RuntimeException e) { Rlog.e(TAG, "Exception sending the SMS: " + e); mSenderCallback.onSendMultipartSmsComplete( CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK, null /* messageRefs */); onSendComplete(CarrierMessagingService.SEND_STATUS_RETRY_ON_CARRIER_NETWORK); } } @Override public void onSendComplete(int result) { mSenderCallback.onSendMultipartSmsComplete(result, null /* messageRefs */); } @Override public SmsTracker getSmsTracker() { Rlog.e(TAG, "getSmsTracker: Unexpected call for MultipartSmsSender"); return null; } @Override public SmsTracker[] getSmsTrackers() { return mTrackers; } } Loading @@ -657,6 +702,7 @@ public abstract class SMSDispatcher extends Handler { */ @Override public void onSendMultipartSmsComplete(int result, int[] messageRefs) { mSmsSender.removeTimeout(); mSmsSender.mCarrierMessagingServiceWrapper.disconnect(); if (mSmsSender.mTrackers == null) { Loading
tests/telephonytests/src/com/android/internal/telephony/SimulatedCommands.java +2 −1 Original line number Diff line number Diff line Loading @@ -1146,7 +1146,8 @@ public class SimulatedCommands extends BaseCommands */ @Override public void sendSMSExpectMore (String smscPDU, String pdu, Message result) { unimplemented(result); SimulatedCommandsVerifier.getInstance().sendSMSExpectMore(smscPDU, pdu, result); resultSuccess(result, new SmsResponse(0 /*messageRef*/, null, SmsResponse.NO_ERROR_CODE)); } @Override Loading
tests/telephonytests/src/com/android/internal/telephony/gsm/GsmSmsDispatcherTest.java +93 −0 Original line number Diff line number Diff line Loading @@ -347,6 +347,7 @@ public class GsmSmsDispatcherTest extends TelephonyTest { throws RemoteException { when(stub.queryLocalInterface(anyString())).thenReturn(stub); when(stub.asBinder()).thenReturn(stub); // for single part doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Loading @@ -360,6 +361,21 @@ public class GsmSmsDispatcherTest extends TelephonyTest { }).when(stub).sendTextSms( anyString(), anyInt(), anyString(), anyInt(), any(ICarrierMessagingCallback.class)); // for multi part doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Object[] args = invocation.getArguments(); ICarrierMessagingCallback callback = (ICarrierMessagingCallback) args[4]; if (callOnFilterComplete) { callback.onSendMultipartSmsComplete(result, null); } return null; } }).when(stub).sendMultipartTextSms( any(), anyInt(), anyString(), anyInt(), any(ICarrierMessagingCallback.class)); } @Test Loading Loading @@ -417,4 +433,81 @@ public class GsmSmsDispatcherTest extends TelephonyTest { processAllMessages(); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } private void sendMultipartTextSms(boolean withSentIntents) { // initiate parameters for a multipart sms ArrayList<String> parts = new ArrayList<>(); parts.add("segment1"); parts.add("segment2"); ArrayList<PendingIntent> sentIntents = new ArrayList<>(); PendingIntent sentIntent1 = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0, new Intent(TEST_INTENT), PendingIntent.FLAG_MUTABLE); PendingIntent sentIntent2 = PendingIntent.getBroadcast(TestApplication.getAppContext(), 0, new Intent(TEST_INTENT), PendingIntent.FLAG_MUTABLE); sentIntents.add(sentIntent1); sentIntents.add(sentIntent2); mGsmSmsDispatcher.sendMultipartText("6501002000" /*destAddr*/, "222" /*scAddr*/, parts, withSentIntents ? sentIntents : null, null, null, null, false, -1, false, -1, 0L); } @Test @SmallTest public void testSendMultipartSmsByCarrierApp() throws Exception { mockCarrierApp(); mockCarrierAppStubResults(CarrierMessagingService.SEND_STATUS_OK, mICarrierAppMessagingService, true); registerTestIntentReceiver(); // send SMS and check sentIntent mReceivedTestIntent = false; sendMultipartTextSms(true); processAllMessages(); synchronized (mLock) { if (!mReceivedTestIntent) { // long wait since sometimes broadcasts can take a long time if the system is loaded mLock.wait(60000); } assertEquals(true, mReceivedTestIntent); int resultCode = mTestReceiver.getResultCode(); assertTrue("Unexpected result code: " + resultCode, resultCode == SmsManager.RESULT_ERROR_NONE || resultCode == Activity.RESULT_OK); verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(), any(Message.class)); } } @Test @SmallTest public void testSendMultipartSmsByCarrierAppNoResponse() throws Exception { mockCarrierApp(); // do not mock result, instead reduce the timeout for test mGsmSmsDispatcher.mCarrierMessagingTimeout = 100; sendMultipartTextSms(false); // wait for timeout waitForMs(150); verify(mSimulatedCommandsVerifier).sendSMSExpectMore(anyString(), anyString(), any(Message.class)); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } @Test @SmallTest public void testSendMultipartSmsByCarrierAppBindingFailed() throws Exception { mContextFixture.mockBindingFailureForPackage(CARRIER_APP_PACKAGE_NAME); // mock presence of carrier app, but do not create a mock service to make binding fail mockUiccWithCarrierApp(); sendMultipartTextSms(false); processAllMessages(); verify(mSimulatedCommandsVerifier).sendSMSExpectMore(anyString(), anyString(), any(Message.class)); verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); } }