/*
 * 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.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
import android.os.UserHandle;
import android.permission.PermissionManager;
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.LocalLog;
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 com.android.internal.telephony.util.TelephonyUtils;

import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.stream.Collectors;

/**
 * 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;
                try {
                    mLocalLog.log("onServiceConnected");
                    Log.d(LOG_TAG, "ImsService(" + name + "): onServiceConnected with binder: "
                            + service);
                    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();
                    mLocalLog.log("onConnected exception=" + e.getMessage() + ", retry in "
                            + mBackoff.getCurrentDelay() + " mS");
                    Log.e(LOG_TAG, "ImsService(" + name + ") RemoteException:"
                            + e.getMessage());
                }
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            synchronized (mLock) {
                mIsBinding = false;
            }
            cleanupConnection();
            mLocalLog.log("onServiceDisconnected");
            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;
            }
            if (mImsServiceConnection != null) {
                // according to the docs, we should fully unbind before rebinding again.
                mContext.unbindService(mImsServiceConnection);
            }
            cleanupConnection();
            Log.w(LOG_TAG, "ImsService(" + name + "): onBindingDied. Starting rebind...");
            startDelayedRebindToService();
            mLocalLog.log("onBindingDied, retrying in " + mBackoff.getCurrentDelay() + " mS");
        }

        @Override
        public void onNullBinding(ComponentName name) {
            Log.w(LOG_TAG, "ImsService(" + name + "): onNullBinding. Removing.");
            mLocalLog.log("onNullBinding");
            synchronized (mLock) {
                mIsBinding = false;
                mIsBound = false;
            }
            cleanupConnection();
            if (mCallbacks != null) {
                // Will trigger an unbind.
                mCallbacks.imsServiceBindPermanentError(getComponentName());
            }
        }

        // Does not clear features, just removes all active features.
        private void cleanupConnection() {
            cleanupAllFeatures();
            cleanUpService();
        }
    }

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

        /**
         * Called by the ImsServiceController when there has been an error binding that is
         * not recoverable, such as the ImsService returning a null binder.
         */
        void imsServiceBindPermanentError(ComponentName name);
    }

    /**
     * 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 static final long CHANGE_PERMISSION_TIMEOUT_MS = 15 * 1000; // 15 seconds
    private final ComponentName mComponentName;
    private final HandlerThread mHandlerThread = new HandlerThread("ImsServiceControllerHandler");
    private final PermissionManager mPermissionManager;
    private ImsServiceControllerCallbacks mCallbacks;
    private ExponentialBackoff mBackoff;

    private boolean mIsBound = false;
    private boolean mIsBinding = false;
    // Set of a pair of slotId->feature
    private Set<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<>();
    private final LocalLog mLocalLog = new LocalLog(10);

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

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

    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="
                        + ImsFeature.FEATURE_LOG_MAP.get(mFeatureType) + ", status="
                        + ImsFeature.STATE_LOG_MAP.get(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);
        mPermissionManager =
                (PermissionManager) mContext.getSystemService(Context.PERMISSION_SERVICE);
    }

    @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);
        mPermissionManager = 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(Set<ImsFeatureConfiguration.FeatureSlotPair> imsFeatureSet) {
        synchronized (mLock) {
            if (!mIsBound && !mIsBinding) {
                mIsBinding = true;
                sanitizeFeatureConfig(imsFeatureSet);
                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;
                mLocalLog.log("binding " + imsFeatureSet);
                Log.i(LOG_TAG, "Binding ImsService:" + mComponentName);
                try {
                    boolean bindSucceeded = mContext.bindService(imsServiceIntent,
                            mImsServiceConnection, serviceFlags);
                    if (!bindSucceeded) {
                        mLocalLog.log("    binding failed, retrying in "
                                + mBackoff.getCurrentDelay() + " mS");
                        mIsBinding = false;
                        mBackoff.notifyFailed();
                    }
                    return bindSucceeded;
                } catch (Exception e) {
                    mBackoff.notifyFailed();
                    mLocalLog.log("    binding exception=" + e.getMessage() + ", retrying in "
                            + mBackoff.getCurrentDelay() + " mS");
                    Log.e(LOG_TAG, "Error binding (" + mComponentName + ") with exception: "
                            + e.getMessage() + ", rebinding in " + mBackoff.getCurrentDelay()
                            + " ms");
                    return false;
                }
            } else {
                return false;
            }
        }
    }

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

    /**
     * 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);
            mLocalLog.log("unbinding");
            mContext.unbindService(mImsServiceConnection);
            mIsBound = false;
            mIsBinding = false;
            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(
            Set<ImsFeatureConfiguration.FeatureSlotPair> newImsFeatures)
            throws RemoteException {
        sanitizeFeatureConfig(newImsFeatures);
        synchronized (mLock) {
            if (mImsFeatures.equals(newImsFeatures)) {
                return;
            }
            mLocalLog.log("Features changed (" + mImsFeatures + "->" + newImsFeatures + ")");
            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. PermissionManager ensures that the ImsService is
    // system/signed before granting permissions.
    private void grantPermissionsToService() {
        mLocalLog.log("grant permissions to " + getComponentName());
        Log.i(LOG_TAG, "Granting Runtime permissions to:" + getComponentName());
        String[] pkgToGrant = {mComponentName.getPackageName()};
        try {
            if (mPermissionManager != null) {
                CountDownLatch latch = new CountDownLatch(1);
                mPermissionManager.grantDefaultPermissionsToEnabledImsServices(
                        pkgToGrant, UserHandle.of(UserHandle.myUserId()), Runnable::run,
                        isSuccess -> {
                            if (isSuccess) {
                                latch.countDown();
                            } else {
                                Log.e(LOG_TAG, "Failed to grant permissions to service.");
                            }
                        });
                TelephonyUtils.waitUntilReady(latch, CHANGE_PERMISSION_TIMEOUT_MS);
            }
        } catch (RuntimeException 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);
        } else {
            // Don't update ImsService for emergency MMTEL feature.
            Log.i(LOG_TAG, "supports emergency calling on slot " + featurePair.slotId);
        }
        // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
        mCallbacks.imsServiceFeatureCreated(featurePair.slotId, featurePair.featureType, this);
        // 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;
        }
        // Signal ImsResolver to change supported ImsFeatures for this ImsServiceController
        mCallbacks.imsServiceFeatureRemoved(featurePair.slotId, featurePair.featureType, this);
        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);
            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 {"
                        + ImsFeature.FEATURE_LOG_MAP.get(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);
        }
    }

    @Override
    public String toString() {
        synchronized (mLock) {
            return "[ImsServiceController: componentName=" + getComponentName() + ", features="
                    + mImsFeatures + ", isBinding=" + mIsBinding + ", isBound=" + mIsBound
                    + ", serviceController=" + getImsServiceController() + ", rebindDelay="
                    + getRebindDelay() + "]";
        }
    }

    public void dump(PrintWriter printWriter) {
        mLocalLog.dump(printWriter);
    }
}
