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