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

Commit 60b39fce authored by Sarah Chin's avatar Sarah Chin Committed by android-build-merger
Browse files

Merge "Handle 5G meteredness in telephony framework"

am: 7ab0782a

Change-Id: Ic2af138f1a857f909172c30b8751be7c6cc7f60b
parents 27c4820e 7ab0782a
Loading
Loading
Loading
Loading
+0 −27
Original line number Diff line number Diff line
@@ -18,10 +18,8 @@ package com.android.internal.telephony.dataconnection;

import android.content.Context;
import android.hardware.radio.V1_4.DataConnActiveStatus;
import android.net.INetworkPolicyListener;
import android.net.LinkAddress;
import android.net.LinkProperties.CompareResult;
import android.net.NetworkPolicyManager;
import android.net.NetworkUtils;
import android.os.AsyncResult;
import android.os.Handler;
@@ -69,7 +67,6 @@ public class DcController extends StateMachine {
    private DccDefaultState mDccDefaultState = new DccDefaultState();

    final TelephonyManager mTelephonyManager;
    final NetworkPolicyManager mNetworkPolicyManager;

    private PhoneStateListener mPhoneStateListener;

@@ -107,8 +104,6 @@ public class DcController extends StateMachine {

        mTelephonyManager = (TelephonyManager) phone.getContext()
                .getSystemService(Context.TELEPHONY_SERVICE);
        mNetworkPolicyManager = (NetworkPolicyManager) phone.getContext()
                .getSystemService(Context.NETWORK_POLICY_SERVICE);

        mDcTesterDeactivateAll = (TelephonyUtils.IS_DEBUGGABLE)
                ? new DcTesterDeactivateAll(mPhone, DcController.this, getHandler())
@@ -173,21 +168,6 @@ public class DcController extends StateMachine {
        return mExecutingCarrierChange;
    }

    private final INetworkPolicyListener mListener = new NetworkPolicyManager.Listener() {
        @Override
        public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) {
            if (mPhone == null || mPhone.getSubId() != subId) return;

            final HashMap<Integer, DataConnection> dcListActiveByCid;
            synchronized (mDcListAll) {
                dcListActiveByCid = new HashMap<>(mDcListActiveByCid);
            }
            for (DataConnection dc : dcListActiveByCid.values()) {
                dc.onSubscriptionOverride(overrideMask, overrideValue);
            }
        }
    };

    private class DccDefaultState extends State {
        @Override
        public void enter() {
@@ -199,10 +179,6 @@ public class DcController extends StateMachine {

            mDataServiceManager.registerForDataCallListChanged(getHandler(),
                    DataConnection.EVENT_DATA_STATE_CHANGED);

            if (mNetworkPolicyManager != null) {
                mNetworkPolicyManager.registerListener(mListener);
            }
        }

        @Override
@@ -216,9 +192,6 @@ public class DcController extends StateMachine {
            if (mDcTesterDeactivateAll != null) {
                mDcTesterDeactivateAll.dispose();
            }
            if (mNetworkPolicyManager != null) {
                mNetworkPolicyManager.unregisterListener(mListener);
            }
        }

        @Override
+148 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.internal.telephony.dataconnection;

import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE;
import static android.net.NetworkPolicyManager.OVERRIDE_UNMETERED;
import static android.telephony.NetworkRegistrationInfo.NR_STATE_CONNECTED;
import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_NR;

@@ -41,10 +43,12 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.INetworkPolicyListener;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.ProxyInfo;
import android.net.TrafficStats;
@@ -67,6 +71,7 @@ import android.telephony.AccessNetworkConstants;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.Annotation.ApnType;
import android.telephony.Annotation.DataFailureCause;
import android.telephony.Annotation.NetworkType;
import android.telephony.CarrierConfigManager;
import android.telephony.CellLocation;
import android.telephony.DataFailCause;
@@ -333,6 +338,20 @@ public class DcTracker extends Handler {
    private final LocalLog mDataRoamingLeakageLog = new LocalLog(50);
    private final LocalLog mApnSettingsInitializationLog = new LocalLog(50);

    /* Default for 5G connection reevaluation alarm durations */
    private long mHysteresisTimeMs = 0;
    private long mWatchdogTimeMs = 1000 * 60 * 60;

    /* Used to check whether 5G timers are currently active and waiting to go off */
    private boolean mHysteresis = false;
    private boolean mWatchdog = false;

    /* Used to check whether phone was recently connected to 5G. */
    private boolean m5GWasConnected = false;

    /* Used to keep track of unmetered overrides per network type */
    private long mUnmeteredOverrideBitMask = 0;

    private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver () {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -361,6 +380,17 @@ public class DcTracker extends Handler {
                if (mIccRecords.get() != null && mIccRecords.get().getRecordsLoaded()) {
                    setDefaultDataRoamingEnabled();
                }
                CarrierConfigManager configManager = (CarrierConfigManager) mPhone.getContext()
                        .getSystemService(Context.CARRIER_CONFIG_SERVICE);
                if (configManager != null) {
                    PersistableBundle b = configManager.getConfigForSubId(mPhone.getSubId());
                    if (b != null) {
                        mHysteresisTimeMs = b.getLong(
                                CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT);
                        mWatchdogTimeMs = b.getLong(
                                CarrierConfigManager.KEY_5G_WATCHDOG_TIME_MS_LONG);
                    }
                }
            } else {
                if (DBG) log("onReceive: Unknown action=" + action);
            }
@@ -414,6 +444,23 @@ public class DcTracker extends Handler {
        }
    };

    private NetworkPolicyManager mNetworkPolicyManager;
    private final INetworkPolicyListener mNetworkPolicyListener =
            new NetworkPolicyManager.Listener() {
        @Override
        public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue,
                long networkTypeMask) {
            if (mPhone == null || mPhone.getSubId() != subId) return;

            if (overrideMask == OVERRIDE_UNMETERED) {
                mUnmeteredOverrideBitMask = overrideValue == 0 ? 0 : networkTypeMask;
                reevaluateUnmeteredConnections();
            } else {
                overrideDataConnections(overrideMask, overrideValue);
            }
        }
    };

    private final SettingsObserver mSettingsObserver;

    private void registerSettingsObserver() {
@@ -695,6 +742,9 @@ public class DcTracker extends Handler {
        mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
        mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);

        mNetworkPolicyManager = NetworkPolicyManager.from(mPhone.getContext());
        mNetworkPolicyManager.registerListener(mNetworkPolicyListener);

        HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
        dcHandlerThread.start();
        Handler dcHandler = new Handler(dcHandlerThread.getLooper());
@@ -749,6 +799,7 @@ public class DcTracker extends Handler {
                DctConstants.EVENT_PS_RESTRICT_DISABLED, null);
        mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(mTransportType, this,
                DctConstants.EVENT_DATA_RAT_CHANGED, null);
        mPhone.registerForServiceStateChanged(this, DctConstants.EVENT_5G_NETWORK_CHANGED, null);
    }

    public void unregisterServiceStateTrackerEvents() {
@@ -760,6 +811,7 @@ public class DcTracker extends Handler {
        mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
        mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType,
                this);
        mPhone.unregisterForServiceStateChanged(this);
    }

    private void registerForAllEvents() {
@@ -805,6 +857,7 @@ public class DcTracker extends Handler {

        mSubscriptionManager
                .removeOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
        mNetworkPolicyManager.unregisterListener(mNetworkPolicyListener);
        mDcc.dispose();
        mDcTesterFailBringUpAll.dispose();

@@ -857,6 +910,12 @@ public class DcTracker extends Handler {
        }
    }

    private void overrideDataConnections(int overrideMask, int overrideValue) {
        for (DataConnection dataConnection : mDataConnections.values()) {
            dataConnection.onSubscriptionOverride(overrideMask, overrideValue);
        }
    }

    public long getSubId() {
        return mPhone.getSubId();
    }
@@ -3755,6 +3814,17 @@ public class DcTracker extends Handler {
            case DctConstants.EVENT_DATA_ENABLED_OVERRIDE_RULES_CHANGED:
                onDataEnabledOverrideRulesChanged();
                break;
            case DctConstants.EVENT_5G_NETWORK_CHANGED:
                reevaluateUnmeteredConnections();
                break;
            case DctConstants.EVENT_5G_TIMER_HYSTERESIS:
                reevaluateUnmeteredConnections();
                mHysteresis = false;
                break;
            case DctConstants.EVENT_5G_TIMER_WATCHDOG:
                mWatchdog = false;
                reevaluateUnmeteredConnections();
                break;
            default:
                Rlog.e("DcTracker", "Unhandled event=" + msg);
                break;
@@ -3913,6 +3983,53 @@ public class DcTracker extends Handler {
        }
    }

    private void reevaluateUnmeteredConnections() {
        if (isNetworkTypeUnmetered(NETWORK_TYPE_NR)) {
            if (mPhone.getServiceState().getNrState() == NR_STATE_CONNECTED) {
                if (!m5GWasConnected) { //4G -> 5G
                    stopHysteresisAlarm();
                    overrideDataConnections(OVERRIDE_UNMETERED, OVERRIDE_UNMETERED);
                }
                if (!mWatchdog) {
                    startWatchdogAlarm();
                }
                m5GWasConnected = true;
            } else {
                if (m5GWasConnected) { //5G -> 4G
                    if (!mHysteresis && !startHysteresisAlarm()) {
                        // hysteresis is not active but carrier does not support hysteresis
                        stopWatchdogAlarm();
                        overrideMeterednessForNetworkType(
                                mTelephonyManager.getNetworkType(mPhone.getSubId()));
                    }
                    m5GWasConnected = false;
                } else { //4G -> 4G
                    if (!hasMessages(DctConstants.EVENT_5G_TIMER_HYSTERESIS)) {
                        stopWatchdogAlarm();
                        overrideMeterednessForNetworkType(
                                mTelephonyManager.getNetworkType(mPhone.getSubId()));
                    }
                    // do nothing if waiting for hysteresis alarm to go off
                }
            }
        } else {
            stopWatchdogAlarm();
            stopHysteresisAlarm();
            overrideMeterednessForNetworkType(mTelephonyManager.getNetworkType(mPhone.getSubId()));
            m5GWasConnected = false;
        }
    }

    private void overrideMeterednessForNetworkType(@NetworkType int networkType) {
        int overrideValue = isNetworkTypeUnmetered(networkType) ? OVERRIDE_UNMETERED : 0;
        overrideDataConnections(OVERRIDE_UNMETERED, overrideValue);
    }

    private boolean isNetworkTypeUnmetered(@NetworkType int networkType) {
        long networkTypeMask = TelephonyManager.getBitMaskForNetworkType(networkType);
        return (mUnmeteredOverrideBitMask & networkTypeMask) == networkTypeMask;
    }

    private void log(String s) {
        Rlog.d(mLogTag, s);
    }
@@ -4745,6 +4862,37 @@ public class DcTracker extends Handler {
        }
    }

    /**
     * 5G connection reevaluation alarms
     */
    private boolean startHysteresisAlarm() {
        if (mHysteresisTimeMs > 0) {
            // only create hysteresis alarm if CarrierConfig allows it
            sendMessageDelayed(obtainMessage(DctConstants.EVENT_5G_TIMER_HYSTERESIS),
                    mHysteresisTimeMs);
            mHysteresis = true;
            return true;
        } else {
            return false;
        }
    }

    private void stopHysteresisAlarm() {
        removeMessages(DctConstants.EVENT_5G_TIMER_HYSTERESIS);
        mHysteresis = false;
    }

    private void startWatchdogAlarm() {
        sendMessageDelayed(obtainMessage(DctConstants.EVENT_5G_TIMER_WATCHDOG),
                mWatchdogTimeMs);
        mWatchdog = true;
    }

    private void stopWatchdogAlarm() {
        removeMessages(DctConstants.EVENT_5G_TIMER_WATCHDOG);
        mWatchdog = false;
    }

    private static DataProfile createDataProfile(ApnSetting apn, boolean isPreferred) {
        return createDataProfile(apn, apn.getProfileId(), isPreferred);
    }
+5 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import android.hardware.radio.V1_0.SetupDataCallResult;
import android.net.LinkProperties;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkPolicyManager;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncResult;
@@ -147,6 +148,8 @@ public class DcTrackerTest extends TelephonyTest {
    PackageManagerService mMockPackageManagerInternal;
    @Mock
    Handler mHandler;
    @Mock
    NetworkPolicyManager mNetworkPolicyManager;

    private DcTracker mDct;
    private DcTrackerTestHandler mDcTrackerTestHandler;
@@ -505,7 +508,8 @@ public class DcTrackerTest extends TelephonyTest {
                }
        ).when(mSubscriptionManager).addOnSubscriptionsChangedListener(any());
        doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(anyInt());

        doReturn(mNetworkPolicyManager).when(mContext)
                .getSystemService(Context.NETWORK_POLICY_SERVICE);
        doReturn(1).when(mIsub).getDefaultDataSubId();
        doReturn(mIsub).when(mBinder).queryLocalInterface(anyString());
        mServiceManagerMockedServices.put("isub", mBinder);