Loading src/java/com/android/internal/telephony/dataconnection/DataConnection.java +39 −26 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.internal.telephony.dataconnection; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.telephony.data.DataCallResponse.PDU_SESSION_ID_NOT_SET; import static com.android.internal.telephony.dataconnection.DcTracker.REQUEST_TYPE_HANDOVER; Loading Loading @@ -299,7 +297,7 @@ public class DataConnection extends StateMachine { private int mLastFailCause; private static final String NULL_IP = "0.0.0.0"; private Object mUserData; private int mSubscriptionOverride; private boolean mCongestedOverride; private boolean mUnmeteredOverride; private int mRilRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; private int mDataRegState = Integer.MAX_VALUE; Loading Loading @@ -349,7 +347,7 @@ public class DataConnection extends StateMachine { static final int EVENT_BW_REFRESH_RESPONSE = BASE + 14; static final int EVENT_DATA_CONNECTION_VOICE_CALL_STARTED = BASE + 15; static final int EVENT_DATA_CONNECTION_VOICE_CALL_ENDED = BASE + 16; static final int EVENT_DATA_CONNECTION_OVERRIDE_CHANGED = BASE + 17; static final int EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED = BASE + 17; static final int EVENT_KEEPALIVE_STATUS = BASE + 18; static final int EVENT_KEEPALIVE_STARTED = BASE + 19; static final int EVENT_KEEPALIVE_STOPPED = BASE + 20; Loading Loading @@ -394,8 +392,8 @@ public class DataConnection extends StateMachine { "EVENT_DATA_CONNECTION_VOICE_CALL_STARTED"; sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE] = "EVENT_DATA_CONNECTION_VOICE_CALL_ENDED"; sCmdToString[EVENT_DATA_CONNECTION_OVERRIDE_CHANGED - BASE] = "EVENT_DATA_CONNECTION_OVERRIDE_CHANGED"; sCmdToString[EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED - BASE] = "EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED"; sCmdToString[EVENT_KEEPALIVE_STATUS - BASE] = "EVENT_KEEPALIVE_STATUS"; sCmdToString[EVENT_KEEPALIVE_STARTED - BASE] = "EVENT_KEEPALIVE_STARTED"; sCmdToString[EVENT_KEEPALIVE_STOPPED - BASE] = "EVENT_KEEPALIVE_STOPPED"; Loading Loading @@ -1036,14 +1034,16 @@ public class DataConnection extends StateMachine { setHandoverState(HANDOVER_STATE_IDLE); } public void onSubscriptionOverride(int overrideMask, int overrideValue) { mSubscriptionOverride = (mSubscriptionOverride & ~overrideMask) | (overrideValue & overrideMask); sendMessage(obtainMessage(EVENT_DATA_CONNECTION_OVERRIDE_CHANGED)); /** * Update NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED based on congested override * @param isCongested whether this DC should be set to congested or not */ public void onCongestednessChanged(boolean isCongested) { sendMessage(obtainMessage(EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED, isCongested)); } /** * Update NetworkCapabilities.NET_CAPABILITY_NOT_METERED based on meteredness * Update NetworkCapabilities.NET_CAPABILITY_NOT_METERED based on metered override * @param isUnmetered whether this DC should be set to unmetered or not */ public void onMeterednessChanged(boolean isUnmetered) { Loading Loading @@ -1247,7 +1247,7 @@ public class DataConnection extends StateMachine { mDcFailCause = DataFailCause.NONE; mDisabledApnTypeBitMask = 0; mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mSubscriptionOverride = 0; mCongestedOverride = false; mUnmeteredOverride = false; mDownlinkBandwidth = 14; mUplinkBandwidth = 14; Loading Loading @@ -1783,15 +1783,9 @@ public class DataConnection extends StateMachine { result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !mPhone.getServiceState().getDataRoaming()); result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); // Override values set above when requested by policy if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_UNMETERED) != 0) { result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); } if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_CONGESTED) != 0) { result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); } result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED, !mCongestedOverride); //result.setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED, // mUnmeteredOverride); // TODO: Remove this after b/176119724 is fixed. This is just a workaround to prevent // NET_CAPABILITY_TEMPORARILY_NOT_METERED incorrectly set on devices that are not supposed Loading Loading @@ -2866,10 +2860,29 @@ public class DataConnection extends StateMachine { break; } mUnmeteredOverride = isUnmetered; // fallthrough if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), DataConnection.this); } retVal = HANDLED; break; case EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED: boolean isCongested = (boolean) msg.obj; if (isCongested == mCongestedOverride) { retVal = HANDLED; break; } mCongestedOverride = isCongested; if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), DataConnection.this); } retVal = HANDLED; break; case EVENT_DATA_CONNECTION_ROAM_ON: case EVENT_DATA_CONNECTION_ROAM_OFF: case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED: { case EVENT_DATA_CONNECTION_ROAM_OFF: { if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), Loading Loading @@ -3661,7 +3674,7 @@ public class DataConnection extends StateMachine { * Dump the current state. * * @param fd * @param pw * @param printWriter * @param args */ @Override Loading Loading @@ -3693,10 +3706,10 @@ public class DataConnection extends StateMachine { pw.println("mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime)); pw.println("mLastFailCause=" + DataFailCause.toString(mLastFailCause)); pw.println("mUserData=" + mUserData); pw.println("mSubscriptionOverride=" + Integer.toHexString(mSubscriptionOverride)); pw.println("mRestrictedNetworkOverride=" + mRestrictedNetworkOverride); pw.println("mUnmeteredUseOnly=" + mUnmeteredUseOnly); pw.println("mUnmeteredOverride=" + mUnmeteredOverride); pw.println("mCongestedOverride=" + mCongestedOverride); pw.println("mDownlinkBandwidth" + mDownlinkBandwidth); pw.println("mUplinkBandwidth=" + mUplinkBandwidth); pw.println("mDefaultQos=" + mDefaultQos); Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +70 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.internal.telephony.dataconnection; import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import static android.telephony.TelephonyManager.NETWORK_TYPE_NR; import static android.telephony.data.ApnSetting.PROTOCOL_IPV4V6; Loading Loading @@ -340,13 +342,23 @@ public class DcTracker extends Handler { private boolean mNrSaAllUnmetered = false; private boolean mNrSaMmwaveUnmetered = false; private boolean mNrSaSub6Unmetered = false; private boolean mRoamingUnmetered = false; private boolean mNrNsaRoamingUnmetered = false; // stats per data call recovery event private DataStallRecoveryStats mDataStallRecoveryStats; /* List of SubscriptionPlans, updated when initialized and when plans are changed. */ private List<SubscriptionPlan> mSubscriptionPlans = null; /* List of network types an unmetered override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ private List<Integer> mUnmeteredNetworkTypes = null; /* List of network types a congested override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ private List<Integer> mCongestedNetworkTypes = null; /* Whether an unmetered override is currently active. */ private boolean mUnmeteredOverride = false; /* Whether a congested override is currently active. */ private boolean mCongestedOverride = false; @SimState private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; Loading Loading @@ -427,11 +439,26 @@ public class DcTracker extends Handler { private final NetworkPolicyManager.SubscriptionCallback mSubscriptionCallback = new NetworkPolicyManager.SubscriptionCallback() { @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, int[] networkTypes) { if (mPhone == null || mPhone.getSubId() != subId) return; for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onSubscriptionOverride(overrideMask, overrideValue); List<Integer> tempList = new ArrayList<>(); for (int networkType : networkTypes) { tempList.add(networkType); } log("Subscription override: overrideMask=" + overrideMask + ", overrideValue=" + overrideValue + ", networkTypes=" + tempList); if (overrideMask == SUBSCRIPTION_OVERRIDE_UNMETERED) { mUnmeteredNetworkTypes = tempList; mUnmeteredOverride = overrideValue != 0; reevaluateUnmeteredConnections(); } else if (overrideMask == SUBSCRIPTION_OVERRIDE_CONGESTED) { mCongestedNetworkTypes = tempList; mCongestedOverride = overrideValue != 0; reevaluateCongestedConnections(); } } Loading Loading @@ -3981,6 +4008,7 @@ public class DcTracker extends Handler { reevaluateUnmeteredConnections(); break; case DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED: reevaluateCongestedConnections(); reevaluateUnmeteredConnections(); break; case DctConstants.EVENT_CARRIER_CONFIG_CHANGED: Loading Loading @@ -4157,10 +4185,22 @@ public class DcTracker extends Handler { } } private void reevaluateCongestedConnections() { log("reevaluateCongestedConnections"); int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); // congested override and either network is specified or unknown and all networks specified boolean isCongested = mCongestedOverride && (mCongestedNetworkTypes.contains(rat) || mUnmeteredNetworkTypes.containsAll(Arrays.stream( TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet()))); for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onCongestednessChanged(isCongested); } } private void reevaluateUnmeteredConnections() { log("reevaluateUnmeteredConnections"); int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); if (isNrUnmetered() && !mPhone.getServiceState().getRoaming() || mRoamingUnmetered) { if (isNrUnmetered() && (!mPhone.getServiceState().getRoaming() || mNrNsaRoamingUnmetered)) { setDataConnectionUnmetered(true); if (!mWatchdog) { startWatchdogAlarm(); Loading @@ -4178,6 +4218,26 @@ public class DcTracker extends Handler { } private boolean isNetworkTypeUnmetered(@NetworkType int networkType) { boolean isUnmetered; if (mUnmeteredNetworkTypes == null || !mUnmeteredOverride) { // check SubscriptionPlans if override is not defined isUnmetered = isNetworkTypeUnmeteredViaSubscriptionPlan(networkType); log("isNetworkTypeUnmeteredViaSubscriptionPlan: networkType=" + networkType + ", isUnmetered=" + isUnmetered); return isUnmetered; } // unmetered override and either network is specified or unknown and all networks specified isUnmetered = mUnmeteredNetworkTypes.contains(networkType) || mUnmeteredNetworkTypes.containsAll(Arrays.stream( TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet())); if (DBG) { log("isNetworkTypeUnmetered: networkType=" + networkType + ", isUnmetered=" + isUnmetered); } return isUnmetered; } private boolean isNetworkTypeUnmeteredViaSubscriptionPlan(@NetworkType int networkType) { if (mSubscriptionPlans == null || mSubscriptionPlans.size() == 0) { // safe return false if unable to get subscription plans or plans don't exist return false; Loading Loading @@ -4209,9 +4269,7 @@ public class DcTracker extends Handler { } private boolean isPlanUnmetered(SubscriptionPlan plan) { return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED && (plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN || plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED); return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED; } private boolean isNrUnmetered() { Loading @@ -4222,13 +4280,13 @@ public class DcTracker extends Handler { if (isNetworkTypeUnmetered(NETWORK_TYPE_NR)) { if (mNrNsaMmwaveUnmetered) { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE) { if (DBG) log("NR unmetered for mmwave only via SubscriptionPlans"); if (DBG) log("NR unmetered for mmwave only"); return true; } return false; } else if (mNrNsaSub6Unmetered) { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { if (DBG) log("NR unmetered for sub6 only via SubscriptionPlans"); if (DBG) log("NR unmetered for sub6 only"); return true; } return false; Loading @@ -4236,7 +4294,7 @@ public class DcTracker extends Handler { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || rat == NETWORK_TYPE_NR) { if (DBG) log("NR unmetered for all frequencies via SubscriptionPlans"); if (DBG) log("NR unmetered for all frequencies"); return true; } return false; Loading Loading @@ -5258,7 +5316,7 @@ public class DcTracker extends Handler { CarrierConfigManager.KEY_UNMETERED_NR_SA_MMWAVE_BOOL); mNrSaSub6Unmetered = b.getBoolean( CarrierConfigManager.KEY_UNMETERED_NR_SA_SUB6_BOOL); mRoamingUnmetered = b.getBoolean( mNrNsaRoamingUnmetered = b.getBoolean( CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL); } } Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java +23 −9 Original line number Diff line number Diff line Loading @@ -18,8 +18,7 @@ package com.android.internal.telephony.dataconnection; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_ADDRESS; Loading Loading @@ -54,6 +53,8 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.CarrierConfigManager; import android.telephony.ServiceState; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; import android.telephony.data.DataProfile; Loading Loading @@ -642,20 +643,31 @@ public class DataConnectionTest extends TelephonyTest { mContextFixture.getCarrierConfigBundle().putStringArray( CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS, new String[] { "default" }); // TODO: Remove these checks after b/176119724 is fixed. doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR) .when(mPhone).getRadioAccessFamily(); mContextFixture.getCarrierConfigBundle().putBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, true); doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA)) .when(mDisplayInfoController).getTelephonyDisplayInfo(); doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType(); testConnectEvent(); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED, SUBSCRIPTION_OVERRIDE_UNMETERED); mDc.onMeterednessChanged(true); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED, 0); mDc.onMeterednessChanged(false); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); } Loading @@ -667,17 +679,19 @@ public class DataConnectionTest extends TelephonyTest { testConnectEvent(); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED, SUBSCRIPTION_OVERRIDE_CONGESTED); mDc.onCongestednessChanged(true); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED, 0); mDc.onCongestednessChanged(false); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); } Loading tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java +58 −3 Original line number Diff line number Diff line Loading @@ -1814,9 +1814,9 @@ public class DcTrackerTest extends TelephonyTest { clearInvocations(mHandler); } private void setUpSubscriptionPlans(boolean is5GUnmetered) throws Exception { private void setUpSubscriptionPlans(boolean isNrUnmetered) throws Exception { List<SubscriptionPlan> plans = new ArrayList<>(); if (is5GUnmetered) { if (isNrUnmetered) { plans.add(SubscriptionPlan.Builder .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), Period.ofMonths(1)) Loading @@ -1834,6 +1834,28 @@ public class DcTrackerTest extends TelephonyTest { replaceInstance(DcTracker.class, "mSubscriptionPlans", mDct, plans); } private void resetSubscriptionPlans() throws Exception { replaceInstance(DcTracker.class, "mSubscriptionPlans", mDct, null); } private void setUpSubscriptionOverride(int[] networkTypes, boolean isUnmetered) throws Exception { List<Integer> networkTypesList = null; if (networkTypes != null) { networkTypesList = new ArrayList<>(); for (int networkType : networkTypes) { networkTypesList.add(networkType); } } replaceInstance(DcTracker.class, "mUnmeteredNetworkTypes", mDct, networkTypesList); replaceInstance(DcTracker.class, "mUnmeteredOverride", mDct, isUnmetered); } private void resetSubscriptionOverride() throws Exception { replaceInstance(DcTracker.class, "mUnmeteredNetworkTypes", mDct, null); replaceInstance(DcTracker.class, "mUnmeteredOverride", mDct, false); } private boolean isNetworkTypeUnmetered(int networkType) throws Exception { Method method = DcTracker.class.getDeclaredMethod( "isNetworkTypeUnmetered", int.class); Loading Loading @@ -1877,6 +1899,34 @@ public class DcTrackerTest extends TelephonyTest { public void testIsNetworkTypeUnmetered() throws Exception { initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL}); // only 5G unmetered setUpSubscriptionOverride(new int[]{TelephonyManager.NETWORK_TYPE_NR}, true); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); // all network types metered setUpSubscriptionOverride(TelephonyManager.getAllNetworkTypes(), false); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); // all network types unmetered setUpSubscriptionOverride(TelephonyManager.getAllNetworkTypes(), true); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); resetSubscriptionOverride(); } @Test public void testIsNetworkTypeUnmeteredViaSubscriptionPlans() throws Exception { initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL}); // only 5G unmetered setUpSubscriptionPlans(true); Loading @@ -1896,7 +1946,6 @@ public class DcTrackerTest extends TelephonyTest { plans.add(SubscriptionPlan.Builder .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), Period.ofMonths(1)) .setTitle("Some 5GB Plan") .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED, SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) .build()); Loading @@ -1905,6 +1954,8 @@ public class DcTrackerTest extends TelephonyTest { assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); resetSubscriptionPlans(); } @Test Loading Loading @@ -1953,6 +2004,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(2)).onMeterednessChanged(true); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2014,6 +2066,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(2)).onMeterednessChanged(true); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2042,6 +2095,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(1)).onMeterednessChanged(false); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2074,6 +2128,7 @@ public class DcTrackerTest extends TelephonyTest { assertFalse(getWatchdogStatus()); resetDataConnection(id); resetSubscriptionPlans(); } /** Loading Loading
src/java/com/android/internal/telephony/dataconnection/DataConnection.java +39 −26 Original line number Diff line number Diff line Loading @@ -16,8 +16,6 @@ package com.android.internal.telephony.dataconnection; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.telephony.data.DataCallResponse.PDU_SESSION_ID_NOT_SET; import static com.android.internal.telephony.dataconnection.DcTracker.REQUEST_TYPE_HANDOVER; Loading Loading @@ -299,7 +297,7 @@ public class DataConnection extends StateMachine { private int mLastFailCause; private static final String NULL_IP = "0.0.0.0"; private Object mUserData; private int mSubscriptionOverride; private boolean mCongestedOverride; private boolean mUnmeteredOverride; private int mRilRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; private int mDataRegState = Integer.MAX_VALUE; Loading Loading @@ -349,7 +347,7 @@ public class DataConnection extends StateMachine { static final int EVENT_BW_REFRESH_RESPONSE = BASE + 14; static final int EVENT_DATA_CONNECTION_VOICE_CALL_STARTED = BASE + 15; static final int EVENT_DATA_CONNECTION_VOICE_CALL_ENDED = BASE + 16; static final int EVENT_DATA_CONNECTION_OVERRIDE_CHANGED = BASE + 17; static final int EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED = BASE + 17; static final int EVENT_KEEPALIVE_STATUS = BASE + 18; static final int EVENT_KEEPALIVE_STARTED = BASE + 19; static final int EVENT_KEEPALIVE_STOPPED = BASE + 20; Loading Loading @@ -394,8 +392,8 @@ public class DataConnection extends StateMachine { "EVENT_DATA_CONNECTION_VOICE_CALL_STARTED"; sCmdToString[EVENT_DATA_CONNECTION_VOICE_CALL_ENDED - BASE] = "EVENT_DATA_CONNECTION_VOICE_CALL_ENDED"; sCmdToString[EVENT_DATA_CONNECTION_OVERRIDE_CHANGED - BASE] = "EVENT_DATA_CONNECTION_OVERRIDE_CHANGED"; sCmdToString[EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED - BASE] = "EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED"; sCmdToString[EVENT_KEEPALIVE_STATUS - BASE] = "EVENT_KEEPALIVE_STATUS"; sCmdToString[EVENT_KEEPALIVE_STARTED - BASE] = "EVENT_KEEPALIVE_STARTED"; sCmdToString[EVENT_KEEPALIVE_STOPPED - BASE] = "EVENT_KEEPALIVE_STOPPED"; Loading Loading @@ -1036,14 +1034,16 @@ public class DataConnection extends StateMachine { setHandoverState(HANDOVER_STATE_IDLE); } public void onSubscriptionOverride(int overrideMask, int overrideValue) { mSubscriptionOverride = (mSubscriptionOverride & ~overrideMask) | (overrideValue & overrideMask); sendMessage(obtainMessage(EVENT_DATA_CONNECTION_OVERRIDE_CHANGED)); /** * Update NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED based on congested override * @param isCongested whether this DC should be set to congested or not */ public void onCongestednessChanged(boolean isCongested) { sendMessage(obtainMessage(EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED, isCongested)); } /** * Update NetworkCapabilities.NET_CAPABILITY_NOT_METERED based on meteredness * Update NetworkCapabilities.NET_CAPABILITY_NOT_METERED based on metered override * @param isUnmetered whether this DC should be set to unmetered or not */ public void onMeterednessChanged(boolean isUnmetered) { Loading Loading @@ -1247,7 +1247,7 @@ public class DataConnection extends StateMachine { mDcFailCause = DataFailCause.NONE; mDisabledApnTypeBitMask = 0; mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; mSubscriptionOverride = 0; mCongestedOverride = false; mUnmeteredOverride = false; mDownlinkBandwidth = 14; mUplinkBandwidth = 14; Loading Loading @@ -1783,15 +1783,9 @@ public class DataConnection extends StateMachine { result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING, !mPhone.getServiceState().getDataRoaming()); result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); // Override values set above when requested by policy if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_UNMETERED) != 0) { result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); } if ((mSubscriptionOverride & SUBSCRIPTION_OVERRIDE_CONGESTED) != 0) { result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); } result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED, !mCongestedOverride); //result.setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED, // mUnmeteredOverride); // TODO: Remove this after b/176119724 is fixed. This is just a workaround to prevent // NET_CAPABILITY_TEMPORARILY_NOT_METERED incorrectly set on devices that are not supposed Loading Loading @@ -2866,10 +2860,29 @@ public class DataConnection extends StateMachine { break; } mUnmeteredOverride = isUnmetered; // fallthrough if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), DataConnection.this); } retVal = HANDLED; break; case EVENT_DATA_CONNECTION_CONGESTEDNESS_CHANGED: boolean isCongested = (boolean) msg.obj; if (isCongested == mCongestedOverride) { retVal = HANDLED; break; } mCongestedOverride = isCongested; if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), DataConnection.this); } retVal = HANDLED; break; case EVENT_DATA_CONNECTION_ROAM_ON: case EVENT_DATA_CONNECTION_ROAM_OFF: case EVENT_DATA_CONNECTION_OVERRIDE_CHANGED: { case EVENT_DATA_CONNECTION_ROAM_OFF: { if (mNetworkAgent != null) { mNetworkAgent.updateLegacySubtype(DataConnection.this); mNetworkAgent.sendNetworkCapabilities(getNetworkCapabilities(), Loading Loading @@ -3661,7 +3674,7 @@ public class DataConnection extends StateMachine { * Dump the current state. * * @param fd * @param pw * @param printWriter * @param args */ @Override Loading Loading @@ -3693,10 +3706,10 @@ public class DataConnection extends StateMachine { pw.println("mLastFailTime=" + TimeUtils.logTimeOfDay(mLastFailTime)); pw.println("mLastFailCause=" + DataFailCause.toString(mLastFailCause)); pw.println("mUserData=" + mUserData); pw.println("mSubscriptionOverride=" + Integer.toHexString(mSubscriptionOverride)); pw.println("mRestrictedNetworkOverride=" + mRestrictedNetworkOverride); pw.println("mUnmeteredUseOnly=" + mUnmeteredUseOnly); pw.println("mUnmeteredOverride=" + mUnmeteredOverride); pw.println("mCongestedOverride=" + mCongestedOverride); pw.println("mDownlinkBandwidth" + mDownlinkBandwidth); pw.println("mUplinkBandwidth=" + mUplinkBandwidth); pw.println("mDefaultQos=" + mDefaultQos); Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +70 −12 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.internal.telephony.dataconnection; import static android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.telephony.TelephonyManager.NETWORK_TYPE_LTE; import static android.telephony.TelephonyManager.NETWORK_TYPE_NR; import static android.telephony.data.ApnSetting.PROTOCOL_IPV4V6; Loading Loading @@ -340,13 +342,23 @@ public class DcTracker extends Handler { private boolean mNrSaAllUnmetered = false; private boolean mNrSaMmwaveUnmetered = false; private boolean mNrSaSub6Unmetered = false; private boolean mRoamingUnmetered = false; private boolean mNrNsaRoamingUnmetered = false; // stats per data call recovery event private DataStallRecoveryStats mDataStallRecoveryStats; /* List of SubscriptionPlans, updated when initialized and when plans are changed. */ private List<SubscriptionPlan> mSubscriptionPlans = null; /* List of network types an unmetered override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ private List<Integer> mUnmeteredNetworkTypes = null; /* List of network types a congested override applies to, set by onSubscriptionOverride * and cleared when the device is rebooted or the override expires. */ private List<Integer> mCongestedNetworkTypes = null; /* Whether an unmetered override is currently active. */ private boolean mUnmeteredOverride = false; /* Whether a congested override is currently active. */ private boolean mCongestedOverride = false; @SimState private int mSimState = TelephonyManager.SIM_STATE_UNKNOWN; Loading Loading @@ -427,11 +439,26 @@ public class DcTracker extends Handler { private final NetworkPolicyManager.SubscriptionCallback mSubscriptionCallback = new NetworkPolicyManager.SubscriptionCallback() { @Override public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue) { public void onSubscriptionOverride(int subId, int overrideMask, int overrideValue, int[] networkTypes) { if (mPhone == null || mPhone.getSubId() != subId) return; for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onSubscriptionOverride(overrideMask, overrideValue); List<Integer> tempList = new ArrayList<>(); for (int networkType : networkTypes) { tempList.add(networkType); } log("Subscription override: overrideMask=" + overrideMask + ", overrideValue=" + overrideValue + ", networkTypes=" + tempList); if (overrideMask == SUBSCRIPTION_OVERRIDE_UNMETERED) { mUnmeteredNetworkTypes = tempList; mUnmeteredOverride = overrideValue != 0; reevaluateUnmeteredConnections(); } else if (overrideMask == SUBSCRIPTION_OVERRIDE_CONGESTED) { mCongestedNetworkTypes = tempList; mCongestedOverride = overrideValue != 0; reevaluateCongestedConnections(); } } Loading Loading @@ -3981,6 +4008,7 @@ public class DcTracker extends Handler { reevaluateUnmeteredConnections(); break; case DctConstants.EVENT_TELEPHONY_DISPLAY_INFO_CHANGED: reevaluateCongestedConnections(); reevaluateUnmeteredConnections(); break; case DctConstants.EVENT_CARRIER_CONFIG_CHANGED: Loading Loading @@ -4157,10 +4185,22 @@ public class DcTracker extends Handler { } } private void reevaluateCongestedConnections() { log("reevaluateCongestedConnections"); int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); // congested override and either network is specified or unknown and all networks specified boolean isCongested = mCongestedOverride && (mCongestedNetworkTypes.contains(rat) || mUnmeteredNetworkTypes.containsAll(Arrays.stream( TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet()))); for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onCongestednessChanged(isCongested); } } private void reevaluateUnmeteredConnections() { log("reevaluateUnmeteredConnections"); int rat = mPhone.getDisplayInfoController().getTelephonyDisplayInfo().getNetworkType(); if (isNrUnmetered() && !mPhone.getServiceState().getRoaming() || mRoamingUnmetered) { if (isNrUnmetered() && (!mPhone.getServiceState().getRoaming() || mNrNsaRoamingUnmetered)) { setDataConnectionUnmetered(true); if (!mWatchdog) { startWatchdogAlarm(); Loading @@ -4178,6 +4218,26 @@ public class DcTracker extends Handler { } private boolean isNetworkTypeUnmetered(@NetworkType int networkType) { boolean isUnmetered; if (mUnmeteredNetworkTypes == null || !mUnmeteredOverride) { // check SubscriptionPlans if override is not defined isUnmetered = isNetworkTypeUnmeteredViaSubscriptionPlan(networkType); log("isNetworkTypeUnmeteredViaSubscriptionPlan: networkType=" + networkType + ", isUnmetered=" + isUnmetered); return isUnmetered; } // unmetered override and either network is specified or unknown and all networks specified isUnmetered = mUnmeteredNetworkTypes.contains(networkType) || mUnmeteredNetworkTypes.containsAll(Arrays.stream( TelephonyManager.getAllNetworkTypes()).boxed().collect(Collectors.toSet())); if (DBG) { log("isNetworkTypeUnmetered: networkType=" + networkType + ", isUnmetered=" + isUnmetered); } return isUnmetered; } private boolean isNetworkTypeUnmeteredViaSubscriptionPlan(@NetworkType int networkType) { if (mSubscriptionPlans == null || mSubscriptionPlans.size() == 0) { // safe return false if unable to get subscription plans or plans don't exist return false; Loading Loading @@ -4209,9 +4269,7 @@ public class DcTracker extends Handler { } private boolean isPlanUnmetered(SubscriptionPlan plan) { return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED && (plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_UNKNOWN || plan.getDataLimitBehavior() == SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED); return plan.getDataLimitBytes() == SubscriptionPlan.BYTES_UNLIMITED; } private boolean isNrUnmetered() { Loading @@ -4222,13 +4280,13 @@ public class DcTracker extends Handler { if (isNetworkTypeUnmetered(NETWORK_TYPE_NR)) { if (mNrNsaMmwaveUnmetered) { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE) { if (DBG) log("NR unmetered for mmwave only via SubscriptionPlans"); if (DBG) log("NR unmetered for mmwave only"); return true; } return false; } else if (mNrNsaSub6Unmetered) { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA) { if (DBG) log("NR unmetered for sub6 only via SubscriptionPlans"); if (DBG) log("NR unmetered for sub6 only"); return true; } return false; Loading @@ -4236,7 +4294,7 @@ public class DcTracker extends Handler { if (override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE || override == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || rat == NETWORK_TYPE_NR) { if (DBG) log("NR unmetered for all frequencies via SubscriptionPlans"); if (DBG) log("NR unmetered for all frequencies"); return true; } return false; Loading Loading @@ -5258,7 +5316,7 @@ public class DcTracker extends Handler { CarrierConfigManager.KEY_UNMETERED_NR_SA_MMWAVE_BOOL); mNrSaSub6Unmetered = b.getBoolean( CarrierConfigManager.KEY_UNMETERED_NR_SA_SUB6_BOOL); mRoamingUnmetered = b.getBoolean( mNrNsaRoamingUnmetered = b.getBoolean( CarrierConfigManager.KEY_UNMETERED_NR_NSA_WHEN_ROAMING_BOOL); } } Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/DataConnectionTest.java +23 −9 Original line number Diff line number Diff line Loading @@ -18,8 +18,7 @@ package com.android.internal.telephony.dataconnection; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED; import static com.android.internal.telephony.TelephonyTestUtils.waitForMs; import static com.android.internal.telephony.dataconnection.DcTrackerTest.FAKE_ADDRESS; Loading Loading @@ -54,6 +53,8 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.CarrierConfigManager; import android.telephony.ServiceState; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; import android.telephony.data.DataProfile; Loading Loading @@ -642,20 +643,31 @@ public class DataConnectionTest extends TelephonyTest { mContextFixture.getCarrierConfigBundle().putStringArray( CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS, new String[] { "default" }); // TODO: Remove these checks after b/176119724 is fixed. doReturn((int) TelephonyManager.NETWORK_TYPE_BITMASK_NR) .when(mPhone).getRadioAccessFamily(); mContextFixture.getCarrierConfigBundle().putBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, true); doReturn(new TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_LTE, TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA)) .when(mDisplayInfoController).getTelephonyDisplayInfo(); doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType(); testConnectEvent(); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED, SUBSCRIPTION_OVERRIDE_UNMETERED); mDc.onMeterednessChanged(true); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_UNMETERED, 0); mDc.onMeterednessChanged(false); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); } Loading @@ -667,17 +679,19 @@ public class DataConnectionTest extends TelephonyTest { testConnectEvent(); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED, SUBSCRIPTION_OVERRIDE_CONGESTED); mDc.onCongestednessChanged(true); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); mDc.onSubscriptionOverride(SUBSCRIPTION_OVERRIDE_CONGESTED, 0); mDc.onCongestednessChanged(false); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_METERED)); assertFalse(getNetworkCapabilities().hasCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)); assertTrue(getNetworkCapabilities().hasCapability(NET_CAPABILITY_NOT_CONGESTED)); } Loading
tests/telephonytests/src/com/android/internal/telephony/dataconnection/DcTrackerTest.java +58 −3 Original line number Diff line number Diff line Loading @@ -1814,9 +1814,9 @@ public class DcTrackerTest extends TelephonyTest { clearInvocations(mHandler); } private void setUpSubscriptionPlans(boolean is5GUnmetered) throws Exception { private void setUpSubscriptionPlans(boolean isNrUnmetered) throws Exception { List<SubscriptionPlan> plans = new ArrayList<>(); if (is5GUnmetered) { if (isNrUnmetered) { plans.add(SubscriptionPlan.Builder .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), Period.ofMonths(1)) Loading @@ -1834,6 +1834,28 @@ public class DcTrackerTest extends TelephonyTest { replaceInstance(DcTracker.class, "mSubscriptionPlans", mDct, plans); } private void resetSubscriptionPlans() throws Exception { replaceInstance(DcTracker.class, "mSubscriptionPlans", mDct, null); } private void setUpSubscriptionOverride(int[] networkTypes, boolean isUnmetered) throws Exception { List<Integer> networkTypesList = null; if (networkTypes != null) { networkTypesList = new ArrayList<>(); for (int networkType : networkTypes) { networkTypesList.add(networkType); } } replaceInstance(DcTracker.class, "mUnmeteredNetworkTypes", mDct, networkTypesList); replaceInstance(DcTracker.class, "mUnmeteredOverride", mDct, isUnmetered); } private void resetSubscriptionOverride() throws Exception { replaceInstance(DcTracker.class, "mUnmeteredNetworkTypes", mDct, null); replaceInstance(DcTracker.class, "mUnmeteredOverride", mDct, false); } private boolean isNetworkTypeUnmetered(int networkType) throws Exception { Method method = DcTracker.class.getDeclaredMethod( "isNetworkTypeUnmetered", int.class); Loading Loading @@ -1877,6 +1899,34 @@ public class DcTrackerTest extends TelephonyTest { public void testIsNetworkTypeUnmetered() throws Exception { initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL}); // only 5G unmetered setUpSubscriptionOverride(new int[]{TelephonyManager.NETWORK_TYPE_NR}, true); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); // all network types metered setUpSubscriptionOverride(TelephonyManager.getAllNetworkTypes(), false); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertFalse(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); // all network types unmetered setUpSubscriptionOverride(TelephonyManager.getAllNetworkTypes(), true); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); resetSubscriptionOverride(); } @Test public void testIsNetworkTypeUnmeteredViaSubscriptionPlans() throws Exception { initApns(PhoneConstants.APN_TYPE_DEFAULT, new String[]{PhoneConstants.APN_TYPE_ALL}); // only 5G unmetered setUpSubscriptionPlans(true); Loading @@ -1896,7 +1946,6 @@ public class DcTrackerTest extends TelephonyTest { plans.add(SubscriptionPlan.Builder .createRecurring(ZonedDateTime.parse("2007-03-14T00:00:00.000Z"), Period.ofMonths(1)) .setTitle("Some 5GB Plan") .setDataLimit(SubscriptionPlan.BYTES_UNLIMITED, SubscriptionPlan.LIMIT_BEHAVIOR_THROTTLED) .build()); Loading @@ -1905,6 +1954,8 @@ public class DcTrackerTest extends TelephonyTest { assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_NR)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_LTE)); assertTrue(isNetworkTypeUnmetered(TelephonyManager.NETWORK_TYPE_UNKNOWN)); resetSubscriptionPlans(); } @Test Loading Loading @@ -1953,6 +2004,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(2)).onMeterednessChanged(true); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2014,6 +2066,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(2)).onMeterednessChanged(true); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2042,6 +2095,7 @@ public class DcTrackerTest extends TelephonyTest { verify(mDataConnection, times(1)).onMeterednessChanged(false); resetDataConnection(id); resetSubscriptionPlans(); } @Test Loading Loading @@ -2074,6 +2128,7 @@ public class DcTrackerTest extends TelephonyTest { assertFalse(getWatchdogStatus()); resetDataConnection(id); resetSubscriptionPlans(); } /** Loading