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 −82 Original line number Diff line number Diff line Loading @@ -49,14 +49,12 @@ import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; 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 @@ -109,7 +107,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; import java.util.function.Consumer; Loading Loading @@ -1557,60 +1554,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 @@ -1721,31 +1664,8 @@ public class DataConnection extends StateMachine { !mPhone.getServiceState().getDataRoaming()); 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 // 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); } result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED, !mIsSuspended); result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); Loading src/java/com/android/internal/telephony/dataconnection/DcTracker.java +81 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,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 @@ -136,6 +137,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 @@ -4189,9 +4191,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 @@ -4312,6 +4333,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 @@ -392,6 +394,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 @@ -400,6 +403,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -422,6 +426,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 @@ -435,6 +440,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -455,10 +461,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 @@ -467,6 +473,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -490,6 +497,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 @@ -503,6 +511,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 @@ -527,6 +536,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 @@ -536,6 +546,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 @@ -544,6 +555,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -568,6 +580,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 @@ -577,6 +590,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 @@ -590,6 +604,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -615,6 +630,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 @@ -624,6 +640,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 @@ -632,6 +649,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -657,6 +675,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 @@ -666,6 +685,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 @@ -679,6 +699,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 @@ -704,6 +725,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 @@ -714,5 +736,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 −82 Original line number Diff line number Diff line Loading @@ -49,14 +49,12 @@ import android.telephony.Annotation.ApnType; import android.telephony.Annotation.DataFailureCause; import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; 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 @@ -109,7 +107,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; import java.util.function.Consumer; Loading Loading @@ -1557,60 +1554,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 @@ -1721,31 +1664,8 @@ public class DataConnection extends StateMachine { !mPhone.getServiceState().getDataRoaming()); 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 // 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); } result.setCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED, !mIsSuspended); result.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED); Loading
src/java/com/android/internal/telephony/dataconnection/DcTracker.java +81 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,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 @@ -136,6 +137,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 @@ -4189,9 +4191,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 @@ -4312,6 +4333,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 @@ -392,6 +394,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 @@ -400,6 +403,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -422,6 +426,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 @@ -435,6 +440,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -455,10 +461,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 @@ -467,6 +473,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -490,6 +497,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 @@ -503,6 +511,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 @@ -527,6 +536,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 @@ -536,6 +546,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 @@ -544,6 +555,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -568,6 +580,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 @@ -577,6 +590,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 @@ -590,6 +604,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -615,6 +630,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 @@ -624,6 +640,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 @@ -632,6 +649,7 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("connected", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } @Test Loading @@ -657,6 +675,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 @@ -666,6 +685,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 @@ -679,6 +699,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 @@ -704,6 +725,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 @@ -714,5 +736,6 @@ public class NetworkTypeControllerTest extends TelephonyTest { assertEquals("legacy", getCurrentState().getName()); assertEquals(TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE, mNetworkTypeController.getOverrideNetworkType()); assertFalse(mNetworkTypeController.is5GHysteresisActive()); } }