/*
 * 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.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.IPackageManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.ServiceManager;
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.aidl.IImsServiceController;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.util.Log;

import com.android.ims.internal.IImsFeatureStatusCallback;
import com.android.ims.internal.IImsServiceFeatureCallback;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.ExponentialBackoff;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Manages the Binding lifecycle of one ImsService as well as the relevant ImsFeatures that the
 * ImsService will support.
 *
 * When the ImsService is first bound, {@link ImsService#createMmTelFeature(int)} and
 * {@link ImsService#createRcsFeature(int)} will be called
 * on each feature that the service supports. For each ImsFeature that is created,
 * {@link ImsServiceControllerCallbacks#imsServiceFeatureCreated} will be called to notify the
 * listener that the ImsService now supports that feature.
 *
 * When {@link #changeImsServiceFeatures} is called with a set of features that is different from
 * the original set, create*Feature and {@link IImsServiceController#removeImsFeature} will be
 * called for each feature that is created/removed.
 */
public class ImsServiceController {

    class ImsServiceConnection implements ServiceConnection {

        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mBackoff.stop();
            synchronized (mLock) {
                mIsBound = true;
                mIsBinding = false;
                Log.d(LOG_TAG, "ImsService(" + name + "): onServiceConnected with binder: "
                        + service);
                if (service != null) {
                    try {
                        setServiceController(service);
                        notifyImsServiceReady();
                        // create all associated features in the ImsService
                        for (ImsFeatureConfiguration.FeatureSlotPair i : mImsFeatures) {
                            addImsServiceFeature(i);
                        }
                    } catch (RemoteException e) {
                        mIsBound = false;
                        mIsBinding = false;
                        // Remote exception means that the binder already died.
                        cleanupConnection();
                        startDelayedRebindToService();
                        Log.e(LOG_TAG, "ImsService(" + name + ") RemoteException:"
                                + e.getMessage());
                    }
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            synchronized (mLock) {
                mIsBinding = false;
            }
            cleanupConnection();
            Log.w(LOG_TAG, "ImsService(" + name + "): onServiceDisconnected. Waiting...");
            // Service disconnected, but we are still technically bound. Waiting for reconnect.
        }

        @Override
        public void onBindingDied(ComponentName name) {
            synchronized (mLock) {
                mIsBinding = false;
                mIsBound = false;
            }
            cleanupConnection();
            Log.w(LOG_TAG, "ImsService(" + name + "): onBindingDied. Starting rebind...");
            startDelayedRebindToService();
        }

        private void cleanupConnection() {
            cleanupAllFeatures();
            cleanUpService();
        }
    }

    private ImsService.Listener mFeatureChangedListener = new ImsService.Listener() {
        @Override
        public void onUpdateSupportedImsFeatures(ImsFeatureConfiguration c) {
            if (mCallbacks == null) {
                return;
            }
            mCallbacks.imsServiceFeaturesChanged(c, ImsServiceController.this);
        }
    };

    /**
     * Defines callbacks that are used by the ImsServiceController to notify when an ImsService
     * has created or removed a new feature as well as the associated ImsServiceController.
     */
    public interface ImsServiceControllerCallbacks {
        /**
         * Called by ImsServiceController when a new MMTEL or RCS feature has been created.
         */
        void imsServiceFeatureCreated(int slotId, int feature, ImsServiceController controller);
        /**
         * Called by ImsServiceController when a new MMTEL or RCS feature has been removed.
         */
        void imsServiceFeatureRemoved(int slotId, int feature, ImsServiceController controller);

        /**
         * Called by the ImsServiceController when the ImsService has notified the framework that
         * its features have changed.
         */
        void imsServiceFeaturesChanged(ImsFeatureConfiguration config,
                ImsServiceController controller);
    }

    /**
     * Returns the currently defined rebind retry timeout. Used for testing.
     */
    @VisibleForTesting
    public interface RebindRetry {
        /**
         * Returns a long in ms indicating how long the ImsServiceController should wait before
         * rebinding for the first time.
         */
        long getStartDelay();

        /**
         * Returns a long in ms indicating the maximum time the ImsServiceController should wait
         * before rebinding.
         */
        long getMaximumDelay();
    }

    private static final String LOG_TAG = "ImsServiceController";
    private static final int REBIND_START_DELAY_MS = 2 * 1000; // 2 seconds
    private static final int REBIND_MAXIMUM_DELAY_MS = 60 * 1000; // 1 minute
    private final ComponentName mComponentName;
    private final HandlerThread mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
    private final IPackageManager mPackageManager;
    private ImsServiceControllerCallbacks mCallbacks;
    private ExponentialBackoff mBackoff;

    private boolean mIsBound = false;
    private boolean mIsBinding = false;
    // Set of a pair of slotId->feature
    private HashSet<ImsFeatureConfiguration.FeatureSlotPair> mImsFeatures;
    // Binder interfaces to the features set in mImsFeatures;
    private HashSet<ImsFeatureContainer> mImsFeatureBinders = new HashSet<>();
    private IImsServiceController mIImsServiceController;
    private ImsServiceConnection mImsServiceConnection;
    private Set<IImsServiceFeatureCallback> mImsStatusCallbacks = ConcurrentHashMap.newKeySet();
    // Only added or removed, never accessed on purpose.
    private Set<ImsFeatureStatusCallback> mFeatureStatusCallbacks = new HashSet<>();

    protected final Object mLock = new Object();
    protected final Context mContext;

    private class ImsFeatureContainer {
        public int slotId;
        public int featureType;
        private IInterface mBinder;

        ImsFeatureContainer(int slotId, int featureType, IInterface binder) {
            this.slotId = slotId;
            this.featureType = featureType;
            this.mBinder = binder;
        }

        // Casts the IInterface into the binder class we are looking for.
        public <T extends IInterface> T resolve(Class<T> className) {
            return className.cast(mBinder);
        }

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

            ImsFeatureContainer that = (ImsFeatureContainer) o;

            if (slotId != that.slotId) return false;
            if (featureType != that.featureType) return false;
            return mBinder != null ? mBinder.equals(that.mBinder) : that.mBinder == null;
        }

        @Override
        public int hashCode() {
            int result = slotId;
            result = 31 * result + featureType;
            result = 31 * result + (mBinder != null ? mBinder.hashCode() : 0);
            return result;
        }
    }

    /**
     * Container class for the IImsFeatureStatusCallback callback implementation. This class is
     * never used directly, but we need to keep track of the IImsFeatureStatusCallback
     * implementations explicitly.
     */
    private class ImsFeatureStatusCallback {
        private int mSlotId;
        private int mFeatureType;

        private final IImsFeatureStatusCallback mCallback = new IImsFeatureStatusCallback.Stub() {

            @Override
            public void notifyImsFeatureStatus(int featureStatus) throws RemoteException {
                Log.i(LOG_TAG, "notifyImsFeatureStatus: slot=" + mSlotId + ", feature="
                        + mFeatureType + ", status=" + featureStatus);
                sendImsFeatureStatusChanged(mSlotId, mFeatureType, featureStatus);
            }
        };

        ImsFeatureStatusCallback(int slotId, int featureType) {
            mSlotId = slotId;
            mFeatureType = featureType;
        }

        public IImsFeatureStatusCallback getCallback() {
            return mCallback;
        }
    }

    // Retry the bind to the ImsService that has died after mRebindRetry timeout.
    private Runnable mRestartImsServiceRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (mLock) {
                if (mIsBound) {
                    return;
                }
                bind(mImsFeatures);
            }
        }
    };

    private RebindRetry mRebindRetry = new RebindRetry() {
        @Override
        public long getStartDelay() {
            return REBIND_START_DELAY_MS;
        }

        @Override
        public long getMaximumDelay() {
            return REBIND_MAXIMUM_DELAY_MS;
        }
    };

    public ImsServiceController(Context context, ComponentName componentName,
            ImsServiceControllerCallbacks callbacks) {
        mContext = context;
        mComponentName = componentName;
        mCallbacks = callbacks;
        mHandlerThread.start();
        mBackoff = new ExponentialBackoff(
                mRebindRetry.getStartDelay(),
                mRebindRetry.getMaximumDelay(),
                2, /* multiplier */
                mHandlerThread.getLooper(),
                mRestartImsServiceRunnable);
        mPackageManager = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    }

    @VisibleForTesting
    // Creating a new HandlerThread and background handler for each test causes a segfault, so for
    // testing, use a handler supplied by the testing system.
    public ImsServiceController(Context context, ComponentName componentName,
            ImsServiceControllerCallbacks callbacks, Handler handler, RebindRetry rebindRetry) {
        mContext = context;
        mComponentName = componentName;
        mCallbacks = callbacks;
        mBackoff = new ExponentialBackoff(
                rebindRetry.getStartDelay(),
                rebindRetry.getMaximumDelay(),
                2, /* multiplier */
                handler,
                mRestartImsServiceRunnable);
        mPackageManager = null;
    }

    /**
     * Sends request to bind to ImsService designated by the {@link ComponentName} with the feature
     * set imsFeatureSet.
     *
     * @param imsFeatureSet a Set of Pairs that designate the slotId->featureId that need to be
     *                      created once the service is bound.
     * @return {@link true} if the service is in the process of being bound, {@link false} if it
     * has failed.
     */
    public boolean bind(HashSet<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet) {
        synchronized (mLock) {
            if (!mIsBound && !mIsBinding) {
                mIsBinding = true;
                mImsFeatures = imsFeatureSet;
                grantPermissionsToService();
                Intent imsServiceIntent = new Intent(getServiceInterface()).setComponent(
                        mComponentName);
                mImsServiceConnection = new ImsServiceConnection();
                int serviceFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_IMPORTANT;
                Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
                try {
                    boolean bindSucceeded = startBindToService(imsServiceIntent,
                            mImsServiceConnection, serviceFlags);
                    if (!bindSucceeded) {
                        mIsBinding = false;
                        mBackoff.notifyFailed();
                    }
                    return bindSucceeded;
                } catch (Exception e) {
                    mBackoff.notifyFailed();
                    Log.e(LOG_TAG, "Error binding (" + mComponentName + ") with exception: "
                            + e.getMessage() + ", rebinding in " + mBackoff.getCurrentDelay()
                            + " ms");
                    return false;
                }
            } else {
                return false;
            }
        }
    }

    /**
     * Starts the bind to the ImsService. Overridden by subclasses that need to access the service
     * in a different fashion.
     */
    protected boolean startBindToService(Intent intent, ImsServiceConnection connection,
            int flags) {
        return mContext.bindService(intent, connection, flags);
    }

    /**
     * Calls {@link IImsServiceController#removeImsFeature} on all features that the
     * ImsService supports and then unbinds the service.
     */
    public void unbind() throws RemoteException {
        synchronized (mLock) {
            mBackoff.stop();
            if (mImsServiceConnection == null) {
                return;
            }
            // Clean up all features
            changeImsServiceFeatures(new HashSet<>());
            removeImsServiceFeatureCallbacks();
            Log.i(LOG_TAG, "Unbinding ImsService: " + mComponentName);
            mContext.unbindService(mImsServiceConnection);
            cleanUpService();
        }
    }

    /**
     * For every feature that is added, the service calls the associated create. For every
     * ImsFeature that is removed, {@link IImsServiceController#removeImsFeature} is called.
     */
    public void changeImsServiceFeatures(
            HashSet<ImsFeatureConfiguration.FeatureSlotPair> newImsFeatures)
            throws RemoteException {
        synchronized (mLock) {
            Log.i(LOG_TAG, "Features changed (" + mImsFeatures + "->" + newImsFeatures + ") for "
                    + "ImsService: " + mComponentName);
            HashSet<ImsFeatureConfiguration.FeatureSlotPair> oldImsFeatures =
                    new HashSet<>(mImsFeatures);
            // Set features first in case we lose binding and need to rebind later.
            mImsFeatures = newImsFeatures;
            if (mIsBound) {
                // add features to service.
                HashSet<ImsFeatureConfiguration.FeatureSlotPair> newFeatures =
                        new HashSet<>(mImsFeatures);
                newFeatures.removeAll(oldImsFeatures);
                for (ImsFeatureConfiguration.FeatureSlotPair i : newFeatures) {
                    addImsServiceFeature(i);
                }
                // remove old features
                HashSet<ImsFeatureConfiguration.FeatureSlotPair> oldFeatures =
                        new HashSet<>(oldImsFeatures);
                oldFeatures.removeAll(mImsFeatures);
                for (ImsFeatureConfiguration.FeatureSlotPair i : oldFeatures) {
                    removeImsServiceFeature(i);
                }
            }
        }
    }

    @VisibleForTesting
    public IImsServiceController getImsServiceController() {
        return mIImsServiceController;
    }

    @VisibleForTesting
    public long getRebindDelay() {
        return mBackoff.getCurrentDelay();
    }

    @VisibleForTesting
    public void stopBackoffTimerForTesting() {
        mBackoff.stop();
    }

    public ComponentName getComponentName() {
        return mComponentName;
    }

    /**
     * Add a callback to ImsManager that signals a new feature that the ImsServiceProxy can handle.
     */
    public void addImsServiceFeatureCallback(IImsServiceFeatureCallback callback) {
        mImsStatusCallbacks.add(callback);
        synchronized (mLock) {
            if (mImsFeatures == null || mImsFeatures.isEmpty()) {
                return;
            }
            // notify the new status callback of the features that are available.
            try {
                for (ImsFeatureConfiguration.FeatureSlotPair i : mImsFeatures) {
                    callback.imsFeatureCreated(i.slotId, i.featureType);
                }
            } catch (RemoteException e) {
                Log.w(LOG_TAG, "addImsServiceFeatureCallback: exception notifying callback");
            }
        }
    }

    public void enableIms(int slotId) {
        try {
            synchronized (mLock) {
                if (isServiceControllerAvailable()) {
                    mIImsServiceController.enableIms(slotId);
                }
            }
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Couldn't enable IMS: " + e.getMessage());
        }
    }

    public void disableIms(int slotId) {
        try {
            synchronized (mLock) {
                if (isServiceControllerAvailable()) {
                    mIImsServiceController.disableIms(slotId);
                }
            }
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Couldn't disable IMS: " + e.getMessage());
        }
    }

    /**
     * Return the {@Link MMTelFeature} binder on the slot associated with the slotId.
     * Used for normal calling.
     */
    public IImsMmTelFeature getMmTelFeature(int slotId) {
        synchronized (mLock) {
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.FEATURE_MMTEL);
            if (f == null) {
                Log.w(LOG_TAG, "Requested null MMTelFeature on slot " + slotId);
                return null;
            }
            return f.resolve(IImsMmTelFeature.class);
        }
    }

    /**
     * Return the {@Link RcsFeature} binder on the slot associated with the slotId.
     */
    public IImsRcsFeature getRcsFeature(int slotId) {
        synchronized (mLock) {
            ImsFeatureContainer f = getImsFeatureContainer(slotId, ImsFeature.FEATURE_RCS);
            if (f == null) {
                Log.w(LOG_TAG, "Requested null RcsFeature on slot " + slotId);
                return null;
            }
            return f.resolve(IImsRcsFeature.class);
        }
    }

    /**
     * @return the IImsRegistration that corresponds to the slot id specified.
     */
    public IImsRegistration getRegistration(int slotId) throws RemoteException {
        synchronized (mLock) {
            return isServiceControllerAvailable()
                    ? mIImsServiceController.getRegistration(slotId) : null;
        }
    }

    /**
     * @return the IImsConfig that corresponds to the slot id specified.
     */
    public IImsConfig getConfig(int slotId) throws RemoteException {
        synchronized (mLock) {
            return isServiceControllerAvailable() ? mIImsServiceController.getConfig(slotId) : null;
        }
    }

    /**
     * notify the ImsService that the ImsService is ready for feature creation.
     */
    protected void notifyImsServiceReady() throws RemoteException {
        synchronized (mLock) {
            if (isServiceControllerAvailable()) {
                Log.d(LOG_TAG, "notifyImsServiceReady");
                mIImsServiceController.setListener(mFeatureChangedListener);
                mIImsServiceController.notifyImsServiceReadyForFeatureCreation();
            }
        }
    }

    protected String getServiceInterface() {
        return ImsService.SERVICE_INTERFACE;
    }

    /**
     * Sets the IImsServiceController instance. Overridden by compat layers to set compatibility
     * versions of this service controller.
     */
    protected void setServiceController(IBinder serviceController) {
        mIImsServiceController = IImsServiceController.Stub.asInterface(serviceController);
    }

    /**
     * @return true if the controller is currently bound.
     */
    public boolean isBound() {
        synchronized (mLock) {
            return mIsBound;
        }
    }

    /**
     * Check to see if the service controller is available, overridden for compat versions,
     * @return true if available, false otherwise;
     */
    protected boolean isServiceControllerAvailable() {
        return mIImsServiceController != null;
    }

    @VisibleForTesting
    public void removeImsServiceFeatureCallbacks() {
            mImsStatusCallbacks.clear();
    }

    // Only add a new rebind if there are no pending rebinds waiting.
    private void startDelayedRebindToService() {
        mBackoff.start();
    }

    // Grant runtime permissions to ImsService. PackageManager ensures that the ImsService is
    // system/signed before granting permissions.
    private void grantPermissionsToService() {
        Log.i(LOG_TAG, "Granting Runtime permissions to:" + getComponentName());
        String[] pkgToGrant = {mComponentName.getPackageName()};
        try {
            if (mPackageManager != null) {
                mPackageManager.grantDefaultPermissionsToEnabledImsServices(pkgToGrant,
                        mContext.getUserId());
            }
        } catch (RemoteException e) {
            Log.w(LOG_TAG, "Unable to grant permissions, binder died.");
        }
    }

    private void sendImsFeatureCreatedCallback(int slot, int feature) {
        for (Iterator<IImsServiceFeatureCallback> i = mImsStatusCallbacks.iterator();
                i.hasNext(); ) {
            IImsServiceFeatureCallback callbacks = i.next();
            try {
                callbacks.imsFeatureCreated(slot, feature);
            } catch (RemoteException e) {
                // binder died, remove callback.
                Log.w(LOG_TAG, "sendImsFeatureCreatedCallback: Binder died, removing "
                        + "callback. Exception:" + e.getMessage());
                i.remove();
            }
        }
    }

    private void sendImsFeatureRemovedCallback(int slot, int feature) {
        for (Iterator<IImsServiceFeatureCallback> i = mImsStatusCallbacks.iterator();
                i.hasNext(); ) {
            IImsServiceFeatureCallback callbacks = i.next();
            try {
                callbacks.imsFeatureRemoved(slot, feature);
            } catch (RemoteException e) {
                // binder died, remove callback.
                Log.w(LOG_TAG, "sendImsFeatureRemovedCallback: Binder died, removing "
                        + "callback. Exception:" + e.getMessage());
                i.remove();
            }
        }
    }

    private void sendImsFeatureStatusChanged(int slot, int feature, int status) {
        for (Iterator<IImsServiceFeatureCallback> i = mImsStatusCallbacks.iterator();
                i.hasNext(); ) {
            IImsServiceFeatureCallback callbacks = i.next();
            try {
                callbacks.imsStatusChanged(slot, feature, status);
            } catch (RemoteException e) {
                // binder died, remove callback.
                Log.w(LOG_TAG, "sendImsFeatureStatusChanged: Binder died, removing "
                        + "callback. Exception:" + e.getMessage());
                i.remove();
            }
        }
    }

    // This method should only be called when synchronized on mLock
    private void addImsServiceFeature(ImsFeatureConfiguration.FeatureSlotPair featurePair)
            throws RemoteException {
        if (!isServiceControllerAvailable() || mCallbacks == null) {
            Log.w(LOG_TAG, "addImsServiceFeature called with null values.");
            return;
        }
        if (featurePair.featureType != ImsFeature.FEATURE_EMERGENCY_MMTEL) {
            ImsFeatureStatusCallback c = new ImsFeatureStatusCallback(featurePair.slotId,
                    featurePair.featureType);
            mFeatureStatusCallbacks.add(c);
            IInterface f = createImsFeature(featurePair.slotId, featurePair.featureType,
                    c.getCallback());
            addImsFeatureBinder(featurePair.slotId, featurePair.featureType, f);
            // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
            mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
        } else {
            // Don't update ImsService for emergency MMTEL feature.
            Log.i(LOG_TAG, "supports emergency calling on slot " + featurePair.slotId);
        }
        // Send callback to ImsServiceProxy to change supported ImsFeatures including emergency
        // MMTEL state.
        sendImsFeatureCreatedCallback(featurePair.slotId, featurePair.featureType);
    }

    // This method should only be called when synchronized on mLock
    private void removeImsServiceFeature(ImsFeatureConfiguration.FeatureSlotPair featurePair) {
        if (!isServiceControllerAvailable() || mCallbacks == null) {
            Log.w(LOG_TAG, "removeImsServiceFeature called with null values.");
            return;
        }
        if (featurePair.featureType != ImsFeature.FEATURE_EMERGENCY_MMTEL) {
            ImsFeatureStatusCallback callbackToRemove = mFeatureStatusCallbacks.stream().filter(c ->
                    c.mSlotId == featurePair.slotId && c.mFeatureType == featurePair.featureType)
                    .findFirst().orElse(null);
            // Remove status callbacks from list.
            if (callbackToRemove != null) {
                mFeatureStatusCallbacks.remove(callbackToRemove);
            }
            removeImsFeatureBinder(featurePair.slotId, featurePair.featureType);
            // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
            mCallbacks.imsServiceFeatureRemoved(featurePair.slotId, featurePair.featureType, this);
            try {
                removeImsFeature(featurePair.slotId, featurePair.featureType,
                        (callbackToRemove != null ? callbackToRemove.getCallback() : null));
            } catch (RemoteException e) {
                // The connection to this ImsService doesn't exist. This may happen if the service
                // has died and we are removing features.
                Log.i(LOG_TAG, "Couldn't remove feature {" + featurePair.featureType
                        + "}, connection is down: " + e.getMessage());
            }
        } else {
            // Don't update ImsService for emergency MMTEL feature.
            Log.i(LOG_TAG, "doesn't support emergency calling on slot " + featurePair.slotId);
        }
        // Send callback to ImsServiceProxy to change supported ImsFeatures
        // Ensure that ImsServiceProxy callback occurs after ImsResolver callback. If an
        // ImsManager requests the ImsService while it is being removed in ImsResolver, this
        // callback will clean it up after.
        sendImsFeatureRemovedCallback(featurePair.slotId, featurePair.featureType);
    }

    // This method should only be called when already synchronized on mLock.
    // overridden by compat layer to create features
    protected IInterface createImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        switch (featureType) {
            case ImsFeature.FEATURE_MMTEL: {
                return mIImsServiceController.createMmTelFeature(slotId, c);
            }
            case ImsFeature.FEATURE_RCS: {
                return mIImsServiceController.createRcsFeature(slotId, c);
            }
            default:
                return null;
        }
    }

    // overridden by compat layer to remove features
    protected void removeImsFeature(int slotId, int featureType, IImsFeatureStatusCallback c)
            throws RemoteException {
        mIImsServiceController.removeImsFeature(slotId, featureType, c);
    }

    // This method should only be called when synchronized on mLock
    private void addImsFeatureBinder(int slotId, int featureType, IInterface b) {
        mImsFeatureBinders.add(new ImsFeatureContainer(slotId, featureType, b));
    }

    // This method should only be called when synchronized on mLock
    private void removeImsFeatureBinder(int slotId, int featureType) {
        ImsFeatureContainer container = mImsFeatureBinders.stream()
                .filter(f-> (f.slotId == slotId && f.featureType == featureType))
                .findFirst().orElse(null);
        if (container != null) {
            mImsFeatureBinders.remove(container);
        }
    }

    private ImsFeatureContainer getImsFeatureContainer(int slotId, int featureType) {
        return mImsFeatureBinders.stream()
                .filter(f-> (f.slotId == slotId && f.featureType == featureType))
                .findFirst().orElse(null);
    }

    private void cleanupAllFeatures() {
        synchronized (mLock) {
            // Remove all features and clean up all associated Binders.
            for (ImsFeatureConfiguration.FeatureSlotPair i : mImsFeatures) {
                removeImsServiceFeature(i);
            }
            // remove all MmTelFeatureConnection callbacks, since we have already sent removed
            // callback.
            removeImsServiceFeatureCallbacks();
        }
    }

    private void cleanUpService() {
        synchronized (mLock) {
            mImsServiceConnection = null;
            setServiceController(null);
        }
    }
}
