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

Commit a81d3084 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Support auto-downgrade of video calls when mobile data is metered.

The previous code supported downgrading video calls (either to audio,
or pausing video, or terminating the call, depending on carrier reqs)
when mobile data is disabled.

These changes provide support for downgrading a video call over wifi
when it hands over to LTE (that work is in onCallHandover).  The rest
of the changes in ImsPhoneCallTracker were to refactor the downgrade
code so it could be reused.

In ImsPhoneConnection, added support for temporarily disabling VT on the
local side.  This way, if a wifi video call downgrades to audio-only due
to mobile data being disabled, the "upgrade to video" button will not
be available allowing the user to upgrade back to video (thereby defeating
the fact data is disabled).

Test: Manual
Bug: 36900451
Change-Id: Ib29c7b2fb31f4dcf505609bedfbaca0be7f8f265
parent 819955be
Loading
Loading
Loading
Loading
+115 −49
Original line number Diff line number Diff line
@@ -298,6 +298,7 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
    private ImsCall mCallExpectedToResume = null;
    private boolean mAllowEmergencyVideoCalls = false;
    private boolean mIgnoreDataEnabledChangedForVideoCalls = false;
    private boolean mIsViLteDataMetered = false;

    /**
     * Listeners to changes in the phone state.  Intended for use by other interested IMS components
@@ -948,6 +949,8 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                CarrierConfigManager.KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL);
        mIgnoreDataEnabledChangedForVideoCalls = carrierConfig.getBoolean(
                CarrierConfigManager.KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS);
        mIsViLteDataMetered = carrierConfig.getBoolean(
                CarrierConfigManager.KEY_VILTE_DATA_IS_METERED_BOOL);
        mSupportPauseVideo = carrierConfig.getBoolean(
                CarrierConfigManager.KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL);

@@ -2449,20 +2452,29 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                removeMessages(EVENT_CHECK_FOR_WIFI_HANDOVER);
            }

            ImsPhoneConnection conn = findConnection(imsCall);
            if (conn != null) {
                // Only consider it a handover from WIFI if the source and target radio tech is known.
            boolean isHandoverFromWifi = srcAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
                boolean isHandoverFromWifi =
                        srcAccessTech == ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
                                && targetAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN
                                && targetAccessTech != ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN;
            if (mNotifyHandoverVideoFromWifiToLTE && isHandoverFromWifi && imsCall.isVideoCall()) {
                if (isHandoverFromWifi && imsCall.isVideoCall()) {
                    if (mNotifyHandoverVideoFromWifiToLTE) {
                        log("onCallHandover :: notifying of WIFI to LTE handover.");
                ImsPhoneConnection conn = findConnection(imsCall);
                if (conn != null) {
                        conn.onConnectionEvent(
                                TelephonyManager.EVENT_HANDOVER_VIDEO_FROM_WIFI_TO_LTE, null);
                } else {
                    loge("onCallHandover :: failed to notify of handover; connection is null.");
                    }

                    if (!mIsDataEnabled && mIsViLteDataMetered) {
                        // Call was downgraded from WIFI to LTE and data is metered; downgrade the
                        // call now.
                        downgradeVideoCall(ImsReasonInfo.CODE_DATA_DISABLED, conn);
                    }
                }
            } else {
                loge("onCallHandover :: connection null.");
            }

            mMetrics.writeOnImsCallHandoverEvent(mPhone.getPhoneId(),
                    TelephonyCallSession.Event.Type.IMS_CALL_HANDOVER, imsCall.getCallSession(),
@@ -3285,17 +3297,18 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
        ImsManager.getInstance(mPhone.getContext(), mPhone.getPhoneId()).setDataEnabled(enabled);
        mIsDataEnabled = enabled;

        if (mIgnoreDataEnabledChangedForVideoCalls) {
            log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " due to carrier policy.");
        if (!mIsViLteDataMetered) {
            log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " - carrier policy "
                    + "indicates that data is not metered for ViLTE calls.");
            return;
        }

        if (mIgnoreDataEnabledChangedForVideoCalls) {
            log("Ignore data " + ((enabled) ? "enabled" : "disabled") + " due to carrier policy.");
            return;
        // Inform connections that data has been disabled to ensure we turn off video capability
        // if this is an LTE call.
        for (ImsPhoneConnection conn : mConnections) {
            conn.handleDataEnabledChange(enabled);
        }

        if (!enabled) {
        int reasonCode;
        if (reason == DataEnabledSettings.REASON_POLICY_DATA_ENABLED) {
            reasonCode = ImsReasonInfo.CODE_DATA_LIMIT_REACHED;
@@ -3306,6 +3319,24 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
            reasonCode = ImsReasonInfo.CODE_DATA_DISABLED;
        }

        // Potentially send connection events so the InCall UI knows that video calls are being
        // downgraded due to data being enabled/disabled.
        maybeNotifyDataDisabled(enabled, reasonCode);
        // Handle video state changes required as a result of data being enabled/disabled.
        handleDataEnabledChange(enabled, reasonCode);

        // We do not want to update the ImsConfig for REASON_REGISTERED, since it can happen before
        // the carrier config has loaded and will deregister IMS.
        if (!mShouldUpdateImsConfigOnDisconnect
                && reason != DataEnabledSettings.REASON_REGISTERED) {
            // This will call into updateVideoCallFeatureValue and eventually all clients will be
            // asynchronously notified that the availability of VT over LTE has changed.
            ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
        }
    }

    private void maybeNotifyDataDisabled(boolean enabled, int reasonCode) {
        if (!enabled) {
            // If data is disabled while there are ongoing VT calls which are not taking place over
            // wifi, then they should be disconnected to prevent the user from incurring further
            // data charges.
@@ -3325,27 +3356,38 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
                            conn.onConnectionEvent(
                                    TelephonyManager.EVENT_DOWNGRADE_DATA_LIMIT_REACHED, null);
                        }
                        modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
                    } else if (mSupportPauseVideo) {
                        // The carrier supports video pause signalling, so pause the video.
                        mShouldUpdateImsConfigOnDisconnect = true;
                        conn.pauseVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
                    } else {
                        // At this point the only choice we have is to terminate the call.
                        try {
                            imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
                        } catch (ImsException ie) {
                            loge("Couldn't terminate call " + imsCall);
                    }
                }
            }
        }
    }

    /**
     * Handles changes to the enabled state of mobile data.
     * When data is disabled, handles auto-downgrade of video calls over LTE.
     * When data is enabled, handled resuming of video calls paused when data was disabled.
     * @param enabled {@code true} if mobile data is enabled, {@code false} if mobile data is
     *                            disabled.
     * @param reasonCode The {@link ImsReasonInfo} code for the data enabled state change.
     */
    private void handleDataEnabledChange(boolean enabled, int reasonCode) {
        if (!enabled) {
            // If data is disabled while there are ongoing VT calls which are not taking place over
            // wifi, then they should be disconnected to prevent the user from incurring further
            // data charges.
            for (ImsPhoneConnection conn : mConnections) {
                ImsCall imsCall = conn.getImsCall();
                if (imsCall != null && imsCall.isVideoCall() && !imsCall.isWifiCall()) {
                    log("handleDataEnabledChange - downgrading " + conn);
                    downgradeVideoCall(reasonCode, conn);
                }
            }
        } else if (mSupportPauseVideo) {
            // Data was re-enabled, so un-pause previously paused video calls.
            for (ImsPhoneConnection conn : mConnections) {
                // If video is paused, check to see if there are any pending pauses due to enabled
                // state of data changing.
                log("onDataEnabledChanged - resuming " + conn);
                log("handleDataEnabledChange - resuming " + conn);
                if (VideoProfile.isPaused(conn.getVideoState()) &&
                        conn.wasVideoPausedFromSource(VideoPauseTracker.SOURCE_DATA_ENABLED)) {
                    // The data enabled state was a cause of a pending pause, so potentially
@@ -3355,15 +3397,39 @@ public class ImsPhoneCallTracker extends CallTracker implements ImsPullCall {
            }
            mShouldUpdateImsConfigOnDisconnect = false;
        }
    }

    /**
     * Handles downgrading a video call.  The behavior depends on carrier capabilities; we will
     * attempt to take one of the following actions (in order of precedence):
     * 1. If supported by the carrier, the call will be downgraded to an audio-only call.
     * 2. If the carrier supports video pause signalling, the video will be paused.
     * 3. The call will be disconnected.
     * @param reasonCode The {@link ImsReasonInfo} reason code for the downgrade.
     * @param conn The {@link ImsPhoneConnection} to downgrade.
     */
    private void downgradeVideoCall(int reasonCode, ImsPhoneConnection conn) {
        ImsCall imsCall = conn.getImsCall();
        if (imsCall != null) {
            if (conn.hasCapabilities(
                    Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_LOCAL |
                            Connection.Capability.SUPPORTS_DOWNGRADE_TO_VOICE_REMOTE)) {

        // We do not want to update the ImsConfig for REASON_REGISTERED, since it can happen before
        // the carrier config has loaded and will deregister IMS.
        if (!mShouldUpdateImsConfigOnDisconnect
                && reason != DataEnabledSettings.REASON_REGISTERED) {
            // This will call into updateVideoCallFeatureValue and eventually all clients will be
            // asynchronously notified that the availability of VT over LTE has changed.
            ImsManager.updateImsServiceConfig(mPhone.getContext(), mPhone.getPhoneId(), true);
                // If the carrier supports downgrading to voice, then we can simply issue a
                // downgrade to voice instead of terminating the call.
                modifyVideoCall(imsCall, VideoProfile.STATE_AUDIO_ONLY);
            } else if (mSupportPauseVideo) {
                // The carrier supports video pause signalling, so pause the video.
                mShouldUpdateImsConfigOnDisconnect = true;
                conn.pauseVideo(VideoPauseTracker.SOURCE_DATA_ENABLED);
            } else {
                // At this point the only choice we have is to terminate the call.
                try {
                    imsCall.terminate(ImsReasonInfo.CODE_USER_TERMINATED, reasonCode);
                } catch (ImsException ie) {
                    loge("Couldn't terminate call " + imsCall);
                }
            }
        }
    }

+25 −2
Original line number Diff line number Diff line
@@ -111,6 +111,14 @@ public class ImsPhoneConnection extends Connection implements
     */
    private boolean mIsMergeInProcess = false;

    /**
     * Used as an override to determine whether video is locally available for this call.
     * This allows video availability to be overridden in the case that the modem says video is
     * currently available, but mobile data is off and the carrier is metering data for video
     * calls.
     */
    private boolean mIsVideoEnabled = true;

    //***** Event Constants
    private static final int EVENT_DTMF_DONE = 1;
    private static final int EVENT_PAUSE_DONE = 2;
@@ -246,11 +254,15 @@ public class ImsPhoneConnection extends Connection implements
        return (a == null) ? (b == null) : (b != null && a.startsWith (b));
    }

    private static int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
        Rlog.w(LOG_TAG, "applyLocalCallCapabilities - localProfile = "+localProfile);
    private int applyLocalCallCapabilities(ImsCallProfile localProfile, int capabilities) {
        Rlog.i(LOG_TAG, "applyLocalCallCapabilities - localProfile = " + localProfile);
        capabilities = removeCapability(capabilities,
                Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL);

        if (!mIsVideoEnabled) {
            Rlog.i(LOG_TAG, "applyLocalCallCapabilities - disabling video (overidden)");
            return capabilities;
        }
        switch (localProfile.mCallType) {
            case ImsCallProfile.CALL_TYPE_VT:
                // Fall-through
@@ -1229,4 +1241,15 @@ public class ImsPhoneConnection extends Connection implements
        updateVideoState(newVideoState);
        mShouldIgnoreVideoStateChanges = false;
    }

    public void handleDataEnabledChange(boolean isDataEnabled) {
        mIsVideoEnabled = isDataEnabled;
        Rlog.i(LOG_TAG, "handleDataEnabledChange: isDataEnabled=" + isDataEnabled
                + "; updating local video availability.");
        updateMediaCapabilities(getImsCall());
        if (mImsVideoCallProviderWrapper != null) {
            mImsVideoCallProviderWrapper.setIsVideoEnabled(
                    hasCapabilities(Connection.Capability.SUPPORTS_VT_LOCAL_BIDIRECTIONAL));
        }
    }
}