/*
 * 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.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.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
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.stub.ImsFeatureConfiguration;
import android.text.TextUtils;
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 java.util.ArrayList;
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.stream.Collectors;
import java.util.stream.Stream;

/**
 * Creates a list of ImsServices that are available to bind to based on the Device configuration
 * overlay value "config_ims_package" and Carrier Configuration value
 * "config_ims_package_override_string".
 * These ImsServices are then bound to in the following order:
 *
 * 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";

    public static final String METADATA_EMERGENCY_MMTEL_FEATURE =
            "android.telephony.ims.EMERGENCY_MMTEL_FEATURE";
    public static final String METADATA_MMTEL_FEATURE = "android.telephony.ims.MMTEL_FEATURE";
    public static final String METADATA_RCS_FEATURE = "android.telephony.ims.RCS_FEATURE";

    // 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 query to request ImsService features has completed or the ImsService has updated features.
    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;

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


    /**
     * 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;
        private final int mNumSlots;

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

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

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

        @VisibleForTesting
        public HashSet<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() {
            StringBuilder res = new StringBuilder();
            res.append("[ImsServiceInfo] name=");
            res.append(name);
            res.append(", supportedFeatures=[ ");
            for (ImsFeatureConfiguration.FeatureSlotPair feature : mSupportedFeatures) {
                res.append("(");
                res.append(feature.slotId);
                res.append(",");
                res.append(feature.featureType);
                res.append(") ");
            }
            return res.toString();
        }
    }

    // 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 SIM change for invalid slot id.");
                return;
            }

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

            mHandler.obtainMessage(HANDLER_CONFIG_CHANGED, slotId).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);
    }

    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 ImsServiceControllerFactory mImsServiceControllerFactoryStaticBindingCompat =
            new ImsServiceControllerFactory() {
                @Override
                public String getServiceInterface() {
                    // The static method of binding does not use service interfaces.
                    return null;
                }

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

    private ImsDynamicQueryManagerFactory mDynamicQueryManagerFactory =
            ImsServiceFeatureQueryManager::new;

    private final CarrierConfigManager mCarrierConfigManager;
    private final Context mContext;
    // Locks mBoundImsServicesByFeature only. Be careful to avoid deadlocks from
    // ImsServiceController callbacks.
    private final Object mBoundServicesLock = new Object();
    private final int mNumSlots;
    private final boolean mIsDynamicBinding;
    // Package name of the default device service.
    private String mDeviceService;

    // Synchronize all messages 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_CONFIG_CHANGED: {
                int slotId = (Integer) msg.obj;
                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: {
                int slotId = msg.arg1;
                // arg2 will be equal to 1 if it is a carrier service.
                boolean isCarrierImsService = (msg.arg2 == 1);
                String packageName = (String) msg.obj;
                if (isCarrierImsService) {
                    Log.i(TAG, "overriding carrier ImsService - slot=" + slotId + " packageName="
                            + packageName);
                    maybeRebindService(slotId, packageName);
                } else {
                    Log.i(TAG, "overriding device ImsService -  packageName=" + packageName);
                    if (packageName == null || packageName.isEmpty()) {
                        unbindImsService(getImsServiceInfoFromCache(mDeviceService));
                    }
                    mDeviceService = packageName;
                    bindImsService(getImsServiceInfoFromCache(packageName));
                }
                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 + "features:"
                            + printFeatures(features));
                    handleFeaturesChanged(name, features);
                }

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

    // Array index corresponds to slot Id associated with the service package name.
    private String[] mCarrierServices;
    // List index corresponds to Slot Id, Maps ImsFeature.FEATURE->bound ImsServiceController
    // Locked on mBoundServicesLock
    private List<SparseArray<ImsServiceController>> mBoundImsServicesByFeature;
    // not locked, only accessed on a handler thread.
    private Map<ComponentName, ImsServiceInfo> mInstalledServicesCache = new HashMap<>();
    // not locked, only accessed on a handler thread.
    private Map<ComponentName, ImsServiceController> mActiveControllers = new HashMap<>();
    // Only used as the Component name for legacy ImsServices that did not use dynamic binding.
    private final ComponentName mStaticComponent;
    private ImsServiceFeatureQueryManager mFeatureQueryManager;

    public ImsResolver(Context context, String defaultImsPackageName, int numSlots,
            boolean isDynamicBinding) {
        mContext = context;
        mDeviceService = defaultImsPackageName;
        mNumSlots = numSlots;
        mIsDynamicBinding = isDynamicBinding;
        mStaticComponent = new ComponentName(mContext, ImsResolver.class);
        if (!mIsDynamicBinding) {
            Log.i(TAG, "ImsResolver initialized with static binding.");
            mDeviceService = mStaticComponent.getPackageName();
        }
        mCarrierConfigManager = (CarrierConfigManager) mContext.getSystemService(
                Context.CARRIER_CONFIG_SERVICE);
        mCarrierServices = new String[numSlots];
        mBoundImsServicesByFeature = Stream.generate(SparseArray<ImsServiceController>::new)
                .limit(mNumSlots).collect(Collectors.toList());

        // Only register for Package/CarrierConfig updates if dynamic binding.
        if(mIsDynamicBinding) {
            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");
            context.registerReceiverAsUser(mAppChangedReceiver, UserHandle.ALL, appChangedFilter,
                    null,
                    null);

            context.registerReceiver(mConfigChangedReceiver, new IntentFilter(
                    CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
        }
    }

    @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 first populate the cache and possibly bind to
     * ImsServices.
     */
    public void initPopulateCacheAndStartBind() {
        Log.i(TAG, "Initializing cache and binding.");
        mFeatureQueryManager = mDynamicQueryManagerFactory.create(mContext, mDynamicQueryListener);
        // Populates the CarrierConfig override package names for each slot
        mHandler.obtainMessage(HANDLER_CONFIG_CHANGED,
                SubscriptionManager.INVALID_SIM_SLOT_INDEX).sendToTarget();
        // Starts first bind to the system.
        mHandler.obtainMessage(HANDLER_ADD_PACKAGE, null).sendToTarget();
    }

    /**
     * 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;
    }

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

        if (packageName == null) {
            Log.w(TAG, "overrideImsServiceConfiguration: null packageName!");
            return false;
        }

        // encode boolean to int for Message.
        int carrierService = isCarrierService ? 1 : 0;
        Message.obtain(mHandler, HANDLER_OVERRIDE_IMS_SERVICE_CONFIG, slotId, carrierService,
                packageName).sendToTarget();
        return true;
    }

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

        return isCarrierService ? mCarrierServices[slotId] : mDeviceService;
    }

    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.add(slotId, services);
            }
            Log.i(TAG, "ImsServiceController added on slot: " + slotId + " with feature: "
                    + feature + " using package: " + controller.getComponentName());
            services.put(feature, controller);
        }
    }

    private ImsServiceController removeImsController(int slotId, int feature) {
        if (slotId < 0 || slotId >= mNumSlots || 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) {
                Log.i(TAG, "ImsServiceController removed on slot: " + slotId + " with feature: "
                        + 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);
        List<ImsServiceInfo> newlyAddedInfos = new ArrayList<>();
        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) {
                    // update features in the cache
                    Log.i(TAG, "Updating features in cached ImsService: " + info.name);
                    Log.d(TAG, "Updating features - Old features: " + match + " new features: "
                            + info);
                    match.replaceFeatures(info.getSupportedFeatures());
                    updateImsServiceFeatures(info);
                } else {
                    // start a query to get ImsService features
                    scheduleQueryForFeatures(info);
                }
            } else {
                Log.i(TAG, "Adding newly added ImsService to cache: " + info.name);
                mInstalledServicesCache.put(info.name, info);
                if (info.featureFromMetadata) {
                    newlyAddedInfos.add(info);
                } else {
                    // newly added ImsServiceInfo that has not had features queried yet. Start async
                    // bind and query features.
                    scheduleQueryForFeatures(info);
                }
            }
        }
        // Loop through the newly created ServiceInfos in a separate loop to make sure the cache
        // is fully updated.
        for (ImsServiceInfo info : newlyAddedInfos) {
            if (isActiveCarrierService(info)) {
                // New ImsService is registered to active carrier services and must be newly
                // bound.
                bindImsService(info);
                // Update existing device service features
                updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
            } else if (isDeviceService(info)) {
                // New ImsService is registered as device default and must be newly bound.
                bindImsService(info);
            }
        }
    }

    // Remove the ImsService from the cache. At this point, the ImsService will have already been
    // killed.
    // Called from the handler ONLY
    private boolean maybeRemovedImsService(String packageName) {
        ImsServiceInfo match = getInfoByPackageName(mInstalledServicesCache, packageName);
        if (match != null) {
            mInstalledServicesCache.remove(match.name);
            Log.i(TAG, "Removing ImsService: " + match.name);
            unbindImsService(match);
            updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
            return true;
        }
        return false;
    }

    // Returns true if the CarrierConfig that has been loaded includes this ImsServiceInfo
    // package name.
    // Called from Handler ONLY
    private boolean isActiveCarrierService(ImsServiceInfo info) {
        for (int i = 0; i < mNumSlots; i++) {
            if (TextUtils.equals(mCarrierServices[i], info.name.getPackageName())) {
                return true;
            }
        }
        return false;
    }

    private boolean isDeviceService(ImsServiceInfo info) {
        return TextUtils.equals(mDeviceService, info.name.getPackageName());
    }

    private int getSlotForActiveCarrierService(ImsServiceInfo info) {
        for (int i = 0; i < mNumSlots; i++) {
            if (TextUtils.equals(mCarrierServices[i], info.name.getPackageName())) {
                return i;
            }
        }
        return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
    }

    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);
    }

    // Creates new features in active ImsServices and removes obsolete cached features. If
    // cachedInfo == null, then newInfo is assumed to be a new ImsService and will have all features
    // created.
    private void updateImsServiceFeatures(ImsServiceInfo newInfo) {
        if (newInfo == null) {
            return;
        }
        ImsServiceController controller = getControllerByServiceInfo(mActiveControllers, newInfo);
        // Will return zero if these features are overridden or it should not currently have any
        // features because it is not carrier/device.
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> features =
                calculateFeaturesToCreate(newInfo);
        if (shouldFeaturesCauseBind(features)) {
            try {
                if (controller != null) {
                    Log.i(TAG, "Updating features for ImsService: "
                            + controller.getComponentName());
                    Log.d(TAG, "Updating Features - New Features: " + features);
                    controller.changeImsServiceFeatures(features);
                } else {
                    Log.i(TAG, "updateImsServiceFeatures: unbound with active features, rebinding");
                    bindImsServiceWithFeatures(newInfo, features);
                }
                // If the carrier service features have changed, the device features will also
                // need to be recalculated.
                if (isActiveCarrierService(newInfo)
                        // Prevent infinite recursion from bad behavior
                        && !TextUtils.equals(newInfo.name.getPackageName(), mDeviceService)) {
                    Log.i(TAG, "Updating device default");
                    updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
                }
            } catch (RemoteException e) {
                Log.e(TAG, "updateImsServiceFeatures: Remote Exception: " + e.getMessage());
            }
        // Don't stay bound if the ImsService is providing no features.
        } else if (controller != null) {
            Log.i(TAG, "Unbinding: features = 0 for ImsService: " + controller.getComponentName());
            unbindImsService(newInfo);
        }
    }

    // Bind to an ImsService and wait for the service to be connected to create ImsFeatures.
    private void bindImsService(ImsServiceInfo info) {
        if (info == null) {
            return;
        }
        HashSet<ImsFeatureConfiguration.FeatureSlotPair> features = calculateFeaturesToCreate(info);
        bindImsServiceWithFeatures(info, features);
    }

    private void bindImsServiceWithFeatures(ImsServiceInfo info,
            HashSet<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, 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);
            }
            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());
                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<>();
        // Check if the info is a carrier service
        int slotId = getSlotForActiveCarrierService(info);
        if (slotId != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
                    // Match slotId with feature slotId.
                    .filter(feature -> slotId == feature.slotId)
                    .collect(Collectors.toList()));
        } else if (isDeviceService(info)) {
            // For all slots that are not currently using a carrier ImsService, enable all features
            // for the device default.
            for (int i = 0; i < mNumSlots; i++) {
                final int currSlotId = i;
                ImsServiceInfo carrierImsInfo = getImsServiceInfoFromCache(mCarrierServices[i]);
                if (carrierImsInfo == null) {
                    // No Carrier override, add all features for this slot
                    imsFeaturesBySlot.addAll(info.getSupportedFeatures().stream()
                            .filter(feature -> currSlotId == feature.slotId)
                            .collect(Collectors.toList()));
                } else {
                    // Add all features to the device service that are not currently covered by
                    // the carrier ImsService.
                    HashSet<ImsFeatureConfiguration.FeatureSlotPair> deviceFeatures =
                            new HashSet<>(info.getSupportedFeatures());
                    deviceFeatures.removeAll(carrierImsInfo.getSupportedFeatures());
                    // only add features for current slot
                    imsFeaturesBySlot.addAll(deviceFeatures.stream()
                            .filter(feature -> currSlotId == feature.slotId).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());
        handleFeaturesChanged(controller.getComponentName(), config.getServiceFeatures());
    }

    /**
     * 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(
            HashSet<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 if currently installed ImsServices were changed or if
    // the SIM card has changed.
    // Called from the handler ONLY
    private void maybeRebindService(int slotId, String newPackageName) {
        if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            // not specified, replace package on all slots.
            for (int i = 0; i < mNumSlots; i++) {
                updateBoundCarrierServices(i, newPackageName);
            }
        } else {
            updateBoundCarrierServices(slotId, newPackageName);
        }

    }

    private void carrierConfigChanged(int slotId) {
        int subId = mSubscriptionManagerProxy.getSubId(slotId);
        PersistableBundle config = mCarrierConfigManager.getConfigForSubId(subId);
        if (config != null) {
            String newPackageName = config.getString(
                    CarrierConfigManager.KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING, null);
            maybeRebindService(slotId, newPackageName);
        } else {
            Log.w(TAG, "carrierConfigChanged: CarrierConfig is null!");
        }
    }

    private void updateBoundCarrierServices(int slotId, String newPackageName) {
        if (slotId > SubscriptionManager.INVALID_SIM_SLOT_INDEX && slotId < mNumSlots) {
            String oldPackageName = mCarrierServices[slotId];
            mCarrierServices[slotId] = newPackageName;
            if (!TextUtils.equals(newPackageName, oldPackageName)) {
                Log.i(TAG, "Carrier Config updated, binding new ImsService");
                // Unbind old ImsService, not needed anymore
                // ImsService is retrieved from the cache. If the cache hasn't been populated yet,
                // the calls to unbind/bind will fail (intended during initial start up).
                unbindImsService(getImsServiceInfoFromCache(oldPackageName));
                ImsServiceInfo newInfo = getImsServiceInfoFromCache(newPackageName);
                // if there is no carrier ImsService, newInfo is null. This we still want to update
                // bindings for device ImsService to pick up the missing features.
                if (newInfo == null || newInfo.featureFromMetadata) {
                    bindImsService(newInfo);
                    // Recalculate the device ImsService features to reflect changes.
                    updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
                } else {
                    // ImsServiceInfo that has not had features queried yet. Start async
                    // bind and query features.
                    scheduleQueryForFeatures(newInfo);
                }
            }
        }
    }

    /**
     * Schedules a query for dynamic ImsService features.
     */
    private void scheduleQueryForFeatures(ImsServiceInfo service, int delayMs) {
        // if not current device/carrier service, don't perform query. If this changes, this method
        // will be called again.
        if (!isDeviceService(service) && getSlotForActiveCarrierService(service)
                == SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
            Log.i(TAG, "scheduleQueryForFeatures: skipping query for ImsService that is not"
                    + " set as carrier/device ImsService.");
            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();
    }

    // Starts a dynamic query. Called from handler ONLY.
    private void startDynamicQuery(ImsServiceInfo service) {
        boolean queryStarted = mFeatureQueryManager.startQuery(service.name,
                service.controllerFactory.getServiceInterface());
        if (!queryStarted) {
            Log.w(TAG, "startDynamicQuery: service could not connect. Retrying after delay.");
            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, "handleFeaturesChanged: Couldn't find cached info for name: "
                    + name);
            return;
        }
        // Add features to service
        service.replaceFeatures(features);
        if (isActiveCarrierService(service)) {
            // New ImsService is registered to active carrier services and must be newly
            // bound.
            bindImsService(service);
            // Update existing device service features
            updateImsServiceFeatures(getImsServiceInfoFromCache(mDeviceService));
        } else if (isDeviceService(service)) {
            // New ImsService is registered as device default and must be newly bound.
            bindImsService(service);
        }
    }

    /**
     * @return true if the ImsResolver is in the process of resolving a dynamic query and should not
     * be considered available, false if the ImsResolver is idle.
     */
    public boolean isResolvingBinding() {
        return mHandler.hasMessages(HANDLER_START_DYNAMIC_FEATURE_QUERY)
                // We haven't processed this message yet, so it is still resolving.
                || mHandler.hasMessages(HANDLER_DYNAMIC_FEATURE_CHANGE)
                || mFeatureQueryManager.isQueryInProgress();
    }

    private 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(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<>();
        if (!mIsDynamicBinding) {
            // always return the same ImsService info.
            infos.addAll(getStaticImsService());
        } else {
            // 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> getStaticImsService() {
        List<ImsServiceInfo> infos = new ArrayList<>();

        ImsServiceInfo info = new ImsServiceInfo(mNumSlots);
        info.name = mStaticComponent;
        info.controllerFactory = mImsServiceControllerFactoryStaticBindingCompat;
        info.addFeatureForAllSlots(ImsFeature.FEATURE_EMERGENCY_MMTEL);
        info.addFeatureForAllSlots(ImsFeature.FEATURE_MMTEL);
        infos.add(info);
        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,
                mContext.getUserId())) {
            ServiceInfo serviceInfo = entry.serviceInfo;

            if (serviceInfo != null) {
                ImsServiceInfo info = new ImsServiceInfo(mNumSlots);
                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_EMERGENCY_MMTEL_FEATURE,
                                false)) {
                            info.addFeatureForAllSlots(ImsFeature.FEATURE_EMERGENCY_MMTEL);
                        }
                        if (serviceInfo.metaData.getBoolean(METADATA_MMTEL_FEATURE, false)) {
                            info.addFeatureForAllSlots(ImsFeature.FEATURE_MMTEL);
                        }
                        if (serviceInfo.metaData.getBoolean(METADATA_RCS_FEATURE, false)) {
                            info.addFeatureForAllSlots(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.
                if (TextUtils.equals(serviceInfo.permission,
                        Manifest.permission.BIND_IMS_SERVICE)) {
                    infos.add(info);
                } else {
                    Log.w(TAG, "ImsService is not protected with BIND_IMS_SERVICE permission: "
                            + info.name);
                }
            }
        }
        return infos;
    }
}
