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.nullable;
23import static org.mockito.Mockito.anyInt;
24import static org.mockito.Mockito.doAnswer;
25import static org.mockito.Mockito.doReturn;
26import static org.mockito.Mockito.eq;
27
28import android.app.ActivityManager;
29import android.app.IActivityManager;
30import android.content.ContentResolver;
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.Looper;
43import android.os.RegistrantList;
44import android.os.ServiceManager;
45import android.provider.BlockedNumberContract;
46import android.provider.Settings;
47import android.telephony.ServiceState;
48import android.telephony.SubscriptionManager;
49import android.telephony.TelephonyManager;
50import android.telephony.euicc.EuiccManager;
51import android.telephony.ims.ImsCallProfile;
52import android.test.mock.MockContentProvider;
53import android.test.mock.MockContentResolver;
54import android.util.Log;
55import android.util.Singleton;
56
57import com.android.ims.ImsCall;
58import com.android.ims.ImsEcbm;
59import com.android.ims.ImsManager;
60import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
61import com.android.internal.telephony.cdma.EriManager;
62import com.android.internal.telephony.dataconnection.DcTracker;
63import com.android.internal.telephony.imsphone.ImsExternalCallTracker;
64import com.android.internal.telephony.imsphone.ImsPhone;
65import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
66import com.android.internal.telephony.test.SimulatedCommands;
67import com.android.internal.telephony.test.SimulatedCommandsVerifier;
68import com.android.internal.telephony.uicc.IccCardStatus;
69import com.android.internal.telephony.uicc.IccRecords;
70import com.android.internal.telephony.uicc.IsimUiccRecords;
71import com.android.internal.telephony.uicc.RuimRecords;
72import com.android.internal.telephony.uicc.SIMRecords;
73import com.android.internal.telephony.uicc.UiccCard;
74import com.android.internal.telephony.uicc.UiccCardApplication;
75import com.android.internal.telephony.uicc.UiccController;
76import com.android.internal.telephony.uicc.UiccProfile;
77
78import org.mockito.Mock;
79import org.mockito.MockitoAnnotations;
80import org.mockito.invocation.InvocationOnMock;
81import org.mockito.stubbing.Answer;
82
83import java.lang.reflect.Field;
84import java.lang.reflect.InvocationTargetException;
85import java.lang.reflect.Method;
86import java.util.HashMap;
87import java.util.HashSet;
88import java.util.Iterator;
89import java.util.LinkedList;
90import java.util.Set;
91import java.util.concurrent.CountDownLatch;
92import java.util.concurrent.TimeUnit;
93
94public 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;
226        InstanceKey(final Class c, final String instName, final Object obj) {
227            mClass = c;
228            mInstName = instName;
229            mObj = obj;
230        }
231
232        @Override
233        public int hashCode() {
234            return (mClass.getName().hashCode() * 31 + mInstName.hashCode()) * 31;
235        }
236
237        @Override
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
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
262    protected void setReady(boolean ready) {
263        synchronized (mLock) {
264            mReady = ready;
265            mLock.notifyAll();
266        }
267    }
268
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
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
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
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
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
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
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
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
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
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
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