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 
17 package com.android.internal.telephony;
18 
19 import static org.junit.Assert.fail;
20 import static org.mockito.Matchers.anyBoolean;
21 import static org.mockito.Matchers.anyLong;
22 import static org.mockito.Matchers.nullable;
23 import static org.mockito.Mockito.anyInt;
24 import static org.mockito.Mockito.doAnswer;
25 import static org.mockito.Mockito.doReturn;
26 import static org.mockito.Mockito.eq;
27 
28 import android.app.ActivityManager;
29 import android.app.IActivityManager;
30 import android.content.ContentResolver;
31 import android.content.Context;
32 import android.content.IIntentSender;
33 import android.content.Intent;
34 import android.content.SharedPreferences;
35 import android.content.pm.PackageInfo;
36 import android.content.pm.PackageManager;
37 import android.database.Cursor;
38 import android.os.Bundle;
39 import android.os.Handler;
40 import android.os.IBinder;
41 import android.os.IDeviceIdleController;
42 import android.os.Looper;
43 import android.os.RegistrantList;
44 import android.os.ServiceManager;
45 import android.provider.BlockedNumberContract;
46 import android.provider.Settings;
47 import android.telephony.ServiceState;
48 import android.telephony.SubscriptionManager;
49 import android.telephony.TelephonyManager;
50 import android.telephony.euicc.EuiccManager;
51 import android.telephony.ims.ImsCallProfile;
52 import android.test.mock.MockContentProvider;
53 import android.test.mock.MockContentResolver;
54 import android.util.Log;
55 import android.util.Singleton;
56 
57 import com.android.ims.ImsCall;
58 import com.android.ims.ImsEcbm;
59 import com.android.ims.ImsManager;
60 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
61 import com.android.internal.telephony.cdma.EriManager;
62 import com.android.internal.telephony.dataconnection.DcTracker;
63 import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
64 import com.android.internal.telephony.imsphone.ImsPhone;
65 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
66 import com.android.internal.telephony.test.SimulatedCommands;
67 import com.android.internal.telephony.test.SimulatedCommandsVerifier;
68 import com.android.internal.telephony.uicc.IccCardStatus;
69 import com.android.internal.telephony.uicc.IccRecords;
70 import com.android.internal.telephony.uicc.IsimUiccRecords;
71 import com.android.internal.telephony.uicc.RuimRecords;
72 import com.android.internal.telephony.uicc.SIMRecords;
73 import com.android.internal.telephony.uicc.UiccCard;
74 import com.android.internal.telephony.uicc.UiccCardApplication;
75 import com.android.internal.telephony.uicc.UiccController;
76 import com.android.internal.telephony.uicc.UiccProfile;
77 
78 import org.mockito.Mock;
79 import org.mockito.MockitoAnnotations;
80 import org.mockito.invocation.InvocationOnMock;
81 import org.mockito.stubbing.Answer;
82 
83 import java.lang.reflect.Field;
84 import java.lang.reflect.InvocationTargetException;
85 import java.lang.reflect.Method;
86 import java.util.HashMap;
87 import java.util.HashSet;
88 import java.util.Iterator;
89 import java.util.LinkedList;
90 import java.util.Set;
91 import java.util.concurrent.CountDownLatch;
92 import java.util.concurrent.TimeUnit;
93 
94 public abstract class TelephonyTest {
95     protected static String TAG;
96 
97     private static final int MAX_INIT_WAIT_MS = 30000; // 30 seconds
98 
99     @Mock
100     protected GsmCdmaPhone mPhone;
101     @Mock
102     protected ImsPhone mImsPhone;
103     @Mock
104     protected ServiceStateTracker mSST;
105     @Mock
106     protected GsmCdmaCallTracker mCT;
107     @Mock
108     protected ImsPhoneCallTracker mImsCT;
109     @Mock
110     protected UiccController mUiccController;
111     @Mock
112     protected UiccProfile mUiccProfile;
113     @Mock
114     protected CallManager mCallManager;
115     @Mock
116     protected PhoneNotifier mNotifier;
117     @Mock
118     protected TelephonyComponentFactory mTelephonyComponentFactory;
119     @Mock
120     protected CdmaSubscriptionSourceManager mCdmaSSM;
121     @Mock
122     protected RegistrantList mRegistrantList;
123     @Mock
124     protected IccPhoneBookInterfaceManager mIccPhoneBookIntManager;
125     @Mock
126     protected ImsManager mImsManager;
127     @Mock
128     protected DcTracker mDcTracker;
129     @Mock
130     protected GsmCdmaCall mGsmCdmaCall;
131     @Mock
132     protected ImsCall mImsCall;
133     @Mock
134     protected ImsEcbm mImsEcbm;
135     @Mock
136     protected SubscriptionController mSubscriptionController;
137     @Mock
138     protected ServiceState mServiceState;
139     @Mock
140     protected SimulatedCommandsVerifier mSimulatedCommandsVerifier;
141     @Mock
142     protected IDeviceIdleController mIDeviceIdleController;
143     @Mock
144     protected InboundSmsHandler mInboundSmsHandler;
145     @Mock
146     protected WspTypeDecoder mWspTypeDecoder;
147     @Mock
148     protected UiccCardApplication mUiccCardApplication3gpp;
149     @Mock
150     protected UiccCardApplication mUiccCardApplication3gpp2;
151     @Mock
152     protected UiccCardApplication mUiccCardApplicationIms;
153     @Mock
154     protected SIMRecords mSimRecords;
155     @Mock
156     protected RuimRecords mRuimRecords;
157     @Mock
158     protected IsimUiccRecords mIsimUiccRecords;
159     @Mock
160     protected ProxyController mProxyController;
161     @Mock
162     protected Singleton<IActivityManager> mIActivityManagerSingleton;
163     @Mock
164     protected IActivityManager mIActivityManager;
165     @Mock
166     protected InboundSmsTracker mInboundSmsTracker;
167     @Mock
168     protected IIntentSender mIIntentSender;
169     @Mock
170     protected IBinder mIBinder;
171     @Mock
172     protected SmsStorageMonitor mSmsStorageMonitor;
173     @Mock
174     protected SmsUsageMonitor mSmsUsageMonitor;
175     @Mock
176     protected PackageInfo mPackageInfo;
177     @Mock
178     protected EriManager mEriManager;
179     @Mock
180     protected IBinder mConnMetLoggerBinder;
181     @Mock
182     protected CarrierSignalAgent mCarrierSignalAgent;
183     @Mock
184     protected CarrierActionAgent mCarrierActionAgent;
185     @Mock
186     protected ImsExternalCallTracker mImsExternalCallTracker;
187     @Mock
188     protected AppSmsManager mAppSmsManager;
189     @Mock
190     protected DeviceStateMonitor mDeviceStateMonitor;
191     @Mock
192     protected IntentBroadcaster mIntentBroadcaster;
193     @Mock
194     protected NitzStateMachine mNitzStateMachine;
195     @Mock
196     protected RadioConfig mMockRadioConfig;
197     @Mock
198     protected SubscriptionInfoUpdater mSubInfoRecordUpdater;
199     @Mock
200     protected LocaleTracker mLocaleTracker;
201 
202     protected ImsCallProfile mImsCallProfile;
203     protected TelephonyManager mTelephonyManager;
204     protected SubscriptionManager mSubscriptionManager;
205     protected EuiccManager mEuiccManager;
206     protected PackageManager mPackageManager;
207     protected SimulatedCommands mSimulatedCommands;
208     protected ContextFixture mContextFixture;
209     protected Context mContext;
210     protected FakeBlockedNumberContentProvider mFakeBlockedNumberContentProvider;
211     private Object mLock = new Object();
212     private boolean mReady;
213     protected HashMap<String, IBinder> mServiceManagerMockedServices = new HashMap<>();
214     private Phone[] mPhones;
215 
216 
217     protected HashMap<Integer, ImsManager> mImsManagerInstances = new HashMap<>();
218     private HashMap<InstanceKey, Object> mOldInstances = new HashMap<InstanceKey, Object>();
219 
220     private LinkedList<InstanceKey> mInstanceKeys = new LinkedList<InstanceKey>();
221 
222     private class InstanceKey {
223         public final Class mClass;
224         public final String mInstName;
225         public final Object mObj;
InstanceKey(final Class c, final String instName, final Object obj)226         InstanceKey(final Class c, final String instName, final Object obj) {
227             mClass = c;
228             mInstName = instName;
229             mObj = obj;
230         }
231 
232         @Override
hashCode()233         public int hashCode() {
234             return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
235         }
236 
237         @Override
equals(Object obj)238         public boolean equals(Object obj) {
239             if (obj == null || obj.getClass() != getClass()) {
240                 return false;
241             }
242 
243             InstanceKey other = (InstanceKey) obj;
244             return (other.mClass == mClass && other.mInstName.equals(mInstName)
245                     && other.mObj == mObj);
246         }
247     }
248 
waitUntilReady()249     protected void waitUntilReady() {
250         synchronized (mLock) {
251             try {
252                 mLock.wait(MAX_INIT_WAIT_MS);
253             } catch (InterruptedException ie) {
254             }
255 
256             if (!mReady) {
257                 fail("Telephony tests failed to initialize");
258             }
259         }
260     }
261 
setReady(boolean ready)262     protected void setReady(boolean ready) {
263         synchronized (mLock) {
264             mReady = ready;
265             mLock.notifyAll();
266         }
267     }
268 
replaceInstance(final Class c, final String instanceName, final Object obj, final Object newValue)269     protected synchronized void replaceInstance(final Class c, final String instanceName,
270                                                 final Object obj, final Object newValue)
271             throws Exception {
272         Field field = c.getDeclaredField(instanceName);
273         field.setAccessible(true);
274 
275         InstanceKey key = new InstanceKey(c, instanceName, obj);
276         if (!mOldInstances.containsKey(key)) {
277             mOldInstances.put(key, field.get(obj));
278             mInstanceKeys.add(key);
279         }
280         field.set(obj, newValue);
281     }
282 
restoreInstance(final Class c, final String instanceName, final Object obj)283     protected synchronized void restoreInstance(final Class c, final String instanceName,
284                                                 final Object obj) throws Exception {
285         InstanceKey key = new InstanceKey(c, instanceName, obj);
286         if (mOldInstances.containsKey(key)) {
287             Field field = c.getDeclaredField(instanceName);
288             field.setAccessible(true);
289             field.set(obj, mOldInstances.get(key));
290             mOldInstances.remove(key);
291             mInstanceKeys.remove(key);
292         }
293     }
294 
restoreInstances()295     protected synchronized void restoreInstances() throws Exception {
296         Iterator<InstanceKey> it = mInstanceKeys.descendingIterator();
297 
298         while (it.hasNext()) {
299             InstanceKey key = it.next();
300             Field field = key.mClass.getDeclaredField(key.mInstName);
301             field.setAccessible(true);
302             field.set(key.mObj, mOldInstances.get(key));
303         }
304 
305         mInstanceKeys.clear();
306         mOldInstances.clear();
307     }
308 
setUp(String tag)309     protected void setUp(String tag) throws Exception {
310         TAG = tag;
311         MockitoAnnotations.initMocks(this);
312 
313         mPhones = new Phone[] {mPhone};
314         mImsCallProfile = new ImsCallProfile();
315         mSimulatedCommands = new SimulatedCommands();
316         mContextFixture = new ContextFixture();
317         mContext = mContextFixture.getTestDouble();
318         mFakeBlockedNumberContentProvider = new FakeBlockedNumberContentProvider();
319         ((MockContentResolver)mContext.getContentResolver()).addProvider(
320                 BlockedNumberContract.AUTHORITY, mFakeBlockedNumberContentProvider);
321         mPhone.mCi = mSimulatedCommands;
322         mCT.mCi = mSimulatedCommands;
323         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
324         mSubscriptionManager = (SubscriptionManager) mContext.getSystemService(
325                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
326         mEuiccManager = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE);
327         mPackageManager = mContext.getPackageManager();
328 
329         //mTelephonyComponentFactory
330         doReturn(mSST).when(mTelephonyComponentFactory)
331                 .makeServiceStateTracker(nullable(GsmCdmaPhone.class),
332                         nullable(CommandsInterface.class));
333         doReturn(mUiccProfile).when(mTelephonyComponentFactory)
334                 .makeUiccProfile(nullable(Context.class), nullable(CommandsInterface.class),
335                         nullable(IccCardStatus.class), anyInt(), nullable(UiccCard.class),
336                         nullable(Object.class));
337         doReturn(mCT).when(mTelephonyComponentFactory)
338                 .makeGsmCdmaCallTracker(nullable(GsmCdmaPhone.class));
339         doReturn(mIccPhoneBookIntManager).when(mTelephonyComponentFactory)
340                 .makeIccPhoneBookInterfaceManager(nullable(Phone.class));
341         doReturn(mDcTracker).when(mTelephonyComponentFactory)
342                 .makeDcTracker(nullable(Phone.class));
343         doReturn(mWspTypeDecoder).when(mTelephonyComponentFactory)
344                 .makeWspTypeDecoder(nullable(byte[].class));
345         doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
346                 .makeInboundSmsTracker(nullable(byte[].class), anyLong(), anyInt(), anyBoolean(),
347                         anyBoolean(), nullable(String.class), nullable(String.class),
348                         nullable(String.class));
349         doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
350                 .makeInboundSmsTracker(nullable(byte[].class), anyLong(), anyInt(), anyBoolean(),
351                         nullable(String.class), nullable(String.class), anyInt(), anyInt(),
352                         anyInt(), anyBoolean(), nullable(String.class));
353         doReturn(mInboundSmsTracker).when(mTelephonyComponentFactory)
354                 .makeInboundSmsTracker(nullable(Cursor.class), anyBoolean());
355         doReturn(mImsCT).when(mTelephonyComponentFactory)
356                 .makeImsPhoneCallTracker(nullable(ImsPhone.class));
357         doReturn(mCdmaSSM).when(mTelephonyComponentFactory)
358                 .getCdmaSubscriptionSourceManagerInstance(nullable(Context.class),
359                         nullable(CommandsInterface.class), nullable(Handler.class),
360                         anyInt(), nullable(Object.class));
361         doReturn(mIDeviceIdleController).when(mTelephonyComponentFactory)
362                 .getIDeviceIdleController();
363         doReturn(mImsExternalCallTracker).when(mTelephonyComponentFactory)
364                 .makeImsExternalCallTracker(nullable(ImsPhone.class));
365         doReturn(mAppSmsManager).when(mTelephonyComponentFactory)
366                 .makeAppSmsManager(nullable(Context.class));
367         doReturn(mCarrierSignalAgent).when(mTelephonyComponentFactory)
368                 .makeCarrierSignalAgent(nullable(Phone.class));
369         doReturn(mCarrierActionAgent).when(mTelephonyComponentFactory)
370                 .makeCarrierActionAgent(nullable(Phone.class));
371         doReturn(mDeviceStateMonitor).when(mTelephonyComponentFactory)
372                 .makeDeviceStateMonitor(nullable(Phone.class));
373         doReturn(mNitzStateMachine).when(mTelephonyComponentFactory)
374                 .makeNitzStateMachine(nullable(GsmCdmaPhone.class));
375         doReturn(mLocaleTracker).when(mTelephonyComponentFactory)
376                 .makeLocaleTracker(nullable(Phone.class), nullable(Looper.class));
377 
378         //mPhone
379         doReturn(mContext).when(mPhone).getContext();
380         doReturn(mContext).when(mImsPhone).getContext();
381         doReturn(true).when(mPhone).getUnitTestMode();
382         doReturn(mUiccProfile).when(mPhone).getIccCard();
383         doReturn(mServiceState).when(mPhone).getServiceState();
384         doReturn(mServiceState).when(mImsPhone).getServiceState();
385         doReturn(mPhone).when(mImsPhone).getDefaultPhone();
386         doReturn(true).when(mPhone).isPhoneTypeGsm();
387         doReturn(PhoneConstants.PHONE_TYPE_GSM).when(mPhone).getPhoneType();
388         doReturn(mCT).when(mPhone).getCallTracker();
389         doReturn(mSST).when(mPhone).getServiceStateTracker();
390         doReturn(mCarrierSignalAgent).when(mPhone).getCarrierSignalAgent();
391         doReturn(mCarrierActionAgent).when(mPhone).getCarrierActionAgent();
392         doReturn(mAppSmsManager).when(mPhone).getAppSmsManager();
393         mPhone.mEriManager = mEriManager;
394 
395         //mUiccController
396         doReturn(mUiccCardApplication3gpp).when(mUiccController).getUiccCardApplication(anyInt(),
397                 eq(UiccController.APP_FAM_3GPP));
398         doReturn(mUiccCardApplication3gpp2).when(mUiccController).getUiccCardApplication(anyInt(),
399                 eq(UiccController.APP_FAM_3GPP2));
400         doReturn(mUiccCardApplicationIms).when(mUiccController).getUiccCardApplication(anyInt(),
401                 eq(UiccController.APP_FAM_IMS));
402 
403         doAnswer(new Answer<IccRecords>() {
404             public IccRecords answer(InvocationOnMock invocation) {
405                 switch ((Integer) invocation.getArguments()[1]) {
406                     case UiccController.APP_FAM_3GPP:
407                         return mSimRecords;
408                     case UiccController.APP_FAM_3GPP2:
409                         return mRuimRecords;
410                     case UiccController.APP_FAM_IMS:
411                         return mIsimUiccRecords;
412                     default:
413                         logd("Unrecognized family " + invocation.getArguments()[1]);
414                         return null;
415                 }
416             }
417         }).when(mUiccController).getIccRecords(anyInt(), anyInt());
418 
419         //UiccCardApplication
420         doReturn(mSimRecords).when(mUiccCardApplication3gpp).getIccRecords();
421         doReturn(mRuimRecords).when(mUiccCardApplication3gpp2).getIccRecords();
422         doReturn(mIsimUiccRecords).when(mUiccCardApplicationIms).getIccRecords();
423 
424         //mUiccProfile
425         doReturn(mSimRecords).when(mUiccProfile).getIccRecords();
426         doAnswer(new Answer<IccRecords>() {
427             public IccRecords answer(InvocationOnMock invocation) {
428                 return (mPhone.isPhoneTypeGsm()) ? mSimRecords : mRuimRecords;
429             }
430         }).when(mUiccProfile).getIccRecords();
431 
432         //mUiccProfile
433         doReturn(mUiccCardApplication3gpp).when(mUiccProfile).getApplication(
434                 eq(UiccController.APP_FAM_3GPP));
435         doReturn(mUiccCardApplication3gpp2).when(mUiccProfile).getApplication(
436                 eq(UiccController.APP_FAM_3GPP2));
437         doReturn(mUiccCardApplicationIms).when(mUiccProfile).getApplication(
438                 eq(UiccController.APP_FAM_IMS));
439 
440         //SMS
441         doReturn(true).when(mSmsStorageMonitor).isStorageAvailable();
442         doReturn(true).when(mSmsUsageMonitor).check(nullable(String.class), anyInt());
443         doReturn(true).when(mTelephonyManager).getSmsReceiveCapableForPhone(anyInt(), anyBoolean());
444         doReturn(true).when(mTelephonyManager).getSmsSendCapableForPhone(
445                 anyInt(), anyBoolean());
446 
447         //Misc
448         doReturn(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS).when(mServiceState).
449                 getRilDataRadioTechnology();
450         doReturn(mPhone).when(mCT).getPhone();
451         mImsManagerInstances.put(mPhone.getPhoneId(), mImsManager);
452         doReturn(mImsEcbm).when(mImsManager).getEcbmInterface();
453         doReturn(mPhone).when(mInboundSmsHandler).getPhone();
454         doReturn(mImsCallProfile).when(mImsCall).getCallProfile();
455         doReturn(mIBinder).when(mIIntentSender).asBinder();
456         doReturn(mIIntentSender).when(mIActivityManager).getIntentSender(anyInt(),
457                 nullable(String.class), nullable(IBinder.class), nullable(String.class), anyInt(),
458                 nullable(Intent[].class), nullable(String[].class), anyInt(),
459                 nullable(Bundle.class), anyInt());
460         mSST.mSS = mServiceState;
461         mServiceManagerMockedServices.put("connectivity_metrics_logger", mConnMetLoggerBinder);
462 
463         //SIM
464         doReturn(1).when(mTelephonyManager).getSimCount();
465         doReturn(1).when(mTelephonyManager).getPhoneCount();
466 
467         //Data
468         //Initial state is: userData enabled, provisioned.
469         ContentResolver resolver = mContext.getContentResolver();
470         Settings.Global.putInt(resolver, Settings.Global.MOBILE_DATA, 1);
471         Settings.Global.putInt(resolver, Settings.Global.DEVICE_PROVISIONED, 1);
472         Settings.Global.putInt(resolver,
473                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, 1);
474 
475         //Use reflection to mock singletons
476         replaceInstance(CallManager.class, "INSTANCE", null, mCallManager);
477         replaceInstance(TelephonyComponentFactory.class, "sInstance", null,
478                 mTelephonyComponentFactory);
479         replaceInstance(UiccController.class, "mInstance", null, mUiccController);
480         replaceInstance(CdmaSubscriptionSourceManager.class, "sInstance", null, mCdmaSSM);
481         replaceInstance(ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances);
482         replaceInstance(SubscriptionController.class, "sInstance", null, mSubscriptionController);
483         replaceInstance(ProxyController.class, "sProxyController", null, mProxyController);
484         replaceInstance(ActivityManager.class, "IActivityManagerSingleton", null,
485                 mIActivityManagerSingleton);
486         replaceInstance(CdmaSubscriptionSourceManager.class,
487                 "mCdmaSubscriptionSourceChangedRegistrants", mCdmaSSM, mRegistrantList);
488         replaceInstance(SimulatedCommandsVerifier.class, "sInstance", null,
489                 mSimulatedCommandsVerifier);
490         replaceInstance(Singleton.class, "mInstance", mIActivityManagerSingleton,
491                 mIActivityManager);
492         replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices);
493         replaceInstance(IntentBroadcaster.class, "sIntentBroadcaster", null, mIntentBroadcaster);
494         replaceInstance(TelephonyManager.class, "sInstance", null,
495                 mContext.getSystemService(Context.TELEPHONY_SERVICE));
496         replaceInstance(PhoneFactory.class, "sMadeDefaults", null, true);
497         replaceInstance(PhoneFactory.class, "sPhone", null, mPhone);
498         replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
499         replaceInstance(PhoneFactory.class, "sSubInfoRecordUpdater", null, mSubInfoRecordUpdater);
500         replaceInstance(RadioConfig.class, "sRadioConfig", null, mMockRadioConfig);
501 
502         setReady(false);
503     }
504 
tearDown()505     protected void tearDown() throws Exception {
506 
507         mSimulatedCommands.dispose();
508 
509         SharedPreferences sharedPreferences = mContext.getSharedPreferences((String) null, 0);
510         sharedPreferences.edit().clear().commit();
511 
512         restoreInstances();
513     }
514 
logd(String s)515     protected static void logd(String s) {
516         Log.d(TAG, s);
517     }
518 
519     public static class FakeBlockedNumberContentProvider extends MockContentProvider {
520         public Set<String> mBlockedNumbers = new HashSet<>();
521         public int mNumEmergencyContactNotifications = 0;
522 
523         @Override
call(String method, String arg, Bundle extras)524         public Bundle call(String method, String arg, Bundle extras) {
525             switch (method) {
526                 case BlockedNumberContract.SystemContract.METHOD_SHOULD_SYSTEM_BLOCK_NUMBER:
527                     Bundle bundle = new Bundle();
528                     bundle.putBoolean(BlockedNumberContract.RES_NUMBER_IS_BLOCKED,
529                             mBlockedNumbers.contains(arg));
530                     return bundle;
531                 case BlockedNumberContract.SystemContract.METHOD_NOTIFY_EMERGENCY_CONTACT:
532                     mNumEmergencyContactNotifications++;
533                     return new Bundle();
534                 default:
535                     fail("Method not expected: " + method);
536             }
537             return null;
538         }
539     }
540 
setupMockPackagePermissionChecks()541     protected void setupMockPackagePermissionChecks() throws Exception {
542         doReturn(new String[]{TAG}).when(mPackageManager).getPackagesForUid(anyInt());
543         doReturn(mPackageInfo).when(mPackageManager).getPackageInfo(eq(TAG), anyInt());
544         doReturn(mPackageInfo).when(mPackageManager).getPackageInfoAsUser(
545                 eq(TAG), anyInt(), anyInt());
546     }
547 
waitForHandlerAction(Handler h, long timeoutMillis)548     protected final void waitForHandlerAction(Handler h, long timeoutMillis) {
549         final CountDownLatch lock = new CountDownLatch(1);
550         h.post(lock::countDown);
551         while (lock.getCount() > 0) {
552             try {
553                 lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
554             } catch (InterruptedException e) {
555                 // do nothing
556             }
557         }
558     }
559 
waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs)560     protected final void waitForHandlerActionDelayed(Handler h, long timeoutMillis, long delayMs) {
561         final CountDownLatch lock = new CountDownLatch(1);
562         h.postDelayed(lock::countDown, delayMs);
563         while (lock.getCount() > 0) {
564             try {
565                 lock.await(timeoutMillis, TimeUnit.MILLISECONDS);
566             } catch (InterruptedException e) {
567                 // do nothing
568             }
569         }
570     }
571 
invokeMethod( Object instance, String methodName, Class<?>[] parameterClasses, Object[] parameters)572     public static Object invokeMethod(
573             Object instance, String methodName, Class<?>[] parameterClasses, Object[] parameters) {
574         try {
575             Method method = instance.getClass().getDeclaredMethod(methodName, parameterClasses);
576             method.setAccessible(true);
577             return method.invoke(instance, parameters);
578         } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
579             fail(instance.getClass() + " " + methodName + " " + e.getClass().getName());
580         }
581         return null;
582     }
583 }
584