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