1/* 2 * Copyright (C) 2016 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 17package com.android.internal.telephony.gsm; 18 19import static android.telephony.SmsManager.RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED; 20 21import static com.android.internal.telephony.SmsUsageMonitor.CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE; 22import static com.android.internal.telephony.SmsUsageMonitor.PREMIUM_SMS_PERMISSION_NEVER_ALLOW; 23import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 24 25import static org.junit.Assert.assertEquals; 26import static org.mockito.Matchers.any; 27import static org.mockito.Matchers.anyInt; 28import static org.mockito.Matchers.anyString; 29import static org.mockito.Mockito.doReturn; 30import static org.mockito.Mockito.times; 31import static org.mockito.Mockito.verify; 32import static org.mockito.Mockito.when; 33 34import android.app.ActivityManager; 35import android.app.PendingIntent; 36import android.content.BroadcastReceiver; 37import android.content.Context; 38import android.content.Intent; 39import android.content.IntentFilter; 40import android.location.Country; 41import android.location.CountryDetector; 42import android.os.HandlerThread; 43import android.os.Message; 44import android.os.SystemProperties; 45import android.provider.Settings; 46import android.provider.Telephony; 47import android.support.test.filters.FlakyTest; 48import android.telephony.SmsManager; 49import android.test.suitebuilder.annotation.MediumTest; 50import android.test.suitebuilder.annotation.SmallTest; 51import android.util.Singleton; 52 53import com.android.internal.telephony.ContextFixture; 54import com.android.internal.telephony.ISub; 55import com.android.internal.telephony.SMSDispatcher; 56import com.android.internal.telephony.SmsDispatchersController; 57import com.android.internal.telephony.TelephonyTest; 58import com.android.internal.telephony.TelephonyTestUtils; 59import com.android.internal.telephony.TestApplication; 60 61import org.junit.After; 62import org.junit.Before; 63import org.junit.Ignore; 64import org.junit.Test; 65import org.mockito.ArgumentCaptor; 66import org.mockito.Mock; 67 68import java.util.HashMap; 69 70public class GsmSmsDispatcherTest extends TelephonyTest { 71 72 private static final long TIMEOUT_MS = 500; 73 74 @Mock 75 private android.telephony.SmsMessage mSmsMessage; 76 @Mock 77 private SmsMessage mGsmSmsMessage; 78 @Mock 79 private SmsDispatchersController mSmsDispatchersController; 80 @Mock 81 private GsmInboundSmsHandler mGsmInboundSmsHandler; 82 @Mock 83 private CountryDetector mCountryDetector; 84 @Mock 85 private SMSDispatcher.SmsTracker mSmsTracker; 86 @Mock 87 private ISub.Stub mISubStub; 88 private Object mLock = new Object(); 89 private boolean mReceivedTestIntent = false; 90 private static final String TEST_INTENT = "com.android.internal.telephony.TEST_INTENT"; 91 private BroadcastReceiver mTestReceiver = new BroadcastReceiver() { 92 @Override 93 public void onReceive(Context context, Intent intent) { 94 logd("onReceive"); 95 synchronized (mLock) { 96 mReceivedTestIntent = true; 97 } 98 } 99 }; 100 101 private GsmSMSDispatcher mGsmSmsDispatcher; 102 private GsmSmsDispatcherTestHandler mGsmSmsDispatcherTestHandler; 103 104 private class GsmSmsDispatcherTestHandler extends HandlerThread { 105 106 private GsmSmsDispatcherTestHandler(String name) { 107 super(name); 108 } 109 110 @Override 111 public void onLooperPrepared() { 112 mGsmSmsDispatcher = new GsmSMSDispatcher(mPhone, mSmsDispatchersController, 113 mGsmInboundSmsHandler); 114 setReady(true); 115 } 116 } 117 118 @Before 119 public void setUp() throws Exception { 120 121 super.setUp(getClass().getSimpleName()); 122 123 // Note that this replaces only cached services in ServiceManager. If a service is not found 124 // in the cache, a real instance is used. 125 mServiceManagerMockedServices.put("isub", mISubStub); 126 127 doReturn(mSmsUsageMonitor).when(mSmsDispatchersController).getUsageMonitor(); 128 mGsmSmsDispatcherTestHandler = new GsmSmsDispatcherTestHandler(getClass().getSimpleName()); 129 mGsmSmsDispatcherTestHandler.start(); 130 waitUntilReady(); 131 } 132 133 @After 134 public void tearDown() throws Exception { 135 mGsmSmsDispatcher = null; 136 mGsmSmsDispatcherTestHandler.quit(); 137 super.tearDown(); 138 } 139 140 @Test @SmallTest 141 public void testSmsStatus() { 142 mSimulatedCommands.notifySmsStatus(new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF}); 143 TelephonyTestUtils.waitForMs(50); 144 verify(mSimulatedCommandsVerifier).acknowledgeLastIncomingGsmSms(true, 145 Telephony.Sms.Intents.RESULT_SMS_HANDLED, null); 146 } 147 148 @Test @MediumTest 149 public void testSendSmsToRegularNumber_doesNotNotifyblockedNumberProvider() throws Exception { 150 setupMockPackagePermissionChecks(); 151 152 mContextFixture.setSystemService(Context.COUNTRY_DETECTOR, mCountryDetector); 153 when(mCountryDetector.detectCountry()) 154 .thenReturn(new Country("US", Country.COUNTRY_SOURCE_SIM)); 155 156 mGsmSmsDispatcher.sendText("6501002000", "121" /*scAddr*/, "test sms", 157 null, null, null, null, false, -1, false, -1); 158 159 verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); 160 // Blocked number provider is notified about the emergency contact asynchronously. 161 TelephonyTestUtils.waitForMs(50); 162 assertEquals(0, mFakeBlockedNumberContentProvider.mNumEmergencyContactNotifications); 163 } 164 165 @FlakyTest 166 @Ignore 167 @Test @MediumTest 168 public void testSendSmsToEmergencyNumber_notifiesBlockedNumberProvider() throws Exception { 169 setupMockPackagePermissionChecks(); 170 171 mContextFixture.setSystemService(Context.COUNTRY_DETECTOR, mCountryDetector); 172 when(mCountryDetector.detectCountry()) 173 .thenReturn(new Country("US", Country.COUNTRY_SOURCE_SIM)); 174 175 mGsmSmsDispatcher.sendText( 176 getEmergencyNumberFromSystemPropertiesOrDefault(), "121" /*scAddr*/, "test sms", 177 null, null, null, null, false, -1, false, -1); 178 179 verify(mSimulatedCommandsVerifier).sendSMS(anyString(), anyString(), any(Message.class)); 180 // Blocked number provider is notified about the emergency contact asynchronously. 181 TelephonyTestUtils.waitForMs(50); 182 assertEquals(1, mFakeBlockedNumberContentProvider.mNumEmergencyContactNotifications); 183 } 184 185 @Test @SmallTest 186 public void testSmsMessageValidityPeriod() throws Exception { 187 int vp; 188 vp = SmsMessage.getRelativeValidityPeriod(-5); 189 assertEquals(-1, vp); 190 191 vp = SmsMessage.getRelativeValidityPeriod(100); 192 assertEquals(100 / 5 - 1, vp); 193 } 194 195 private String getEmergencyNumberFromSystemPropertiesOrDefault() { 196 String systemEmergencyNumbers = SystemProperties.get("ril.ecclist"); 197 if (systemEmergencyNumbers == null) { 198 return "911"; 199 } else { 200 return systemEmergencyNumbers.split(",")[0]; 201 } 202 } 203 204 @Test 205 @SmallTest 206 @FlakyTest 207 @Ignore 208 public void testSendTextWithInvalidDestAddr() throws Exception { 209 // unmock ActivityManager to be able to register receiver, create real PendingIntent and 210 // receive TEST_INTENT 211 restoreInstance(Singleton.class, "mInstance", mIActivityManagerSingleton); 212 restoreInstance(ActivityManager.class, "IActivityManagerSingleton", null); 213 Context realContext = TestApplication.getAppContext(); 214 realContext.registerReceiver(mTestReceiver, new IntentFilter(TEST_INTENT)); 215 PendingIntent pendingIntent = PendingIntent.getBroadcast(realContext, 0, 216 new Intent(TEST_INTENT), 0); 217 // send invalid dest address: + 218 mGsmSmsDispatcher.sendText("+", "222" /*scAddr*/, TAG, 219 pendingIntent, null, null, null, false, -1, false, -1); 220 waitForMs(500); 221 verify(mSimulatedCommandsVerifier, times(0)).sendSMS(anyString(), anyString(), 222 any(Message.class)); 223 synchronized (mLock) { 224 assertEquals(true, mReceivedTestIntent); 225 assertEquals(SmsManager.RESULT_ERROR_NULL_PDU, mTestReceiver.getResultCode()); 226 } 227 } 228 229 @Test 230 public void testSendRawPduWithEventStopSending() throws Exception { 231 setupMockPackagePermissionChecks(); 232 mContextFixture.removeCallingOrSelfPermission(ContextFixture.PERMISSION_ENABLE_ALL); 233 234 // return a fake value to pass getData() 235 HashMap data = new HashMap<String, String>(); 236 data.put("pdu", new byte[1]); 237 when(mSmsTracker.getData()).thenReturn(data); 238 239 // Set values to return to simulate EVENT_STOP_SENDING 240 when(mSmsUsageMonitor.checkDestination(any(), any())) 241 .thenReturn(CATEGORY_POSSIBLE_PREMIUM_SHORT_CODE); 242 when(mSmsUsageMonitor.getPremiumSmsPermission(any())) 243 .thenReturn(PREMIUM_SMS_PERMISSION_NEVER_ALLOW); 244 when(mSmsTracker.getAppPackageName()).thenReturn(""); 245 246 // Settings.Global.DEVICE_PROVISIONED to 1 247 Settings.Global.putInt(mContext.getContentResolver(), 248 Settings.Global.DEVICE_PROVISIONED, 1); 249 250 mGsmSmsDispatcher.sendRawPdu(mSmsTracker); 251 waitForHandlerAction(mGsmSmsDispatcher, TIMEOUT_MS); 252 253 verify(mSmsUsageMonitor, times(1)).checkDestination(any(), any()); 254 verify(mSmsUsageMonitor, times(1)).getPremiumSmsPermission(any()); 255 ArgumentCaptor<Integer> argumentCaptor = ArgumentCaptor 256 .forClass(Integer.class); 257 verify(mSmsTracker, times(1)).onFailed(any(), argumentCaptor.capture(), anyInt()); 258 assertEquals(RESULT_ERROR_SHORT_CODE_NEVER_ALLOWED, (int) argumentCaptor.getValue()); 259 } 260} 261