/*
 * Copyright (C) 2017 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.internal.telephony.ims;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsService;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsMmTelFeature;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.LocalLog;
import android.util.Log;
import android.util.SparseArray;

import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import com.android.internal.telephony.PhoneConfigurationManager;
import com.android.internal.util.IndentingPrintWriter;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Creates a list of ImsServices that are available to bind to based on the Device configuration
 * overlay values "config_ims_rcs_package" and "config_ims_mmtel_package" as well as Carrier
 * Configuration value "config_ims_rcs_package_override_string" and
 * "config_ims_mmtel_package_override_string".
 * These ImsServices are then bound to in the following order for each mmtel and rcs feature:
 *
 * 1. Carrier Config defined override value per SIM.
 * 2. Device overlay default value (including no SIM case).
 *
 * ImsManager can then retrieve the binding to the correct ImsService using
 * {@link #getImsServiceControllerAndListen} on a per-slot and per feature basis.
 */

public class ImsResolver implements ImsServiceController.ImsServiceControllerCallbacks {

    private static final String TAG = "ImsResolver";
    private static final int GET_IMS_SERVICE_TIMEOUT_MS = 5000;

    @VisibleForTesting
    public static final String METADATA_EMERGENCY_MMTEL_FEATURE =
            "android.telephony.ims.EMERGENCY_MMTEL_FEATURE";
    @VisibleForTesting
    public static final String METADATA_MMTEL_FEATURE = "android.telephony.ims.MMTEL_FEATURE";
    @VisibleForTesting
    public static final String METADATA_RCS_FEATURE = "android.telephony.ims.RCS_FEATURE";
    // Overrides the sanity permission check of android.permission.BIND_IMS_SERVICE for any
    // ImsService that is connecting to the platform.
    // This should ONLY be used for testing and should not be used in production ImsServices.
    private static final String METADATA_OVERRIDE_PERM_CHECK = "override_bind_check";

    // Based on updates from PackageManager
    private static final int HANDLER_ADD_PACKAGE = 0;
    // Based on updates from PackageManager
    private static final int HANDLER_REMOVE_PACKAGE = 1;
    // Based on updates from CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED
    private static final int HANDLER_CONFIG_CHANGED = 2;
    // A query has been started for an ImsService to relay the features they support.
    private static final int HANDLER_START_DYNAMIC_FEATURE_QUERY = 3;
    // A dynamic query to request ImsService features has completed.
    private static final int HANDLER_DYNAMIC_FEATURE_CHANGE = 4;
    // Testing: Overrides the current configuration for ImsService binding
    private static final int HANDLER_OVERRIDE_IMS_SERVICE_CONFIG = 5;
    // Based on boot complete indication. When this happens, there may be ImsServices that are not
    // direct boot aware that need to be started.
    private static final int HANDLER_BOOT_COMPLETE = 6;
    // Sent when the number of slots has dynamically changed on the device. We will need to
    // resize available ImsServiceController slots and perform dynamic queries again.
    private static final int HANDLER_MSIM_CONFIGURATION_CHANGE = 7;

    // Delay between dynamic ImsService queries.
    private static final int DELAY_DYNAMIC_QUERY_MS = 5000;

    private static class OverrideConfig {
        public final int slotId;
        public final boolean isCarrierService;
        public final Map<Integer, String> featureTypeToPackageMap;

        OverrideConfig(int slotIndex, boolean isCarrier, Map<Integer, String> feature) {
            slotId = slotIndex;
            isCarrierService = isCarrier;
            featureTypeToPackageMap = feature;
        }
    }

    /**
     * Stores information about an ImsService, including the package name, class name, and features
     * that the service supports.
     */
    @VisibleForTesting
    public static class ImsServiceInfo {
        public ComponentName name;
        // Determines if features were created from metadata in the manifest or through dynamic
        // query.
        public boolean featureFromMetadata = true;
        public ImsServiceControllerFactory controllerFactory;

        // Map slotId->Feature
        private final HashSet<ImsFeatureConfiguration.FeatureSlotPair> mSupportedFeatures;

        public ImsServiceInfo() {
            mSupportedFeatures = new HashSet<>();
        }

        void addFeatureForAllSlots(int numSlots, int feature) {
            for (int i = 0; i < numSlots; i++) {
                mSupportedFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(i, feature));
            }
        }

        void replaceFeatures(Set<ImsFeatureConfiguration.FeatureSlotPair> newFeatures) {
            mSupportedFeatures.clear();
            mSupportedFeatures.addAll(newFeatures);
        }

        @VisibleForTesting
        public Set<ImsFeatureConfiguration.FeatureSlotPair> getSupportedFeatures() {
            return mSupportedFeatures;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ImsServiceInfo that = (ImsServiceInfo) o;

            if (name != null ? !name.equals(that.name) : that.name != null) return false;
            if (!mSupportedFeatures.equals(that.mSupportedFeatures)) {
                return false;
            }
            return controllerFactory != null ? controllerFactory.equals(that.controllerFactory)
                    : that.controllerFactory == null;
        }

        @Override
        public int hashCode() {
            // We do not include mSupportedFeatures in hashcode because the internal structure
            // changes after adding.
            int result = name != null ? name.hashCode() : 0;
            result = 31 * result + (controllerFactory != null ? controllerFactory.hashCode() : 0);
            return result;
        }

        @Override
        public String toString() {
            return "[ImsServiceInfo] name="
                    + name
                    + ", featureFromMetadata="
                    + featureFromMetadata
                    + ","
                    + printFeatures(mSupportedFeatures);
        }
    }

    // Receives broadcasts from the system involving changes to the installed applications. If
    // an ImsService that we are configured to use is installed, we must bind to it.
    private BroadcastReceiver mAppChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();
            final String packageName = intent.getData().getSchemeSpecificPart();
            switch (action) {
                case Intent.ACTION_PACKAGE_ADDED:
                    // intentional fall-through
                case Intent.ACTION_PACKAGE_REPLACED:
                    // intentional fall-through
                case Intent.ACTION_PACKAGE_CHANGED:
                    mHandler.obtainMessage(HANDLER_ADD_PACKAGE, packageName).sendToTarget();
                    break;
                case Intent.ACTION_PACKAGE_REMOVED:
                    mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, packageName).sendToTarget();
                    break;
                default:
                    return;
            }
        }
    };

    // Receives the broadcast that a new Carrier Config has been loaded in order to possibly
    // unbind from one service and bind to another.
    private BroadcastReceiver mConfigChangedReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            int slotId = intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX,
                    SubscriptionManager.INVALID_SIM_SLOT_INDEX);

            if (slotId == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
                Log.i(TAG, "Received CCC for invalid slot id.");
                return;
            }

            int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX,
                    SubscriptionManager.INVALID_SUBSCRIPTION_ID);
            int slotSimState = mTelephonyManagerProxy.getSimState(mContext, slotId);
            if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID
                    && slotSimState != TelephonyManager.SIM_STATE_ABSENT) {
                // We only care about carrier config updates that happen when a slot is known to be
                // absent or populated and the carrier config has been loaded.
                Log.i(TAG, "Received CCC for slot " + slotId + " and sim state "
                        + slotSimState + ", ignoring.");
                return;
            }

            Log.i(TAG, "Received Carrier Config Changed for SlotId: " + slotId);

            mHandler.obtainMessage(HANDLER_CONFIG_CHANGED, slotId).sendToTarget();
        }
    };

    // Receives the broadcast that the device has finished booting (and the device is no longer
    // encrypted).
    private BroadcastReceiver mBootCompleted = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "Received BOOT_COMPLETED");
            // Recalculate all cached services to pick up ones that have just been enabled since
            // boot complete.
            mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
        }
    };

    /**
     * Testing interface used to mock SubscriptionManager in testing
     */
    @VisibleForTesting
    public interface SubscriptionManagerProxy {
        /**
         * Mock-able interface for {@link SubscriptionManager#getSubId(int)} used for testing.
         */
        int getSubId(int slotId);
        /**
         * Mock-able interface for {@link SubscriptionManager#getSlotIndex(int)} used for testing.
         */
        int getSlotIndex(int subId);
    }

    /**
     * Testing interface used to stub out TelephonyManager dependencies.
     */
    @VisibleForTesting
    public interface TelephonyManagerProxy {
        /**
         * @return the SIM state for the slot ID specified.
         */
        int getSimState(Context context, int slotId);
    }

    private TelephonyManagerProxy mTelephonyManagerProxy = new TelephonyManagerProxy() {
        @Override
        public int getSimState(Context context, int slotId) {
            TelephonyManager tm = context.getSystemService(TelephonyManager.class);
            if (tm == null) {
                return TelephonyManager.SIM_STATE_UNKNOWN;
            }
            return tm.getSimState(slotId);
        }
    };

    private SubscriptionManagerProxy mSubscriptionManagerProxy = new SubscriptionManagerProxy() {
        @Override
        public int getSubId(int slotId) {
            int[] subIds = SubscriptionManager.getSubId(slotId);
            if (subIds != null) {
                // This is done in all other places getSubId is used.
                return subIds[0];
            }
            return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
        }

        @Override
        public int getSlotIndex(int subId) {
            return SubscriptionManager.getSlotIndex(subId);
        }
    };

    /**
     * Testing interface for injecting mock ImsServiceControllers.
     */
    @VisibleForTesting
    public interface ImsServiceControllerFactory {
        /**
         * @return the Service Interface String used for binding the ImsService.
         */
        String getServiceInterface();
        /**
         * @return the ImsServiceController created using the context and componentName supplied.
         */
        ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks);
    }

    private ImsServiceControllerFactory mImsServiceControllerFactory =
            new ImsServiceControllerFactory() {

        @Override
        public String getServiceInterface() {
            return ImsService.SERVICE_INTERFACE;
        }

        @Override
        public ImsServiceController create(Context context, ComponentName componentName,
                ImsServiceController.ImsServiceControllerCallbacks callbacks) {
            return new ImsServiceController(context, componentName, callbacks);
        }
    };

    /**
     * Used for testing.
     */
    @VisibleForTesting
    public interface ImsDynamicQueryManagerFactory {
        ImsServiceFeatureQueryManager create(Context context,
                ImsServiceFeatureQueryManager.Listener listener);
    }

    private ImsServiceControllerFactory mImsServiceControllerFactoryCompat =
            new ImsServiceControllerFactory() {
                @Override
                public String getServiceInterface() {
                    return android.telephony.ims.compat.ImsService.SERVICE_INTERFACE;
                }

                @Override
                public ImsServiceController create(Context context, ComponentName componentName,
                        ImsServiceController.ImsServiceControllerCallbacks callbacks) {
                    return new ImsServiceControllerCompat(context, componentName, callbacks);
                }
            };

    private ImsDynamicQueryManagerFactory mDynamicQueryManagerFactory =
            ImsServiceFeatureQueryManager::new;

    private final CarrierConfigManager mCarrierConfigManager;
    private final Context mContext;
    // Special context created only for registering receivers for all users using UserHandle.ALL.
    // The lifetime of a registered receiver is bounded by the lifetime of the context it's
    // registered through, so we must retain the Context as long as we need the receiver to be
    // active.
    private final Context mReceiverContext;
    // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from
    // ImsServiceController callbacks.
    private final Object mBoundServicesLock = new Object();
    private int mNumSlots;
    // Array index corresponds to slot, per slot there is a feature->package name mapping.
    // should only be accessed from handler
    private SparseArray<Map<Integer, String>> mCarrierServices;
    // Package name of the default device services, Maps ImsFeature -> packageName.
    // should only be accessed from handler
    private Map<Integer, String> mDeviceServices;
    // Persistent Logging
    private final LocalLog mEventLog = new LocalLog(50);

    private boolean mBootCompletedHandlerRan = false;

    // Synchronize all events on a handler to ensure that the cache includes the most recent
    // version of the installed ImsServices.
    private Handler mHandler = new Handler(Looper.getMainLooper(), (msg) -> {
        switch (msg.what) {
            case HANDLER_ADD_PACKAGE: {
                String packageName = (String) msg.obj;
                maybeAddedImsService(packageName);
                break;
            }
            case HANDLER_REMOVE_PACKAGE: {
                String packageName = (String) msg.obj;
                maybeRemovedImsService(packageName);
                break;
            }
            case HANDLER_BOOT_COMPLETE: {
                if (!mBootCompletedHandlerRan) {
                    mBootCompletedHandlerRan = true;
                    mEventLog.log("handling BOOT_COMPLETE");
                    // Re-evaluate bound services for all slots after requerying packagemanager
                    maybeAddedImsService(null /*packageName*/);
                }
                break;
            }
            case HANDLER_CONFIG_CHANGED: {
                int slotId = (Integer) msg.obj;
                // If the msim config has changed and there is a residual event for an invalid slot,
                // ignore.
                if (slotId >= mNumSlots) {
                    Log.w(TAG, "HANDLER_CONFIG_CHANGED for invalid slotid=" + slotId);
                    break;
                }
                carrierConfigChanged(slotId);
                break;
            }
            case HANDLER_START_DYNAMIC_FEATURE_QUERY: {
                ImsServiceInfo info = (ImsServiceInfo) msg.obj;
                startDynamicQuery(info);
                break;
            }
            case HANDLER_DYNAMIC_FEATURE_CHANGE: {
                SomeArgs args = (SomeArgs) msg.obj;
                ComponentName name = (ComponentName) args.arg1;
                Set<ImsFeatureConfiguration.FeatureSlotPair> features =
                        (Set<ImsFeatureConfiguration.FeatureSlotPair>) args.arg2;
                args.recycle();
                dynamicQueryComplete(name, features);
                break;
            }
            case HANDLER_OVERRIDE_IMS_SERVICE_CONFIG: {
                OverrideConfig config = (OverrideConfig) msg.obj;
                if (config.isCarrierService) {
                    overrideCarrierService(config.slotId,
                            config.featureTypeToPackageMap);
                } else {
                    overrideDeviceService(config.featureTypeToPackageMap);
                }
                break;
            }
            case HANDLER_MSIM_CONFIGURATION_CHANGE: {
                AsyncResult result = (AsyncResult) msg.obj;
                handleMsimConfigChange((Integer) result.result);
                break;
            }
            default:
                return false;
        }
        return true;
    });

    // Results from dynamic queries to ImsService regarding the features they support.
    private ImsServiceFeatureQueryManager.Listener mDynamicQueryListener =
            new ImsServiceFeatureQueryManager.Listener() {

                @Override
                public void onComplete(ComponentName name,
                        Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
                    Log.d(TAG, "onComplete called for name: " + name + printFeatures(features));
                    handleFeaturesChanged(name, features);
                }

                @Override
                public void onError(ComponentName name) {
                    Log.w(TAG, "onError: " + name + "returned with an error result");
                    mEventLog.log("onError - dynamic query error for " + name);
                    scheduleQueryForFeatures(name, DELAY_DYNAMIC_QUERY_MS);
                }

                @Override
                public void onPermanentError(ComponentName name) {
                    Log.w(TAG, "onPermanentError: component=" + name);
                    mEventLog.log("onPermanentError - error for " + name);
                    mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE,
                            name.getPackageName()).sendToTarget();
                }
            };

    // Used during testing, overrides the carrier services while non-empty.
    // Array index corresponds to slot, per slot there is a feature->package name mapping.
    // should only be accessed from handler
    private SparseArray<SparseArray<String>> mOverrideServices;
    // Outer array index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
    // Locked on mBoundServicesLock
    private SparseArray<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
    // not locked, only accessed on a handler thread.
    // Tracks list of all installed ImsServices
    private Map<ComponentName, ImsServiceInfo> mInstalledServicesCache = new HashMap<>();
    // not locked, only accessed on a handler thread.
    // Active ImsServiceControllers, which are bound to ImsServices.
    private Map<ComponentName, ImsServiceController> mActiveControllers = new HashMap<>();
    private ImsServiceFeatureQueryManager mFeatureQueryManager;

    public ImsResolver(Context context, String defaultMmTelPackageName,
            String defaultRcsPackageName, int numSlots) {
        Log.i(TAG, "device MMTEL package: " + defaultMmTelPackageName + ", device RCS package:"
                + defaultRcsPackageName);
        mContext = context;
        mNumSlots = numSlots;
        mReceiverContext = context.createContextAsUser(UserHandle.ALL, 0 /*flags*/);

        mCarrierServices = new SparseArray<>(mNumSlots);
        mDeviceServices = new ArrayMap<>();
        setDeviceConfiguration(defaultMmTelPackageName, ImsFeature.FEATURE_EMERGENCY_MMTEL);
        setDeviceConfiguration(defaultMmTelPackageName, ImsFeature.FEATURE_MMTEL);
        setDeviceConfiguration(defaultRcsPackageName, ImsFeature.FEATURE_RCS);
        mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
                Context.CARRIER_CONFIG_SERVICE);
        mOverrideServices = new SparseArray<>(0 /*initial size*/);
        mBoundImsServicesByFeature = new SparseArray<>(mNumSlots);

        IntentFilter appChangedFilter = new IntentFilter();
        appChangedFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
        appChangedFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
        appChangedFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
        appChangedFilter.addDataScheme("package");
        mReceiverContext.registerReceiver(mAppChangedReceiver, appChangedFilter);
        mReceiverContext.registerReceiver(mConfigChangedReceiver, new IntentFilter(
                CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));

        UserManager userManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
        if (userManager.isUserUnlocked()) {
            mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
        } else {
            mReceiverContext.registerReceiver(mBootCompleted, new IntentFilter(
                    Intent.ACTION_BOOT_COMPLETED));
            if (userManager.isUserUnlocked()) {
                mHandler.obtainMessage(HANDLER_BOOT_COMPLETE, null).sendToTarget();
            }
        }
    }

    @VisibleForTesting
    public void setTelephonyManagerProxy(TelephonyManagerProxy proxy) {
        mTelephonyManagerProxy = proxy;
    }

    @VisibleForTesting
    public void setSubscriptionManagerProxy(SubscriptionManagerProxy proxy) {
        mSubscriptionManagerProxy = proxy;
    }

    @VisibleForTesting
    public void setImsServiceControllerFactory(ImsServiceControllerFactory factory) {
        mImsServiceControllerFactory = factory;
    }

    @VisibleForTesting
    public Handler getHandler() {
        return mHandler;
    }

    @VisibleForTesting
    public void setImsDynamicQueryManagerFactory(ImsDynamicQueryManagerFactory m) {
        mDynamicQueryManagerFactory = m;
    }

    /**
     * Needs to be called after the constructor to kick off the process of binding to ImsServices.
     */
    public void initialize() {
        mEventLog.log("Initializing");
        Log.i(TAG, "Initializing cache.");
        PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
                HANDLER_MSIM_CONFIGURATION_CHANGE, null);
        mFeatureQueryManager = mDynamicQueryManagerFactory.create(mContext, mDynamicQueryListener);

        // This will get all services with the correct intent filter from PackageManager
        List<ImsServiceInfo> infos = getImsServiceInfo(null);
        for (ImsServiceInfo info : infos) {
            if (!mInstalledServicesCache.containsKey(info.name)) {
                mInstalledServicesCache.put(info.name, info);
            }
        }
        // Update the package names of the carrier ImsServices if they do not exist already and
        // possibly bind if carrier configs exist. Otherwise wait for CarrierConfigChanged
        // indication.
        bindCarrierServicesIfAvailable();
    }

    /**
     * Destroys this ImsResolver. Used for tearing down static resources during testing.
     */
    @VisibleForTesting
    public void destroy() {
        PhoneConfigurationManager.unregisterForMultiSimConfigChange(mHandler);
        mHandler.removeCallbacksAndMessages(null);
    }

    // Only start the bind if there is an existing Carrier Configuration. Otherwise, wait for
    // carrier config changed.
    private void bindCarrierServicesIfAvailable() {
        boolean hasConfigChanged = false;
        for (int slotId = 0; slotId < mNumSlots; slotId++) {
            Map<Integer, String> featureMap = getImsPackageOverrideConfig(slotId);
            for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
                String newPackageName = featureMap.getOrDefault(f, "");
                if (!TextUtils.isEmpty(newPackageName)) {
                    mEventLog.log("bindCarrierServicesIfAvailable - carrier package found: "
                            + newPackageName + " on slot " + slotId);
                    setCarrierConfiguredPackageName(newPackageName, slotId, f);
                    ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
                    // We do not want to trigger feature configuration changes unless there is
                    // already a valid carrier config change.
                    if (info != null && info.featureFromMetadata) {
                        hasConfigChanged = true;
                    } else {
                        // Config will change when this query completes
                        scheduleQueryForFeatures(info);
                    }
                }
            }
        }
        if (hasConfigChanged) calculateFeatureConfigurationChange();
    }

    /**
     * Notify ImsService to enable IMS for the framework. This will trigger IMS registration and
     * trigger ImsFeature status updates.
     */
    public void enableIms(int slotId) {
        SparseArray<ImsServiceController> controllers = getImsServiceControllers(slotId);
        if (controllers != null) {
            for (int i = 0; i < controllers.size(); i++) {
                int key = controllers.keyAt(i);
                controllers.get(key).enableIms(slotId);
            }
        }
    }

    /**
     * Notify ImsService to disable IMS for the framework. This will trigger IMS de-registration and
     * trigger ImsFeature capability status to become false.
     */
    public void disableIms(int slotId) {
        SparseArray<ImsServiceController> controllers = getImsServiceControllers(slotId);
        if (controllers != null) {
            for (int i = 0; i < controllers.size(); i++) {
                int key = controllers.keyAt(i);
                controllers.get(key).disableIms(slotId);
            }
        }
    }

    /**
     * Returns the {@link IImsMmTelFeature} that corresponds to the given slot Id or {@link null} if
     * the service is not available. If an IImsMMTelFeature is available, the
     * {@link IImsServiceFeatureCallback} callback is registered as a listener for feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsMmTelFeature} for.
     * @param callback Listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsMmTelFeature} interface or {@link null} if it is unavailable.
     */
    public IImsMmTelFeature getMmTelFeatureAndListen(int slotId,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.FEATURE_MMTEL, callback);
        return (controller != null) ? controller.getMmTelFeature(slotId) : null;
    }

    /**
     * Returns the {@link IImsRcsFeature} that corresponds to the given slot Id for emergency
     * calling or {@link null} if the service is not available. If an IImsMMTelFeature is
     * available, the {@link IImsServiceFeatureCallback} callback is registered as a listener for
     * feature updates.
     * @param slotId The SIM slot that we are requesting the {@link IImsRcsFeature} for.
     * @param callback listener that will send updates to ImsManager when there are updates to
     * the feature.
     * @return {@link IImsRcsFeature} interface or {@link null} if it is unavailable.
     */
    public IImsRcsFeature getRcsFeatureAndListen(int slotId, IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceControllerAndListen(slotId,
                ImsFeature.FEATURE_RCS, callback);
        return (controller != null) ? controller.getRcsFeature(slotId) : null;
    }

    /**
     * Returns the ImsRegistration structure associated with the slotId and feature specified.
     */
    public @Nullable IImsRegistration getImsRegistration(int slotId, int feature)
            throws RemoteException {
        ImsServiceController controller = getImsServiceController(slotId, feature);
        if (controller != null) {
            return controller.getRegistration(slotId);
        }
        return null;
    }

    /**
     * Returns the ImsConfig structure associated with the slotId and feature specified.
     */
    public @Nullable IImsConfig getImsConfig(int slotId, int feature)
            throws RemoteException {
        ImsServiceController controller = getImsServiceController(slotId, feature);
        if (controller != null) {
            return controller.getConfig(slotId);
        }
        return null;
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceController(int slotId, int feature) {
        if (slotId < 0 || slotId >= mNumSlots) {
            return null;
        }
        ImsServiceController controller;
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                return null;
            }
            controller = services.get(feature);
        }
        return controller;
    }

    private  SparseArray<ImsServiceController> getImsServiceControllers(int slotId) {
        if (slotId < 0 || slotId >= mNumSlots) {
            return null;
        }
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                return null;
            }
            return services;
        }
    }

    @VisibleForTesting
    public ImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceController(slotId, feature);

        if (controller != null) {
            controller.addImsServiceFeatureCallback(callback);
            return controller;
        }
        return null;
    }

    /**
     * Unregister a previously registered IImsServiceFeatureCallback through
     * {@link #getImsServiceControllerAndListen(int, int, IImsServiceFeatureCallback)} .
     * @param slotId The slot id associated with the ImsFeature.
     * @param feature The {@link ImsFeature.FeatureType}
     * @param callback The callback to be unregistered.
     */
    public void unregisterImsFeatureCallback(int slotId, int feature,
            IImsServiceFeatureCallback callback) {
        ImsServiceController controller = getImsServiceController(slotId, feature);

        if (controller != null) {
            controller.removeImsServiceFeatureCallback(callback);
        }
    }

    // Used for testing only.
    public boolean overrideImsServiceConfiguration(int slotId, boolean isCarrierService,
            Map<Integer, String> featureConfig) {
        if (slotId < 0 || slotId >= mNumSlots) {
            Log.w(TAG, "overrideImsServiceConfiguration: invalid slotId!");
            return false;
        }

        OverrideConfig overrideConfig = new OverrideConfig(slotId, isCarrierService, featureConfig);
        Message.obtain(mHandler, HANDLER_OVERRIDE_IMS_SERVICE_CONFIG, overrideConfig)
                .sendToTarget();
        return true;
    }

    // not synchronized, access through handler ONLY.
    private String getDeviceConfiguration(@ImsFeature.FeatureType int featureType) {
        return mDeviceServices.getOrDefault(featureType, "");
    }

    // not synchronized, access in handler ONLY.
    private void setDeviceConfiguration(String name, @ImsFeature.FeatureType int featureType) {
        mDeviceServices.put(featureType, name);
    }

    // not synchronized, access in handler ONLY.
    private void setCarrierConfiguredPackageName(@NonNull String packageName, int slotId,
            @ImsFeature.FeatureType int featureType) {
        getCarrierConfiguredPackageNames(slotId).put(featureType, packageName);
    }

    // not synchronized, access in handler ONLY.
    private @NonNull String getCarrierConfiguredPackageName(int slotId,
            @ImsFeature.FeatureType int featureType) {
        return getCarrierConfiguredPackageNames(slotId).getOrDefault(featureType, "");
    }

    // not synchronized, access in handler ONLY.
    private @NonNull Map<Integer, String> getCarrierConfiguredPackageNames(int slotId) {
        Map<Integer, String> carrierConfig = mCarrierServices.get(slotId);
        if (carrierConfig == null) {
            carrierConfig = new ArrayMap<>();
            mCarrierServices.put(slotId, carrierConfig);
        }
        return carrierConfig;
    }

    // not synchronized, access in handler ONLY.
    private void setOverridePackageName(@Nullable String packageName, int slotId,
            @ImsFeature.FeatureType int featureType) {
        getOverridePackageName(slotId).put(featureType, packageName);
    }

    // not synchronized, access in handler ONLY.
    private @Nullable String getOverridePackageName(int slotId,
            @ImsFeature.FeatureType int featureType) {
        return getOverridePackageName(slotId).get(featureType);
    }

    // not synchronized, access in handler ONLY.
    private @NonNull SparseArray<String> getOverridePackageName(int slotId) {
        SparseArray<String> carrierConfig = mOverrideServices.get(slotId);
        if (carrierConfig == null) {
            carrierConfig = new SparseArray<>();
            mOverrideServices.put(slotId, carrierConfig);
        }
        return carrierConfig;
    }

    /**
     * @return true if there is a carrier configuration that exists for the slot & featureType pair
     * and the cached carrier ImsService associated with the configuration also supports the
     * requested ImsFeature type.
     */
    // not synchronized, access in handler ONLY.
    private boolean doesCarrierConfigurationExist(int slotId,
            @ImsFeature.FeatureType int featureType) {
        String carrierPackage = getCarrierConfiguredPackageName(slotId, featureType);
        if (TextUtils.isEmpty(carrierPackage)) {
            return false;
        }
        // Config exists, but the carrier ImsService also needs to support this feature
        ImsServiceInfo info = getImsServiceInfoFromCache(carrierPackage);
        return info != null && info.getSupportedFeatures().stream().anyMatch(
                feature -> feature.slotId == slotId && feature.featureType == featureType);
    }

    /**
     * @return the package name of the ImsService with the requested configuration.
     */
    // used in shell commands queries during testing only.
    public String getImsServiceConfiguration(int slotId, boolean isCarrierService,
            @ImsFeature.FeatureType int featureType) {
        if (slotId < 0 || slotId >= mNumSlots) {
            Log.w(TAG, "getImsServiceConfiguration: invalid slotId!");
            return "";
        }

        LinkedBlockingQueue<String> result = new LinkedBlockingQueue<>(1);
        // access the configuration on the handler.
        mHandler.post(() -> result.offer(isCarrierService
                ? getCarrierConfiguredPackageName(slotId, featureType) :
                getDeviceConfiguration(featureType)));
        try {
            return result.poll(GET_IMS_SERVICE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            Log.w(TAG, "getImsServiceConfiguration: exception=" + e.getMessage());
            return null;
        }
    }

    private void putImsController(int slotId, int feature, ImsServiceController controller) {
        if (slotId < 0 || slotId >= mNumSlots || feature <= ImsFeature.FEATURE_INVALID
                || feature >= ImsFeature.FEATURE_MAX) {
            Log.w(TAG, "putImsController received invalid parameters - slot: " + slotId
                    + ", feature: " + feature);
            return;
        }
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                services = new SparseArray<>();
                mBoundImsServicesByFeature.put(slotId, services);
            }
            mEventLog.log("putImsController - [" + slotId + ", "
                    + ImsFeature.FEATURE_LOG_MAP.get(feature) + "] -> " + controller);
            Log.i(TAG, "ImsServiceController added on slot: " + slotId + " with feature: "
                    + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
                    + controller.getComponentName());
            services.put(feature, controller);
        }
    }

    private ImsServiceController removeImsController(int slotId, int feature) {
        if (slotId < 0 || feature <= ImsFeature.FEATURE_INVALID
                || feature >= ImsFeature.FEATURE_MAX) {
            Log.w(TAG, "removeImsController received invalid parameters - slot: " + slotId
                    + ", feature: " + feature);
            return null;
        }
        synchronized (mBoundServicesLock) {
            SparseArray<ImsServiceController> services = mBoundImsServicesByFeature.get(slotId);
            if (services == null) {
                return null;
            }
            ImsServiceController c = services.get(feature, null);
            if (c != null) {
                mEventLog.log("removeImsController - [" + slotId + ", "
                        + ImsFeature.FEATURE_LOG_MAP.get(feature) + "] -> " + c);
                Log.i(TAG, "ImsServiceController removed on slot: " + slotId + " with feature: "
                        + ImsFeature.FEATURE_LOG_MAP.get(feature) + " using package: "
                        + c.getComponentName());
                services.remove(feature);
            }
            return c;
        }
    }

    // Update the current cache with the new ImsService(s) if it has been added or update the
    // supported IMS features if they have changed.
    // Called from the handler ONLY
    private void maybeAddedImsService(String packageName) {
        Log.d(TAG, "maybeAddedImsService, packageName: " + packageName);
        List<ImsServiceInfo> infos = getImsServiceInfo(packageName);
        // Wait until all ImsServiceInfo is cached before calling
        // calculateFeatureConfigurationChange to reduce churn.
        boolean requiresCalculation = false;
        for (ImsServiceInfo info : infos) {
            // Checking to see if the ComponentName is the same, so we can update the supported
            // features. Will only be one (if it exists), since it is a set.
            ImsServiceInfo match = getInfoByComponentName(mInstalledServicesCache, info.name);
            if (match != null) {
                // for dynamic query the new "info" will have no supported features yet. Don't wipe
                // out the cache for the existing features or update yet. Instead start a query
                // for features dynamically.
                if (info.featureFromMetadata) {
                    mEventLog.log("maybeAddedImsService - updating features for " + info.name
                            + ": " + printFeatures(match.getSupportedFeatures()) + " -> "
                            + printFeatures(info.getSupportedFeatures()));
                    Log.i(TAG, "Updating features in cached ImsService: " + info.name);
                    Log.d(TAG, "Updating features - Old features: " + match + " new features: "
                            + info);
                    // update features in the cache
                    match.replaceFeatures(info.getSupportedFeatures());
                    requiresCalculation = true;
                } else {
                    mEventLog.log("maybeAddedImsService - scheduling query for " + info);
                    // start a query to get ImsService features
                    scheduleQueryForFeatures(info);
                }
            } else {
                Log.i(TAG, "Adding newly added ImsService to cache: " + info.name);
                mEventLog.log("maybeAddedImsService - adding new ImsService: " + info);
                mInstalledServicesCache.put(info.name, info);
                if (info.featureFromMetadata) {
                    requiresCalculation = true;
                } else {
                    // newly added ImsServiceInfo that has not had features queried yet. Start async
                    // bind and query features.
                    scheduleQueryForFeatures(info);
                }
            }
        }
        if (requiresCalculation) calculateFeatureConfigurationChange();
    }

    // Remove the ImsService from the cache. This may have been due to the ImsService being removed
    // from the device or was returning permanent errors when bound.
    // Called from the handler ONLY
    private boolean maybeRemovedImsService(String packageName) {
        ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
        if (match != null) {
            mInstalledServicesCache.remove(match.name);
            mEventLog.log("maybeRemovedImsService - removing ImsService: " + match);
            Log.i(TAG, "Removing ImsService: " + match.name);
            unbindImsService(match);
            calculateFeatureConfigurationChange();
            return true;
        }
        return false;
    }

    private boolean isDeviceService(ImsServiceInfo info) {
        if (info == null) return false;
        return mDeviceServices.containsValue(info.name.getPackageName());
    }

    private List<Integer> getSlotsForActiveCarrierService(ImsServiceInfo info) {
        if (info == null) return Collections.emptyList();
        List<Integer> slots = new ArrayList<>(mNumSlots);
        for (int i = 0; i < mNumSlots; i++) {
            if (!TextUtils.isEmpty(getCarrierConfiguredPackageNames(i).values().stream()
                    .filter(e -> e.equals(info.name.getPackageName())).findAny().orElse(""))) {
                slots.add(i);
            }
        }
        return slots;
    }

    private ImsServiceController getControllerByServiceInfo(
            Map<ComponentName, ImsServiceController> searchMap, ImsServiceInfo matchValue) {
        return searchMap.values().stream()
                .filter(c -> Objects.equals(c.getComponentName(), matchValue.name))
                .findFirst().orElse(null);
    }

    private ImsServiceInfo getInfoByPackageName(Map<ComponentName, ImsServiceInfo> searchMap,
            String matchValue) {
        return searchMap.values().stream()
                .filter((i) -> Objects.equals(i.name.getPackageName(), matchValue))
                .findFirst().orElse(null);
    }

    private ImsServiceInfo getInfoByComponentName(
            Map<ComponentName, ImsServiceInfo> searchMap, ComponentName matchValue) {
        return searchMap.get(matchValue);
    }

    private void bindImsServiceWithFeatures(ImsServiceInfo info,
            Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        // Only bind if there are features that will be created by the service.
        if (shouldFeaturesCauseBind(features)) {
            // Check to see if an active controller already exists
            ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, info);
            if (controller != null) {
                Log.i(TAG, "ImsService connection exists for " + info.name + ", updating features "
                        + features);
                try {
                    controller.changeImsServiceFeatures(features);
                    // Features have been set, there was an error adding/removing. When the
                    // controller recovers, it will add/remove again.
                } catch (RemoteException e) {
                    Log.w(TAG, "bindImsService: error=" + e.getMessage());
                }
            } else {
                controller = info.controllerFactory.create(mContext, info.name, this);
                Log.i(TAG, "Binding ImsService: " + controller.getComponentName()
                        + " with features: " + features);
                controller.bind(features);
                mEventLog.log("bindImsServiceWithFeatures - create new controller: "
                        + controller);
            }
            mActiveControllers.put(info.name, controller);
        }
    }

    // Clean up and unbind from an ImsService
    private void unbindImsService(ImsServiceInfo info) {
        if (info == null) {
            return;
        }
        ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, info);
        if (controller != null) {
            // Calls imsServiceFeatureRemoved on all features in the controller
            try {
                Log.i(TAG, "Unbinding ImsService: " + controller.getComponentName());
                mEventLog.log("unbindImsService - unbinding and removing " + controller);
                controller.unbind();
            } catch (RemoteException e) {
                Log.e(TAG, "unbindImsService: Remote Exception: " + e.getMessage());
            }
            mActiveControllers.remove(info.name);
        }
    }

    // Calculate which features an ImsServiceController will need. If it is the carrier specific
    // ImsServiceController, it will be granted all of the features it requests on the associated
    // slot. If it is the device ImsService, it will get all of the features not covered by the
    // carrier implementation.
    private HashSet<ImsFeatureConfiguration.FeatureSlotPair> calculateFeaturesToCreate(
            ImsServiceInfo info) {
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> imsFeaturesBySlot = new HashSet<>();
        List<Integer> slots = getSlotsForActiveCarrierService(info);
        if (!slots.isEmpty()) {
            // There is an active carrier config associated with this. Return with the ImsService's
            // supported features that are also within the carrier configuration
            imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
                    .filter(feature -> info.name.getPackageName().equals(
                            getCarrierConfiguredPackageName(feature.slotId, feature.featureType)))
                    .collect(Collectors.toList()));
            return imsFeaturesBySlot;
        }
        if (isDeviceService(info)) {
            imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
                    // only allow supported features that are also set for this package as the
                    // device configuration.
                    .filter(feature -> info.name.getPackageName().equals(
                            getDeviceConfiguration(feature.featureType)))
                    // filter out any separate carrier configuration, since that feature is handled
                    // by the carrier ImsService.
                    .filter(feature -> !doesCarrierConfigurationExist(feature.slotId,
                            feature.featureType))
                    .collect(Collectors.toList()));
        }
        return imsFeaturesBySlot;
    }

    /**
     * Implementation of
     * {@link ImsServiceController.ImsServiceControllerCallbacks#imsServiceFeatureCreated}, which
     * removes the ImsServiceController from the mBoundImsServicesByFeature structure.
     */
    public void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller) {
        putImsController(slotId, feature, controller);
    }

    /**
     * Implementation of
     * {@link ImsServiceController.ImsServiceControllerCallbacks#imsServiceFeatureRemoved}, which
     * removes the ImsServiceController from the mBoundImsServicesByFeature structure.
     */
    public void imsServiceFeatureRemoved(int slotId, int feature, ImsServiceController controller) {
        removeImsController(slotId, feature);
    }

    /**
     * Implementation of
     * {@link ImsServiceController.ImsServiceControllerCallbacks#imsServiceFeaturesChanged, which
     * notify the ImsResolver of a change to the supported ImsFeatures of a connected ImsService.
     */
    public void imsServiceFeaturesChanged(ImsFeatureConfiguration config,
            ImsServiceController controller) {
        if (controller == null || config == null) {
            return;
        }
        Log.i(TAG, "imsServiceFeaturesChanged: config=" + config.getServiceFeatures()
                + ", ComponentName=" + controller.getComponentName());
        mEventLog.log("imsServiceFeaturesChanged - for " + controller + ", new config "
                + config.getServiceFeatures());
        handleFeaturesChanged(controller.getComponentName(), config.getServiceFeatures());
    }

    @Override
    public void imsServiceBindPermanentError(ComponentName name) {
        if (name == null) {
            return;
        }
        Log.w(TAG, "imsServiceBindPermanentError: component=" + name);
        mEventLog.log("imsServiceBindPermanentError - for " + name);
        mHandler.obtainMessage(HANDLER_REMOVE_PACKAGE, name.getPackageName()).sendToTarget();
    }

    /**
     * Determines if the features specified should cause a bind or keep a binding active to an
     * ImsService.
     * @return true if MMTEL or RCS features are present, false if they are not or only
     * EMERGENCY_MMTEL is specified.
     */
    private boolean shouldFeaturesCauseBind(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        long bindableFeatures = features.stream()
                // remove all emergency features
                .filter(f -> f.featureType != ImsFeature.FEATURE_EMERGENCY_MMTEL).count();
        return bindableFeatures > 0;
    }

    // Possibly rebind to another ImsService for testing carrier ImsServices.
    // Called from the handler ONLY
    private void overrideCarrierService(int slotId, Map<Integer, String> featureMap) {
        for (Integer featureType : featureMap.keySet()) {
            String overridePackageName = featureMap.get(featureType);
            mEventLog.log("overriding carrier ImsService to " + overridePackageName
                    + " on slot " + slotId + " for feature "
                    + ImsFeature.FEATURE_LOG_MAP.getOrDefault(featureType, "invalid"));
            setOverridePackageName(overridePackageName, slotId, featureType);
        }
        updateBoundServices(slotId, Collections.emptyMap());
    }

    // Possibly rebind to another ImsService for testing carrier ImsServices.
    // Called from the handler ONLY
    private void overrideDeviceService(Map<Integer, String> featureMap) {
        boolean requiresRecalc = false;
        for (Integer featureType : featureMap.keySet()) {
            String overridePackageName = featureMap.get(featureType);
            mEventLog.log("overriding device ImsService to " + overridePackageName + " for feature "
                    + ImsFeature.FEATURE_LOG_MAP.getOrDefault(featureType, "invalid"));
            String oldPackageName = getDeviceConfiguration(featureType);
            if (!TextUtils.equals(oldPackageName, overridePackageName)) {
                Log.i(TAG, "overrideDeviceService - device package changed (override): "
                        + oldPackageName + " -> " + overridePackageName);
                mEventLog.log("overrideDeviceService - device package changed (override): "
                        + oldPackageName + " -> " + overridePackageName);
                setDeviceConfiguration(overridePackageName, featureType);
                ImsServiceInfo info = getImsServiceInfoFromCache(overridePackageName);
                if (info == null || info.featureFromMetadata) {
                    requiresRecalc = true;
                } else {
                    // Config will change when this query completes
                    scheduleQueryForFeatures(info);
                }
            }
        }
        if (requiresRecalc) calculateFeatureConfigurationChange();
    }

    // Called from handler ONLY.
    private void carrierConfigChanged(int slotId) {
        updateBoundDeviceServices();

        if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            // not specified, update carrier override cache and possibly rebind on all slots.
            for (int i = 0; i < mNumSlots; i++) {
                updateBoundServices(i, getImsPackageOverrideConfig(i));
            }
        }
        updateBoundServices(slotId, getImsPackageOverrideConfig(slotId));
    }

    private void updateBoundDeviceServices() {
        Log.d(TAG, "updateBoundDeviceServices: called");
        ArrayMap<String, ImsServiceInfo> featureDynamicImsPackages = new ArrayMap<>();
        for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
            String packageName = getDeviceConfiguration(f);
            ImsServiceInfo serviceInfo = getImsServiceInfoFromCache(packageName);
            if (serviceInfo != null && !serviceInfo.featureFromMetadata
                    && !featureDynamicImsPackages.containsKey(packageName)) {
                featureDynamicImsPackages.put(packageName, serviceInfo);

                Log.d(TAG, "updateBoundDeviceServices: Schedule query for package=" + packageName);
                scheduleQueryForFeatures(featureDynamicImsPackages.get(packageName));
            }
        }
    }

    private void updateBoundServices(int slotId, Map<Integer, String> featureMap) {
        if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX || slotId >= mNumSlots) {
            return;
        }
        boolean hasConfigChanged = false;
        boolean didQuerySchedule = false;
        for (int f = ImsFeature.FEATURE_EMERGENCY_MMTEL; f < ImsFeature.FEATURE_MAX; f++) {
            String overridePackageName = getOverridePackageName(slotId, f);
            String oldPackageName = getCarrierConfiguredPackageName(slotId, f);
            String newPackageName = featureMap.getOrDefault(f, "");
            if (!TextUtils.isEmpty(overridePackageName)) {
                // Do not allow carrier config changes to change the override package while it
                // is in effect.
                Log.i(TAG, String.format("updateBoundServices: overriding %s with %s for feature"
                                + " %s on slot %d",
                        TextUtils.isEmpty(newPackageName) ? "(none)" : newPackageName,
                        overridePackageName,
                        ImsFeature.FEATURE_LOG_MAP.getOrDefault(f, "invalid"), slotId));
                newPackageName = overridePackageName;
            }

            setCarrierConfiguredPackageName(newPackageName, slotId, f);
            // Carrier config may have not changed, but we still want to kick off a recalculation
            // in case there has been a change to the supported device features.
            ImsServiceInfo info = getImsServiceInfoFromCache(newPackageName);
            mEventLog.log("updateBoundServices - carrier package changed: "
                    + oldPackageName + " -> " + newPackageName + " on slot " + slotId
                    + ", hasConfigChanged=" + hasConfigChanged);
            if (info == null || info.featureFromMetadata) {
                hasConfigChanged = true;
            } else {
                // Config will change when this query completes
                scheduleQueryForFeatures(info);
                didQuerySchedule = true;
            }
        }
        if (hasConfigChanged) calculateFeatureConfigurationChange();

        if (hasConfigChanged && didQuerySchedule) {
            mEventLog.log("[warning] updateBoundServices - both hasConfigChange and query "
                    + "scheduled on slot " + slotId);
        }
    }

    private @NonNull Map<Integer, String> getImsPackageOverrideConfig(int slotId) {
        int subId = mSubscriptionManagerProxy.getSubId(slotId);
        PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
        if (config == null) return Collections.emptyMap();
        String packageNameMmTel = config.getString(
                CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
        // Set the config equal for the deprecated key.
        String packageNameRcs = packageNameMmTel;
        packageNameMmTel = config.getString(
                CarrierConfigManager.KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING,
                packageNameMmTel);
        packageNameRcs = config.getString(
                CarrierConfigManager.KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING, packageNameRcs);
        Map<Integer, String> result = new ArrayMap<>();
        if (!TextUtils.isEmpty(packageNameMmTel)) {
            result.put(ImsFeature.FEATURE_EMERGENCY_MMTEL, packageNameMmTel);
            result.put(ImsFeature.FEATURE_MMTEL, packageNameMmTel);
        }
        if (!TextUtils.isEmpty(packageNameRcs)) {
            result.put(ImsFeature.FEATURE_RCS, packageNameRcs);
        }
        return result;
    }

    /**
     * Schedules a query for dynamic ImsService features.
     */
    private void scheduleQueryForFeatures(ImsServiceInfo service, int delayMs) {
        if (service == null) {
            return;
        }
        Message msg = Message.obtain(mHandler, HANDLER_START_DYNAMIC_FEATURE_QUERY, service);
        if (mHandler.hasMessages(HANDLER_START_DYNAMIC_FEATURE_QUERY, service)) {
            Log.d(TAG, "scheduleQueryForFeatures: dynamic query for " + service.name
                    + " already scheduled");
            return;
        }
        Log.d(TAG, "scheduleQueryForFeatures: starting dynamic query for " + service.name
                + " in " + delayMs + "ms.");
        mHandler.sendMessageDelayed(msg, delayMs);
    }

    private void scheduleQueryForFeatures(ComponentName name, int delayMs) {
        ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
        if (service == null) {
            Log.w(TAG, "scheduleQueryForFeatures: Couldn't find cached info for name: " + name);
            return;
        }
        scheduleQueryForFeatures(service, delayMs);
    }

    private void scheduleQueryForFeatures(ImsServiceInfo service) {
        scheduleQueryForFeatures(service, 0);
    }

    /**
     * Schedules the processing of a completed query.
     */
    private void handleFeaturesChanged(ComponentName name,
            Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        SomeArgs args = SomeArgs.obtain();
        args.arg1 = name;
        args.arg2 = features;
        mHandler.obtainMessage(HANDLER_DYNAMIC_FEATURE_CHANGE, args).sendToTarget();
    }

    private void handleMsimConfigChange(Integer newNumSlots) {
        int oldLen = mNumSlots;
        if (oldLen == newNumSlots) {
            return;
        }
        mNumSlots = newNumSlots;
        Log.i(TAG, "handleMsimConfigChange: oldLen=" + oldLen + ", newLen=" + newNumSlots);
        mEventLog.log("MSIM config change: " + oldLen + " -> " + newNumSlots);
        if (newNumSlots < oldLen) {
            // we need to trim data structures that use slots, however mBoundImsServicesByFeature
            // will be updated by ImsServiceController changing to remove features on old slots.
            // start at the index of the new highest slot + 1.
            for (int oldSlot = newNumSlots; oldSlot < oldLen; oldSlot++) {
                // First clear old carrier configs
                Map<Integer, String> carrierConfigs = getCarrierConfiguredPackageNames(oldSlot);
                for (Integer feature : carrierConfigs.keySet()) {
                    setCarrierConfiguredPackageName("", oldSlot, feature);
                }
                // next clear old overrides
                SparseArray<String> overrideConfigs = getOverridePackageName(oldSlot);
                for (int i = 0; i < overrideConfigs.size(); i++) {
                    int feature = overrideConfigs.keyAt(i);
                    setOverridePackageName("", oldSlot, feature);
                }
            }
        }
        // Get the new config for each ImsService. For manifest queries, this will update the
        // number of slots.
        // This will get all services with the correct intent filter from PackageManager
        List<ImsServiceInfo> infos = getImsServiceInfo(null);
        for (ImsServiceInfo info : infos) {
            ImsServiceInfo cachedInfo = mInstalledServicesCache.get(info.name);
            if (cachedInfo != null) {
                if (info.featureFromMetadata) {
                    cachedInfo.replaceFeatures(info.getSupportedFeatures());
                } else {
                    // Remove features that are no longer supported by the device configuration.
                    cachedInfo.getSupportedFeatures()
                            .removeIf(filter -> filter.slotId >= newNumSlots);
                }
            } else {
                // This is unexpected, put the new service on the queue to be added
                mEventLog.log("handleMsimConfigChange: detected untracked service - " + info);
                Log.w(TAG, "handleMsimConfigChange: detected untracked package, queueing to add "
                        + info);
                mHandler.obtainMessage(HANDLER_ADD_PACKAGE,
                        info.name.getPackageName()).sendToTarget();
            }
        }

        if (newNumSlots < oldLen) {
            // A CarrierConfigChange will happen for the new slot, so only recalculate if there are
            // less new slots because we need to remove the old capabilities.
            calculateFeatureConfigurationChange();
        }
    }

    // Starts a dynamic query. Called from handler ONLY.
    private void startDynamicQuery(ImsServiceInfo service) {
        // if not current device/carrier service, don't perform query. If this changes, this method
        // will be called again.
        if (!isDeviceService(service) && getSlotsForActiveCarrierService(service).isEmpty()) {
            Log.i(TAG, "scheduleQueryForFeatures: skipping query for ImsService that is not"
                    + " set as carrier/device ImsService.");
            return;
        }
        mEventLog.log("startDynamicQuery - starting query for " + service);
        boolean queryStarted = mFeatureQueryManager.startQuery(service.name,
                service.controllerFactory.getServiceInterface());
        if (!queryStarted) {
            Log.w(TAG, "startDynamicQuery: service could not connect. Retrying after delay.");
            mEventLog.log("startDynamicQuery - query failed. Retrying in "
                    + DELAY_DYNAMIC_QUERY_MS + " mS");
            scheduleQueryForFeatures(service, DELAY_DYNAMIC_QUERY_MS);
        } else {
            Log.d(TAG, "startDynamicQuery: Service queried, waiting for response.");
        }
    }

    // process complete dynamic query. Called from handler ONLY.
    private void dynamicQueryComplete(ComponentName name,
            Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        ImsServiceInfo service = getImsServiceInfoFromCache(name.getPackageName());
        if (service == null) {
            Log.w(TAG, "dynamicQueryComplete: Couldn't find cached info for name: "
                    + name);
            return;
        }
        mEventLog.log("dynamicQueryComplete: for package " + name + ", features: "
                + printFeatures(service.getSupportedFeatures()) + " -> " + printFeatures(features));
        sanitizeFeatureConfig(features);
        // Add features to service
        service.replaceFeatures(features);
        // Wait until all queries have completed before changing the configuration to reduce churn.
        if (!mFeatureQueryManager.isQueryInProgress()) {
            if (mHandler.hasMessages(HANDLER_DYNAMIC_FEATURE_CHANGE)) {
                mEventLog.log("[warning] dynamicQueryComplete - HANDLER_DYNAMIC_FEATURE_CHANGE "
                        + "pending with calculateFeatureConfigurationChange()");
            }
            calculateFeatureConfigurationChange();
        }
    }

    /**
     * Ensure the feature includes MMTEL when it supports EMERGENCY_MMTEL, if not, remove.
     */
    private void sanitizeFeatureConfig(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        Set<ImsFeatureConfiguration.FeatureSlotPair> emergencyMmtelFeatures = features.stream()
                .filter(feature -> feature.featureType == ImsFeature.FEATURE_EMERGENCY_MMTEL)
                .collect(Collectors.toSet());
        for (ImsFeatureConfiguration.FeatureSlotPair feature : emergencyMmtelFeatures) {
            if (!features.contains(new ImsFeatureConfiguration.FeatureSlotPair(feature.slotId,
                    ImsFeature.FEATURE_MMTEL))) {
                features.remove(feature);
            }
        }
    }

    // Calculate the new configuration for the bound ImsServices.
    // Should ONLY be called from the handler.
    private void calculateFeatureConfigurationChange() {
        for (ImsServiceInfo info : mInstalledServicesCache.values()) {
            Set<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
            if (shouldFeaturesCauseBind(features)) {
                bindImsServiceWithFeatures(info, features);
            } else {
                unbindImsService(info);
            }
        }
    }

    private static String printFeatures(Set<ImsFeatureConfiguration.FeatureSlotPair> features) {
        StringBuilder featureString = new StringBuilder();
        featureString.append(" features: [");
        if (features != null) {
            for (ImsFeatureConfiguration.FeatureSlotPair feature : features) {
                featureString.append("{");
                featureString.append(feature.slotId);
                featureString.append(",");
                featureString.append(ImsFeature.FEATURE_LOG_MAP.get(feature.featureType));
                featureString.append("}");
            }
            featureString.append("]");
        }
        return featureString.toString();
    }

    /**
     * Returns the ImsServiceInfo that matches the provided packageName. Visible for testing
     * the ImsService caching functionality.
     */
    @VisibleForTesting
    public ImsServiceInfo getImsServiceInfoFromCache(String packageName) {
        if (TextUtils.isEmpty(packageName)) {
            return null;
        }
        ImsServiceInfo infoFilter = getInfoByPackageName(mInstalledServicesCache, packageName);
        if (infoFilter != null) {
            return infoFilter;
        } else {
            return null;
        }
    }

    // Return the ImsServiceInfo specified for the package name. If the package name is null,
    // get all packages that support ImsServices.
    private List<ImsServiceInfo> getImsServiceInfo(String packageName) {
        List<ImsServiceInfo> infos = new ArrayList<>();
        // Search for Current ImsService implementations
        infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactory));
        // Search for compat ImsService Implementations
        infos.addAll(searchForImsServices(packageName, mImsServiceControllerFactoryCompat));
        return infos;
    }

    private List<ImsServiceInfo> searchForImsServices(String packageName,
            ImsServiceControllerFactory controllerFactory) {
        List<ImsServiceInfo> infos = new ArrayList<>();

        Intent serviceIntent = new Intent(controllerFactory.getServiceInterface());
        serviceIntent.setPackage(packageName);

        PackageManager packageManager = mContext.getPackageManager();
        for (ResolveInfo entry : packageManager.queryIntentServicesAsUser(
                serviceIntent,
                PackageManager.GET_META_DATA,
                UserHandle.getUserHandleForUid(UserHandle.myUserId()))) {
            ServiceInfo serviceInfo = entry.serviceInfo;

            if (serviceInfo != null) {
                ImsServiceInfo info = new ImsServiceInfo();
                info.name = new ComponentName(serviceInfo.packageName, serviceInfo.name);
                info.controllerFactory = controllerFactory;

                // we will allow the manifest method of declaring manifest features in two cases:
                // 1) it is the device overlay "default" ImsService, where the features do not
                // change (the new method can still be used if the default does not define manifest
                // entries).
                // 2) using the "compat" ImsService, which only supports manifest query.
                if (isDeviceService(info)
                        || mImsServiceControllerFactoryCompat == controllerFactory) {
                    if (serviceInfo.metaData != null) {
                        if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
                            info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_MMTEL);
                            // only allow FEATURE_EMERGENCY_MMTEL if FEATURE_MMTEL is defined.
                            if (serviceInfo.metaData.getBoolean(METADATA_EMERGENCY_MMTEL_FEATURE,
                                    false)) {
                                info.addFeatureForAllSlots(mNumSlots,
                                        ImsFeature.FEATURE_EMERGENCY_MMTEL);
                            }
                        }
                        if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
                            info.addFeatureForAllSlots(mNumSlots, ImsFeature.FEATURE_RCS);
                        }
                    }
                    // Only dynamic query if we are not a compat version of ImsService and the
                    // default service.
                    if (mImsServiceControllerFactoryCompat != controllerFactory
                            && info.getSupportedFeatures().isEmpty()) {
                        // metadata empty, try dynamic query instead
                        info.featureFromMetadata = false;
                    }
                } else {
                    // We are a carrier service and not using the compat version of ImsService.
                    info.featureFromMetadata = false;
                }
                Log.i(TAG, "service name: " + info.name + ", manifest query: "
                        + info.featureFromMetadata);
                // Check manifest permission to be sure that the service declares the correct
                // permissions. Overridden if the METADATA_OVERRIDE_PERM_CHECK metadata is set to
                // true.
                // NOTE: METADATA_OVERRIDE_PERM_CHECK should only be set for testing.
                if (TextUtils.equals(serviceInfo.permission, Manifest.permission.BIND_IMS_SERVICE)
                        || serviceInfo.metaData.getBoolean(METADATA_OVERRIDE_PERM_CHECK, false)) {
                    infos.add(info);
                } else {
                    Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
                            + info.name);
                }
            }
        }
        return infos;
    }

    // Dump is called on the main thread, since ImsResolver Handler is also handled on main thread,
    // we shouldn't need to worry about concurrent access of private params.
    public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
        IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
        pw.println("ImsResolver:");
        pw.increaseIndent();
        pw.println("Configurations:");
        pw.increaseIndent();
        pw.println("Device:");
        pw.increaseIndent();
        for (Integer i : mDeviceServices.keySet()) {
            pw.println(ImsFeature.FEATURE_LOG_MAP.get(i) + " -> " + mDeviceServices.get(i));
        }
        pw.decreaseIndent();
        pw.println("Carrier: ");
        pw.increaseIndent();
        for (int i = 0; i < mNumSlots; i++) {
            for (int j = 0; j < MmTelFeature.FEATURE_MAX; j++) {
                pw.print("slot=");
                pw.print(i);
                pw.print(", feature=");
                pw.print(ImsFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
                pw.println(": ");
                pw.increaseIndent();
                String name = getCarrierConfiguredPackageName(i, j);
                pw.println(TextUtils.isEmpty(name) ? "none" : name);
                pw.decreaseIndent();
            }
        }
        pw.decreaseIndent();
        pw.decreaseIndent();
        pw.println("Bound Features:");
        pw.increaseIndent();
        for (int i = 0; i < mNumSlots; i++) {
            for (int j = 0; j < MmTelFeature.FEATURE_MAX; j++) {
                pw.print("slot=");
                pw.print(i);
                pw.print(", feature=");
                pw.print(ImsFeature.FEATURE_LOG_MAP.getOrDefault(j, "?"));
                pw.println(": ");
                pw.increaseIndent();
                ImsServiceController c = getImsServiceController(i, j);
                pw.println(c == null ? "none" : c);
                pw.decreaseIndent();
            }
        }
        pw.decreaseIndent();
        pw.println("Cached ImsServices:");
        pw.increaseIndent();
        for (ImsServiceInfo i : mInstalledServicesCache.values()) {
            pw.println(i);
        }
        pw.decreaseIndent();
        pw.println("Active controllers:");
        pw.increaseIndent();
        for (ImsServiceController c : mActiveControllers.values()) {
            pw.println(c);
            pw.increaseIndent();
            c.dump(pw);
            pw.decreaseIndent();
        }
        pw.decreaseIndent();
        pw.println("Event Log:");
        pw.increaseIndent();
        mEventLog.dump(pw);
        pw.decreaseIndent();
    }
}
