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 */ 16package com.android.internal.telephony; 17 18import android.Manifest; 19import android.content.ContentProvider; 20import android.content.ContentValues; 21import android.content.Context; 22import android.content.Intent; 23import android.content.pm.UserInfo; 24import android.net.Uri; 25import android.os.AsyncResult; 26import android.os.HandlerThread; 27import android.os.Message; 28import android.provider.Telephony; 29import android.telephony.CarrierConfigManager; 30import android.telephony.SubscriptionInfo; 31import android.telephony.SubscriptionManager; 32import android.test.mock.MockContentProvider; 33import android.test.mock.MockContentResolver; 34import android.test.suitebuilder.annotation.SmallTest; 35 36import com.android.internal.telephony.uicc.IccCardProxy; 37import com.android.internal.telephony.uicc.IccFileHandler; 38import com.android.internal.telephony.uicc.IccRecords; 39import com.android.internal.telephony.uicc.IccUtils; 40 41import org.junit.After; 42import org.junit.Assert; 43import org.junit.Before; 44import org.junit.Test; 45import org.mockito.ArgumentCaptor; 46import org.mockito.Mock; 47import org.mockito.invocation.InvocationOnMock; 48import org.mockito.stubbing.Answer; 49 50import java.util.Arrays; 51import java.util.HashMap; 52 53import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; 54import static org.junit.Assert.assertEquals; 55import static org.mockito.Mockito.any; 56import static org.mockito.Mockito.anyBoolean; 57import static org.mockito.Mockito.anyInt; 58import static org.mockito.Mockito.anyString; 59import static org.mockito.Mockito.doAnswer; 60import static org.mockito.Mockito.doReturn; 61import static org.mockito.Mockito.eq; 62import static org.mockito.Mockito.times; 63import static org.mockito.Mockito.verify; 64 65public class SubscriptionInfoUpdaterTest extends TelephonyTest { 66 67 private static final int FAKE_SUB_ID = 1; 68 private static final String FAKE_PLMN = "123456"; 69 70 private SubscriptionInfoUpdaterHandlerThread mSubscriptionInfoUpdaterHandlerThread; 71 private IccRecords mIccRecord; 72 @Mock 73 private UserInfo mUserInfo; 74 @Mock 75 private SubscriptionInfo mSubInfo; 76 @Mock 77 private ContentProvider mContentProvider; 78 @Mock 79 private HashMap<String, Object> mSubscriptionContent; 80 @Mock 81 private IccFileHandler mIccFileHandler; 82 83 /*Custom ContentProvider */ 84 private class FakeSubscriptionContentProvider extends MockContentProvider { 85 @Override 86 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 87 for (String key : values.keySet()) { 88 mSubscriptionContent.put(key, values.get(key)); 89 } 90 return 1; 91 } 92 } 93 94 private class SubscriptionInfoUpdaterHandlerThread extends HandlerThread { 95 96 private SubscriptionInfoUpdaterHandlerThread(String name) { 97 super(name); 98 } 99 100 @Override 101 public void onLooperPrepared() { 102 new SubscriptionInfoUpdater(mContext, new Phone[]{mPhone}, 103 new CommandsInterface[]{mSimulatedCommands}); 104 setReady(true); 105 } 106 } 107 108 @Before 109 public void setUp() throws Exception { 110 super.setUp(this.getClass().getSimpleName()); 111 112 replaceInstance(SubscriptionInfoUpdater.class, "mIccId", null, 113 new String[SubscriptionInfoUpdater.STATUS_SIM1_INSERTED]); 114 replaceInstance(SubscriptionInfoUpdater.class, "mInsertSimState", null, 115 new int[SubscriptionInfoUpdater.STATUS_SIM1_INSERTED]); 116 replaceInstance(SubscriptionInfoUpdater.class, "mContext", null, null); 117 replaceInstance(SubscriptionInfoUpdater.class, "PROJECT_SIM_NUM", null, 118 SubscriptionInfoUpdater.STATUS_SIM1_INSERTED); 119 120 doReturn(SubscriptionInfoUpdater.STATUS_SIM1_INSERTED) 121 .when(mTelephonyManager).getSimCount(); 122 doReturn(SubscriptionInfoUpdater.STATUS_SIM1_INSERTED) 123 .when(mTelephonyManager).getPhoneCount(); 124 125 doReturn(mUserInfo).when(mIActivityManager).getCurrentUser(); 126 doReturn(new int[]{FAKE_SUB_ID}).when(mSubscriptionController).getSubId(0); 127 mContentProvider = new FakeSubscriptionContentProvider(); 128 ((MockContentResolver) mContext.getContentResolver()).addProvider( 129 SubscriptionManager.CONTENT_URI.getAuthority(), 130 mContentProvider); 131 mIccRecord = mIccCardProxy.getIccRecords(); 132 133 mSubscriptionInfoUpdaterHandlerThread = new SubscriptionInfoUpdaterHandlerThread(TAG); 134 mSubscriptionInfoUpdaterHandlerThread.start(); 135 waitUntilReady(); 136 } 137 138 @After 139 public void tearDown() throws Exception { 140 mSubscriptionInfoUpdaterHandlerThread.quitSafely(); 141 super.tearDown(); 142 } 143 144 @Test 145 @SmallTest 146 public void testSimAbsent() { 147 doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController) 148 .getSubInfoUsingSlotIdWithCheck(eq(0), anyBoolean(), anyString()); 149 Intent mIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 150 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 151 IccCardConstants.INTENT_VALUE_ICC_ABSENT); 152 mIntent.putExtra(PhoneConstants.PHONE_KEY, 0); 153 154 mContext.sendBroadcast(mIntent); 155 156 waitForMs(100); 157 verify(mSubscriptionContent).put(eq(SubscriptionManager.SIM_SLOT_INDEX), 158 eq(SubscriptionManager.INVALID_SIM_SLOT_INDEX)); 159 160 CarrierConfigManager mConfigManager = (CarrierConfigManager) 161 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 162 verify(mConfigManager).updateConfigForPhoneId(eq(0), 163 eq(IccCardConstants.INTENT_VALUE_ICC_ABSENT)); 164 verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged(); 165 } 166 167 @Test 168 @SmallTest 169 public void testSimUnknown() { 170 Intent mIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 171 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 172 IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 173 mIntent.putExtra(PhoneConstants.PHONE_KEY, FAKE_SUB_ID); 174 175 mContext.sendBroadcast(mIntent); 176 177 waitForMs(100); 178 verify(mSubscriptionContent, times(0)).put(anyString(), any()); 179 CarrierConfigManager mConfigManager = (CarrierConfigManager) 180 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 181 verify(mConfigManager).updateConfigForPhoneId(eq(1), 182 eq(IccCardConstants.INTENT_VALUE_ICC_UNKNOWN)); 183 verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); 184 } 185 186 @Test 187 @SmallTest 188 public void testSimError() { 189 Intent mIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 190 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 191 IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 192 mIntent.putExtra(PhoneConstants.PHONE_KEY, 2); 193 194 mContext.sendBroadcast(mIntent); 195 waitForMs(100); 196 verify(mSubscriptionContent, times(0)).put(anyString(), any()); 197 CarrierConfigManager mConfigManager = (CarrierConfigManager) 198 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 199 verify(mConfigManager).updateConfigForPhoneId(eq(2), 200 eq(IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR)); 201 verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); 202 } 203 204 @Test 205 @SmallTest 206 public void testWrongSimState() { 207 Intent mIntent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 208 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 209 IccCardConstants.INTENT_VALUE_ICC_IMSI); 210 mIntent.putExtra(PhoneConstants.PHONE_KEY, 2); 211 212 mContext.sendBroadcast(mIntent); 213 waitForMs(100); 214 verify(mSubscriptionContent, times(0)).put(anyString(), any()); 215 CarrierConfigManager mConfigManager = (CarrierConfigManager) 216 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 217 verify(mConfigManager, times(0)).updateConfigForPhoneId(eq(2), 218 eq(IccCardConstants.INTENT_VALUE_ICC_IMSI)); 219 verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); 220 } 221 222 @Test 223 @SmallTest 224 public void testSimLoaded() { 225 /* mock new sim got loaded and there is no sim loaded before */ 226 doReturn(null).when(mSubscriptionController) 227 .getSubInfoUsingSlotIdWithCheck(eq(0), anyBoolean(), anyString()); 228 doReturn("89012604200000000000").when(mIccRecord).getIccId(); 229 doReturn(FAKE_PLMN).when(mTelephonyManager).getSimOperatorNumericForPhone(0); 230 Intent intentInternalSimStateChanged = 231 new Intent(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED); 232 intentInternalSimStateChanged.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 233 IccCardConstants.INTENT_VALUE_ICC_LOADED); 234 intentInternalSimStateChanged.putExtra(PhoneConstants.PHONE_KEY, 0); 235 236 mContext.sendBroadcast(intentInternalSimStateChanged); 237 waitForMs(100); 238 239 // verify SIM_STATE_CHANGED broadcast. It should be broadcast twice, once for 240 // READ_PHONE_STATE and once for READ_PRIVILEGED_PHONE_STATE 241 /* todo: cannot verify as intent is sent using ActivityManagerNative.broadcastStickyIntent() 242 * uncomment code below when that is fixed 243 */ 244 /* ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class); 245 ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class); 246 verify(mContext, times(2)).sendBroadcast(intentArgumentCaptor.capture(), 247 stringArgumentCaptor.capture()); 248 assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED, 249 intentArgumentCaptor.getAllValues().get(0).getAction()); 250 assertEquals(Manifest.permission.READ_PHONE_STATE, 251 stringArgumentCaptor.getAllValues().get(0)); 252 assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED, 253 intentArgumentCaptor.getAllValues().get(1).getAction()); 254 assertEquals(Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 255 stringArgumentCaptor.getAllValues().get(1)); */ 256 257 SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext); 258 verify(mTelephonyManager).getSimOperatorNumericForPhone(0); 259 verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord( 260 eq("89012604200000000000"), eq(0)); 261 verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged(); 262 verify(mSubscriptionController, times(1)).setMccMnc(FAKE_PLMN, FAKE_SUB_ID); 263 CarrierConfigManager mConfigManager = (CarrierConfigManager) 264 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 265 verify(mConfigManager, times(1)).updateConfigForPhoneId(eq(0), 266 eq(IccCardConstants.INTENT_VALUE_ICC_LOADED)); 267 268 // ACTION_USER_UNLOCKED should trigger another SIM_STATE_CHANGED 269 Intent intentSimStateChanged = new Intent(Intent.ACTION_USER_UNLOCKED); 270 mContext.sendBroadcast(intentSimStateChanged); 271 waitForMs(100); 272 273 // verify SIM_STATE_CHANGED broadcast 274 /* todo: cannot verify as intent is sent using ActivityManagerNative.broadcastStickyIntent() 275 * uncomment code below when that is fixed 276 */ 277 /* verify(mContext, times(4)).sendBroadcast(intentArgumentCaptor.capture(), 278 stringArgumentCaptor.capture()); 279 assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED, 280 intentArgumentCaptor.getAllValues().get(2).getAction()); 281 assertEquals(Manifest.permission.READ_PHONE_STATE, 282 stringArgumentCaptor.getAllValues().get(2)); 283 assertEquals(TelephonyIntents.ACTION_SIM_STATE_CHANGED, 284 intentArgumentCaptor.getAllValues().get(3).getAction()); 285 assertEquals(Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 286 stringArgumentCaptor.getAllValues().get(3)); */ 287 } 288 289 @Test 290 @SmallTest 291 public void testSimLoadedEmptyOperatorNumeric() { 292 /* mock new sim got loaded and there is no sim loaded before */ 293 doReturn(null).when(mSubscriptionController) 294 .getSubInfoUsingSlotIdWithCheck(eq(0), anyBoolean(), anyString()); 295 doReturn("89012604200000000000").when(mIccRecord).getIccId(); 296 // operator numeric is empty 297 doReturn("").when(mTelephonyManager).getSimOperatorNumericForPhone(0); 298 Intent mIntent = new Intent(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED); 299 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 300 IccCardConstants.INTENT_VALUE_ICC_LOADED); 301 mIntent.putExtra(PhoneConstants.PHONE_KEY, 0); 302 303 mContext.sendBroadcast(mIntent); 304 waitForMs(100); 305 SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext); 306 verify(mTelephonyManager).getSimOperatorNumericForPhone(0); 307 verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord( 308 eq("89012604200000000000"), eq(0)); 309 verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged(); 310 verify(mSubscriptionController, times(0)).setMccMnc(anyString(), anyInt()); 311 CarrierConfigManager mConfigManager = (CarrierConfigManager) 312 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 313 verify(mConfigManager, times(1)).updateConfigForPhoneId(eq(0), 314 eq(IccCardConstants.INTENT_VALUE_ICC_LOADED)); 315 } 316 317 @Test 318 @SmallTest 319 public void testSimLockedWithOutIccId() { 320 /* mock no IccId Info present and try to query IccId 321 after IccId query, update subscriptionDB */ 322 doReturn(mIccFileHandler).when(mIccCardProxy).getIccFileHandler(); 323 doAnswer(new Answer<Void>() { 324 @Override 325 public Void answer(InvocationOnMock invocation) throws Throwable { 326 Message msg = (Message) invocation.getArguments()[1]; 327 AsyncResult.forMessage(msg).result = IccUtils 328 .hexStringToBytes("89012604200000000000"); 329 msg.sendToTarget(); 330 return null; 331 } 332 }).when(mIccFileHandler).loadEFTransparent(anyInt(), any(Message.class)); 333 334 doReturn(Arrays.asList(mSubInfo)).when(mSubscriptionController) 335 .getSubInfoUsingSlotIdWithCheck(eq(0), anyBoolean(), anyString()); 336 337 Intent mIntent = new Intent(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED); 338 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 339 IccCardConstants.INTENT_VALUE_ICC_LOCKED); 340 mIntent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, "TESTING"); 341 mIntent.putExtra(PhoneConstants.PHONE_KEY, 0); 342 343 mContext.sendBroadcast(mIntent); 344 waitForMs(100); 345 346 /* old IccId != new queried IccId */ 347 verify(mSubscriptionContent).put(eq(SubscriptionManager.SIM_SLOT_INDEX), 348 eq(SubscriptionManager.INVALID_SIM_SLOT_INDEX)); 349 SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext); 350 verify(mSubscriptionManager, times(1)).addSubscriptionInfoRecord( 351 eq("98106240020000000000"), eq(0)); 352 353 verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged(); 354 CarrierConfigManager mConfigManager = (CarrierConfigManager) 355 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 356 verify(mConfigManager, times(1)).updateConfigForPhoneId(eq(0), 357 eq(IccCardConstants.INTENT_VALUE_ICC_LOCKED)); 358 } 359 360 @Test 361 @SmallTest 362 public void testSimLockWIthIccId() { 363 /* no need for IccId query */ 364 try { 365 replaceInstance(SubscriptionInfoUpdater.class, "mIccId", null, 366 new String[]{"89012604200000000000"}); 367 } catch (Exception ex) { 368 Assert.fail("unexpected exception thrown" + ex.getMessage()); 369 } 370 doReturn(mIccFileHandler).when(mIccCardProxy).getIccFileHandler(); 371 372 Intent mIntent = new Intent(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED); 373 mIntent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, 374 IccCardConstants.INTENT_VALUE_ICC_LOCKED); 375 mIntent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, "TESTING"); 376 mIntent.putExtra(PhoneConstants.PHONE_KEY, 0); 377 378 mContext.sendBroadcast(mIntent); 379 waitForMs(100); 380 381 verify(mIccFileHandler, times(0)).loadEFTransparent(anyInt(), any(Message.class)); 382 SubscriptionManager mSubscriptionManager = SubscriptionManager.from(mContext); 383 verify(mSubscriptionManager, times(0)).addSubscriptionInfoRecord( 384 anyString(), eq(0)); 385 verify(mSubscriptionController, times(0)).notifySubscriptionInfoChanged(); 386 CarrierConfigManager mConfigManager = (CarrierConfigManager) 387 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 388 /* broadcast is done */ 389 verify(mConfigManager, times(1)).updateConfigForPhoneId(eq(0), 390 eq(IccCardConstants.INTENT_VALUE_ICC_LOCKED)); 391 } 392 393}