Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright (C) 2015 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.server.telecom.tests;
     18 
     19 import com.google.common.collect.ArrayListMultimap;
     20 import com.google.common.collect.Multimap;
     21 
     22 import com.android.internal.telecom.IConnectionService;
     23 import com.android.internal.telecom.IInCallService;
     24 
     25 import org.mockito.MockitoAnnotations;
     26 import org.mockito.invocation.InvocationOnMock;
     27 import org.mockito.stubbing.Answer;
     28 
     29 import android.app.AppOpsManager;
     30 import android.app.NotificationManager;
     31 import android.app.StatusBarManager;
     32 import android.content.BroadcastReceiver;
     33 import android.content.ComponentName;
     34 import android.content.ContentResolver;
     35 import android.content.Context;
     36 import android.content.IContentProvider;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.ServiceConnection;
     40 import android.content.pm.ApplicationInfo;
     41 import android.content.pm.PackageManager;
     42 import android.content.pm.ResolveInfo;
     43 import android.content.pm.ServiceInfo;
     44 import android.content.res.Configuration;
     45 import android.content.res.Resources;
     46 import android.location.Country;
     47 import android.location.CountryDetector;
     48 import android.media.AudioManager;
     49 import android.os.Bundle;
     50 import android.os.Handler;
     51 import android.os.IInterface;
     52 import android.os.UserHandle;
     53 import android.os.UserManager;
     54 import android.telecom.CallAudioState;
     55 import android.telecom.ConnectionService;
     56 import android.telecom.Log;
     57 import android.telecom.InCallService;
     58 import android.telecom.PhoneAccount;
     59 import android.telecom.TelecomManager;
     60 import android.telephony.CarrierConfigManager;
     61 import android.telephony.SubscriptionManager;
     62 import android.telephony.TelephonyManager;
     63 import android.test.mock.MockContext;
     64 
     65 import java.io.File;
     66 import java.io.IOException;
     67 import java.util.ArrayList;
     68 import java.util.Arrays;
     69 import java.util.HashMap;
     70 import java.util.List;
     71 import java.util.Locale;
     72 import java.util.Map;
     73 
     74 import static org.mockito.Matchers.anyString;
     75 import static org.mockito.Mockito.any;
     76 import static org.mockito.Mockito.anyInt;
     77 import static org.mockito.Mockito.doAnswer;
     78 import static org.mockito.Mockito.doReturn;
     79 import static org.mockito.Mockito.eq;
     80 import static org.mockito.Mockito.mock;
     81 import static org.mockito.Mockito.spy;
     82 import static org.mockito.Mockito.when;
     83 
     84 /**
     85  * Controls a test {@link Context} as would be provided by the Android framework to an
     86  * {@code Activity}, {@code Service} or other system-instantiated component.
     87  *
     88  * The {@link Context} created by this object is "hollow" but its {@code applicationContext}
     89  * property points to an application context implementing all the nontrivial functionality.
     90  */
     91 public class ComponentContextFixture implements TestFixture<Context> {
     92 
     93     public class FakeApplicationContext extends MockContext {
     94         @Override
     95         public PackageManager getPackageManager() {
     96             return mPackageManager;
     97         }
     98 
     99         @Override
    100         public String getPackageName() {
    101             return "com.android.server.telecom.tests";
    102         }
    103 
    104         @Override
    105         public String getPackageResourcePath() {
    106             return "/tmp/i/dont/know";
    107         }
    108 
    109         @Override
    110         public Context getApplicationContext() {
    111             return mApplicationContextSpy;
    112         }
    113 
    114         @Override
    115         public File getFilesDir() {
    116             try {
    117                 return File.createTempFile("temp", "temp").getParentFile();
    118             } catch (IOException e) {
    119                 throw new RuntimeException(e);
    120             }
    121         }
    122 
    123         @Override
    124         public boolean bindServiceAsUser(
    125                 Intent serviceIntent,
    126                 ServiceConnection connection,
    127                 int flags,
    128                 UserHandle userHandle) {
    129             // TODO: Implement "as user" functionality
    130             return bindService(serviceIntent, connection, flags);
    131         }
    132 
    133         @Override
    134         public boolean bindService(
    135                 Intent serviceIntent,
    136                 ServiceConnection connection,
    137                 int flags) {
    138             if (mServiceByServiceConnection.containsKey(connection)) {
    139                 throw new RuntimeException("ServiceConnection already bound: " + connection);
    140             }
    141             IInterface service = mServiceByComponentName.get(serviceIntent.getComponent());
    142             if (service == null) {
    143                 throw new RuntimeException("ServiceConnection not found: "
    144                         + serviceIntent.getComponent());
    145             }
    146             mServiceByServiceConnection.put(connection, service);
    147             connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder());
    148             return true;
    149         }
    150 
    151         @Override
    152         public void unbindService(
    153                 ServiceConnection connection) {
    154             IInterface service = mServiceByServiceConnection.remove(connection);
    155             if (service == null) {
    156                 throw new RuntimeException("ServiceConnection not found: " + connection);
    157             }
    158             connection.onServiceDisconnected(mComponentNameByService.get(service));
    159         }
    160 
    161         @Override
    162         public Object getSystemService(String name) {
    163             switch (name) {
    164                 case Context.AUDIO_SERVICE:
    165                     return mAudioManager;
    166                 case Context.TELEPHONY_SERVICE:
    167                     return mTelephonyManager;
    168                 case Context.APP_OPS_SERVICE:
    169                     return mAppOpsManager;
    170                 case Context.NOTIFICATION_SERVICE:
    171                     return mNotificationManager;
    172                 case Context.STATUS_BAR_SERVICE:
    173                     return mStatusBarManager;
    174                 case Context.USER_SERVICE:
    175                     return mUserManager;
    176                 case Context.TELEPHONY_SUBSCRIPTION_SERVICE:
    177                     return mSubscriptionManager;
    178                 case Context.TELECOM_SERVICE:
    179                     return mTelecomManager;
    180                 case Context.CARRIER_CONFIG_SERVICE:
    181                     return mCarrierConfigManager;
    182                 case Context.COUNTRY_DETECTOR:
    183                     return mCountryDetector;
    184                 default:
    185                     return null;
    186             }
    187         }
    188 
    189         @Override
    190         public String getSystemServiceName(Class<?> svcClass) {
    191             if (svcClass == UserManager.class) {
    192                 return Context.USER_SERVICE;
    193             }
    194             throw new UnsupportedOperationException();
    195         }
    196 
    197         @Override
    198         public int getUserId() {
    199             return 0;
    200         }
    201 
    202         @Override
    203         public Resources getResources() {
    204             return mResources;
    205         }
    206 
    207         @Override
    208         public String getOpPackageName() {
    209             return "com.android.server.telecom.tests";
    210         }
    211 
    212         @Override
    213         public ApplicationInfo getApplicationInfo() {
    214             return mTestApplicationInfo;
    215         }
    216 
    217         @Override
    218         public ContentResolver getContentResolver() {
    219             return new ContentResolver(mApplicationContextSpy) {
    220                 @Override
    221                 protected IContentProvider acquireProvider(Context c, String name) {
    222                     Log.i(this, "acquireProvider %s", name);
    223                     return getOrCreateProvider(name);
    224                 }
    225 
    226                 @Override
    227                 public boolean releaseProvider(IContentProvider icp) {
    228                     return true;
    229                 }
    230 
    231                 @Override
    232                 protected IContentProvider acquireUnstableProvider(Context c, String name) {
    233                     Log.i(this, "acquireUnstableProvider %s", name);
    234                     return getOrCreateProvider(name);
    235                 }
    236 
    237                 private IContentProvider getOrCreateProvider(String name) {
    238                     if (!mIContentProviderByUri.containsKey(name)) {
    239                         mIContentProviderByUri.put(name, mock(IContentProvider.class));
    240                     }
    241                     return mIContentProviderByUri.get(name);
    242                 }
    243 
    244                 @Override
    245                 public boolean releaseUnstableProvider(IContentProvider icp) {
    246                     return false;
    247                 }
    248 
    249                 @Override
    250                 public void unstableProviderDied(IContentProvider icp) {
    251                 }
    252             };
    253         }
    254 
    255         @Override
    256         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
    257             // TODO -- this is called by WiredHeadsetManager!!!
    258             return null;
    259         }
    260 
    261         @Override
    262         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
    263                 String broadcastPermission, Handler scheduler) {
    264             return null;
    265         }
    266 
    267         @Override
    268         public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
    269                 IntentFilter filter, String broadcastPermission, Handler scheduler) {
    270             return null;
    271         }
    272 
    273         @Override
    274         public void sendBroadcast(Intent intent) {
    275             // TODO -- need to ensure this is captured
    276         }
    277 
    278         @Override
    279         public void sendBroadcast(Intent intent, String receiverPermission) {
    280             // TODO -- need to ensure this is captured
    281         }
    282 
    283         @Override
    284         public void sendBroadcastAsUser(Intent intent, UserHandle userHandle) {
    285             // TODO -- need to ensure this is captured
    286         }
    287 
    288         @Override
    289         public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
    290                 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
    291                 int initialCode, String initialData, Bundle initialExtras) {
    292             // TODO -- need to ensure this is captured
    293         }
    294 
    295         @Override
    296         public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
    297                 String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
    298                 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
    299         }
    300 
    301         @Override
    302         public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
    303                 throws PackageManager.NameNotFoundException {
    304             return this;
    305         }
    306 
    307         @Override
    308         public int checkCallingOrSelfPermission(String permission) {
    309             return PackageManager.PERMISSION_GRANTED;
    310         }
    311 
    312         @Override
    313         public void enforceCallingOrSelfPermission(String permission, String message) {
    314             // Don't bother enforcing anything in mock.
    315         }
    316 
    317         @Override
    318         public void enforcePermission(
    319                 String permission, int pid, int uid, String message) {
    320             // By default, don't enforce anything in mock.
    321         }
    322 
    323         @Override
    324         public void startActivityAsUser(Intent intent, UserHandle userHandle) {
    325             // For capturing
    326         }
    327     }
    328 
    329     public class FakeAudioManager extends AudioManager {
    330 
    331         private boolean mMute = false;
    332         private boolean mSpeakerphoneOn = false;
    333         private int mAudioStreamValue = 1;
    334         private int mMode = AudioManager.MODE_NORMAL;
    335         private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
    336 
    337         public FakeAudioManager(Context context) {
    338             super(context);
    339         }
    340 
    341         @Override
    342         public void setMicrophoneMute(boolean value) {
    343             mMute = value;
    344         }
    345 
    346         @Override
    347         public boolean isMicrophoneMute() {
    348             return mMute;
    349         }
    350 
    351         @Override
    352         public void setSpeakerphoneOn(boolean value) {
    353             mSpeakerphoneOn = value;
    354         }
    355 
    356         @Override
    357         public boolean isSpeakerphoneOn() {
    358             return mSpeakerphoneOn;
    359         }
    360 
    361         @Override
    362         public void setMode(int mode) {
    363             mMode = mode;
    364         }
    365 
    366         @Override
    367         public int getMode() {
    368             return mMode;
    369         }
    370 
    371         @Override
    372         public void setRingerModeInternal(int ringerMode) {
    373             mRingerMode = ringerMode;
    374         }
    375 
    376         @Override
    377         public int getRingerModeInternal() {
    378             return mRingerMode;
    379         }
    380 
    381         @Override
    382         public void setStreamVolume(int streamTypeUnused, int index, int flagsUnused){
    383             mAudioStreamValue = index;
    384         }
    385 
    386         @Override
    387         public int getStreamVolume(int streamValueUnused) {
    388             return mAudioStreamValue;
    389         }
    390     }
    391 
    392     private final Multimap<String, ComponentName> mComponentNamesByAction =
    393             ArrayListMultimap.create();
    394     private final Map<ComponentName, IInterface> mServiceByComponentName = new HashMap<>();
    395     private final Map<ComponentName, ServiceInfo> mServiceInfoByComponentName = new HashMap<>();
    396     private final Map<IInterface, ComponentName> mComponentNameByService = new HashMap<>();
    397     private final Map<ServiceConnection, IInterface> mServiceByServiceConnection = new HashMap<>();
    398 
    399     private final Context mContext = new MockContext() {
    400         @Override
    401         public Context getApplicationContext() {
    402             return mApplicationContextSpy;
    403         }
    404 
    405         @Override
    406         public Resources getResources() {
    407             return mResources;
    408         }
    409     };
    410 
    411     // The application context is the most important object this class provides to the system
    412     // under test.
    413     private final Context mApplicationContext = new FakeApplicationContext();
    414 
    415     // We then create a spy on the application context allowing standard Mockito-style
    416     // when(...) logic to be used to add specific little responses where needed.
    417 
    418     private final Resources mResources = mock(Resources.class);
    419     private final Context mApplicationContextSpy = spy(mApplicationContext);
    420     private final PackageManager mPackageManager = mock(PackageManager.class);
    421     private final AudioManager mAudioManager = spy(new FakeAudioManager(mContext));
    422     private final TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
    423     private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class);
    424     private final NotificationManager mNotificationManager = mock(NotificationManager.class);
    425     private final UserManager mUserManager = mock(UserManager.class);
    426     private final StatusBarManager mStatusBarManager = mock(StatusBarManager.class);
    427     private final SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.class);
    428     private final CarrierConfigManager mCarrierConfigManager = mock(CarrierConfigManager.class);
    429     private final CountryDetector mCountryDetector = mock(CountryDetector.class);
    430     private final Map<String, IContentProvider> mIContentProviderByUri = new HashMap<>();
    431     private final Configuration mResourceConfiguration = new Configuration();
    432     private final ApplicationInfo mTestApplicationInfo = new ApplicationInfo();
    433 
    434     private TelecomManager mTelecomManager = null;
    435 
    436     public ComponentContextFixture() {
    437         MockitoAnnotations.initMocks(this);
    438         when(mResources.getConfiguration()).thenReturn(mResourceConfiguration);
    439         when(mResources.getString(anyInt())).thenReturn("");
    440         when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
    441         mResourceConfiguration.setLocale(Locale.TAIWAN);
    442 
    443         // TODO: Move into actual tests
    444         doReturn(false).when(mAudioManager).isWiredHeadsetOn();
    445 
    446         doAnswer(new Answer<List<ResolveInfo>>() {
    447             @Override
    448             public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
    449                 return doQueryIntentServices(
    450                         (Intent) invocation.getArguments()[0],
    451                         (Integer) invocation.getArguments()[1]);
    452             }
    453         }).when(mPackageManager).queryIntentServices((Intent) any(), anyInt());
    454 
    455         doAnswer(new Answer<List<ResolveInfo>>() {
    456             @Override
    457             public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
    458                 return doQueryIntentServices(
    459                         (Intent) invocation.getArguments()[0],
    460                         (Integer) invocation.getArguments()[1]);
    461             }
    462         }).when(mPackageManager).queryIntentServicesAsUser((Intent) any(), anyInt(), anyInt());
    463 
    464         when(mTelephonyManager.getSubIdForPhoneAccount((PhoneAccount) any())).thenReturn(1);
    465 
    466         when(mTelephonyManager.getNetworkOperatorName()).thenReturn("label1");
    467         when(mTelephonyManager.getMultiSimConfiguration()).thenReturn(
    468                 TelephonyManager.MultiSimVariants.UNKNOWN);
    469         when(mResources.getBoolean(eq(R.bool.grant_location_permission_enabled))).thenReturn(false);
    470         doAnswer(new Answer<Void>(){
    471             @Override
    472             public Void answer(InvocationOnMock invocation) throws Throwable {
    473                 return null;
    474             }
    475         }).when(mAppOpsManager).checkPackage(anyInt(), anyString());
    476 
    477         when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);
    478 
    479         when(mUserManager.getSerialNumberForUser(any(UserHandle.class))).thenReturn(-1L);
    480 
    481         doReturn(null).when(mApplicationContextSpy).registerReceiver(any(BroadcastReceiver.class),
    482                 any(IntentFilter.class));
    483     }
    484 
    485     @Override
    486     public Context getTestDouble() {
    487         return mContext;
    488     }
    489 
    490     public void addConnectionService(
    491             ComponentName componentName,
    492             IConnectionService service)
    493             throws Exception {
    494         addService(ConnectionService.SERVICE_INTERFACE, componentName, service);
    495         ServiceInfo serviceInfo = new ServiceInfo();
    496         serviceInfo.permission = android.Manifest.permission.BIND_CONNECTION_SERVICE;
    497         serviceInfo.packageName = componentName.getPackageName();
    498         serviceInfo.name = componentName.getClassName();
    499         mServiceInfoByComponentName.put(componentName, serviceInfo);
    500     }
    501 
    502     public void addInCallService(
    503             ComponentName componentName,
    504             IInCallService service)
    505             throws Exception {
    506         addService(InCallService.SERVICE_INTERFACE, componentName, service);
    507         ServiceInfo serviceInfo = new ServiceInfo();
    508         serviceInfo.permission = android.Manifest.permission.BIND_INCALL_SERVICE;
    509         serviceInfo.packageName = componentName.getPackageName();
    510         serviceInfo.name = componentName.getClassName();
    511         mServiceInfoByComponentName.put(componentName, serviceInfo);
    512     }
    513 
    514     public void putResource(int id, final String value) {
    515         when(mResources.getText(eq(id))).thenReturn(value);
    516         when(mResources.getString(eq(id))).thenReturn(value);
    517         when(mResources.getString(eq(id), any())).thenAnswer(new Answer<String>() {
    518             @Override
    519             public String answer(InvocationOnMock invocation) {
    520                 Object[] args = invocation.getArguments();
    521                 return String.format(value, Arrays.copyOfRange(args, 1, args.length));
    522             }
    523         });
    524     }
    525 
    526     public void putBooleanResource(int id, boolean value) {
    527         when(mResources.getBoolean(eq(id))).thenReturn(value);
    528     }
    529 
    530     public void setTelecomManager(TelecomManager telecomManager) {
    531         mTelecomManager = telecomManager;
    532     }
    533 
    534     public TelephonyManager getTelephonyManager() {
    535         return mTelephonyManager;
    536     }
    537 
    538     private void addService(String action, ComponentName name, IInterface service) {
    539         mComponentNamesByAction.put(action, name);
    540         mServiceByComponentName.put(name, service);
    541         mComponentNameByService.put(service, name);
    542     }
    543 
    544     private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
    545         List<ResolveInfo> result = new ArrayList<>();
    546         for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
    547             ResolveInfo resolveInfo = new ResolveInfo();
    548             resolveInfo.serviceInfo = mServiceInfoByComponentName.get(componentName);
    549             resolveInfo.serviceInfo.metaData = new Bundle();
    550             resolveInfo.serviceInfo.metaData.putBoolean(
    551                     TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
    552             result.add(resolveInfo);
    553         }
    554         return result;
    555     }
    556 }
    557