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

Commit 82ee99d4 authored by Anju Mathapati's avatar Anju Mathapati Committed by Linux Build Service Account
Browse files

Telephony: IMS changes for VoLTE and VT.

- Additional APIs in CallManager for IMS calls
- Create separate ImsPhone for IMS calls
- Register IMS phone with CallManager,
  after registering the CDMA base phone as default phone
- Use ImsPhone for IMS specific API calls
- CallManager handles both CS & PS calls

- Add hold, switching and conference capabilities for IMS calls

- VT: Add getCallType api to Phone interface

- Add API to check VT call modify capability

- VT: Add addional call types for VT TX and VT RX

- IMS Conference URI update Call Details

- Supplementary Service Notification support for IMS

- Add ECBM support for ImsPhone

- Expose method to get index of connection

- Add getPhoneInCall utility in CallManager

Change-Id: I4590dc6ba19b33ab0cd7ccab5f8bd0cc5cfa8e72
parent 747a7820
Loading
Loading
Loading
Loading
+186 −0
Original line number Diff line number Diff line
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *  * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *  * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.internal.telephony;

import java.util.Map;
import java.util.Map.Entry;

/**
 * CallDetails class takes care of all the additional details like call type
 * and domain needed for IMS calls. This class is not relevant for non-IMS calls
 */
public class CallDetails {

    /*
     * Type of the call based on the media type and the direction of the media.
     */

    public static final int CALL_TYPE_VOICE = 0; /*
                                                  * Voice call-audio in both
                                                  * directions
                                                  */

    public static final int CALL_TYPE_VT_TX = 1; /*
                                                  * PS Video telephony call: one
                                                  * way TX video, two way audio
                                                  */

    public static final int CALL_TYPE_VT_RX = 2; /*
                                                  * Video telephony call: one
                                                  * way RX video, two way audio
                                                  */

    public static final int CALL_TYPE_VT = 3; /*
                                               * Video telephony call: two way
                                               * video, two way audio
                                               */

    public static final int CALL_TYPE_VT_NODIR = 4; /*
                                                     * Video telephony call: no
                                                     * direction, two way audio,
                                                     * intermediate state in a
                                                     * video call till video
                                                     * link is setup
                                                     */

    public static final int CALL_TYPE_UNKNOWN = 10; /*
                                                     * Unknown Call type, may be
                                                     * used for answering call
                                                     * with same call type as
                                                     * incoming call. This is
                                                     * only for telephony, not
                                                     * meant to be passed to RIL
                                                     */

    public static final int CALL_DOMAIN_UNKNOWN = 0; /*
                                                      * Unknown domain. Sent by
                                                      * RIL when modem has not
                                                      * yet selected a domain
                                                      * for a call
                                                      */
    public static final int CALL_DOMAIN_CS = 1; /*
                                                 * Circuit switched domain
                                                 */
    public static final int CALL_DOMAIN_PS = 2; /*
                                                 * Packet switched domain
                                                 */
    public static final int CALL_DOMAIN_AUTOMATIC = 3; /*
                                                        * Automatic domain. Sent
                                                        * by Android to indicate
                                                        * that the domain for a
                                                        * new call should be
                                                        * selected by modem
                                                        */
    public static final int CALL_DOMAIN_NOT_SET = 4; /*
                                                      * Init value used
                                                      * internally by telephony
                                                      * until domain is set
                                                      */

    public static final String EXTRAS_IS_CONFERENCE_URI = "isConferenceUri";

    public int call_type;
    public int call_domain;

    public String[] extras;

    public CallDetails() {
        call_type = CALL_TYPE_VOICE;
        call_domain = CALL_DOMAIN_NOT_SET;
        extras = null;
    }

    public CallDetails(int callType, int callDomain, String[] extraparams) {
        call_type = callType;
        call_domain = callDomain;
        extras = extraparams;
    }

    public CallDetails(CallDetails srcCall) {
        if (srcCall != null) {
            call_type = srcCall.call_type;
            call_domain = srcCall.call_domain;
            extras = srcCall.extras;
        }
    }

    public void setExtras(String[] extraparams) {
        extras = extraparams;
    }

    public static String[] getExtrasFromMap(Map<String, String> newExtras) {
        String []extras = null;

        if (newExtras == null) {
            return null;
        }

        // TODO: Merge new extras into extras. For now, just serialize and set them
        extras = new String[newExtras.size()];

        if (extras != null) {
            int i = 0;
            for (Entry<String, String> entry : newExtras.entrySet()) {
                extras[i] = "" + entry.getKey() + "=" + entry.getValue();
            }
        }
        return extras;
    }

    public void setExtrasFromMap(Map<String, String> newExtras) {
        this.extras = getExtrasFromMap(newExtras);
    }

    public String getValueForKeyFromExtras(String[] extras, String key) {
        for (int i = 0; extras != null && i < extras.length; i++) {
            if (extras[i] != null) {
                String[] currKey = extras[i].split("=");
                if (currKey.length == 2 && currKey[0].equals(key)) {
                    return currKey[1];
                }
            }
        }
        return null;
    }

    /**
     * @return string representation.
     */
    @Override
    public String toString() {
        String extrasResult = "";
        if (extras != null) {
            for (String s : extras) {
                extrasResult += s;
            }
        }
        return (" " + call_type
                + " " + call_domain
                + " " + extrasResult);
    }
}
+119 −5
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
 * Not a Contribution, Apache license notifications and license are retained
 * for attribution purposes only.
 *
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
@@ -25,6 +29,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.RegistrantList;
import android.os.Registrant;
import android.os.SystemProperties;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.Rlog;
@@ -226,6 +231,14 @@ public final class CallManager {
        return (getPhoneBase(p1) == getPhoneBase(p2));
    }

    /**
     * Returns true if Android supports VoLTE/VT calls on IMS
     */
    public static boolean isCallOnImsEnabled() {
        return SystemProperties.getBoolean(
                TelephonyProperties.CALLS_ON_IMS_ENABLED_PROPERTY, false);
    }

    /**
     * Returns all the registered phone objects.
     * @return all the registered phone objects.
@@ -373,6 +386,22 @@ public final class CallManager {
        return getFirstActiveRingingCall().getPhone();
    }

    /**
     * @return the phone associated with any call
     */
    public Phone getPhoneInCall() {
        Phone phone = null;
        if (!getFirstActiveRingingCall().isIdle()) {
            phone = getFirstActiveRingingCall().getPhone();
        } else if (!getActiveFgCall().isIdle()) {
            phone = getActiveFgCall().getPhone();
        } else {
            // If BG call is idle, we return default phone
            phone = getFirstActiveBgCall().getPhone();
        }
        return phone;
    }

    public void setAudioMode() {
        Context context = getContext();
        if (context == null) return;
@@ -456,7 +485,8 @@ public final class CallManager {
        phone.registerForMmiComplete(mHandler, EVENT_MMI_COMPLETE, null);
        phone.registerForSuppServiceFailed(mHandler, EVENT_SUPP_SERVICE_FAILED, null);
        phone.registerForServiceStateChanged(mHandler, EVENT_SERVICE_STATE_CHANGED, null);
        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM) {
        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM ||
                phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            phone.registerForSuppServiceNotification(mHandler, EVENT_SUPP_SERVICE_NOTIFY, null);
        }

@@ -473,6 +503,10 @@ public final class CallManager {
            phone.registerForCallWaiting(mHandler, EVENT_CALL_WAITING, null);
            phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null);
        }

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            phone.registerForEcmTimerReset(mHandler, EVENT_ECM_TIMER_RESET, null);
        }
    }

    private void unregisterForPhoneStates(Phone phone) {
@@ -507,6 +541,10 @@ public final class CallManager {
            phone.unregisterForCallWaiting(mHandler);
            phone.unregisterForEcmTimerReset(mHandler);
        }

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            phone.unregisterForEcmTimerReset(mHandler);
        }
    }

    /**
@@ -523,11 +561,30 @@ public final class CallManager {
     * @exception CallStateException when call is not ringing or waiting
     */
    public void acceptCall(Call ringingCall) throws CallStateException {
        acceptCall(ringingCall, CallDetails.CALL_TYPE_VOICE);
    }

    /**
     * Answers a ringing or waiting call, with an option to downgrade a Video
     * call Active call, if any, go on hold. If active call can't be held, i.e.,
     * a background call of the same channel exists, the active call will be
     * hang up. Answering occurs asynchronously, and final notification occurs
     * via
     * {@link #registerForPreciseCallStateChanged(android.os.Handler, int, java.lang.Object)
     * registerForPreciseCallStateChanged()}.
     *
     * @param ringingCall The call to answer
     * @param callType The call type to use to answer the call. Values from
     *            CallDetails.RIL_CALL_TYPE
     * @exception CallStateException when call is not ringing or waiting
     */
    public void acceptCall(Call ringingCall, int callType) throws CallStateException {
        Phone ringingPhone = ringingCall.getPhone();

        if (VDBG) {
            Rlog.d(LOG_TAG, "acceptCall api with calltype " + callType);
            Rlog.d(LOG_TAG, "acceptCall(" +ringingCall + " from " + ringingCall.getPhone() + ")");
            Rlog.d(LOG_TAG, toString());
            Rlog.d(LOG_TAG, this.toString());
        }

        if ( hasActiveFgCall() ) {
@@ -565,11 +622,16 @@ public final class CallManager {
            }
        }

        if (ringingPhone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            ringingPhone.acceptCall(callType);
        } else {
            ringingPhone.acceptCall();
        }

        if (VDBG) {
            Rlog.d(LOG_TAG, "Call type in acceptCall " +callType);
            Rlog.d(LOG_TAG, "End acceptCall(" +ringingCall + ")");
            Rlog.d(LOG_TAG, toString());
            Rlog.d(LOG_TAG, this.toString());
        }
    }

@@ -748,6 +810,26 @@ public final class CallManager {
     * handled asynchronously.
     */
    public Connection dial(Phone phone, String dialString) throws CallStateException {
        return dial(phone, dialString, CallDetails.CALL_TYPE_VOICE, null);
    }

    /**
     * Initiate a new connection. This happens asynchronously, so you cannot
     * assume the audio path is connected (or a call index has been assigned)
     * until PhoneStateChanged notification has occurred.
     *
     * @exception CallStateException if a new outgoing call is not currently
     *                possible because no more call slots exist or a call exists
     *                that is dialing, alerting, ringing, or waiting. Other
     *                errors are handled asynchronously.
     * @param phone The phone to use to place the call
     * @param dialString The phone number or URI that identifies the remote
     *            party
     * @param calldetails
     */
    public Connection dial(Phone phone, String dialString, int callType, String[] extras)
            throws CallStateException {

        Phone basePhone = getPhoneBase(phone);
        Connection result;

@@ -779,7 +861,11 @@ public final class CallManager {
            }
        }

        if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
            result = basePhone.dial(dialString, callType, extras);
        } else {
            result = basePhone.dial(dialString);
        }

        if (VDBG) {
            Rlog.d(LOG_TAG, "End dial(" + basePhone + ", "+ dialString + ")");
@@ -1764,6 +1850,34 @@ public final class CallManager {
        return false;
    }

    /**
     * @return true if the IMS phone has any active calls. ie. there are active
     *         IMS calls at present
     */
    public boolean isImsPhoneActive() {
        for (Phone phone : mPhones) {
            if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS
                    && phone.getState() != PhoneConstants.State.IDLE) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return true if IMS Phone is in idle state ie. there are no IMS calls
     *         active at present
     */
    public boolean isImsPhoneIdle() {
        for (Phone phone : mPhones) {
            if (phone.getPhoneType() == PhoneConstants.PHONE_TYPE_IMS &&
                    phone.getState() == PhoneConstants.State.IDLE) {
                return true;
            }
        }
        return false;
    }

    private Handler mHandler = new Handler() {

        @Override
+57 −0
Original line number Diff line number Diff line
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *  * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *       copyright notice, this list of conditions and the following
 *       disclaimer in the documentation and/or other materials provided
 *       with the distribution.
 *  * Neither the name of The Linux Foundation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.android.internal.telephony;

public class CallModify {
    public int call_index;

    public CallDetails call_details;

    public CallModify() {
        call_index = 0;
        call_details = new CallDetails();
    }

    public CallModify(CallDetails callDetails, int callIndex) {
        call_index = callIndex;
        call_details = callDetails;
    }

    public void setCallDetails(CallDetails calldetails) {
        call_details = new CallDetails(calldetails);
    }

    /**
     * @return string representation.
     */
    @Override
    public String toString() {
        return (" " + call_index
                + " " + call_details);
    }
}
+11 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.internal.telephony;

import android.telephony.Rlog;
import android.util.Log;
import com.android.internal.telephony.CallStateException;

/**
 * {@hide}
@@ -293,6 +294,16 @@ public abstract class Connection {
     */
    public abstract UUSInfo getUUSInfo();

    /**
     * Gets connection index associated with connection.
     * @return index or exception if unavailable or phone
     * does not support this API
     */

    public int getIndex() throws CallStateException {
        throw new CallStateException("Connection index not assigned");
    }

    /**
     * Build a human representation of a connection instance, suitable for debugging.
     * Don't log personal stuff unless in debug mode.
+1 −2
Original line number Diff line number Diff line
@@ -36,8 +36,7 @@ public class DefaultPhoneNotifier implements PhoneNotifier {

    private ITelephonyRegistry mRegistry;

    /*package*/
    DefaultPhoneNotifier() {
    protected DefaultPhoneNotifier() {
        mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
                    "telephony.registry"));
    }
Loading