Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a2b91ffa authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "IMS:Re-Initiate Conference Call from Leaf Node Causes Conference Call Crash."

parents 0b6c7808 a9ec7f3a
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -16,8 +16,10 @@

package com.android.internal.telephony;

import android.net.Uri;
import android.os.Bundle;
import android.os.SystemClock;
import android.telecom.ConferenceParticipant;
import android.telephony.Rlog;
import android.util.Log;

@@ -47,6 +49,7 @@ public abstract class Connection {
                android.telecom.Connection.VideoProvider videoProvider);
        public void onAudioQualityChanged(int audioQuality);
        public void onCallSubstateChanged(int callSubstate);
        public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants);
    }

    /**
@@ -66,6 +69,8 @@ public abstract class Connection {
        public void onAudioQualityChanged(int audioQuality) {}
        @Override
        public void onCallSubstateChanged(int callSubstate) {}
        @Override
        public void onConferenceParticipantsChanged(List<ConferenceParticipant> participants) {}
    }

    public static final int AUDIO_QUALITY_STANDARD = 1;
@@ -588,6 +593,26 @@ public abstract class Connection {
        mDialString = oriNumber;
    }

    /**
     * Notifies listeners of a change to conference participant(s).
     *
     * @param conferenceParticipants The participant(s).
     */
    public void updateConferenceParticipants(List<ConferenceParticipant> conferenceParticipants) {
        for (Listener l : mListeners) {
            l.onConferenceParticipantsChanged(conferenceParticipants);
        }
    }

    /**
     * Notifies this Connection of a request to disconnect a participant of the conference managed
     * by the connection.
     *
     * @param endpoint the {@link Uri} of the participant to disconnect.
     */
    public void onDisconnectConferenceParticipant(Uri endpoint) {
    }

    /**
     * Build a human representation of a connection instance, suitable for debugging.
     * Don't log personal stuff unless in debug mode.
+68 −1
Original line number Diff line number Diff line
@@ -23,18 +23,35 @@ import android.content.IntentFilter;
import android.os.Build;
import android.telephony.Rlog;

import com.android.internal.telephony.PhoneBase;
import com.android.ims.ImsCall;
import com.android.ims.ImsConferenceState;
import com.android.internal.telephony.imsphone.ImsPhone;
import com.android.internal.telephony.imsphone.ImsPhoneCall;
import com.android.internal.telephony.test.TestConferenceEventPackageParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

/**
 * Telephony tester receives the following intents where {name} is the phone name
 *
 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_detached
 * adb shell am broadcast -a com.android.internal.telephony.{name}.action_attached
 * adb shell am broadcast -a com.android.internal.telephony.TestConferenceEventPackage -e filename
 *      test_filename.xml
 */
public class TelephonyTester {
    private static final String LOG_TAG = "TelephonyTester";
    private static final boolean DBG = true;

    /**
     * Test-only intent used to send a test conference event package to the IMS framework.
     */
    private static final String ACTION_TEST_CONFERENCE_EVENT_PACKAGE =
            "com.android.internal.telephony.TestConferenceEventPackage";
    private static final String EXTRA_FILENAME = "filename";

    private PhoneBase mPhone;

    // The static intent receiver one for all instances and we assume this
@@ -50,6 +67,9 @@ public class TelephonyTester {
            } else if (action.equals(mPhone.getActionAttached())) {
                log("simulate attaching");
                mPhone.getServiceStateTracker().mAttachedRegistrants.notifyRegistrants();
            } else if (action.equals(ACTION_TEST_CONFERENCE_EVENT_PACKAGE)) {
                log("inject simulated conference event package");
                handleTestConferenceEventPackage(context, intent.getStringExtra(EXTRA_FILENAME));
            } else {
                if (DBG) log("onReceive: unknown action=" + action);
            }
@@ -68,6 +88,11 @@ public class TelephonyTester {
            filter.addAction(mPhone.getActionAttached());
            log("register for intent action=" + mPhone.getActionAttached());

            if (mPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
                log("register for intent action=" + ACTION_TEST_CONFERENCE_EVENT_PACKAGE);
                filter.addAction(ACTION_TEST_CONFERENCE_EVENT_PACKAGE);
            }

            phone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone.getHandler());
        }
    }
@@ -81,4 +106,46 @@ public class TelephonyTester {
    private static void log(String s) {
        Rlog.d(LOG_TAG, s);
    }

    /**
     * Handles request to send a test conference event package to the active Ims call.
     *
     * @see com.android.internal.telephony.test.TestConferenceEventPackageParser
     * @param context The context.
     * @param fileName The name of the test conference event package file to read.
     */
    private void handleTestConferenceEventPackage(Context context, String fileName) {
        // Attempt to get the active IMS call before parsing the test XML file.
        ImsPhone imsPhone = (ImsPhone) mPhone;
        if (imsPhone == null) {
            return;
        }

        ImsPhoneCall imsPhoneCall = imsPhone.getForegroundCall();
        if (imsPhoneCall == null) {
            return;
        }

        ImsCall imsCall = imsPhoneCall.getImsCall();
        if (imsCall == null) {
            return;
        }

        File packageFile = new File(context.getFilesDir(), fileName);
        final FileInputStream is;
        try {
            is = new FileInputStream(packageFile);
        } catch (FileNotFoundException ex) {
            log("Test conference event package file not found: " + packageFile.getAbsolutePath());
            return;
        }

        TestConferenceEventPackageParser parser = new TestConferenceEventPackageParser(is);
        ImsConferenceState imsConferenceState = parser.parse();
        if (imsConferenceState == null) {
            return;
        }

        imsCall.conferenceStateUpdated(imsConferenceState);
    }
}
+20 −11
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.os.Bundle;
import android.telephony.Rlog;
import android.telephony.DisconnectCause;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.CallStateException;
import com.android.internal.telephony.Connection;
@@ -85,7 +86,12 @@ public class ImsPhoneCall extends Call {
    @Override
    public boolean
    isMultiparty() {
        return mConnections.size() > 1;
        ImsCall imsCall = getImsCall();
        if (imsCall == null) {
            return false;
        }

        return imsCall.isMultiparty();
    }

    /** Please note: if this is the foreground call and a
@@ -169,10 +175,7 @@ public class ImsPhoneCall extends Call {
    /*package*/ void
    detach(ImsPhoneConnection conn) {
        mConnections.remove(conn);

        if (mConnections.size() == 0) {
            mState = State.IDLE;
        }
        clearDisconnected();
    }

    /**
@@ -244,7 +247,17 @@ public class ImsPhoneCall extends Call {
        }
    }

    /*package*/ ImsCall
    /**
     * Retrieves the {@link ImsCall} for the current {@link ImsPhoneCall}.
     * <p>
     * Marked as {@code VisibleForTesting} so that the
     * {@link com.android.internal.telephony.TelephonyTester} class can inject a test conference
     * event package into a regular ongoing IMS call.
     *
     * @return The {@link ImsCall}.
     */
    @VisibleForTesting
    public ImsCall
    getImsCall() {
        return (getFirstConnection() == null) ? null : getFirstConnection().getImsCall();
    }
@@ -295,11 +308,7 @@ public class ImsPhoneCall extends Call {

    /* package */ ImsPhoneConnection
    getHandoverConnection() {
        ImsPhoneConnection conn = (ImsPhoneConnection) getEarliestConnection();
        if (conn != null) {
            conn.setMultiparty(isMultiparty());
        }
        return conn;
        return (ImsPhoneConnection) getEarliestConnection();
    }

    void switchWith(ImsPhoneCall that) {
+34 −4
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings;
import android.preference.PreferenceManager;
import android.telecom.ConferenceParticipant;
import android.telecom.VideoProfile;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
@@ -53,6 +54,7 @@ import com.android.ims.ImsManager;
import com.android.ims.ImsReasonInfo;
import com.android.ims.ImsServiceClass;
import com.android.ims.ImsUtInterface;
import com.android.ims.internal.CallGroup;
import com.android.ims.internal.IImsVideoCallProvider;
import com.android.ims.internal.ImsCallSession;
import com.android.ims.internal.ImsVideoCallProviderWrapper;
@@ -103,7 +105,6 @@ public final class ImsPhoneCallTracker extends CallTracker {

                    // Normal MT call
                    ImsCall imsCall = mImsManager.takeCall(mServiceId, intent, mImsCallListener);

                    ImsPhoneConnection conn = new ImsPhoneConnection(mPhone.getContext(), imsCall,
                            ImsPhoneCallTracker.this, mRingingCall);
                    addConnection(conn);
@@ -1103,6 +1104,12 @@ public final class ImsPhoneCallTracker extends CallTracker {
                    cause = DisconnectCause.INCOMING_MISSED;
                }
            }

            if (cause == DisconnectCause.NORMAL && conn != null && conn.getImsCall().isMerged()) {
                // Call was terminated while it is merged instead of a remote disconnect.
                cause = DisconnectCause.IMS_MERGED_SUCCESSFULLY;
            }

            processCallStateChange(imsCall, ImsPhoneCall.State.DISCONNECTED, cause);

            if (reasonInfo.getCode() == ImsReasonInfo.CODE_USER_TERMINATED) {
@@ -1122,11 +1129,17 @@ public final class ImsPhoneCallTracker extends CallTracker {
                ImsPhoneCall.State oldState = mBackgroundCall.getState();
                processCallStateChange(imsCall, ImsPhoneCall.State.HOLDING,
                        DisconnectCause.NOT_DISCONNECTED);

                if (oldState == ImsPhoneCall.State.ACTIVE) {
                    if ((mForegroundCall.getState() == ImsPhoneCall.State.HOLDING)
                            || (mRingingCall.getState() == ImsPhoneCall.State.WAITING)) {
                        boolean isOwner = true;
                        CallGroup callGroup =  imsCall.getCallGroup();
                        if (callGroup != null) {
                            isOwner = callGroup.isOwner(imsCall);
                        }
                        if (isOwner) {
                            sendEmptyMessage(EVENT_RESUME_BACKGROUND);
                        }
                    } else {
                        //when multiple connections belong to background call,
                        //only the first callback reaches here
@@ -1212,7 +1225,7 @@ public final class ImsPhoneCallTracker extends CallTracker {
        }

        @Override
        public void onCallMerged(ImsCall call, ImsCall newCall) {
        public void onCallMerged(ImsCall call) {
            if (DBG) log("onCallMerged");

            mForegroundCall.merge(mBackgroundCall, mForegroundCall.getState());
@@ -1225,6 +1238,23 @@ public final class ImsPhoneCallTracker extends CallTracker {
            if (DBG) log("onCallMergeFailed reasonCode=" + reasonInfo.getCode());
            mPhone.notifySuppServiceFailed(Phone.SuppService.CONFERENCE);
        }

        /**
         * Called when the state of IMS conference participant(s) has changed.
         *
         * @param call the call object that carries out the IMS call.
         * @param participants the participant(s) and their new state information.
         */
        @Override
        public void onConferenceParticipantsStateChanged(ImsCall call,
                List<ConferenceParticipant> participants) {
            if (DBG) log("onConferenceParticipantsStateChanged");

            ImsPhoneConnection conn = findConnection(call);
            if (conn != null) {
                conn.updateConferenceParticipants(participants);
            }
        }
    };

    /**
+47 −10
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony.imsphone;

import android.content.Context;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
@@ -25,6 +26,7 @@ import android.os.Message;
import android.os.PowerManager;
import android.os.Registrant;
import android.os.SystemClock;
import android.telecom.Log;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.Rlog;
@@ -74,9 +76,6 @@ public class ImsPhoneConnection extends Connection {
    private int mCause = DisconnectCause.NOT_DISCONNECTED;
    private PostDialState mPostDialState = PostDialState.NOT_STARTED;
    private UUSInfo mUusInfo;

    private boolean mIsMultiparty = false;

    private Handler mHandler;

    private PowerManager.WakeLock mPartialWakeLock;
@@ -595,15 +594,9 @@ public class ImsPhoneConnection extends Connection {
        return null;
    }

    /* package */ void
    setMultiparty(boolean isMultiparty) {
        Rlog.d(LOG_TAG, "setMultiparty " + isMultiparty);
        mIsMultiparty = isMultiparty;
    }

    @Override
    public boolean isMultiparty() {
        return mIsMultiparty;
        return mImsCall != null && mImsCall.isMultiparty();
    }

    /*package*/ ImsCall getImsCall() {
@@ -724,5 +717,49 @@ public class ImsPhoneConnection extends Connection {
    public Bundle getCallExtras() {
        return mCallExtras;
    }

    /**
     * Notifies this Connection of a request to disconnect a participant of the conference managed
     * by the connection.
     *
     * @param endpoint the {@link android.net.Uri} of the participant to disconnect.
     */
    @Override
    public void onDisconnectConferenceParticipant(Uri endpoint) {
        ImsCall imsCall = getImsCall();
        if (imsCall == null) {
            return;
        }
        try {
            imsCall.removeParticipants(new String[]{endpoint.toString()});
        } catch (ImsException e) {
            // No session in place -- no change
            Rlog.e(LOG_TAG, "onDisconnectConferenceParticipant: no session in place. "+
                    "Failed to disconnect endpoint = " + endpoint);
        }
    }

    /**
     * Provides a string representation of the {@link ImsPhoneConnection}.  Primarily intended for
     * use in log statements.
     *
     * @return String representation of call.
     */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("[ImsPhoneConnection objId: ");
        sb.append(System.identityHashCode(this));
        sb.append(" address:");
        sb.append(Log.pii(getAddress()));
        sb.append(" ImsCall:");
        if (mImsCall == null) {
            sb.append("null");
        } else {
            sb.append(mImsCall);
        }
        sb.append("]");
        return sb.toString();
    }
}
Loading