Loading src/java/com/android/internal/telephony/DisplayInfoController.java +8 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,14 @@ public class DisplayInfoController extends Handler { } } /** * @return True if either the primary or secondary 5G hysteresis timer is active, * and false if neither are. */ public boolean is5GHysteresisActive() { return mNetworkTypeController.is5GHysteresisActive(); } /** * Register for TelephonyDisplayInfo changed. * @param h Handler to notify Loading src/java/com/android/internal/telephony/NetworkTypeController.java +8 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,14 @@ public class NetworkTypeController extends StateMachine { return mOverrideNetworkType; } /** * @return True if either the primary or secondary 5G hysteresis timer is active, * and false if neither are. */ public boolean is5GHysteresisActive() { return mIsPrimaryTimerActive || mIsSecondaryTimerActive; } private void registerForAllEvents() { mPhone.registerForRadioOffOrNotAvailable(getHandler(), EVENT_RADIO_OFF_OR_UNAVAILABLE, null); Loading src/java/com/android/internal/telephony/dataconnection/DataConnection.java +2 −79 Original line number Diff line number Diff line Loading @@ -48,13 +48,11 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; Loading Loading @@ -103,7 +101,6 @@ import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -1317,60 +1314,6 @@ public class DataConnection extends StateMachine { return true; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isDevice5GCapable() { return (mPhone.getRadioAccessFamily() & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isTempNotMeteredSupportedByCarrier() { CarrierConfigManager configManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); if (configManager != null) { PersistableBundle bundle = configManager.getConfigForSubId(mSubId); if (bundle != null) { return bundle.getBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL); } } return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isCampedOn5G() { TelephonyDisplayInfo displayInfo = mPhone.getDisplayInfoController() .getTelephonyDisplayInfo(); int overrideNetworkType = displayInfo.getOverrideNetworkType(); NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); int networkType = nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN : nri.getAccessNetworkTechnology(); return networkType == TelephonyManager.NETWORK_TYPE_NR || ((networkType == TelephonyManager.NETWORK_TYPE_LTE || networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) && (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE)); } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean tempNotMeteredPossible() { return isDevice5GCapable() && isTempNotMeteredSupportedByCarrier() && isCampedOn5G(); } /** * Get the network capabilities for this data connection. * Loading Loading @@ -1493,28 +1436,8 @@ public class DataConnection extends StateMachine { result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few // devices and carriers. if (tempNotMeteredPossible()) { result.setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED, mUnmeteredOverride); } else if (mUnmeteredOverride) { // If temp not metered is not possible, but mUnmeteredOverride got set, that means we // hit the bug. SubscriptionManager subscriptionManager = mPhone.getContext() .getSystemService(SubscriptionManager.class); String message = "Unexpected temp not metered detected. carrier supported=" + isTempNotMeteredSupportedByCarrier() + ", device 5G capable=" + isDevice5GCapable() + ", display info=" + mPhone.getDisplayInfoController().getTelephonyDisplayInfo() + ", subscription plans=" + subscriptionManager.getSubscriptionPlans(mSubId) + ", Service state=" + mPhone.getServiceState(); loge(message); AnomalyReporter.reportAnomaly( UUID.fromString("9151f0fc-01df-4afb-b744-9c4529055249"), message); } final boolean suspended = mNetworkInfo.getDetailedState() == NetworkInfo.DetailedState.SUSPENDED; Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +81 −2 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.CellLocation; import android.telephony.DataFailCause; Loading Loading @@ -128,6 +129,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -4143,9 +4145,28 @@ public class DcTracker extends Handler { } private void setDataConnectionUnmetered(boolean isUnmetered) { // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few // devices and carriers. if (!isUnmetered || (isUnmetered && tempNotMeteredPossible())) { for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onMeterednessChanged(isUnmetered); } } else { // isUnmetered=true but TEMP_NOT_METERED is not possible String message = "Unexpected temp not metered detected. carrier supported=" + isTempNotMeteredSupportedByCarrier() + ", device 5G capable=" + isDevice5GCapable() + ", camped on 5G=" + isCampedOn5G() + ", timer active=" + mPhone.getDisplayInfoController().is5GHysteresisActive() + ", display info=" + mPhone.getDisplayInfoController().getTelephonyDisplayInfo() + ", subscription plans=" + mSubscriptionPlans + ", Service state=" + mPhone.getServiceState(); loge(message); AnomalyReporter.reportAnomaly( UUID.fromString("9151f0fc-01df-4afb-b744-9c4529055250"), message); } } private boolean isNetworkTypeUnmetered(@NetworkType int networkType) { Loading Loading @@ -4248,6 +4269,64 @@ public class DcTracker extends Handler { return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isDevice5GCapable() { return (mPhone.getRadioAccessFamily() & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isTempNotMeteredSupportedByCarrier() { CarrierConfigManager configManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); if (configManager != null) { PersistableBundle bundle = configManager.getConfigForSubId(mPhone.getSubId()); if (bundle != null) { return bundle.getBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL); } } return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isCampedOn5G() { TelephonyDisplayInfo displayInfo = mPhone.getDisplayInfoController() .getTelephonyDisplayInfo(); int overrideNetworkType = displayInfo.getOverrideNetworkType(); NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); int networkType = nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN : nri.getAccessNetworkTechnology(); boolean isNrSa = networkType == TelephonyManager.NETWORK_TYPE_NR; boolean isNrNsa = (networkType == TelephonyManager.NETWORK_TYPE_LTE || networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) && (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE); boolean is5GHysteresisActive = mPhone.getDisplayInfoController().is5GHysteresisActive(); // True if device is on NR SA or NR NSA, or neither but 5G hysteresis is active return isNrSa || isNrNsa || is5GHysteresisActive; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean tempNotMeteredPossible() { return isDevice5GCapable() && isTempNotMeteredSupportedByCarrier() && isCampedOn5G(); } protected void log(String s) { Rlog.d(mLogTag, s); } Loading tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java +24 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.internal.telephony; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; Loading Loading @@ -387,6 +389,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // timer expires moveTimeForward(10 * 1000); Loading @@ -395,6 +398,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -417,6 +421,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); Loading @@ -430,6 +435,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -450,10 +456,10 @@ public class NetworkTypeControllerTest extends TelephonyTest { mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED); processAllMessages(); assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // timer expires moveTimeForward(10 * 1000); Loading @@ -462,6 +468,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -485,6 +492,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange(); Loading @@ -498,6 +506,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected_mmwave", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -522,6 +531,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -531,6 +541,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // secondary timer expires moveTimeForward(30 * 1000); Loading @@ -539,6 +550,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -563,6 +575,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -572,6 +585,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); Loading @@ -585,6 +599,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -610,6 +625,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -619,6 +635,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // secondary timer expires moveTimeForward(30 * 1000); Loading @@ -627,6 +644,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -652,6 +670,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -661,6 +680,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange(); Loading @@ -674,6 +694,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected_mmwave", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -699,6 +720,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // rat is UMTS, should stop timer doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mServiceState).getDataNetworkType(); Loading @@ -709,5 +731,6 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } } Loading
src/java/com/android/internal/telephony/DisplayInfoController.java +8 −0 Original line number Diff line number Diff line Loading @@ -69,6 +69,14 @@ public class DisplayInfoController extends Handler { } } /** * @return True if either the primary or secondary 5G hysteresis timer is active, * and false if neither are. */ public boolean is5GHysteresisActive() { return mNetworkTypeController.is5GHysteresisActive(); } /** * Register for TelephonyDisplayInfo changed. * @param h Handler to notify Loading
src/java/com/android/internal/telephony/NetworkTypeController.java +8 −0 Original line number Diff line number Diff line Loading @@ -172,6 +172,14 @@ public class NetworkTypeController extends StateMachine { return mOverrideNetworkType; } /** * @return True if either the primary or secondary 5G hysteresis timer is active, * and false if neither are. */ public boolean is5GHysteresisActive() { return mIsPrimaryTimerActive || mIsSecondaryTimerActive; } private void registerForAllEvents() { mPhone.registerForRadioOffOrNotAvailable(getHandler(), EVENT_RADIO_OFF_OR_UNAVAILABLE, null); Loading
src/java/com/android/internal/telephony/dataconnection/DataConnection.java +2 −79 Original line number Diff line number Diff line Loading @@ -48,13 +48,11 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; Loading Loading @@ -103,7 +101,6 @@ import java.util.Collection; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -1317,60 +1314,6 @@ public class DataConnection extends StateMachine { return true; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isDevice5GCapable() { return (mPhone.getRadioAccessFamily() & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isTempNotMeteredSupportedByCarrier() { CarrierConfigManager configManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); if (configManager != null) { PersistableBundle bundle = configManager.getConfigForSubId(mSubId); if (bundle != null) { return bundle.getBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL); } } return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isCampedOn5G() { TelephonyDisplayInfo displayInfo = mPhone.getDisplayInfoController() .getTelephonyDisplayInfo(); int overrideNetworkType = displayInfo.getOverrideNetworkType(); NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); int networkType = nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN : nri.getAccessNetworkTechnology(); return networkType == TelephonyManager.NETWORK_TYPE_NR || ((networkType == TelephonyManager.NETWORK_TYPE_LTE || networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) && (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE)); } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean tempNotMeteredPossible() { return isDevice5GCapable() && isTempNotMeteredSupportedByCarrier() && isCampedOn5G(); } /** * Get the network capabilities for this data connection. * Loading Loading @@ -1493,28 +1436,8 @@ public class DataConnection extends StateMachine { result.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED); } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few // devices and carriers. if (tempNotMeteredPossible()) { result.setCapability(NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED, mUnmeteredOverride); } else if (mUnmeteredOverride) { // If temp not metered is not possible, but mUnmeteredOverride got set, that means we // hit the bug. SubscriptionManager subscriptionManager = mPhone.getContext() .getSystemService(SubscriptionManager.class); String message = "Unexpected temp not metered detected. carrier supported=" + isTempNotMeteredSupportedByCarrier() + ", device 5G capable=" + isDevice5GCapable() + ", display info=" + mPhone.getDisplayInfoController().getTelephonyDisplayInfo() + ", subscription plans=" + subscriptionManager.getSubscriptionPlans(mSubId) + ", Service state=" + mPhone.getServiceState(); loge(message); AnomalyReporter.reportAnomaly( UUID.fromString("9151f0fc-01df-4afb-b744-9c4529055249"), message); } final boolean suspended = mNetworkInfo.getDetailedState() == NetworkInfo.DetailedState.SUSPENDED; Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +81 −2 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ import android.telephony.AccessNetworkConstants.TransportType; import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.CellLocation; import android.telephony.DataFailCause; Loading Loading @@ -128,6 +129,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; Loading Loading @@ -4143,9 +4145,28 @@ public class DcTracker extends Handler { } private void setDataConnectionUnmetered(boolean isUnmetered) { // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few // devices and carriers. if (!isUnmetered || (isUnmetered && tempNotMeteredPossible())) { for (DataConnection dataConnection : mDataConnections.values()) { dataConnection.onMeterednessChanged(isUnmetered); } } else { // isUnmetered=true but TEMP_NOT_METERED is not possible String message = "Unexpected temp not metered detected. carrier supported=" + isTempNotMeteredSupportedByCarrier() + ", device 5G capable=" + isDevice5GCapable() + ", camped on 5G=" + isCampedOn5G() + ", timer active=" + mPhone.getDisplayInfoController().is5GHysteresisActive() + ", display info=" + mPhone.getDisplayInfoController().getTelephonyDisplayInfo() + ", subscription plans=" + mSubscriptionPlans + ", Service state=" + mPhone.getServiceState(); loge(message); AnomalyReporter.reportAnomaly( UUID.fromString("9151f0fc-01df-4afb-b744-9c4529055250"), message); } } private boolean isNetworkTypeUnmetered(@NetworkType int networkType) { Loading Loading @@ -4248,6 +4269,64 @@ public class DcTracker extends Handler { return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isDevice5GCapable() { return (mPhone.getRadioAccessFamily() & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isTempNotMeteredSupportedByCarrier() { CarrierConfigManager configManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); if (configManager != null) { PersistableBundle bundle = configManager.getConfigForSubId(mPhone.getSubId()); if (bundle != null) { return bundle.getBoolean( CarrierConfigManager.KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL); } } return false; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean isCampedOn5G() { TelephonyDisplayInfo displayInfo = mPhone.getDisplayInfoController() .getTelephonyDisplayInfo(); int overrideNetworkType = displayInfo.getOverrideNetworkType(); NetworkRegistrationInfo nri = mPhone.getServiceState().getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); int networkType = nri == null ? TelephonyManager.NETWORK_TYPE_UNKNOWN : nri.getAccessNetworkTechnology(); boolean isNrSa = networkType == TelephonyManager.NETWORK_TYPE_NR; boolean isNrNsa = (networkType == TelephonyManager.NETWORK_TYPE_LTE || networkType == TelephonyManager.NETWORK_TYPE_LTE_CA) && (overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA || overrideNetworkType == TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE); boolean is5GHysteresisActive = mPhone.getDisplayInfoController().is5GHysteresisActive(); // True if device is on NR SA or NR NSA, or neither but 5G hysteresis is active return isNrSa || isNrNsa || is5GHysteresisActive; } // 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 // to use 5G unmetered network. Currently TEMPORARILY_NOT_METERED can only happen on few devices // and carriers. private boolean tempNotMeteredPossible() { return isDevice5GCapable() && isTempNotMeteredSupportedByCarrier() && isCampedOn5G(); } protected void log(String s) { Rlog.d(mLogTag, s); } Loading
tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java +24 −1 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.internal.telephony; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; Loading Loading @@ -387,6 +389,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // timer expires moveTimeForward(10 * 1000); Loading @@ -395,6 +398,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -417,6 +421,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); Loading @@ -430,6 +435,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -450,10 +456,10 @@ public class NetworkTypeControllerTest extends TelephonyTest { mNetworkTypeController.sendMessage(EVENT_NR_FREQUENCY_CHANGED); processAllMessages(); assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // timer expires moveTimeForward(10 * 1000); Loading @@ -462,6 +468,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -485,6 +492,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange(); Loading @@ -498,6 +506,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected_mmwave", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -522,6 +531,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -531,6 +541,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // secondary timer expires moveTimeForward(30 * 1000); Loading @@ -539,6 +550,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -563,6 +575,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -572,6 +585,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState(); Loading @@ -585,6 +599,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -610,6 +625,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -619,6 +635,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // secondary timer expires moveTimeForward(30 * 1000); Loading @@ -627,6 +644,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -652,6 +670,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // primary timer expires moveTimeForward(10 * 1000); Loading @@ -661,6 +680,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // reconnect to NR in the middle of the timer doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange(); Loading @@ -674,6 +694,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected_mmwave", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -699,6 +720,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE, mNetworkTypeController.getOverrideNetworkType()); assertTrue(mNetworkTypeController.is5GHysteresisActive()); // rat is UMTS, should stop timer doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mServiceState).getDataNetworkType(); Loading @@ -709,5 +731,6 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } }