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