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; 18 19import static org.junit.Assert.fail; 20import static org.mockito.Matchers.anyBoolean; 21import static org.mockito.Matchers.anyLong; 22import static org.mockito.Matchers.anyString; 23import static org.mockito.Mockito.any; 24import static org.mockito.Mockito.anyInt; 25import static org.mockito.Mockito.doAnswer; 26import static org.mockito.Mockito.doReturn; 27import static org.mockito.Mockito.eq; 28 29import android.app.ActivityManagerNative; 30import android.app.IActivityManager; 31import android.content.Context; 32import android.content.IIntentSender; 33import android.content.Intent; 34import android.content.SharedPreferences; 35import android.content.pm.PackageInfo; 36import android.content.pm.PackageManager; 37import android.database.Cursor; 38import android.os.Bundle; 39import android.os.Handler; 40import android.os.IBinder; 41import android.os.IDeviceIdleController; 42import android.os.RegistrantList; 43import android.os.ServiceManager; 44import android.provider.BlockedNumberContract; 45import android.telephony.ServiceState; 46import android.telephony.TelephonyManager; 47import android.test.mock.MockContentProvider; 48import android.test.mock.MockContentResolver; 49import android.util.Log; 50import android.util.Singleton; 51import android.util.SparseArray; 52 53import com.android.ims.ImsCall; 54import com.android.ims.ImsCallProfile; 55import com.android.ims.ImsEcbm; 56import com.android.ims.ImsManager; 57import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 58import com.android.internal.telephony.cdma.EriManager; 59import com.android.internal.telephony.dataconnection.DcTracker; 60import com.android.internal.telephony.imsphone.ImsPhone; 61import com.android.internal.telephony.imsphone.ImsPhoneCallTracker; 62import com.android.internal.telephony.mocks.TelephonyRegistryMock; 63import com.android.internal.telephony.test.SimulatedCommands; 64import com.android.internal.telephony.test.SimulatedCommandsVerifier; 65import com.android.internal.telephony.uicc.IccCardProxy; 66import com.android.internal.telephony.uicc.IccRecords; 67import com.android.internal.telephony.uicc.IsimUiccRecords; 68import com.android.internal.telephony.uicc.RuimRecords; 69import com.android.internal.telephony.uicc.SIMRecords; 70import com.android.internal.telephony.uicc.UiccCardApplication; 71import com.android.internal.telephony.uicc.UiccController; 72 73import org.mockito.Mock; 74import org.mockito.MockitoAnnotations; 75import org.mockito.invocation.InvocationOnMock; 76import org.mockito.stubbing.Answer; 77 78import java.lang.reflect.Field; 79import java.util.HashMap; 80import java.util.HashSet; 81import java.util.Iterator; 82import java.util.LinkedList; 83import java.util.Set; 84 85public abstract class TelephonyTest { 86 protected static String TAG; 87 88 @Mock 89 protected GsmCdmaPhone mPhone; 90 @Mock 91 protected ImsPhone mImsPhone; 92 @Mock 93 protected ServiceStateTracker mSST; 94 @Mock 95 protected GsmCdmaCallTracker mCT; 96 @Mock 97 protected ImsPhoneCallTracker mImsCT; 98 @Mock 99 protected UiccController mUiccController; 100 @Mock 101 protected IccCardProxy mIccCardProxy; 102 @Mock 103 protected CallManager mCallManager; 104 @Mock 105 protected PhoneNotifier mNotifier; 106 @Mock 107 protected TelephonyComponentFactory mTelephonyComponentFactory; 108 @Mock 109 protected CdmaSubscriptionSourceManager mCdmaSSM; 110 @Mock 111 protected RegistrantList mRegistrantList; 112 @Mock 113 protected IccPhoneBookInterfaceManager mIccPhoneBookIntManager; 114 @Mock 115 protected ImsManager mImsManager; 116 @Mock 117 protected DcTracker mDcTracker; 118 @Mock 119 protected GsmCdmaCall mGsmCdmaCall; 120 @Mock 121 protected ImsCall mImsCall; 122 @Mock 123 protected ImsCallProfile mImsCallProfile; 124 @Mock 125 protected ImsEcbm mImsEcbm; 126 @Mock 127 protected SubscriptionController mSubscriptionController; 128 @Mock 129 protected ServiceState mServiceState; 130 @Mock 131 protected SimulatedCommandsVerifier mSimulatedCommandsVerifier; 132 @Mock 133 protected IDeviceIdleController mIDeviceIdleController; 134 @Mock 135 protected InboundSmsHandler mInboundSmsHandler; 136 @Mock 137 protected WspTypeDecoder mWspTypeDecoder; 138 @Mock 139 protected UiccCardApplication mUiccCardApplication3gpp; 140 @Mock 141 protected UiccCardApplication mUiccCardApplication3gpp2; 142 @Mock 143 protected UiccCardApplication mUiccCardApplicationIms; 144 @Mock 145 protected SIMRecords mSimRecords; 146 @Mock 147 protected RuimRecords mRuimRecords; 148 @Mock 149 protected IsimUiccRecords mIsimUiccRecords; 150 @Mock 151 protected ProxyController mProxyController; 152 @Mock 153 protected Singleton<IActivityManager> mIActivityManagerSingleton; 154 @Mock 155 protected IActivityManager mIActivityManager; 156 @Mock 157 protected InboundSmsTracker mInboundSmsTracker; 158 @Mock 159 protected IIntentSender mIIntentSender; 160 @Mock 161 protected IBinder mIBinder; 162 @Mock 163 protected SmsStorageMonitor mSmsStorageMonitor; 164 @Mock 165 protected SmsUsageMonitor mSmsUsageMonitor; 166 @Mock 167 protected PackageInfo mPackageInfo; 168 @Mock 169 protected EriManager mEriManager; 170 @Mock 171 protected IBinder mConnMetLoggerBinder; 172 173 protected TelephonyManager mTelephonyManager; 174 protected SimulatedCommands mSimulatedCommands; 175 protected ContextFixture mContextFixture; 176 protected Context mContext; 177 protected FakeBlockedNumberContentProvider mFakeBlockedNumberContentProvider; 178 private Object mLock = new Object(); 179 private boolean mReady; 180 protected HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>(); 181 182 183 protected HashMap<Integer, ImsManager> mImsManagerInstances = new HashMap<>(); 184 private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>(); 185 186 private LinkedList<InstanceKey> mInstanceKeys = new LinkedList<InstanceKey>(); 187 188 private class InstanceKey { 189 public final Class mClass; 190 public final String mInstName; 191 public final Object mObj; 192 InstanceKey(final Class c, final String instName, final Object obj) { 193 mClass = c; 194 mInstName = instName; 195 mObj = obj; 196 } 197 198 @Override 199 public int hashCode() { 200 return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31; 201 } 202 203 @Override 204 public boolean equals(Object obj) { 205 if (obj == null || obj.getClass() != getClass()) { 206 return false; 207 } 208 209 InstanceKey other = (InstanceKey) obj; 210 return (other.mClass == mClass && other.mInstName.equals(mInstName) 211 && other.mObj == mObj); 212 } 213 } 214 215 protected void waitUntilReady() { 216 while (true) { 217 synchronized (mLock) { 218 if (mReady) { 219 break; 220 } 221 } 222 } 223 } 224 225 protected void setReady(boolean ready) { 226 synchronized (mLock) { 227 mReady = ready; 228 } 229 } 230 231 protected synchronized void replaceInstance(final Class c, final String instanceName, 232 final Object obj, final Object newValue) 233 throws Exception { 234 Field field = c.getDeclaredField(instanceName); 235 field.setAccessible(true); 236 237 InstanceKey key = new InstanceKey(c, instanceName, obj); 238 if (!mOldInstances.containsKey(key)) { 239 mOldInstances.put(key, field.get(obj)); 240 mInstanceKeys.add(key); 241 } 242 field.set(obj, newValue); 243 } 244 245 protected synchronized void restoreInstance(final Class c, final String instanceName, 246 final Object obj) throws Exception { 247 InstanceKey key = new InstanceKey(c, instanceName, obj); 248 if (mOldInstances.containsKey(key)) { 249 Field field = c.getDeclaredField(instanceName); 250 field.setAccessible(true); 251 field.set(obj, mOldInstances.get(key)); 252 mOldInstances.remove(key); 253 mInstanceKeys.remove(key); 254 } 255 } 256 257 protected synchronized void restoreInstances() throws Exception { 258 Iterator<InstanceKey> it = mInstanceKeys.descendingIterator(); 259 260 while (it.hasNext()) { 261 InstanceKey key = it.next(); 262 Field field = key.mClass.getDeclaredField(key.mInstName); 263 field.setAccessible(true); 264 field.set(key.mObj, mOldInstances.get(key)); 265 } 266 267 mInstanceKeys.clear(); 268 mOldInstances.clear(); 269 } 270 271 protected void setUp(String tag) throws Exception { 272 TAG = tag; 273 MockitoAnnotations.initMocks(this); 274 275 //Use reflection to mock singletons 276 replaceInstance(CallManager.class, "INSTANCE", null, mCallManager); 277 replaceInstance(TelephonyComponentFactory.class, "sInstance", null, 278 mTelephonyComponentFactory); 279 replaceInstance(UiccController.class, "mInstance", null, mUiccController); 280 replaceInstance(CdmaSubscriptionSourceManager.class, "sInstance", null, mCdmaSSM); 281 replaceInstance(ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances); 282 replaceInstance(SubscriptionController.class, "sInstance", null, mSubscriptionController); 283 replaceInstance(ProxyController.class, "sProxyController", null, mProxyController); 284 replaceInstance(ActivityManagerNative.class, "gDefault", null, mIActivityManagerSingleton); 285 replaceInstance(CdmaSubscriptionSourceManager.class, 286 "mCdmaSubscriptionSourceChangedRegistrants", mCdmaSSM, mRegistrantList); 287 replaceInstance(SimulatedCommandsVerifier.class, "sInstance", null, 288 mSimulatedCommandsVerifier); 289 replaceInstance(Singleton.class, "mInstance", mIActivityManagerSingleton, 290 mIActivityManager); 291 replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices); 292 293 mSimulatedCommands = new SimulatedCommands(); 294 mContextFixture = new ContextFixture(); 295 mContext = mContextFixture.getTestDouble(); 296 mFakeBlockedNumberContentProvider = new FakeBlockedNumberContentProvider(); 297 ((MockContentResolver)mContext.getContentResolver()).addProvider( 298 BlockedNumberContract.AUTHORITY, mFakeBlockedNumberContentProvider); 299 mPhone.mCi = mSimulatedCommands; 300 mCT.mCi = mSimulatedCommands; 301 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 302 303 replaceInstance(TelephonyManager.class, "sInstance", null, 304 mContext.getSystemService(Context.TELEPHONY_SERVICE)); 305 306 //mTelephonyComponentFactory 307 doReturn(mSST).when(mTelephonyComponentFactory) 308 .makeServiceStateTracker(any(GsmCdmaPhone.class), any(CommandsInterface.class)); 309 doReturn(mIccCardProxy).when(mTelephonyComponentFactory) 310 .makeIccCardProxy(any(Context.class), any(CommandsInterface.class), anyInt()); 311 doReturn(mCT).when(mTelephonyComponentFactory) 312 .makeGsmCdmaCallTracker(any(GsmCdmaPhone.class)); 313 doReturn(mIccPhoneBookIntManager).when(mTelephonyComponentFactory) 314 .makeIccPhoneBookInterfaceManager(any(Phone.class)); 315 doReturn(mDcTracker).when(mTelephonyComponentFactory) 316 .makeDcTracker(any(Phone.class)); 317 doReturn(mWspTypeDecoder).when(mTelephonyComponentFactory) 318 .makeWspTypeDecoder(any(byte[].class)); 319 doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory) 320 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 321 anyBoolean(), anyString(), anyString()); 322 doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory) 323 .makeInboundSmsTracker(any(byte[].class), anyLong(), anyInt(), anyBoolean(), 324 anyString(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyString()); 325 doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory) 326 .makeInboundSmsTracker(any(Cursor.class), anyBoolean()); 327 doReturn(mImsCT).when(mTelephonyComponentFactory) 328 .makeImsPhoneCallTracker(any(ImsPhone.class)); 329 doReturn(mCdmaSSM).when(mTelephonyComponentFactory) 330 .getCdmaSubscriptionSourceManagerInstance(any(Context.class), 331 any(CommandsInterface.class), any(Handler.class), 332 anyInt(), any(Object.class)); 333 doReturn(mIDeviceIdleController).when(mTelephonyComponentFactory) 334 .getIDeviceIdleController(); 335 336 //mPhone 337 doReturn(mContext).when(mPhone).getContext(); 338 doReturn(mContext).when(mImsPhone).getContext(); 339 doReturn(true).when(mPhone).getUnitTestMode(); 340 doReturn(mIccCardProxy).when(mPhone).getIccCard(); 341 doReturn(mServiceState).when(mPhone).getServiceState(); 342 doReturn(mServiceState).when(mImsPhone).getServiceState(); 343 doReturn(true).when(mPhone).isPhoneTypeGsm(); 344 doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType(); 345 doReturn(mCT).when(mPhone).getCallTracker(); 346 doReturn(mSST).when(mPhone).getServiceStateTracker(); 347 mPhone.mEriManager = mEriManager; 348 349 //mUiccController 350 doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(anyInt(), 351 eq(UiccController.APP_FAM_3GPP)); 352 doReturn(mUiccCardApplication3gpp2).when(mUiccController).getUiccCardApplication(anyInt(), 353 eq(UiccController.APP_FAM_3GPP2)); 354 doReturn(mUiccCardApplicationIms).when(mUiccController).getUiccCardApplication(anyInt(), 355 eq(UiccController.APP_FAM_IMS)); 356 357 doAnswer(new Answer<IccRecords>() { 358 public IccRecords answer(InvocationOnMock invocation) { 359 switch ((Integer) invocation.getArguments()[1]) { 360 case UiccController.APP_FAM_3GPP: 361 return mSimRecords; 362 case UiccController.APP_FAM_3GPP2: 363 return mRuimRecords; 364 case UiccController.APP_FAM_IMS: 365 return mIsimUiccRecords; 366 default: 367 logd("Unrecognized family " + invocation.getArguments()[1]); 368 return null; 369 } 370 } 371 }).when(mUiccController).getIccRecords(anyInt(), anyInt()); 372 373 //UiccCardApplication 374 doReturn(mSimRecords).when(mUiccCardApplication3gpp).getIccRecords(); 375 doReturn(mRuimRecords).when(mUiccCardApplication3gpp2).getIccRecords(); 376 doReturn(mIsimUiccRecords).when(mUiccCardApplicationIms).getIccRecords(); 377 378 //mIccCardProxy 379 doReturn(mSimRecords).when(mIccCardProxy).getIccRecords(); 380 doAnswer(new Answer<IccRecords>() { 381 public IccRecords answer(InvocationOnMock invocation) { 382 return (mPhone.isPhoneTypeGsm()) ? mSimRecords : mRuimRecords; 383 } 384 }).when(mIccCardProxy).getIccRecords(); 385 386 //SMS 387 doReturn(true).when(mSmsStorageMonitor).isStorageAvailable(); 388 doReturn(true).when(mSmsUsageMonitor).check(anyString(), anyInt()); 389 doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean()); 390 doReturn(true).when(mTelephonyManager).getSmsSendCapableForPhone( 391 anyInt(), anyBoolean()); 392 393 //Misc 394 doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS).when(mServiceState). 395 getRilDataRadioTechnology(); 396 doReturn(mPhone).when(mCT).getPhone(); 397 mImsManagerInstances.put(mPhone.getPhoneId(), null); 398 doReturn(mImsEcbm).when(mImsManager).getEcbmInterface(anyInt()); 399 doReturn(mPhone).when(mInboundSmsHandler).getPhone(); 400 doReturn(mImsCallProfile).when(mImsCall).getCallProfile(); 401 doReturn(mIBinder).when(mIIntentSender).asBinder(); 402 doReturn(mIIntentSender).when(mIActivityManager).getIntentSender(anyInt(), 403 anyString(), any(IBinder.class), anyString(), anyInt(), any(Intent[].class), 404 any(String[].class), anyInt(), any(Bundle.class), anyInt()); 405 mSST.mSS = mServiceState; 406 mServiceManagerMockedServices.put("connectivity_metrics_logger", mConnMetLoggerBinder); 407 408 setReady(false); 409 } 410 411 protected void tearDown() throws Exception { 412 413 SharedPreferences sharedPreferences = mContext.getSharedPreferences((String) null, 0); 414 sharedPreferences.edit().clear().commit(); 415 416 restoreInstances(); 417 } 418 419 protected static void logd(String s) { 420 Log.d(TAG, s); 421 } 422 423 public static class FakeBlockedNumberContentProvider extends MockContentProvider { 424 public Set<String> mBlockedNumbers = new HashSet<>(); 425 public int mNumEmergencyContactNotifications = 0; 426 427 @Override 428 public Bundle call(String method, String arg, Bundle extras) { 429 switch (method) { 430 case BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER: 431 Bundle bundle = new Bundle(); 432 bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED, 433 mBlockedNumbers.contains(arg)); 434 return bundle; 435 case BlockedNumberContract.SystemContract.METHOD_NOTIFY_EMERGENCY_CONTACT: 436 mNumEmergencyContactNotifications++; 437 return new Bundle(); 438 default: 439 fail("Method not expected: " + method); 440 } 441 return null; 442 } 443 } 444 445 protected void setupMockPackagePermissionChecks() throws Exception { 446 PackageManager mockPackageManager = mContext.getPackageManager(); 447 doReturn(new String[]{TAG}).when(mockPackageManager).getPackagesForUid(anyInt()); 448 doReturn(mPackageInfo).when(mockPackageManager).getPackageInfo(eq(TAG), anyInt()); 449 } 450} 451