• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
getPackageManager()95         public PackageManager getPackageManager() {
96             return mPackageManager;
97         }
98 
99         @Override
getPackageName()100         public String getPackageName() {
101             return "com.android.server.telecom.tests";
102         }
103 
104         @Override
getPackageResourcePath()105         public String getPackageResourcePath() {
106             return "/tmp/i/dont/know";
107         }
108 
109         @Override
getApplicationContext()110         public Context getApplicationContext() {
111             return mApplicationContextSpy;
112         }
113 
114         @Override
getFilesDir()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
bindServiceAsUser( Intent serviceIntent, ServiceConnection connection, int flags, UserHandle userHandle)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
bindService( Intent serviceIntent, ServiceConnection connection, int flags)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
unbindService( ServiceConnection connection)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
getSystemService(String name)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
getSystemServiceName(Class<?> svcClass)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
getUserId()198         public int getUserId() {
199             return 0;
200         }
201 
202         @Override
getResources()203         public Resources getResources() {
204             return mResources;
205         }
206 
207         @Override
getOpPackageName()208         public String getOpPackageName() {
209             return "com.android.server.telecom.tests";
210         }
211 
212         @Override
getApplicationInfo()213         public ApplicationInfo getApplicationInfo() {
214             return mTestApplicationInfo;
215         }
216 
217         @Override
getContentResolver()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
registerReceiver(BroadcastReceiver receiver, IntentFilter filter)256         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
257             // TODO -- this is called by WiredHeadsetManager!!!
258             return null;
259         }
260 
261         @Override
registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)262         public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
263                 String broadcastPermission, Handler scheduler) {
264             return null;
265         }
266 
267         @Override
registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle, IntentFilter filter, String broadcastPermission, Handler scheduler)268         public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
269                 IntentFilter filter, String broadcastPermission, Handler scheduler) {
270             return null;
271         }
272 
273         @Override
sendBroadcast(Intent intent)274         public void sendBroadcast(Intent intent) {
275             // TODO -- need to ensure this is captured
276         }
277 
278         @Override
sendBroadcast(Intent intent, String receiverPermission)279         public void sendBroadcast(Intent intent, String receiverPermission) {
280             // TODO -- need to ensure this is captured
281         }
282 
283         @Override
sendBroadcastAsUser(Intent intent, UserHandle userHandle)284         public void sendBroadcastAsUser(Intent intent, UserHandle userHandle) {
285             // TODO -- need to ensure this is captured
286         }
287 
288         @Override
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)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
sendOrderedBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission, int appOp, BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, String initialData, Bundle initialExtras)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
createPackageContextAsUser(String packageName, int flags, UserHandle user)302         public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
303                 throws PackageManager.NameNotFoundException {
304             return this;
305         }
306 
307         @Override
checkCallingOrSelfPermission(String permission)308         public int checkCallingOrSelfPermission(String permission) {
309             return PackageManager.PERMISSION_GRANTED;
310         }
311 
312         @Override
enforceCallingOrSelfPermission(String permission, String message)313         public void enforceCallingOrSelfPermission(String permission, String message) {
314             // Don't bother enforcing anything in mock.
315         }
316 
317         @Override
enforcePermission( String permission, int pid, int uid, String message)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
startActivityAsUser(Intent intent, UserHandle userHandle)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