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

Commit 333a4a49 authored by Tyler Gunn's avatar Tyler Gunn Committed by Android (Google) Code Review
Browse files

Merge "Support auto-downgrade of video calls when mobile data is metered." into oc-mr1-dev

parents 66128c65 a81d3084
Loading
Loading
Loading
Loading
+115 −49
Original line number Diff line number Diff line
@@ -302,6 +302,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
@@ -977,6 +978,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);

@@ -2513,20 +2516,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(),
@@ -3349,17 +3361,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;
@@ -3370,6 +3383,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.
@@ -3389,27 +3420,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
@@ -3419,15 +3461,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));
        }
    }
}