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

Commit cede8659 authored by Sarah Chin's avatar Sarah Chin Committed by Android (Google) Code Review
Browse files

Merge "Handle 5G meteredness in telephony framework"

parents cbcd61a1 6ace2e9a
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.Build;
@@ -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 = (Build.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;
@@ -78,6 +82,7 @@ import android.telephony.ServiceState.RilRadioTechnology;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.NetworkType;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.data.ApnSetting;
import android.telephony.data.ApnSetting.ApnType;
@@ -331,6 +336,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() {
@@ -727,6 +774,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());
@@ -788,6 +838,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() {
@@ -799,6 +850,7 @@ public class DcTracker extends Handler {
        mPhone.getServiceStateTracker().unregisterForPsRestrictedDisabled(this);
        mPhone.getServiceStateTracker().unregisterForDataRegStateOrRatChanged(mTransportType,
                this);
        mPhone.unregisterForServiceStateChanged(this);
    }

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

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

@@ -896,6 +949,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();
    }
@@ -3808,6 +3867,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;
@@ -3966,6 +4036,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);
    }
@@ -4779,6 +4896,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;
@@ -148,6 +149,8 @@ public class DcTrackerTest extends TelephonyTest {
    PermissionManagerService mMockPermissionManager;
    @Mock
    Handler mHandler;
    @Mock
    NetworkPolicyManager mNetworkPolicyManager;

    private DcTracker mDct;
    private DcTrackerTestHandler mDcTrackerTestHandler;
@@ -506,7 +509,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);