1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.internal.telephony; 18 19import static org.mockito.Mockito.any; 20import static org.mockito.Mockito.anyInt; 21import static org.mockito.Mockito.doAnswer; 22import static org.mockito.Mockito.doReturn; 23import static org.mockito.Mockito.eq; 24import static org.mockito.Mockito.mock; 25import static org.mockito.Mockito.spy; 26import static org.mockito.Mockito.when; 27 28import android.app.AlarmManager; 29import android.app.AppOpsManager; 30import android.app.DownloadManager; 31import android.app.NotificationManager; 32import android.app.usage.UsageStatsManager; 33import android.content.BroadcastReceiver; 34import android.content.ComponentName; 35import android.content.ContentProvider; 36import android.content.ContentResolver; 37import android.content.ContentValues; 38import android.content.Context; 39import android.content.Intent; 40import android.content.IntentFilter; 41import android.content.ServiceConnection; 42import android.content.SharedPreferences; 43import android.content.pm.PackageManager; 44import android.content.pm.ResolveInfo; 45import android.content.pm.ServiceInfo; 46import android.content.res.AssetManager; 47import android.content.res.Configuration; 48import android.content.res.Resources; 49import android.database.Cursor; 50import android.database.MatrixCursor; 51import android.net.ConnectivityManager; 52import android.net.Uri; 53import android.net.wifi.WifiManager; 54import android.os.BatteryManager; 55import android.os.Bundle; 56import android.os.Handler; 57import android.os.IInterface; 58import android.os.PersistableBundle; 59import android.os.UserHandle; 60import android.os.UserManager; 61import android.preference.PreferenceManager; 62import android.provider.Settings; 63import android.provider.Telephony.ServiceStateTable; 64import android.telecom.TelecomManager; 65import android.telephony.CarrierConfigManager; 66import android.telephony.SubscriptionManager; 67import android.telephony.TelephonyManager; 68import android.telephony.euicc.EuiccManager; 69import android.test.mock.MockContentProvider; 70import android.test.mock.MockContentResolver; 71import android.test.mock.MockContext; 72import android.util.Log; 73 74import com.google.common.collect.ArrayListMultimap; 75import com.google.common.collect.Multimap; 76 77import org.mockito.MockitoAnnotations; 78import org.mockito.invocation.InvocationOnMock; 79import org.mockito.stubbing.Answer; 80 81import java.util.ArrayList; 82import java.util.Arrays; 83import java.util.Collection; 84import java.util.HashMap; 85import java.util.HashSet; 86import java.util.List; 87import java.util.Locale; 88import java.util.Map; 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 * Contains Fake<Component> classes like FakeContext for components that require complex and 95 * reusable stubbing. Others can be mocked using Mockito functions in tests or constructor/public 96 * methods of this class. 97 */ 98public class ContextFixture implements TestFixture<Context> { 99 private static final String TAG = "ContextFixture"; 100 public static final String PERMISSION_ENABLE_ALL = "android.permission.STUB_PERMISSION"; 101 102 public class FakeContentProvider extends MockContentProvider { 103 private String[] mColumns = {"name", "value"}; 104 private HashMap<String, String> mKeyValuePairs = new HashMap<String, String>(); 105 private int mNumKeyValuePairs = 0; 106 107 @Override 108 public int delete(Uri uri, String selection, String[] selectionArgs) { 109 return 0; 110 } 111 112 @Override 113 public Uri insert(Uri uri, ContentValues values) { 114 Uri newUri = null; 115 if (values != null) { 116 mKeyValuePairs.put(values.getAsString("name"), values.getAsString("value")); 117 mNumKeyValuePairs++; 118 newUri = Uri.withAppendedPath(uri, "" + mNumKeyValuePairs); 119 } 120 logd("insert called, new mNumKeyValuePairs: " + mNumKeyValuePairs + " uri: " + uri + 121 " newUri: " + newUri); 122 return newUri; 123 } 124 125 @Override 126 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, 127 String sortOrder) { 128 //assuming query will always be of the form 'name = ?' 129 logd("query called, mNumKeyValuePairs: " + mNumKeyValuePairs + " uri: " + uri); 130 if (mKeyValuePairs.containsKey(selectionArgs[0])) { 131 MatrixCursor cursor = new MatrixCursor(projection); 132 cursor.addRow(new String[]{mKeyValuePairs.get(selectionArgs[0])}); 133 return cursor; 134 } 135 return null; 136 } 137 138 @Override 139 public Bundle call(String method, String request, Bundle args) { 140 logd("call called, mNumKeyValuePairs: " + mNumKeyValuePairs + " method: " + method + 141 " request: " + request); 142 switch(method) { 143 case Settings.CALL_METHOD_GET_GLOBAL: 144 case Settings.CALL_METHOD_GET_SECURE: 145 case Settings.CALL_METHOD_GET_SYSTEM: 146 if (mKeyValuePairs.containsKey(request)) { 147 Bundle b = new Bundle(1); 148 b.putCharSequence("value", mKeyValuePairs.get(request)); 149 logd("returning value pair: " + mKeyValuePairs.get(request) + " for " + 150 request); 151 return b; 152 } 153 break; 154 case Settings.CALL_METHOD_PUT_GLOBAL: 155 case Settings.CALL_METHOD_PUT_SECURE: 156 case Settings.CALL_METHOD_PUT_SYSTEM: 157 logd("adding key-value pair: " + request + "-" + (String)args.get("value")); 158 mKeyValuePairs.put(request, (String)args.get("value")); 159 mNumKeyValuePairs++; 160 break; 161 } 162 return null; 163 } 164 } 165 166 private final HashMap<String, Object> mSystemServices = new HashMap<String, Object>(); 167 168 public void setSystemService(String name, Object service) { 169 synchronized (mSystemServices) { 170 mSystemServices.put(name, service); 171 } 172 } 173 174 public class FakeContext extends MockContext { 175 @Override 176 public PackageManager getPackageManager() { 177 return mPackageManager; 178 } 179 180 @Override 181 public boolean bindService( 182 Intent serviceIntent, 183 ServiceConnection connection, 184 int flags) { 185 if (mServiceByServiceConnection.containsKey(connection)) { 186 throw new RuntimeException("ServiceConnection already bound: " + connection); 187 } 188 IInterface service = mServiceByComponentName.get(serviceIntent.getComponent()); 189 if (service == null) { 190 service = mServiceByPackageName.get(serviceIntent.getPackage()); 191 } 192 if (service == null) { 193 throw new RuntimeException( 194 String.format("ServiceConnection not found for component: %s, package: %s", 195 serviceIntent.getComponent(), serviceIntent.getPackage())); 196 } 197 mServiceByServiceConnection.put(connection, service); 198 connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder()); 199 return true; 200 } 201 202 @Override 203 public void unbindService( 204 ServiceConnection connection) { 205 IInterface service = mServiceByServiceConnection.remove(connection); 206 if (service == null) { 207 throw new RuntimeException("ServiceConnection not found: " + connection); 208 } 209 connection.onServiceDisconnected(mComponentNameByService.get(service)); 210 } 211 212 @Override 213 public Object getSystemService(String name) { 214 synchronized (mSystemServices) { 215 Object service = mSystemServices.get(name); 216 if (service != null) return service; 217 } 218 switch (name) { 219 case Context.TELEPHONY_SERVICE: 220 return mTelephonyManager; 221 case Context.APP_OPS_SERVICE: 222 return mAppOpsManager; 223 case Context.NOTIFICATION_SERVICE: 224 return mNotificationManager; 225 case Context.USER_SERVICE: 226 return mUserManager; 227 case Context.CARRIER_CONFIG_SERVICE: 228 return mCarrierConfigManager; 229 case Context.TELEPHONY_SUBSCRIPTION_SERVICE: 230 return mSubscriptionManager; 231 case Context.WIFI_SERVICE: 232 return mWifiManager; 233 case Context.ALARM_SERVICE: 234 return mAlarmManager; 235 case Context.CONNECTIVITY_SERVICE: 236 return mConnectivityManager; 237 case Context.USAGE_STATS_SERVICE: 238 return mUsageStatManager; 239 case Context.BATTERY_SERVICE: 240 return mBatteryManager; 241 case Context.EUICC_SERVICE: 242 return mEuiccManager; 243 case Context.TELECOM_SERVICE: 244 return mTelecomManager; 245 case Context.DOWNLOAD_SERVICE: 246 return mDownloadManager; 247 case Context.DISPLAY_SERVICE: 248 case Context.POWER_SERVICE: 249 // PowerManager and DisplayManager are final classes so cannot be mocked, 250 // return real services. 251 return TestApplication.getAppContext().getSystemService(name); 252 default: 253 return null; 254 } 255 } 256 257 @Override 258 public String getSystemServiceName(Class<?> serviceClass) { 259 if (serviceClass == SubscriptionManager.class) { 260 return Context.TELEPHONY_SUBSCRIPTION_SERVICE; 261 } 262 return super.getSystemServiceName(serviceClass); 263 } 264 265 @Override 266 public int getUserId() { 267 return 0; 268 } 269 270 @Override 271 public AssetManager getAssets() { 272 return mAssetManager; 273 } 274 275 @Override 276 public Resources getResources() { 277 return mResources; 278 } 279 280 @Override 281 public String getOpPackageName() { 282 return "com.android.internal.telephony"; 283 } 284 285 @Override 286 public ContentResolver getContentResolver() { 287 return mContentResolver; 288 } 289 290 @Override 291 public Resources.Theme getTheme() { 292 return null; 293 } 294 295 @Override 296 public void unregisterReceiver(BroadcastReceiver receiver) { 297 } 298 299 @Override 300 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) { 301 return registerReceiver(receiver, filter, null, null); 302 } 303 304 @Override 305 public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, 306 String broadcastPermission, Handler scheduler) { 307 return registerReceiverAsUser(receiver, null, filter, broadcastPermission, scheduler); 308 } 309 310 @Override 311 public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle user, 312 IntentFilter filter, String broadcastPermission, Handler scheduler) { 313 Intent result = null; 314 synchronized (mBroadcastReceiversByAction) { 315 for (int i = 0 ; i < filter.countActions() ; i++) { 316 mBroadcastReceiversByAction.put(filter.getAction(i), receiver); 317 if (result == null) { 318 result = mStickyBroadcastByAction.get(filter.getAction(i)); 319 } 320 } 321 } 322 323 return result; 324 } 325 326 @Override 327 public void sendBroadcast(Intent intent) { 328 logd("sendBroadcast called for " + intent.getAction()); 329 synchronized (mBroadcastReceiversByAction) { 330 for (BroadcastReceiver broadcastReceiver : 331 mBroadcastReceiversByAction.get(intent.getAction())) { 332 broadcastReceiver.onReceive(mContext, intent); 333 } 334 } 335 } 336 337 @Override 338 public void sendBroadcast(Intent intent, String receiverPermission) { 339 logd("sendBroadcast called for " + intent.getAction()); 340 sendBroadcast(intent); 341 } 342 343 @Override 344 public void sendOrderedBroadcast(Intent intent, String receiverPermission) { 345 logd("sendOrderedBroadcast called for " + intent.getAction()); 346 sendBroadcast(intent); 347 } 348 349 @Override 350 public void sendOrderedBroadcast(Intent intent, String receiverPermission, 351 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 352 String initialData, Bundle initialExtras) { 353 sendOrderedBroadcast(intent, receiverPermission); 354 if (resultReceiver != null) { 355 synchronized (mOrderedBroadcastReceivers) { 356 mOrderedBroadcastReceivers.put(intent, resultReceiver); 357 } 358 } 359 } 360 361 @Override 362 public void sendOrderedBroadcast(Intent intent, String receiverPermission, Bundle options, 363 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 364 String initialData, Bundle initialExtras) { 365 sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, 366 initialCode, initialData, initialExtras); 367 } 368 369 @Override 370 public void sendOrderedBroadcast(Intent intent, String receiverPermission, int appOp, 371 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 372 String initialData, Bundle initialExtras) { 373 sendOrderedBroadcast(intent, receiverPermission, resultReceiver, scheduler, 374 initialCode, initialData, initialExtras); 375 } 376 377 @Override 378 public void sendBroadcastAsUser(Intent intent, UserHandle user) { 379 sendBroadcast(intent); 380 } 381 382 @Override 383 public void sendBroadcastAsUser(Intent intent, UserHandle user, 384 String receiverPermission) { 385 sendBroadcast(intent); 386 } 387 388 @Override 389 public void sendBroadcastAsUser(Intent intent, UserHandle user, 390 String receiverPermission, int appOp) { 391 sendBroadcast(intent); 392 } 393 394 @Override 395 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 396 String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler, 397 int initialCode, String initialData, Bundle initialExtras) { 398 logd("sendOrderedBroadcastAsUser called for " + intent.getAction()); 399 sendBroadcast(intent); 400 if (resultReceiver != null) { 401 synchronized (mOrderedBroadcastReceivers) { 402 mOrderedBroadcastReceivers.put(intent, resultReceiver); 403 } 404 } 405 } 406 407 @Override 408 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 409 String receiverPermission, int appOp, BroadcastReceiver resultReceiver, 410 Handler scheduler, int initialCode, String initialData, Bundle initialExtras) { 411 logd("sendOrderedBroadcastAsUser called for " + intent.getAction()); 412 sendBroadcast(intent); 413 if (resultReceiver != null) { 414 synchronized (mOrderedBroadcastReceivers) { 415 mOrderedBroadcastReceivers.put(intent, resultReceiver); 416 } 417 } 418 } 419 420 @Override 421 public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user, 422 String receiverPermission, int appOp, Bundle options, 423 BroadcastReceiver resultReceiver, Handler scheduler, int initialCode, 424 String initialData, Bundle initialExtras) { 425 logd("sendOrderedBroadcastAsUser called for " + intent.getAction()); 426 sendBroadcast(intent); 427 if (resultReceiver != null) { 428 synchronized (mOrderedBroadcastReceivers) { 429 mOrderedBroadcastReceivers.put(intent, resultReceiver); 430 } 431 } 432 } 433 434 @Override 435 public void sendStickyBroadcast(Intent intent) { 436 logd("sendStickyBroadcast called for " + intent.getAction()); 437 synchronized (mBroadcastReceiversByAction) { 438 sendBroadcast(intent); 439 mStickyBroadcastByAction.put(intent.getAction(), intent); 440 } 441 } 442 443 @Override 444 public void sendStickyBroadcastAsUser(Intent intent, UserHandle ignored) { 445 logd("sendStickyBroadcastAsUser called for " + intent.getAction()); 446 sendStickyBroadcast(intent); 447 } 448 449 @Override 450 public Context createPackageContextAsUser(String packageName, int flags, UserHandle user) 451 throws PackageManager.NameNotFoundException { 452 return this; 453 } 454 455 @Override 456 public void enforceCallingOrSelfPermission(String permission, String message) { 457 if (mPermissionTable.contains(permission) 458 || mPermissionTable.contains(PERMISSION_ENABLE_ALL)) { 459 return; 460 } 461 logd("requested permission: " + permission + " got denied"); 462 throw new SecurityException(permission + " denied: " + message); 463 } 464 465 @Override 466 public void enforcePermission(String permission, int pid, int uid, String message) { 467 enforceCallingOrSelfPermission(permission, message); 468 } 469 470 @Override 471 public int checkCallingOrSelfPermission(String permission) { 472 if (mPermissionTable.contains(permission) 473 || mPermissionTable.contains(PERMISSION_ENABLE_ALL)) { 474 logd("checkCallingOrSelfPermission: " + permission + " return GRANTED"); 475 return PackageManager.PERMISSION_GRANTED; 476 } else { 477 logd("checkCallingOrSelfPermission: " + permission + " return DENIED"); 478 return PackageManager.PERMISSION_DENIED; 479 } 480 } 481 482 @Override 483 public int checkPermission(String permission, int pid, int uid) { 484 return checkCallingOrSelfPermission(permission); 485 } 486 487 @Override 488 public SharedPreferences getSharedPreferences(String name, int mode) { 489 return mSharedPreferences; 490 } 491 492 @Override 493 public String getPackageName() { 494 return "com.android.internal.telephony"; 495 } 496 } 497 498 private final Multimap<String, ComponentName> mComponentNamesByAction = 499 ArrayListMultimap.create(); 500 private final Map<ComponentName, IInterface> mServiceByComponentName = 501 new HashMap<ComponentName, IInterface>(); 502 private final Map<String, IInterface> mServiceByPackageName = 503 new HashMap<String, IInterface>(); 504 private final Map<ComponentName, ServiceInfo> mServiceInfoByComponentName = 505 new HashMap<ComponentName, ServiceInfo>(); 506 private final Map<ComponentName, IntentFilter> mIntentFilterByComponentName = new HashMap<>(); 507 private final Map<IInterface, ComponentName> mComponentNameByService = 508 new HashMap<IInterface, ComponentName>(); 509 private final Map<ServiceConnection, IInterface> mServiceByServiceConnection = 510 new HashMap<ServiceConnection, IInterface>(); 511 private final Multimap<String, BroadcastReceiver> mBroadcastReceiversByAction = 512 ArrayListMultimap.create(); 513 private final HashMap<String, Intent> mStickyBroadcastByAction = 514 new HashMap<String, Intent>(); 515 private final Multimap<Intent, BroadcastReceiver> mOrderedBroadcastReceivers = 516 ArrayListMultimap.create(); 517 private final HashSet<String> mPermissionTable = new HashSet<>(); 518 519 520 521 // The application context is the most important object this class provides to the system 522 // under test. 523 private final Context mContext = spy(new FakeContext()); 524 525 // We then create a spy on the application context allowing standard Mockito-style 526 // when(...) logic to be used to add specific little responses where needed. 527 528 private final Resources mResources = mock(Resources.class); 529 private final PackageManager mPackageManager = mock(PackageManager.class); 530 private final TelephonyManager mTelephonyManager = mock(TelephonyManager.class); 531 private final DownloadManager mDownloadManager = mock(DownloadManager.class); 532 private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class); 533 private final NotificationManager mNotificationManager = mock(NotificationManager.class); 534 private final UserManager mUserManager = mock(UserManager.class); 535 private final CarrierConfigManager mCarrierConfigManager = mock(CarrierConfigManager.class); 536 private final SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.class); 537 private final AlarmManager mAlarmManager = mock(AlarmManager.class); 538 private final AssetManager mAssetManager = new AssetManager(); 539 private final ConnectivityManager mConnectivityManager = mock(ConnectivityManager.class); 540 private final UsageStatsManager mUsageStatManager = null; 541 private final WifiManager mWifiManager = mock(WifiManager.class); 542 private final BatteryManager mBatteryManager = mock(BatteryManager.class); 543 private final EuiccManager mEuiccManager = mock(EuiccManager.class); 544 private final TelecomManager mTelecomManager = mock(TelecomManager.class); 545 546 private final ContentProvider mContentProvider = spy(new FakeContentProvider()); 547 548 private final Configuration mConfiguration = new Configuration(); 549 private final SharedPreferences mSharedPreferences = PreferenceManager 550 .getDefaultSharedPreferences(TestApplication.getAppContext()); 551 private final MockContentResolver mContentResolver = new MockContentResolver(); 552 private final PersistableBundle mBundle = new PersistableBundle(); 553 554 public ContextFixture() { 555 MockitoAnnotations.initMocks(this); 556 557 doAnswer(new Answer<List<ResolveInfo>>() { 558 @Override 559 public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable { 560 return doQueryIntentServices( 561 (Intent) invocation.getArguments()[0], 562 (Integer) invocation.getArguments()[1]); 563 } 564 }).when(mPackageManager).queryIntentServices((Intent) any(), anyInt()); 565 566 doAnswer(new Answer<List<ResolveInfo>>() { 567 @Override 568 public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable { 569 return doQueryIntentServices( 570 (Intent) invocation.getArguments()[0], 571 (Integer) invocation.getArguments()[1]); 572 } 573 }).when(mPackageManager).queryIntentServicesAsUser((Intent) any(), anyInt(), anyInt()); 574 575 doReturn(mBundle).when(mCarrierConfigManager).getConfigForSubId(anyInt()); 576 //doReturn(mBundle).when(mCarrierConfigManager).getConfig(anyInt()); 577 doReturn(mBundle).when(mCarrierConfigManager).getConfig(); 578 579 mConfiguration.locale = Locale.US; 580 doReturn(mConfiguration).when(mResources).getConfiguration(); 581 582 mContentResolver.addProvider(Settings.AUTHORITY, mContentProvider); 583 // Settings caches the provider after first get/set call, this is needed to make sure 584 // Settings is using mContentProvider as the cached provider across all tests. 585 Settings.Global.getInt(mContentResolver, Settings.Global.AIRPLANE_MODE_ON, 0); 586 mContentResolver.addProvider(ServiceStateTable.AUTHORITY, mContentProvider); 587 mPermissionTable.add(PERMISSION_ENABLE_ALL); 588 } 589 590 @Override 591 public Context getTestDouble() { 592 return mContext; 593 } 594 595 public void putResource(int id, final String value) { 596 when(mResources.getText(eq(id))).thenReturn(value); 597 when(mResources.getString(eq(id))).thenReturn(value); 598 when(mResources.getString(eq(id), any())).thenAnswer(new Answer<String>() { 599 @Override 600 public String answer(InvocationOnMock invocation) { 601 Object[] args = invocation.getArguments(); 602 return String.format(value, Arrays.copyOfRange(args, 1, args.length)); 603 } 604 }); 605 } 606 607 public void putBooleanResource(int id, boolean value) { 608 when(mResources.getBoolean(eq(id))).thenReturn(value); 609 } 610 611 public void putStringArrayResource(int id, String[] values) { 612 doReturn(values).when(mResources).getStringArray(eq(id)); 613 } 614 615 public void putIntArrayResource(int id, int[] values) { 616 doReturn(values).when(mResources).getIntArray(eq(id)); 617 } 618 619 public void putIntResource(int id, int value) { 620 doReturn(value).when(mResources).getInteger(eq(id)); 621 } 622 623 public PersistableBundle getCarrierConfigBundle() { 624 return mBundle; 625 } 626 627 public void addService(String action, ComponentName name, String packageName, 628 IInterface service, ServiceInfo serviceInfo) { 629 addService(action, name, packageName, service, serviceInfo, null /* filter */); 630 } 631 632 public void addService(String action, ComponentName name, String packageName, 633 IInterface service, ServiceInfo serviceInfo, IntentFilter filter) { 634 mComponentNamesByAction.put(action, name); 635 mServiceInfoByComponentName.put(name, serviceInfo); 636 mIntentFilterByComponentName.put(name, filter); 637 mServiceByComponentName.put(name, service); 638 mServiceByPackageName.put(packageName, service); 639 mComponentNameByService.put(service, name); 640 } 641 642 private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) { 643 List<ResolveInfo> result = new ArrayList<ResolveInfo>(); 644 for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) { 645 ResolveInfo resolveInfo = new ResolveInfo(); 646 resolveInfo.serviceInfo = mServiceInfoByComponentName.get(componentName); 647 resolveInfo.filter = mIntentFilterByComponentName.get(componentName); 648 result.add(resolveInfo); 649 } 650 return result; 651 } 652 653 public void sendBroadcastToOrderedBroadcastReceivers() { 654 synchronized (mOrderedBroadcastReceivers) { 655 // having a map separate from mOrderedBroadcastReceivers is helpful here as onReceive() 656 // call within the loop may lead to sendOrderedBroadcast() which can add to 657 // mOrderedBroadcastReceivers 658 Collection<Map.Entry<Intent, BroadcastReceiver>> map = 659 mOrderedBroadcastReceivers.entries(); 660 for (Map.Entry<Intent, BroadcastReceiver> entry : map) { 661 entry.getValue().onReceive(mContext, entry.getKey()); 662 mOrderedBroadcastReceivers.remove(entry.getKey(), entry.getValue()); 663 } 664 } 665 } 666 667 public void addCallingOrSelfPermission(String permission) { 668 synchronized (mPermissionTable) { 669 if (mPermissionTable != null && permission != null) { 670 mPermissionTable.remove(PERMISSION_ENABLE_ALL); 671 mPermissionTable.add(permission); 672 } 673 } 674 } 675 676 public void removeCallingOrSelfPermission(String permission) { 677 synchronized (mPermissionTable) { 678 if (mPermissionTable != null && permission != null) { 679 mPermissionTable.remove(permission); 680 } 681 } 682 } 683 684 private static void logd(String s) { 685 Log.d(TAG, s); 686 } 687} 688