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