/*
 * Copyright (C) 2014 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.services.telephony;

import android.content.Context;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.telecom.Connection;
import android.telecom.Connection.VideoProvider;
import android.telecom.DisconnectCause;
import android.telecom.PhoneAccountHandle;
import android.telecom.StatusHints;
import android.telecom.TelecomManager;
import android.telecom.VideoProfile;
import android.telephony.CarrierConfigManager;
import android.telephony.PhoneNumberUtils;
import android.util.Pair;

import com.android.ims.internal.ConferenceParticipant;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.phone.PhoneGlobals;
import com.android.phone.PhoneUtils;
import com.android.phone.R;
import com.android.telephony.Rlog;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Represents an IMS conference call.
 * <p>
 * An IMS conference call consists of a conference host connection and potentially a list of
 * conference participants.  The conference host connection represents the radio connection to the
 * IMS conference server.  Since it is not a connection to any one individual, it is not represented
 * in Telecom/InCall as a call.  The conference participant information is received via the host
 * connection via a conference event package.  Conference participant connections do not represent
 * actual radio connections to the participants; they act as a virtual representation of the
 * participant, keyed by a unique endpoint {@link android.net.Uri}.
 * <p>
 * The {@link ImsConference} listens for conference event package data received via the host
 * connection and is responsible for managing the conference participant connections which represent
 * the participants.
 */
public class ImsConference extends TelephonyConferenceBase implements Holdable {

    private static final String LOG_TAG = "ImsConference";

    /**
     * Abstracts out fetching a feature flag.  Makes testing easier.
     */
    public interface FeatureFlagProxy {
        boolean isUsingSinglePartyCallEmulation();
    }

    /**
     * Listener used to respond to changes to the underlying radio connection for the conference
     * host connection.  Used to respond to SRVCC changes.
     */
    private final TelephonyConnection.TelephonyConnectionListener mTelephonyConnectionListener =
            new TelephonyConnection.TelephonyConnectionListener() {

                /**
                 * Updates the state of the conference based on the new state of the host.
                 *
                 * @param c The host connection.
                 * @param state The new state
                 */
                @Override
                public void onStateChanged(android.telecom.Connection c, int state) {
                    setState(state);
                }

                /**
                 * Disconnects the conference when its host connection disconnects.
                 *
                 * @param c The host connection.
                 * @param disconnectCause The host connection disconnect cause.
                 */
                @Override
                public void onDisconnected(android.telecom.Connection c,
                        DisconnectCause disconnectCause) {
                    setDisconnected(disconnectCause);
                }

                @Override
                public void onVideoStateChanged(android.telecom.Connection c, int videoState) {
                    Log.d(this, "onVideoStateChanged video state %d", videoState);
                    setVideoState(c, videoState);
                }

                @Override
                public void onVideoProviderChanged(android.telecom.Connection c,
                        Connection.VideoProvider videoProvider) {
                    Log.d(this, "onVideoProviderChanged: Connection: %s, VideoProvider: %s", c,
                            videoProvider);
                    setVideoProvider(c, videoProvider);
                }

                @Override
                public void onConnectionCapabilitiesChanged(Connection c,
                        int connectionCapabilities) {
                    Log.d(this, "onConnectionCapabilitiesChanged: Connection: %s,"
                            + " connectionCapabilities: %s", c, connectionCapabilities);
                    int capabilites = ImsConference.this.getConnectionCapabilities();
                    boolean isVideoConferencingSupported = mConferenceHost == null ? false :
                            mConferenceHost.isCarrierVideoConferencingSupported();
                    setConnectionCapabilities(
                            applyHostCapabilities(capabilites, connectionCapabilities,
                                    isVideoConferencingSupported));
                }

                @Override
                public void onConnectionPropertiesChanged(Connection c, int connectionProperties) {
                    Log.d(this, "onConnectionPropertiesChanged: Connection: %s,"
                            + " connectionProperties: %s", c, connectionProperties);
                    int properties = ImsConference.this.getConnectionProperties();
                    setConnectionProperties(applyHostProperties(properties, connectionProperties));
                }

                @Override
                public void onStatusHintsChanged(Connection c, StatusHints statusHints) {
                    Log.v(this, "onStatusHintsChanged");
                    updateStatusHints();
                }

                @Override
                public void onExtrasChanged(Connection c, Bundle extras) {
                    Log.v(this, "onExtrasChanged: c=" + c + " Extras=" + extras);
                    putExtras(extras);
                }

                @Override
                public void onExtrasRemoved(Connection c, List<String> keys) {
                    Log.v(this, "onExtrasRemoved: c=" + c + " key=" + keys);
                    removeExtras(keys);
                }

                @Override
                public void onConnectionEvent(Connection c, String event, Bundle extras) {
                    if (Connection.EVENT_MERGE_START.equals(event)) {
                        // Do not pass a merge start event on the underlying host connection; only
                        // indicate a merge has started on the connections which are merged into a
                        // conference.
                        return;
                    }

                    sendConferenceEvent(event, extras);
                }

                @Override
                public void onOriginalConnectionConfigured(TelephonyConnection c) {
                    if (c == mConferenceHost) {
                        handleOriginalConnectionChange();
                    }
                }

                /**
                 * Handles changes to conference participant data as reported by the conference host
                 * connection.
                 *
                 * @param c The connection.
                 * @param participants The participant information.
                 */
                @Override
                public void onConferenceParticipantsChanged(android.telecom.Connection c,
                        List<ConferenceParticipant> participants) {

                    if (c == null || participants == null) {
                        return;
                    }
                    Log.v(this, "onConferenceParticipantsChanged: %d participants",
                            participants.size());
                    TelephonyConnection telephonyConnection = (TelephonyConnection) c;
                    handleConferenceParticipantsUpdate(telephonyConnection, participants);
                }

                /**
                 * Handles request to play a ringback tone.
                 *
                 * @param c The connection.
                 * @param ringback Whether the ringback tone is to be played.
                 */
                @Override
                public void onRingbackRequested(android.telecom.Connection c, boolean ringback) {
                    Log.d(this, "onRingbackRequested ringback %s", ringback ? "Y" : "N");
                    setRingbackRequested(ringback);
                }
            };

    /**
     * The telephony connection service; used to add new participant connections to Telecom.
     */
    private TelephonyConnectionServiceProxy mTelephonyConnectionService;

    /**
     * The connection to the conference server which is hosting the conference.
     */
    private TelephonyConnection mConferenceHost;

    /**
     * The PhoneAccountHandle of the conference host.
     */
    private PhoneAccountHandle mConferenceHostPhoneAccountHandle;

    /**
     * The address of the conference host.
     */
    private Uri[] mConferenceHostAddress;

    private TelecomAccountRegistry mTelecomAccountRegistry;

    /**
     * The participant with which Adhoc Conference call is getting formed.
     */
    private List<Uri> mParticipants;

    /**
     * The known conference participant connections.  The HashMap is keyed by a Pair containing
     * the handle and endpoint Uris.
     * Access to the hashmap is protected by the {@link #mUpdateSyncRoot}.
     */
    private final HashMap<Pair<Uri, Uri>, ConferenceParticipantConnection>
            mConferenceParticipantConnections = new HashMap<>();

    /**
     * Sychronization root used to ensure that updates to the
     * {@link #mConferenceParticipantConnections} happen atomically are are not interleaved across
     * threads.  There are some instances where the network will send conference event package
     * data closely spaced.  If that happens, it is possible that the interleaving of the update
     * will cause duplicate participant info to be added.
     */
    private final Object mUpdateSyncRoot = new Object();

    private boolean mIsHoldable;
    private boolean mCouldManageConference;
    private FeatureFlagProxy mFeatureFlagProxy;
    private boolean mIsEmulatingSinglePartyCall = false;
    private boolean mIsUsingSimCallManager = false;

    /**
     * Where {@link #mIsEmulatingSinglePartyCall} is {@code true}, contains the
     * {@link ConferenceParticipantConnection#getUserEntity()} and
     * {@link ConferenceParticipantConnection#getEndpoint()} of the single participant which this
     * conference pretends to be.
     */
    private Pair<Uri, Uri> mLoneParticipantIdentity = null;

    /**
     * The {@link ConferenceParticipantConnection#getUserEntity()} and
     * {@link ConferenceParticipantConnection#getEndpoint()} of the conference host as they appear
     * in the CEP.  This is determined when we scan the first conference event package.
     * It is possible that this will be {@code null} for carriers which do not include the host
     * in the CEP.
     */
    private Pair<Uri, Uri> mHostParticipantIdentity = null;

    public void updateConferenceParticipantsAfterCreation() {
        if (mConferenceHost != null) {
            Log.v(this, "updateConferenceStateAfterCreation :: process participant update");
            handleConferenceParticipantsUpdate(mConferenceHost,
                    mConferenceHost.getConferenceParticipants());
        } else {
            Log.v(this, "updateConferenceStateAfterCreation :: null mConferenceHost");
        }
    }

    /**
     * Initializes a new {@link ImsConference}.
     *  @param telephonyConnectionService The connection service responsible for adding new
     *                                   conferene participants.
     * @param conferenceHost The telephony connection hosting the conference.
     * @param phoneAccountHandle The phone account handle associated with the conference.
     * @param featureFlagProxy
     */
    public ImsConference(TelecomAccountRegistry telecomAccountRegistry,
            TelephonyConnectionServiceProxy telephonyConnectionService,
            TelephonyConnection conferenceHost, PhoneAccountHandle phoneAccountHandle,
            FeatureFlagProxy featureFlagProxy) {

        super(phoneAccountHandle);

        mTelecomAccountRegistry = telecomAccountRegistry;
        mFeatureFlagProxy = featureFlagProxy;

        // Specify the connection time of the conference to be the connection time of the original
        // connection.
        long connectTime = conferenceHost.getOriginalConnection().getConnectTime();
        long connectElapsedTime = conferenceHost.getOriginalConnection().getConnectTimeReal();
        setConnectionTime(connectTime);
        setConnectionStartElapsedRealtimeMillis(connectElapsedTime);
        // Set the connectTime in the connection as well.
        conferenceHost.setConnectTimeMillis(connectTime);
        conferenceHost.setConnectionStartElapsedRealtimeMillis(connectElapsedTime);

        mTelephonyConnectionService = telephonyConnectionService;
        setConferenceHost(conferenceHost);

        int capabilities = Connection.CAPABILITY_MUTE |
                Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
        if (canHoldImsCalls()) {
            capabilities |= Connection.CAPABILITY_SUPPORT_HOLD | Connection.CAPABILITY_HOLD;
            mIsHoldable = true;
        }
        capabilities = applyHostCapabilities(capabilities,
                mConferenceHost.getConnectionCapabilities(),
                mConferenceHost.isCarrierVideoConferencingSupported());
        setConnectionCapabilities(capabilities);

    }

    /**
     * Transfers capabilities from the conference host to the conference itself.
     *
     * @param conferenceCapabilities The current conference capabilities.
     * @param capabilities The new conference host capabilities.
     * @param isVideoConferencingSupported Whether video conferencing is supported.
     * @return The merged capabilities to be applied to the conference.
     */
    private int applyHostCapabilities(int conferenceCapabilities, int capabilities,
            boolean isVideoConferencingSupported) {

        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                    Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL,
                (capabilities & Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) != 0);

        if (isVideoConferencingSupported) {
            conferenceCapabilities = changeBitmask(conferenceCapabilities,
                    Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL,
                    (capabilities & Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) != 0);
            conferenceCapabilities = changeBitmask(conferenceCapabilities,
                    Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO,
                    (capabilities & Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO) != 0);
        } else {
            // If video conferencing is not supported, explicitly turn off the remote video
            // capability and the ability to upgrade to video.
            Log.v(this, "applyHostCapabilities : video conferencing not supported");
            conferenceCapabilities = changeBitmask(conferenceCapabilities,
                    Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL, false);
            conferenceCapabilities = changeBitmask(conferenceCapabilities,
                    Connection.CAPABILITY_CAN_UPGRADE_TO_VIDEO, false);
        }

        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO,
                (capabilities & Connection.CAPABILITY_CANNOT_DOWNGRADE_VIDEO_TO_AUDIO) != 0);

        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                Connection.CAPABILITY_CAN_PAUSE_VIDEO,
                mConferenceHost.getVideoPauseSupported() && isVideoCapable());

        conferenceCapabilities = changeBitmask(conferenceCapabilities,
                Connection.CAPABILITY_ADD_PARTICIPANT,
                (capabilities & Connection.CAPABILITY_ADD_PARTICIPANT) != 0);

        return conferenceCapabilities;
    }

    /**
     * Transfers properties from the conference host to the conference itself.
     *
     * @param conferenceProperties The current conference properties.
     * @param properties The new conference host properties.
     * @return The merged properties to be applied to the conference.
     */
    private int applyHostProperties(int conferenceProperties, int properties) {
        conferenceProperties = changeBitmask(conferenceProperties,
                Connection.PROPERTY_HIGH_DEF_AUDIO,
                (properties & Connection.PROPERTY_HIGH_DEF_AUDIO) != 0);

        conferenceProperties = changeBitmask(conferenceProperties,
                Connection.PROPERTY_WIFI,
                (properties & Connection.PROPERTY_WIFI) != 0);

        conferenceProperties = changeBitmask(conferenceProperties,
                Connection.PROPERTY_IS_EXTERNAL_CALL,
                (properties & Connection.PROPERTY_IS_EXTERNAL_CALL) != 0);

        conferenceProperties = changeBitmask(conferenceProperties,
                Connection.PROPERTY_REMOTELY_HOSTED, !isConferenceHost());

        conferenceProperties = changeBitmask(conferenceProperties,
                Connection.PROPERTY_IS_ADHOC_CONFERENCE,
                (properties & Connection.PROPERTY_IS_ADHOC_CONFERENCE) != 0);

        return conferenceProperties;
    }

    /**
     * Not used by the IMS conference controller.
     *
     * @return {@code Null}.
     */
    @Override
    public android.telecom.Connection getPrimaryConnection() {
        return null;
    }

    /**
     * Returns VideoProvider of the conference. This can be null.
     *
     * @hide
     */
    @Override
    public VideoProvider getVideoProvider() {
        if (mConferenceHost != null) {
            return mConferenceHost.getVideoProvider();
        }
        return null;
    }

    /**
     * Returns video state of conference
     *
     * @hide
     */
    @Override
    public int getVideoState() {
        if (mConferenceHost != null) {
            return mConferenceHost.getVideoState();
        }
        return VideoProfile.STATE_AUDIO_ONLY;
    }

    public Connection getConferenceHost() {
        return mConferenceHost;
    }

    /**
     * @return The address's to which this Connection is currently communicating.
     */
    public final List<Uri> getParticipants() {
        return mParticipants;
    }

    /**
     * Sets the value of the {@link #getParticipants()}.
     *
     * @param address The new address's.
     */
    public final void setParticipants(List<Uri> address) {
        mParticipants = address;
    }

    /**
     * Invoked when the Conference and all its {@link Connection}s should be disconnected.
     * <p>
     * Hangs up the call via the conference host connection.  When the host connection has been
     * successfully disconnected, the {@link #mTelephonyConnectionListener} listener receives an
     * {@code onDestroyed} event, which triggers the conference participant connections to be
     * disconnected.
     */
    @Override
    public void onDisconnect() {
        Log.v(this, "onDisconnect: hanging up conference host.");
        if (mConferenceHost == null) {
            return;
        }

        disconnectConferenceParticipants();

        Call call = mConferenceHost.getCall();
        if (call != null) {
            try {
                call.hangup();
            } catch (CallStateException e) {
                Log.e(this, e, "Exception thrown trying to hangup conference");
            }
        }
    }

    /**
     * Invoked when the specified {@link android.telecom.Connection} should be separated from the
     * conference call.
     * <p>
     * IMS does not support separating connections from the conference.
     *
     * @param connection The connection to separate.
     */
    @Override
    public void onSeparate(android.telecom.Connection connection) {
        Log.wtf(this, "Cannot separate connections from an IMS conference.");
    }

    /**
     * Invoked when the specified {@link android.telecom.Connection} should be merged into the
     * conference call.
     *
     * @param connection The {@code Connection} to merge.
     */
    @Override
    public void onMerge(android.telecom.Connection connection) {
        try {
            Phone phone = mConferenceHost.getPhone();
            if (phone != null) {
                phone.conference();
            }
        } catch (CallStateException e) {
            Log.e(this, e, "Exception thrown trying to merge call into a conference");
        }
    }

    /**
     * Supports adding participants to an existing conference call
     *
     * @param participants that are pulled to existing conference call
     */
    @Override
    public void onAddConferenceParticipants(List<Uri> participants) {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.performAddConferenceParticipants(participants);
    }

    /**
     * Invoked when the conference is answered.
     */
    @Override
    public void onAnswer(int videoState) {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.performAnswer(videoState);
    }

    /**
     * Invoked when the conference is rejected.
     */
    @Override
    public void onReject() {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.performReject(android.telecom.Call.REJECT_REASON_DECLINED);
    }

    /**
     * Invoked when the conference should be put on hold.
     */
    @Override
    public void onHold() {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.performHold();
    }

    /**
     * Invoked when the conference should be moved from hold to active.
     */
    @Override
    public void onUnhold() {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.performUnhold();
    }

    /**
     * Invoked to play a DTMF tone.
     *
     * @param c A DTMF character.
     */
    @Override
    public void onPlayDtmfTone(char c) {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.onPlayDtmfTone(c);
    }

    /**
     * Invoked to stop playing a DTMF tone.
     */
    @Override
    public void onStopDtmfTone() {
        if (mConferenceHost == null) {
            return;
        }
        mConferenceHost.onStopDtmfTone();
    }

    /**
     * Handles the addition of connections to the {@link ImsConference}.  The
     * {@link ImsConferenceController} does not add connections to the conference.
     *
     * @param connection The newly added connection.
     */
    @Override
    public void onConnectionAdded(android.telecom.Connection connection) {
        // No-op
        Log.d(this, "connection added: " + connection
                + ", time: " + connection.getConnectTimeMillis());
    }

    @Override
    public void setHoldable(boolean isHoldable) {
        mIsHoldable = isHoldable;
        if (!mIsHoldable) {
            removeCapability(Connection.CAPABILITY_HOLD);
        } else {
            addCapability(Connection.CAPABILITY_HOLD);
        }
    }

    @Override
    public boolean isChildHoldable() {
        // The conference should not be a child of other conference.
        return false;
    }

    /**
     * Changes a bit-mask to add or remove a bit-field.
     *
     * @param bitmask The bit-mask.
     * @param bitfield The bit-field to change.
     * @param enabled Whether the bit-field should be set or removed.
     * @return The bit-mask with the bit-field changed.
     */
    private int changeBitmask(int bitmask, int bitfield, boolean enabled) {
        if (enabled) {
            return bitmask | bitfield;
        } else {
            return bitmask & ~bitfield;
        }
    }

    /**
     * Determines if this conference is hosted on the current device or the peer device.
     *
     * @return {@code true} if this conference is hosted on the current device, {@code false} if it
     *      is hosted on the peer device.
     */
    public boolean isConferenceHost() {
        if (mConferenceHost == null) {
            return false;
        }
        com.android.internal.telephony.Connection originalConnection =
                mConferenceHost.getOriginalConnection();

        return originalConnection != null && originalConnection.isMultiparty() &&
                originalConnection.isConferenceHost();
    }

    /**
     * Updates the manage conference capability of the conference.
     *
     * The following cases are handled:
     * <ul>
     *     <li>There is only a single participant in the conference -- manage conference is
     *     disabled.</li>
     *     <li>There is more than one participant in the conference -- manage conference is
     *     enabled.</li>
     *     <li>No conference event package data is available -- manage conference is disabled.</li>
     * </ul>
     * <p>
     * Note: We add and remove {@link Connection#CAPABILITY_CONFERENCE_HAS_NO_CHILDREN} to ensure
     * that the conference is represented appropriately on Bluetooth devices.
     */
    private void updateManageConference() {
        boolean couldManageConference =
                (getConnectionCapabilities() & Connection.CAPABILITY_MANAGE_CONFERENCE) != 0;
        boolean canManageConference = mFeatureFlagProxy.isUsingSinglePartyCallEmulation()
                && mIsEmulatingSinglePartyCall
                ? mConferenceParticipantConnections.size() > 1
                : mConferenceParticipantConnections.size() != 0;
        Log.v(this, "updateManageConference was :%s is:%s", couldManageConference ? "Y" : "N",
                canManageConference ? "Y" : "N");

        if (couldManageConference != canManageConference) {
            int capabilities = getConnectionCapabilities();

            if (canManageConference) {
                capabilities |= Connection.CAPABILITY_MANAGE_CONFERENCE;
                capabilities &= ~Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
            } else {
                capabilities &= ~Connection.CAPABILITY_MANAGE_CONFERENCE;
                capabilities |= Connection.CAPABILITY_CONFERENCE_HAS_NO_CHILDREN;
            }

            setConnectionCapabilities(capabilities);
        }
    }

    /**
     * Sets the connection hosting the conference and registers for callbacks.
     *
     * @param conferenceHost The connection hosting the conference.
     */
    private void setConferenceHost(TelephonyConnection conferenceHost) {
        if (Log.VERBOSE) {
            Log.v(this, "setConferenceHost " + conferenceHost);
        }

        mConferenceHost = conferenceHost;

        // Attempt to get the conference host's address (e.g. the host's own phone number).
        // We need to look at the default phone for the ImsPhone when creating the phone account
        // for the
        if (mConferenceHost.getPhone() != null &&
                mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            // Look up the conference host's address; we need this later for filtering out the
            // conference host in conference event package data.
            Phone imsPhone = mConferenceHost.getPhone();
            mConferenceHostPhoneAccountHandle =
                    PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
            Uri hostAddress = mTelecomAccountRegistry.getAddress(mConferenceHostPhoneAccountHandle);

            ArrayList<Uri> hostAddresses = new ArrayList<>();

            // add address from TelecomAccountRegistry
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }

            // add addresses from phone
            if (imsPhone.getCurrentSubscriberUris() != null) {
                hostAddresses.addAll(
                        new ArrayList<>(Arrays.asList(imsPhone.getCurrentSubscriberUris())));
            }

            mConferenceHostAddress = new Uri[hostAddresses.size()];
            mConferenceHostAddress = hostAddresses.toArray(mConferenceHostAddress);

            mIsUsingSimCallManager = mTelecomAccountRegistry.isUsingSimCallManager(
                    mConferenceHostPhoneAccountHandle);
        }

        // If the conference is not hosted on this device copy over the address and presentation and
        // connect times so that we can log this appropriately in the call log.
        if (!isConferenceHost()) {
            setAddress(mConferenceHost.getAddress(), mConferenceHost.getAddressPresentation());
            setCallerDisplayName(mConferenceHost.getCallerDisplayName(),
                    mConferenceHost.getCallerDisplayNamePresentation());
            setConnectionStartElapsedRealtimeMillis(
                    mConferenceHost.getConnectionStartElapsedRealtimeMillis());
            setConnectionTime(mConferenceHost.getConnectTimeMillis());
        }

        mConferenceHost.addTelephonyConnectionListener(mTelephonyConnectionListener);
        setConnectionCapabilities(applyHostCapabilities(getConnectionCapabilities(),
                mConferenceHost.getConnectionCapabilities(),
                mConferenceHost.isCarrierVideoConferencingSupported()));
        setConnectionProperties(applyHostProperties(getConnectionProperties(),
                mConferenceHost.getConnectionProperties()));

        setState(mConferenceHost.getState());
        updateStatusHints();
        putExtras(mConferenceHost.getExtras());
    }

    /**
     * Handles state changes for conference participant(s).  The participants data passed in
     *
     * @param parent The connection which was notified of the conference participant.
     * @param participants The conference participant information.
     */
    @VisibleForTesting
    public void handleConferenceParticipantsUpdate(
            TelephonyConnection parent, List<ConferenceParticipant> participants) {

        if (participants == null) {
            return;
        }

        if (parent != null && !parent.isManageImsConferenceCallSupported()) {
            Log.i(this, "handleConferenceParticipantsUpdate: manage conference is disallowed");
            return;
        }

        Log.i(this, "handleConferenceParticipantsUpdate: size=%d", participants.size());

        // Perform the update in a synchronized manner.  It is possible for the IMS framework to
        // trigger two onConferenceParticipantsChanged callbacks in quick succession.  If the first
        // update adds new participants, and the second does something like update the status of one
        // of the participants, we can get into a situation where the participant is added twice.
        synchronized (mUpdateSyncRoot) {
            int oldParticipantCount = mConferenceParticipantConnections.size();
            boolean newParticipantsAdded = false;
            boolean oldParticipantsRemoved = false;
            ArrayList<ConferenceParticipant> newParticipants = new ArrayList<>(participants.size());
            HashSet<Pair<Uri,Uri>> participantUserEntities = new HashSet<>(participants.size());

            // Determine if the conference event package represents a single party conference.
            // A single party conference is one where there is no other participant other than the
            // conference host and one other participant.
            // We purposely exclude participants which have a disconnected state in the conference
            // event package; some carriers are known to keep a disconnected participant around in
            // subsequent CEP updates with a state of disconnected, even though its no longer part
            // of the conference.
            // Note: We consider 0 to still be a single party conference since some carriers will
            // send a conference event package with JUST the host in it when the conference is
            // disconnected.  We don't want to change back to conference mode prior to disconnection
            // or we will not log the call.
            boolean isSinglePartyConference = participants.stream()
                    .filter(p -> {
                        Pair<Uri, Uri> pIdent = new Pair<>(p.getHandle(), p.getEndpoint());
                        return !Objects.equals(mHostParticipantIdentity, pIdent)
                                && p.getState() != Connection.STATE_DISCONNECTED;
                    })
                    .count() <= 1;

            // We will only process the CEP data if:
            // 1. We're not emulating a single party call.
            // 2. We're emulating a single party call and the CEP contains more than just the
            //    single party
            if ((mIsEmulatingSinglePartyCall && !isSinglePartyConference) ||
                !mIsEmulatingSinglePartyCall) {
                // Add any new participants and update existing.
                for (ConferenceParticipant participant : participants) {
                    Pair<Uri, Uri> userEntity = new Pair<>(participant.getHandle(),
                            participant.getEndpoint());

                    // We will exclude disconnected participants from the hash set of tracked
                    // participants.  Some carriers are known to leave disconnected participants in
                    // the conference event package data which would cause them to be present in the
                    // conference even though they're disconnected.  Removing them from the hash set
                    // here means we'll clean them up below.
                    if (participant.getState() != Connection.STATE_DISCONNECTED) {
                        participantUserEntities.add(userEntity);
                    }
                    if (!mConferenceParticipantConnections.containsKey(userEntity)) {
                        // Some carriers will also include the conference host in the CEP.  We will
                        // filter that out here.
                        if (!isParticipantHost(mConferenceHostAddress, participant.getHandle())) {
                            createConferenceParticipantConnection(parent, participant);
                            newParticipants.add(participant);
                            newParticipantsAdded = true;
                        } else {
                            // Track the identity of the conference host; its useful to know when
                            // we look at the CEP in the future.
                            mHostParticipantIdentity = userEntity;
                        }
                    } else {
                        ConferenceParticipantConnection connection =
                                mConferenceParticipantConnections.get(userEntity);
                        Log.i(this,
                                "handleConferenceParticipantsUpdate: updateState, participant = %s",
                                participant);
                        connection.updateState(participant.getState());
                        if (participant.getState() == Connection.STATE_DISCONNECTED) {
                            /**
                             * Per {@link ConferenceParticipantConnection#updateState(int)}, we will
                             * destroy the connection when its disconnected.
                             */
                            handleConnectionDestruction(connection);
                        }
                        connection.setVideoState(parent.getVideoState());
                    }
                }

                // Set state of new participants.
                if (newParticipantsAdded) {
                    // Set the state of the new participants at once and add to the conference
                    for (ConferenceParticipant newParticipant : newParticipants) {
                        ConferenceParticipantConnection connection =
                                mConferenceParticipantConnections.get(new Pair<>(
                                        newParticipant.getHandle(),
                                        newParticipant.getEndpoint()));
                        connection.updateState(newParticipant.getState());
                        /**
                         * Per {@link ConferenceParticipantConnection#updateState(int)}, we will
                         * destroy the connection when its disconnected.
                         */
                        if (newParticipant.getState() == Connection.STATE_DISCONNECTED) {
                            handleConnectionDestruction(connection);
                        }
                        connection.setVideoState(parent.getVideoState());
                    }
                }

                // Finally, remove any participants from the conference that no longer exist in the
                // conference event package data.
                Iterator<Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection>> entryIterator =
                        mConferenceParticipantConnections.entrySet().iterator();
                while (entryIterator.hasNext()) {
                    Map.Entry<Pair<Uri, Uri>, ConferenceParticipantConnection> entry =
                            entryIterator.next();

                    if (!participantUserEntities.contains(entry.getKey())) {
                        ConferenceParticipantConnection participant = entry.getValue();
                        participant.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
                        removeTelephonyConnection(participant);
                        participant.destroy();
                        entryIterator.remove();
                        oldParticipantsRemoved = true;
                    }
                }
            }

            int newParticipantCount = mConferenceParticipantConnections.size();
            Log.v(this, "handleConferenceParticipantsUpdate: oldParticipantCount=%d, "
                            + "newParticipantcount=%d", oldParticipantCount, newParticipantCount);
            // If the single party call emulation fature flag is enabled, we can potentially treat
            // the conference as a single party call when there is just one participant.
            if (mFeatureFlagProxy.isUsingSinglePartyCallEmulation() &&
                    !mConferenceHost.isAdhocConferenceCall()) {
                if (oldParticipantCount != 1 && newParticipantCount == 1) {
                    // If number of participants goes to 1, emulate a single party call.
                    startEmulatingSinglePartyCall();
                } else if (mIsEmulatingSinglePartyCall && !isSinglePartyConference) {
                    // Number of participants increased, so stop emulating a single party call.
                    stopEmulatingSinglePartyCall();
                }
            }

            // If new participants were added or old ones were removed, we need to ensure the state
            // of the manage conference capability is updated.
            if (newParticipantsAdded || oldParticipantsRemoved) {
                updateManageConference();
            }
        }
    }

    /**
     * Called after {@link #startEmulatingSinglePartyCall()} to cause the conference to appear as
     * if it is a conference again.
     * 1. Tell telecom we're a conference again.
     * 2. Restore {@link Connection#CAPABILITY_MANAGE_CONFERENCE} capability.
     * 3. Null out the name/address.
     *
     * Note: Single party call emulation is disabled if the conference is taking place via a
     * sim call manager.  Emulating a single party call requires properties of the conference to be
     * changed (connect time, address, conference state) which cannot be guaranteed to be relayed
     * correctly by the sim call manager to Telecom.
     */
    private void stopEmulatingSinglePartyCall() {
        if (mIsUsingSimCallManager) {
            Log.i(this, "stopEmulatingSinglePartyCall: using sim call manager; skip.");
            return;
        }

        Log.i(this, "stopEmulatingSinglePartyCall: conference now has more than one"
                + " participant; make it look conference-like again.");
        mIsEmulatingSinglePartyCall = false;

        if (mCouldManageConference) {
            int currentCapabilities = getConnectionCapabilities();
            currentCapabilities |= Connection.CAPABILITY_MANAGE_CONFERENCE;
            setConnectionCapabilities(currentCapabilities);
        }

        // Null out the address/name so it doesn't look like a single party call
        setAddress(null, TelecomManager.PRESENTATION_UNKNOWN);
        setCallerDisplayName(null, TelecomManager.PRESENTATION_UNKNOWN);

        // Copy the conference connect time back to the previous lone participant.
        ConferenceParticipantConnection loneParticipant =
                mConferenceParticipantConnections.get(mLoneParticipantIdentity);
        if (loneParticipant != null) {
            Log.d(this,
                    "stopEmulatingSinglePartyCall: restored lone participant connect time");
            loneParticipant.setConnectTimeMillis(getConnectionTime());
            loneParticipant.setConnectionStartElapsedRealtimeMillis(
                    getConnectionStartElapsedRealtimeMillis());
        }

        // Tell Telecom its a conference again.
        setConferenceState(true);
    }

    /**
     * Called when a conference drops to a single participant. Causes this conference to present
     * itself to Telecom as if it was a single party call.
     * 1. Remove the participant from Telecom and from local tracking; when we get a new CEP in
     *    the future we'll just re-add the participant anyways.
     * 2. Tell telecom we're not a conference.
     * 3. Remove {@link Connection#CAPABILITY_MANAGE_CONFERENCE} capability.
     * 4. Set the name/address to that of the single participant.
     *
     * Note: Single party call emulation is disabled if the conference is taking place via a
     * sim call manager.  Emulating a single party call requires properties of the conference to be
     * changed (connect time, address, conference state) which cannot be guaranteed to be relayed
     * correctly by the sim call manager to Telecom.
     */
    private void startEmulatingSinglePartyCall() {
        if (mIsUsingSimCallManager) {
            Log.i(this, "startEmulatingSinglePartyCall: using sim call manager; skip.");
            return;
        }

        Log.i(this, "startEmulatingSinglePartyCall: conference has a single "
                + "participant; downgrade to single party call.");

        mIsEmulatingSinglePartyCall = true;
        Iterator<ConferenceParticipantConnection> valueIterator =
                mConferenceParticipantConnections.values().iterator();
        if (valueIterator.hasNext()) {
            ConferenceParticipantConnection entry = valueIterator.next();

            // Set the conference name/number to that of the remaining participant.
            setAddress(entry.getAddress(), entry.getAddressPresentation());
            setCallerDisplayName(entry.getCallerDisplayName(),
                    entry.getCallerDisplayNamePresentation());
            setConnectionStartElapsedRealtimeMillis(
                    entry.getConnectionStartElapsedRealtimeMillis());
            setConnectionTime(entry.getConnectTimeMillis());
            mLoneParticipantIdentity = new Pair<>(entry.getUserEntity(), entry.getEndpoint());

            // Remove the participant from Telecom.  It'll get picked up in a future CEP update
            // again anyways.
            entry.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED,
                    DisconnectCause.REASON_EMULATING_SINGLE_CALL));
            removeTelephonyConnection(entry);
            entry.destroy();
            valueIterator.remove();
        }

        // Have Telecom pretend its not a conference.
        setConferenceState(false);

        // Remove manage conference capability.
        mCouldManageConference =
                (getConnectionCapabilities() & Connection.CAPABILITY_MANAGE_CONFERENCE) != 0;
        int currentCapabilities = getConnectionCapabilities();
        currentCapabilities &= ~Connection.CAPABILITY_MANAGE_CONFERENCE;
        setConnectionCapabilities(currentCapabilities);
    }

    /**
     * Creates a new {@link ConferenceParticipantConnection} to represent a
     * {@link ConferenceParticipant}.
     * <p>
     * The new connection is added to the conference controller and connection service.
     *
     * @param parent The connection which was notified of the participant change (e.g. the
     *                         parent connection).
     * @param participant The conference participant information.
     */
    private void createConferenceParticipantConnection(
            TelephonyConnection parent, ConferenceParticipant participant) {

        // Create and add the new connection in holding state so that it does not become the
        // active call.
        ConferenceParticipantConnection connection = new ConferenceParticipantConnection(
                parent.getOriginalConnection(), participant,
                !isConferenceHost() /* isRemotelyHosted */);
        if (participant.getConnectTime() == 0) {
            connection.setConnectTimeMillis(parent.getConnectTimeMillis());
            connection.setConnectionStartElapsedRealtimeMillis(
                    parent.getConnectionStartElapsedRealtimeMillis());
        } else {
            connection.setConnectTimeMillis(participant.getConnectTime());
            connection.setConnectionStartElapsedRealtimeMillis(participant.getConnectElapsedTime());
        }
        // Indicate whether this is an MT or MO call to Telecom; the participant has the cached
        // data from the time of merge.
        connection.setCallDirection(participant.getCallDirection());

        Log.i(this, "createConferenceParticipantConnection: participant=%s, connection=%s",
                participant, connection);

        synchronized(mUpdateSyncRoot) {
            mConferenceParticipantConnections.put(new Pair<>(participant.getHandle(),
                    participant.getEndpoint()), connection);
        }

        mTelephonyConnectionService.addExistingConnection(mConferenceHostPhoneAccountHandle,
                connection, this);
        addTelephonyConnection(connection);
    }

    /**
     * Removes a conference participant from the conference.
     *
     * @param participant The participant to remove.
     */
    private void removeConferenceParticipant(ConferenceParticipantConnection participant) {
        Log.i(this, "removeConferenceParticipant: %s", participant);

        synchronized(mUpdateSyncRoot) {
            mConferenceParticipantConnections.remove(new Pair<>(participant.getUserEntity(),
                    participant.getEndpoint()));
        }
        participant.destroy();
    }

    /**
     * Disconnects all conference participants from the conference.
     */
    private void disconnectConferenceParticipants() {
        Log.v(this, "disconnectConferenceParticipants");

        synchronized(mUpdateSyncRoot) {
            for (ConferenceParticipantConnection connection :
                    mConferenceParticipantConnections.values()) {

                // Mark disconnect cause as cancelled to ensure that the call is not logged in the
                // call log.
                connection.setDisconnected(new DisconnectCause(DisconnectCause.CANCELED));
                connection.destroy();
            }
            mConferenceParticipantConnections.clear();
            updateManageConference();
        }
    }

    /**
     * Determines if the passed in participant handle is the same as the conference host's handle.
     * Starts with a simple equality check.  However, the handles from a conference event package
     * will be a SIP uri, so we need to pull that apart to look for the participant's phone number.
     *
     * @param hostHandles The handle(s) of the connection hosting the conference.
     * @param handle The handle of the conference participant.
     * @return {@code true} if the host's handle matches the participant's handle, {@code false}
     *      otherwise.
     */
    private boolean isParticipantHost(Uri[] hostHandles, Uri handle) {
        // If there is no host handle or no participant handle, bail early.
        if (hostHandles == null || hostHandles.length == 0 || handle == null) {
            Log.v(this, "isParticipantHost(N) : host or participant uri null");
            return false;
        }

        // Conference event package participants are identified using SIP URIs (see RFC3261).
        // A valid SIP uri has the format: sip:user:password@host:port;uri-parameters?headers
        // Per RFC3261, the "user" can be a telephone number.
        // For example: sip:1650555121;phone-context=blah.com@host.com
        // In this case, the phone number is in the user field of the URI, and the parameters can be
        // ignored.
        //
        // A SIP URI can also specify a phone number in a format similar to:
        // sip:+1-212-555-1212@something.com;user=phone
        // In this case, the phone number is again in user field and the parameters can be ignored.
        // We can get the user field in these instances by splitting the string on the @, ;, or :
        // and looking at the first found item.

        String number = handle.getSchemeSpecificPart();
        String numberParts[] = number.split("[@;:]");

        if (numberParts.length == 0) {
            Log.v(this, "isParticipantHost(N) : no number in participant handle");
            return false;
        }
        number = numberParts[0];

        for (Uri hostHandle : hostHandles) {
            if (hostHandle == null) {
                continue;
            }
            // The host number will be a tel: uri.  Per RFC3966, the part after tel: is the phone
            // number.
            String hostNumber = hostHandle.getSchemeSpecificPart();

            // Use a loose comparison of the phone numbers.  This ensures that numbers that differ
            // by special characters are counted as equal.
            // E.g. +16505551212 would be the same as 16505551212
            boolean isHost = PhoneNumberUtils.compare(hostNumber, number);

            Log.v(this, "isParticipantHost(%s) : host: %s, participant %s", (isHost ? "Y" : "N"),
                    Rlog.pii(LOG_TAG, hostNumber), Rlog.pii(LOG_TAG, number));

            if (isHost) {
                return true;
            }
        }
        return false;
    }

    /**
     * Handles a change in the original connection backing the conference host connection.  This can
     * happen if an SRVCC event occurs on the original IMS connection, requiring a fallback to
     * GSM or CDMA.
     * <p>
     * If this happens, we will add the conference host connection to telecom and tear down the
     * conference.
     */
    private void handleOriginalConnectionChange() {
        if (mConferenceHost == null) {
            Log.w(this, "handleOriginalConnectionChange; conference host missing.");
            return;
        }

        com.android.internal.telephony.Connection originalConnection =
                mConferenceHost.getOriginalConnection();

        if (originalConnection != null &&
                originalConnection.getPhoneType() != PhoneConstants.PHONE_TYPE_IMS) {
            Log.i(this,
                    "handleOriginalConnectionChange : handover from IMS connection to " +
                            "new connection: %s", originalConnection);

            PhoneAccountHandle phoneAccountHandle = null;
            if (mConferenceHost.getPhone() != null) {
                if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
                    Phone imsPhone = mConferenceHost.getPhone();
                    // The phone account handle for an ImsPhone is based on the default phone (ie
                    // the base GSM or CDMA phone, not on the ImsPhone itself).
                    phoneAccountHandle =
                            PhoneUtils.makePstnPhoneAccountHandle(imsPhone.getDefaultPhone());
                } else {
                    // In the case of SRVCC, we still need a phone account, so use the top level
                    // phone to create a phone account.
                    phoneAccountHandle = PhoneUtils.makePstnPhoneAccountHandle(
                            mConferenceHost.getPhone());
                }
            }

            if (mConferenceHost.getPhone().getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
                Log.i(this,"handleOriginalConnectionChange : SRVCC to GSM");
                GsmConnection c = new GsmConnection(originalConnection, getTelecomCallId(),
                        mConferenceHost.isOutgoingCall());
                // This is a newly created conference connection as a result of SRVCC
                c.setConferenceSupported(true);
                c.setTelephonyConnectionProperties(
                        c.getConnectionProperties() | Connection.PROPERTY_IS_DOWNGRADED_CONFERENCE);
                c.updateState();
                // Copy the connect time from the conferenceHost
                c.setConnectTimeMillis(mConferenceHost.getConnectTimeMillis());
                c.setConnectionStartElapsedRealtimeMillis(
                        mConferenceHost.getConnectionStartElapsedRealtimeMillis());
                mTelephonyConnectionService.addExistingConnection(phoneAccountHandle, c);
                mTelephonyConnectionService.addConnectionToConferenceController(c);
            } // CDMA case not applicable for SRVCC
            mConferenceHost.removeTelephonyConnectionListener(mTelephonyConnectionListener);
            mConferenceHost = null;
            setDisconnected(new DisconnectCause(DisconnectCause.OTHER));
            disconnectConferenceParticipants();
            destroyTelephonyConference();
        }

        updateStatusHints();
    }

    /**
     * Changes the state of the Ims conference.
     *
     * @param state the new state.
     */
    public void setState(int state) {
        Log.v(this, "setState %s", Connection.stateToString(state));

        switch (state) {
            case Connection.STATE_INITIALIZING:
            case Connection.STATE_NEW:
                // No-op -- not applicable.
                break;
            case Connection.STATE_RINGING:
                setConferenceOnRinging();
                break;
            case Connection.STATE_DIALING:
                setConferenceOnDialing();
                break;
            case Connection.STATE_DISCONNECTED:
                DisconnectCause disconnectCause;
                if (mConferenceHost == null) {
                    disconnectCause = new DisconnectCause(DisconnectCause.CANCELED);
                } else {
                    if (mConferenceHost.getPhone() != null) {
                        disconnectCause = DisconnectCauseUtil.toTelecomDisconnectCause(
                                mConferenceHost.getOriginalConnection().getDisconnectCause(),
                                null, mConferenceHost.getPhone().getPhoneId());
                    } else {
                        disconnectCause = DisconnectCauseUtil.toTelecomDisconnectCause(
                                mConferenceHost.getOriginalConnection().getDisconnectCause());
                    }
                }
                setDisconnected(disconnectCause);
                disconnectConferenceParticipants();
                destroyTelephonyConference();
                break;
            case Connection.STATE_ACTIVE:
                setConferenceOnActive();
                break;
            case Connection.STATE_HOLDING:
                setConferenceOnHold();
                break;
        }
    }

    /**
     * Determines if the host of this conference is capable of video calling.
     * @return {@code true} if video capable, {@code false} otherwise.
     */
    private boolean isVideoCapable() {
        int capabilities = mConferenceHost.getConnectionCapabilities();
        return (capabilities & Connection.CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL) != 0
                && (capabilities & Connection.CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL) != 0;
    }

    private void updateStatusHints() {
        if (mConferenceHost == null) {
            setStatusHints(null);
            return;
        }

        if (mConferenceHost.isWifi()) {
            Phone phone = mConferenceHost.getPhone();
            if (phone != null) {
                Context context = phone.getContext();
                setStatusHints(new StatusHints(
                        context.getString(R.string.status_hint_label_wifi_call),
                        Icon.createWithResource(
                                context, R.drawable.ic_signal_wifi_4_bar_24dp),
                        null /* extras */));
            }
        } else {
            setStatusHints(null);
        }
    }

    /**
     * Builds a string representation of the {@link ImsConference}.
     *
     * @return String representing the conference.
     */
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[ImsConference objId:");
        sb.append(System.identityHashCode(this));
        sb.append(" telecomCallID:");
        sb.append(getTelecomCallId());
        sb.append(" state:");
        sb.append(Connection.stateToString(getState()));
        sb.append(" hostConnection:");
        sb.append(mConferenceHost);
        sb.append(" participants:");
        sb.append(mConferenceParticipantConnections.size());
        sb.append("]");
        return sb.toString();
    }

    private boolean canHoldImsCalls() {
        PersistableBundle b = getCarrierConfig();
        // Return true if the CarrierConfig is unavailable
        return b == null || b.getBoolean(CarrierConfigManager.KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL);
    }

    private PersistableBundle getCarrierConfig() {
        if (mConferenceHost == null) {
            return null;
        }

        Phone phone = mConferenceHost.getPhone();
        if (phone == null) {
            return null;
        }
        return PhoneGlobals.getInstance().getCarrierConfigForSubId(phone.getSubId());
    }

    /**
     * @return {@code true} if the carrier associated with the conference requires that the maximum
     *      size of the conference is enforced, {@code false} otherwise.
     */
    public boolean isMaximumConferenceSizeEnforced() {
        PersistableBundle b = getCarrierConfig();
        // Return false if the CarrierConfig is unavailable
        return b != null && b.getBoolean(
                CarrierConfigManager.KEY_IS_IMS_CONFERENCE_SIZE_ENFORCED_BOOL);
    }

    /**
     * @return The maximum size of a conference call where
     * {@link #isMaximumConferenceSizeEnforced()} is true.
     */
    public int getMaximumConferenceSize() {
        PersistableBundle b = getCarrierConfig();

        // If there is no carrier config its really a problem, but we'll still define a sane limit
        // of 5 so that we can still make a conference.
        if (b == null) {
            Log.w(this, "getMaximumConferenceSize - failed to get conference size");
            return 5;
        }
        return b.getInt(CarrierConfigManager.KEY_IMS_CONFERENCE_SIZE_LIMIT_INT);
    }

    /**
     * @return The number of participants in the conference.
     */
    public int getNumberOfParticipants() {
        return mConferenceParticipantConnections.size();
    }

    /**
     * @return {@code True} if the carrier enforces a maximum conference size, and the number of
     *      participants in the conference has reached the limit, {@code false} otherwise.
     */
    public boolean isFullConference() {
        return isMaximumConferenceSizeEnforced()
                && getNumberOfParticipants() >= getMaximumConferenceSize();
    }

    /**
     * @return {@code True} if the ImsConference is emulating single party call.
     */
    @VisibleForTesting
    public boolean isEmulatingSinglePartyCall() {
        return mIsEmulatingSinglePartyCall;
    }

    /**
     * Handles destruction of a {@link ConferenceParticipantConnection}.
     * We remove the participant from the list of tracked participants in the conference and
     * update whether the conference can be managed.
     * @param participant the conference participant.
     */
    private void handleConnectionDestruction(ConferenceParticipantConnection participant) {
        removeConferenceParticipant(participant);
        updateManageConference();
    }
}
