/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.telecom.tests;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;

import com.android.internal.telecom.IConnectionService;
import com.android.internal.telecom.IInCallService;

import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import android.Manifest;
import android.app.AppOpsManager;
import android.app.NotificationManager;
import android.app.StatusBarManager;
import android.app.UiModeManager;
import android.app.role.RoleManager;
import android.content.AttributionSource;
import android.content.AttributionSourceState;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.SensorPrivacyManager;
import android.location.CountryDetector;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.IInterface;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.permission.PermissionCheckerManager;
import android.telecom.ConnectionService;
import android.telecom.Log;
import android.telecom.InCallService;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyRegistryManager;
import android.test.mock.MockContext;
import android.util.DisplayMetrics;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Executor;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;

/**
 * Controls a test {@link Context} as would be provided by the Android framework to an
 * {@code Activity}, {@code Service} or other system-instantiated component.
 *
 * The {@link Context} created by this object is "hollow" but its {@code applicationContext}
 * property points to an application context implementing all the nontrivial functionality.
 */
public class ComponentContextFixture implements TestFixture<Context> {

    public class FakeApplicationContext extends MockContext {
        @Override
        public PackageManager getPackageManager() {
            return mPackageManager;
        }

        @Override
        public Executor getMainExecutor() {
            // TODO: This doesn't actually execute anything as we don't need to do so for now, but
            //  future users might need it.
            return mMainExecutor;
        }

        @Override
        public Context createContextAsUser(UserHandle userHandle, int flags) {
            return this;
        }

        @Override
        public String getPackageName() {
            return "com.android.server.telecom.tests";
        }

        @Override
        public String getPackageResourcePath() {
            return "/tmp/i/dont/know";
        }

        @Override
        public Context getApplicationContext() {
            return mApplicationContextSpy;
        }

        @Override
        public Resources.Theme getTheme() {
            return mResourcesTheme;
        }

        @Override
        public File getFilesDir() {
            try {
                return File.createTempFile("temp", "temp").getParentFile();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        @Override
        public boolean bindServiceAsUser(
                Intent serviceIntent,
                ServiceConnection connection,
                int flags,
                UserHandle userHandle) {
            // TODO: Implement "as user" functionality
            return bindService(serviceIntent, connection, flags);
        }

        @Override
        public boolean bindService(
                Intent serviceIntent,
                ServiceConnection connection,
                int flags) {
            if (mServiceByServiceConnection.containsKey(connection)) {
                throw new RuntimeException("ServiceConnection already bound: " + connection);
            }
            IInterface service = mServiceByComponentName.get(serviceIntent.getComponent());
            if (service == null) {
                throw new RuntimeException("ServiceConnection not found: "
                        + serviceIntent.getComponent());
            }
            mServiceByServiceConnection.put(connection, service);
            connection.onServiceConnected(serviceIntent.getComponent(), service.asBinder());
            return true;
        }

        @Override
        public void unbindService(
                ServiceConnection connection) {
            IInterface service = mServiceByServiceConnection.remove(connection);
            if (service == null) {
                throw new RuntimeException("ServiceConnection not found: " + connection);
            }
            connection.onServiceDisconnected(mComponentNameByService.get(service));
        }

        @Override
        public Object getSystemService(String name) {
            switch (name) {
                case Context.AUDIO_SERVICE:
                    return mAudioManager;
                case Context.TELEPHONY_SERVICE:
                    return mTelephonyManager;
                case Context.APP_OPS_SERVICE:
                    return mAppOpsManager;
                case Context.NOTIFICATION_SERVICE:
                    return mNotificationManager;
                case Context.STATUS_BAR_SERVICE:
                    return mStatusBarManager;
                case Context.USER_SERVICE:
                    return mUserManager;
                case Context.TELEPHONY_SUBSCRIPTION_SERVICE:
                    return mSubscriptionManager;
                case Context.TELECOM_SERVICE:
                    return mTelecomManager;
                case Context.CARRIER_CONFIG_SERVICE:
                    return mCarrierConfigManager;
                case Context.COUNTRY_DETECTOR:
                    return mCountryDetector;
                case Context.ROLE_SERVICE:
                    return mRoleManager;
                case Context.TELEPHONY_REGISTRY_SERVICE:
                    return mTelephonyRegistryManager;
                case Context.UI_MODE_SERVICE:
                    return mUiModeManager;
                case Context.VIBRATOR_SERVICE:
                    return mVibrator;
                case Context.VIBRATOR_MANAGER_SERVICE:
                    return mVibratorManager;
                case Context.PERMISSION_CHECKER_SERVICE:
                    return mPermissionCheckerManager;
                case Context.SENSOR_PRIVACY_SERVICE:
                    return mSensorPrivacyManager;
                default:
                    return null;
            }
        }

        @Override
        public String getSystemServiceName(Class<?> svcClass) {
            if (svcClass == UserManager.class) {
                return Context.USER_SERVICE;
            } else if (svcClass == RoleManager.class) {
                return Context.ROLE_SERVICE;
            } else if (svcClass == AudioManager.class) {
                return Context.AUDIO_SERVICE;
            } else if (svcClass == TelephonyManager.class) {
                return Context.TELEPHONY_SERVICE;
            } else if (svcClass == CarrierConfigManager.class) {
                return Context.CARRIER_CONFIG_SERVICE;
            } else if (svcClass == SubscriptionManager.class) {
                return Context.TELEPHONY_SUBSCRIPTION_SERVICE;
            } else if (svcClass == TelephonyRegistryManager.class) {
                return Context.TELEPHONY_REGISTRY_SERVICE;
            } else if (svcClass == UiModeManager.class) {
                return Context.UI_MODE_SERVICE;
            } else if (svcClass == Vibrator.class) {
                return Context.VIBRATOR_SERVICE;
            } else if (svcClass == VibratorManager.class) {
                return Context.VIBRATOR_MANAGER_SERVICE;
            } else if (svcClass == PermissionCheckerManager.class) {
                return Context.PERMISSION_CHECKER_SERVICE;
            } else if (svcClass == SensorPrivacyManager.class) {
                return Context.SENSOR_PRIVACY_SERVICE;
            } else if (svcClass == NotificationManager.class) {
                return Context.NOTIFICATION_SERVICE;
            }
            throw new UnsupportedOperationException();
        }

        @Override
        public int getUserId() {
            return 0;
        }

        @Override
        public Resources getResources() {
            return mResources;
        }

        @Override
        public String getOpPackageName() {
            return "com.android.server.telecom.tests";
        }

        @Override
        public ApplicationInfo getApplicationInfo() {
            return mTestApplicationInfo;
        }

        @Override
        public AttributionSource getAttributionSource() {
            return mAttributionSource;
        }

        @Override
        public ContentResolver getContentResolver() {
            return new ContentResolver(mApplicationContextSpy) {
                @Override
                protected IContentProvider acquireProvider(Context c, String name) {
                    Log.i(this, "acquireProvider %s", name);
                    return getOrCreateProvider(name);
                }

                @Override
                public boolean releaseProvider(IContentProvider icp) {
                    return true;
                }

                @Override
                protected IContentProvider acquireUnstableProvider(Context c, String name) {
                    Log.i(this, "acquireUnstableProvider %s", name);
                    return getOrCreateProvider(name);
                }

                private IContentProvider getOrCreateProvider(String name) {
                    if (!mIContentProviderByUri.containsKey(name)) {
                        mIContentProviderByUri.put(name, mock(IContentProvider.class));
                    }
                    return mIContentProviderByUri.get(name);
                }

                @Override
                public boolean releaseUnstableProvider(IContentProvider icp) {
                    return false;
                }

                @Override
                public void unstableProviderDied(IContentProvider icp) {
                }
            };
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
            // TODO -- this is called by WiredHeadsetManager!!!
            return null;
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, int flags) {
            return null;
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                String broadcastPermission, Handler scheduler) {
            return null;
        }

        @Override
        public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
                String broadcastPermission, Handler scheduler, int flags) {
            return null;
        }

        @Override
        public Intent registerReceiverAsUser(BroadcastReceiver receiver, UserHandle handle,
                IntentFilter filter, String broadcastPermission, Handler scheduler) {
            return null;
        }

        @Override
        public void sendBroadcast(Intent intent) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendBroadcast(Intent intent, String receiverPermission) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendBroadcastAsUser(Intent intent, UserHandle userHandle) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendBroadcastAsUser(Intent intent, UserHandle user, String receiverPermission,
                Bundle options) {
            // Override so that this can be verified via spy.
        }

        @Override
        public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
                String receiverPermission, BroadcastReceiver resultReceiver, Handler scheduler,
                int initialCode, String initialData, Bundle initialExtras) {
            // TODO -- need to ensure this is captured
        }

        @Override
        public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
                String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
                Handler scheduler, int initialCode, String initialData, Bundle initialExtras) {
        }

        @Override
        public void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
                String receiverPermission, int appOp, Bundle options,
                BroadcastReceiver resultReceiver, Handler scheduler, int initialCode,
                String initialData, Bundle initialExtras) {
        }

        @Override
        public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
                throws PackageManager.NameNotFoundException {
            return this;
        }

        @Override
        public int checkCallingOrSelfPermission(String permission) {
            return PackageManager.PERMISSION_GRANTED;
        }

        @Override
        public int checkSelfPermission(String permission) {
            return PackageManager.PERMISSION_GRANTED;
        }

        @Override
        public void enforceCallingOrSelfPermission(String permission, String message) {
            // Don't bother enforcing anything in mock.
        }

        @Override
        public void enforcePermission(
                String permission, int pid, int uid, String message) {
            // By default, don't enforce anything in mock.
        }

        @Override
        public void startActivityAsUser(Intent intent, UserHandle userHandle) {
            // For capturing
        }
    }

    public class FakeAudioManager extends AudioManager {

        private boolean mMute = false;
        private boolean mSpeakerphoneOn = false;
        private int mAudioStreamValue = 1;
        private int mMode = AudioManager.MODE_NORMAL;
        private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
        private AudioDeviceInfo mCommunicationDevice;

        public FakeAudioManager(Context context) {
            super(context);
        }

        @Override
        public void setMicrophoneMute(boolean value) {
            mMute = value;
        }

        @Override
        public boolean isMicrophoneMute() {
            return mMute;
        }

        @Override
        public void setSpeakerphoneOn(boolean value) {
            mSpeakerphoneOn = value;
        }

        @Override
        public boolean isSpeakerphoneOn() {
            return mSpeakerphoneOn;
        }

        @Override
        public void setMode(int mode) {
            mMode = mode;
        }

        @Override
        public int getMode() {
            return mMode;
        }

        @Override
        public void setRingerModeInternal(int ringerMode) {
            mRingerMode = ringerMode;
        }

        @Override
        public int getRingerModeInternal() {
            return mRingerMode;
        }

        @Override
        public void setStreamVolume(int streamTypeUnused, int index, int flagsUnused){
            mAudioStreamValue = index;
        }

        @Override
        public int getStreamVolume(int streamValueUnused) {
            return mAudioStreamValue;
        }

        @Override
        public void clearCommunicationDevice() {
            mCommunicationDevice = null;
        }

        @Override
        public AudioDeviceInfo getCommunicationDevice() {
            return mCommunicationDevice;
        }

        @Override
        public boolean setCommunicationDevice(AudioDeviceInfo device) {
            mCommunicationDevice = device;
            return true;
        }
    }

    private static final String PACKAGE_NAME = "com.android.server.telecom.tests";
    private final AttributionSource mAttributionSource =
            new AttributionSource.Builder(Process.myUid()).setPackageName(PACKAGE_NAME).build();

    private final Multimap<String, ComponentName> mComponentNamesByAction =
            ArrayListMultimap.create();
    private final Map<ComponentName, IInterface> mServiceByComponentName = new HashMap<>();
    private final Map<ComponentName, ServiceInfo> mServiceInfoByComponentName = new HashMap<>();
    private final Map<ComponentName, ActivityInfo> mActivityInfoByComponentName = new HashMap<>();
    private final Map<IInterface, ComponentName> mComponentNameByService = new HashMap<>();
    private final Map<ServiceConnection, IInterface> mServiceByServiceConnection = new HashMap<>();

    private final Context mContext = new MockContext() {
        @Override
        public Context getApplicationContext() {
            return mApplicationContextSpy;
        }

        @Override
        public Resources getResources() {
            return mResources;
        }
    };

    // The application context is the most important object this class provides to the system
    // under test.
    private final Context mApplicationContext = new FakeApplicationContext();

    // We then create a spy on the application context allowing standard Mockito-style
    // when(...) logic to be used to add specific little responses where needed.

    private final Resources.Theme mResourcesTheme = mock(Resources.Theme.class);
    private final Resources mResources = mock(Resources.class);
    private final Context mApplicationContextSpy = spy(mApplicationContext);
    private final DisplayMetrics mDisplayMetrics = mock(DisplayMetrics.class);
    private final PackageManager mPackageManager = mock(PackageManager.class);
    private final Executor mMainExecutor = mock(Executor.class);
    private final AudioManager mAudioManager = spy(new FakeAudioManager(mContext));
    private final TelephonyManager mTelephonyManager = mock(TelephonyManager.class);
    private final AppOpsManager mAppOpsManager = mock(AppOpsManager.class);
    private final NotificationManager mNotificationManager = mock(NotificationManager.class);
    private final UserManager mUserManager = mock(UserManager.class);
    private final StatusBarManager mStatusBarManager = mock(StatusBarManager.class);
    private SubscriptionManager mSubscriptionManager = mock(SubscriptionManager.class);
    private final CarrierConfigManager mCarrierConfigManager = mock(CarrierConfigManager.class);
    private final CountryDetector mCountryDetector = mock(CountryDetector.class);
    private final Map<String, IContentProvider> mIContentProviderByUri = new HashMap<>();
    private final Configuration mResourceConfiguration = new Configuration();
    private final ApplicationInfo mTestApplicationInfo = new ApplicationInfo();
    private final RoleManager mRoleManager = mock(RoleManager.class);
    private final TelephonyRegistryManager mTelephonyRegistryManager =
            mock(TelephonyRegistryManager.class);
    private final Vibrator mVibrator = mock(Vibrator.class);
    private final VibratorManager mVibratorManager = mock(VibratorManager.class);
    private final UiModeManager mUiModeManager = mock(UiModeManager.class);
    private final PermissionCheckerManager mPermissionCheckerManager =
            mock(PermissionCheckerManager.class);
    private final PermissionInfo mPermissionInfo = mock(PermissionInfo.class);
    private final SensorPrivacyManager mSensorPrivacyManager = mock(SensorPrivacyManager.class);

    private TelecomManager mTelecomManager = mock(TelecomManager.class);

    public ComponentContextFixture() {
        MockitoAnnotations.initMocks(this);
        when(mResources.getConfiguration()).thenReturn(mResourceConfiguration);
        when(mResources.getString(anyInt())).thenReturn("");
        when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
        when(mResources.newTheme()).thenReturn(mResourcesTheme);
        when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics);
        mDisplayMetrics.density = 3.125f;
        mResourceConfiguration.setLocale(Locale.TAIWAN);

        // TODO: Move into actual tests
        doReturn(false).when(mAudioManager).isWiredHeadsetOn();

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentServices(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryIntentServices((Intent) any(), anyInt());

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentServices(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryIntentServicesAsUser((Intent) any(), anyInt(), anyInt());

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentReceivers(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryBroadcastReceivers((Intent) any(), anyInt());

        doAnswer(new Answer<List<ResolveInfo>>() {
            @Override
            public List<ResolveInfo> answer(InvocationOnMock invocation) throws Throwable {
                return doQueryIntentReceivers(
                        (Intent) invocation.getArguments()[0],
                        (Integer) invocation.getArguments()[1]);
            }
        }).when(mPackageManager).queryBroadcastReceiversAsUser((Intent) any(), anyInt(), anyInt());

        // By default, tests use non-ui apps instead of 3rd party companion apps.
        when(mPermissionCheckerManager.checkPermission(
                matches(Manifest.permission.CALL_COMPANION_APP), any(AttributionSourceState.class),
                nullable(String.class), anyBoolean(), anyBoolean(), anyBoolean(), anyInt()))
                .thenReturn(PermissionCheckerManager.PERMISSION_HARD_DENIED);

        try {
            when(mPackageManager.getPermissionInfo(anyString(), anyInt())).thenReturn(
                    mPermissionInfo);
        } catch (PackageManager.NameNotFoundException ex) {
        }

        when(mPermissionInfo.isAppOp()).thenReturn(true);
        when(mVibrator.getDefaultVibrationIntensity(anyInt()))
                .thenReturn(Vibrator.VIBRATION_INTENSITY_MEDIUM);
        when(mVibratorManager.getVibratorIds()).thenReturn(new int[0]);
        when(mVibratorManager.getDefaultVibrator()).thenReturn(mVibrator);

        // Used in CreateConnectionProcessor to rank emergency numbers by viability.
        // For the test, make them all equal to INVALID so that the preferred PhoneAccount will be
        // chosen.
        when(mTelephonyManager.getSubscriptionId(any())).thenReturn(
                SubscriptionManager.INVALID_SUBSCRIPTION_ID);

        when(mTelephonyManager.getNetworkOperatorName()).thenReturn("label1");
        when(mTelephonyManager.getMaxNumberOfSimultaneouslyActiveSims()).thenReturn(1);
        when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
        when(mResources.getBoolean(eq(R.bool.grant_location_permission_enabled))).thenReturn(false);
        doAnswer(new Answer<Void>(){
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                return null;
            }
        }).when(mAppOpsManager).checkPackage(anyInt(), anyString());

        when(mNotificationManager.matchesCallFilter(any(Bundle.class))).thenReturn(true);

        when(mCarrierConfigManager.getConfig()).thenReturn(new PersistableBundle());
        when(mCarrierConfigManager.getConfigForSubId(anyInt())).thenReturn(new PersistableBundle());

        when(mUserManager.getSerialNumberForUser(any(UserHandle.class))).thenReturn(-1L);

        doReturn(null).when(mApplicationContextSpy).registerReceiver(any(BroadcastReceiver.class),
                any(IntentFilter.class));

        // Make sure we do not hide PII during testing.
        Log.setTag("TelecomTEST");
        Log.setIsExtendedLoggingEnabled(true);
        Log.setUnitTestingEnabled(true);
        Log.VERBOSE = true;
    }

    @Override
    public Context getTestDouble() {
        return mContext;
    }

    public void addConnectionService(
            ComponentName componentName,
            IConnectionService service)
            throws Exception {
        addService(ConnectionService.SERVICE_INTERFACE, componentName, service);
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.permission = android.Manifest.permission.BIND_CONNECTION_SERVICE;
        serviceInfo.packageName = componentName.getPackageName();
        serviceInfo.name = componentName.getClassName();
        mServiceInfoByComponentName.put(componentName, serviceInfo);
    }

    public void addInCallService(
            ComponentName componentName,
            IInCallService service,
            int uid)
            throws Exception {
        addService(InCallService.SERVICE_INTERFACE, componentName, service);
        ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.permission = android.Manifest.permission.BIND_INCALL_SERVICE;
        serviceInfo.packageName = componentName.getPackageName();
        serviceInfo.applicationInfo = new ApplicationInfo();
        serviceInfo.applicationInfo.uid = uid;
        serviceInfo.metaData = new Bundle();
        serviceInfo.metaData.putBoolean(TelecomManager.METADATA_IN_CALL_SERVICE_UI, false);
        serviceInfo.name = componentName.getClassName();
        mServiceInfoByComponentName.put(componentName, serviceInfo);

        // Used in InCallController to check permissions for CONTROL_INCALL_fvEXPERIENCE
        when(mPackageManager.getPackagesForUid(eq(uid))).thenReturn(new String[] {
                componentName.getPackageName() });
        when(mPackageManager.checkPermission(eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
                eq(componentName.getPackageName()))).thenReturn(PackageManager.PERMISSION_GRANTED);
        when(mPermissionCheckerManager.checkPermission(
                eq(Manifest.permission.CONTROL_INCALL_EXPERIENCE),
                any(AttributionSourceState.class), anyString(), anyBoolean(), anyBoolean(),
                anyBoolean(), anyInt())).thenReturn(PackageManager.PERMISSION_GRANTED);
    }

    public void addIntentReceiver(String action, ComponentName name) {
        mComponentNamesByAction.put(action, name);
        ActivityInfo activityInfo = new ActivityInfo();
        activityInfo.packageName = name.getPackageName();
        activityInfo.name = name.getClassName();
        mActivityInfoByComponentName.put(name, activityInfo);
    }

    public void putResource(int id, final String value) {
        when(mResources.getText(eq(id))).thenReturn(value);
        when(mResources.getString(eq(id))).thenReturn(value);
        when(mResources.getString(eq(id), any())).thenAnswer(new Answer<String>() {
            @Override
            public String answer(InvocationOnMock invocation) {
                Object[] args = invocation.getArguments();
                return String.format(value, Arrays.copyOfRange(args, 1, args.length));
            }
        });
    }

    public void putFloatResource(int id, final float value) {
        when(mResources.getFloat(eq(id))).thenReturn(value);
    }

    public void putBooleanResource(int id, boolean value) {
        when(mResources.getBoolean(eq(id))).thenReturn(value);
    }

    public void putStringArrayResource(int id, String[] value) {
        when(mResources.getStringArray(eq(id))).thenReturn(value);
    }

    public void setTelecomManager(TelecomManager telecomManager) {
        mTelecomManager = telecomManager;
    }

    public void setSubscriptionManager(SubscriptionManager subscriptionManager) {
        mSubscriptionManager = subscriptionManager;
    }

    public TelephonyManager getTelephonyManager() {
        return mTelephonyManager;
    }

    public CarrierConfigManager getCarrierConfigManager() {
        return mCarrierConfigManager;
    }

    public NotificationManager getNotificationManager() {
        return mNotificationManager;
    }

    private void addService(String action, ComponentName name, IInterface service) {
        mComponentNamesByAction.put(action, name);
        mServiceByComponentName.put(name, service);
        mComponentNameByService.put(service, name);
    }

    private List<ResolveInfo> doQueryIntentServices(Intent intent, int flags) {
        List<ResolveInfo> result = new ArrayList<>();
        for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
            ResolveInfo resolveInfo = new ResolveInfo();
            resolveInfo.serviceInfo = mServiceInfoByComponentName.get(componentName);
            resolveInfo.serviceInfo.metaData = new Bundle();
            resolveInfo.serviceInfo.metaData.putBoolean(
                    TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
            result.add(resolveInfo);
        }
        return result;
    }

    private List<ResolveInfo> doQueryIntentReceivers(Intent intent, int flags) {
        List<ResolveInfo> result = new ArrayList<>();
        for (ComponentName componentName : mComponentNamesByAction.get(intent.getAction())) {
            ResolveInfo resolveInfo = new ResolveInfo();
            resolveInfo.activityInfo = mActivityInfoByComponentName.get(componentName);
            result.add(resolveInfo);
        }
        return result;
    }
}
