Loading src/java/com/android/internal/telephony/SlidingWindowEventCounter.java +22 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,28 @@ public class SlidingWindowEventCounter { } @VisibleForTesting int getNumOccurrences() { int getQueuedNumOccurrences() { return mTimestampQueueMillis.size(); } /** * @return the time span in ms of the sliding window. */ public synchronized long getWindowSizeMillis() { return mWindowSizeMillis; } /** * @return the least number of occurrences for {@link #isInWindow} to be true. */ public synchronized int getNumOccurrences() { return mNumOccurrences; } @Override public String toString() { return String.format("SlidingWindowEventCounter=[windowSizeMillis=" + mWindowSizeMillis + ", numOccurrences=" + mNumOccurrences + ", timestampQueueMillis=" + mTimestampQueueMillis + "]"); } } src/java/com/android/internal/telephony/data/DataConfigManager.java +214 −17 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.telephony.data.ApnSetting; import android.text.TextUtils; import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.data.DataNetworkController.HandoverRule; import com.android.internal.telephony.data.DataRetryManager.DataHandoverRetryRule; Loading Loading @@ -72,6 +73,9 @@ public class DataConfigManager extends Handler { /** Event for carrier config changed. */ private static final int EVENT_CARRIER_CONFIG_CHANGED = 1; /** Event for device config changed. */ private static final int EVENT_DEVICE_CONFIG_CHANGED = 2; /** Indicates the bandwidth estimation source is from the modem. */ private static final String BANDWIDTH_SOURCE_MODEM_STRING_VALUE = "modem"; Loading Loading @@ -185,13 +189,52 @@ public class DataConfigManager extends Handler { @Retention(RetentionPolicy.SOURCE) private @interface DataConfigNetworkType {} /** DeviceConfig key of anomaly report threshold for back to back ims release-request. */ private static final String KEY_ANOMALY_IMS_RELEASE_REQUEST = "anomaly_ims_release_request"; /** DeviceConfig key of anomaly report threshold for frequent setup data failure. */ private static final String KEY_ANOMALY_SETUP_DATA_CALL_FAILURE = "anomaly_setup_data_call_failure"; /** DeviceConfig key of anomaly report threshold for frequent network-unwanted call. */ private static final String KEY_ANOMALY_NETWORK_UNWANTED = "anomaly_network_unwanted"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in connecting state. */ private static final String KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT = "anomaly_network_connecting_timeout"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in disconnecting state.*/ private static final String KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT = "anomaly_network_disconnecting_timeout"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in handover state. */ private static final String KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT = "anomaly_network_handover_timeout"; /** Anomaly report thresholds for frequent setup data call failure. */ private EventFrequency mSetupDataCallAnomalyReportThreshold; /** Anomaly report thresholds for back to back release-request of IMS. */ private EventFrequency mImsReleaseRequestAnomalyReportThreshold; /** * Anomaly report thresholds for frequent network unwanted call * at {@link TelephonyNetworkAgent#onNetworkUnwanted} */ private EventFrequency mNetworkUnwantedAnomalyReportThreshold; /** * The minimal time window for duplicate release-request for IMS, the violation of which * triggers anomaly report in {@link DataNetworkController}. * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#ConnectingState}. */ private final long mImsRequestReleaseThrottleAnomalyWindowMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_TELEPHONY, "ims_release_request_window", 0); private int mNetworkConnectingTimeout; /** * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#DisconnectingState}. */ private int mNetworkDisconnectingTimeout; /** * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#HandoverState}. */ private int mNetworkHandoverTimeout; private @NonNull final Phone mPhone; private @NonNull final String mLogTag; Loading Loading @@ -247,6 +290,7 @@ public class DataConfigManager extends Handler { mCarrierConfigManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); // Register for carrier configs update IntentFilter filter = new IntentFilter(); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); mPhone.getContext().registerReceiver(new BroadcastReceiver() { Loading @@ -262,8 +306,20 @@ public class DataConfigManager extends Handler { } }, filter, null, mPhone); // Register for device config update DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_TELEPHONY, this::post, properties -> { if (TextUtils.equals(DeviceConfig.NAMESPACE_TELEPHONY, properties.getNamespace())) { sendEmptyMessage(EVENT_DEVICE_CONFIG_CHANGED); } }); // Must be called to set mCarrierConfig and mResources to non-null values updateConfig(); updateCarrierConfig(); updateDeviceConfig(); mConfigUpdateRegistrants.notifyRegistrants(); } @Override Loading @@ -271,13 +327,44 @@ public class DataConfigManager extends Handler { switch (msg.what) { case EVENT_CARRIER_CONFIG_CHANGED: log("EVENT_CARRIER_CONFIG_CHANGED"); updateConfig(); updateCarrierConfig(); mConfigUpdateRegistrants.notifyRegistrants(); break; case EVENT_DEVICE_CONFIG_CHANGED: log("EVENT_DEVICE_CONFIG_CHANGED"); updateDeviceConfig(); mConfigUpdateRegistrants.notifyRegistrants(); break; default: loge("Unexpected message " + msg.what); } } /** Update local properties from {@link DeviceConfig} */ private void updateDeviceConfig() { DeviceConfig.Properties properties = //read all telephony properties DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TELEPHONY); mImsReleaseRequestAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_IMS_RELEASE_REQUEST, null), 300000, 12); mNetworkUnwantedAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_NETWORK_UNWANTED, null), 300000, 12); mSetupDataCallAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_SETUP_DATA_CALL_FAILURE, null), 0, 2); mNetworkConnectingTimeout = properties.getInt( KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT, 86400000); mNetworkDisconnectingTimeout = properties.getInt( KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT, 86400000); mNetworkHandoverTimeout = properties.getInt( KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT, 86400000); } /** * @return {@code true} if the configuration is carrier specific. {@code false} if the * configuration is the default (i.e. SIM not inserted). Loading @@ -287,9 +374,9 @@ public class DataConfigManager extends Handler { } /** * Update the configuration. * Update the configuration from carrier configs and resources. */ private void updateConfig() { private void updateCarrierConfig() { if (mCarrierConfigManager != null) { mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); } Loading @@ -310,8 +397,6 @@ public class DataConfigManager extends Handler { log("Data config updated. Config is " + (isConfigCarrierSpecific() ? "" : "not ") + "carrier specific."); mConfigUpdateRegistrants.notifyRegistrants(); } /** Loading Loading @@ -666,10 +751,52 @@ public class DataConfigManager extends Handler { } /** * @return The IMS back to back request/release minimal interval. * Anomaly report thresholds for frequent setup data call failure. * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalySetupDataCallThreshold() { return mSetupDataCallAnomalyReportThreshold; } /** * Anomaly report thresholds for frequent network unwanted call * at {@link TelephonyNetworkAgent#onNetworkUnwanted} * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalyNetworkUnwantedThreshold() { return mNetworkUnwantedAnomalyReportThreshold; } /** * Anomaly report thresholds for back to back release-request of IMS. * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalyImsReleaseRequestThreshold() { return mImsReleaseRequestAnomalyReportThreshold; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#ConnectingState}. */ public long getImsRequestReleaseThrottleAnomalyWindowMs() { return mImsRequestReleaseThrottleAnomalyWindowMs; public int getAnomalyNetworkConnectingTimeoutMs() { return mNetworkConnectingTimeout; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#DisconnectingState}. */ public int getAnomalyNetworkDisconnectingTimeoutMs() { return mNetworkDisconnectingTimeout; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#HandoverState}. */ public int getNetworkHandoverTimeoutMs() { return mNetworkHandoverTimeout; } /** Loading Loading @@ -794,6 +921,72 @@ public class DataConfigManager extends Handler { } } /** * Describe an event occurs eventNumOccurrence within a time span timeWindow */ public static class EventFrequency { /** The time window in ms within which event occurs. */ public final long timeWindow; /** The number of time the event occurs. */ public final int eventNumOccurrence; /** * Constructor * * @param timeWindow The time window in ms within which event occurs. * @param eventNumOccurrence The number of time the event occurs. */ public EventFrequency(long timeWindow, int eventNumOccurrence) { this.timeWindow = timeWindow; this.eventNumOccurrence = eventNumOccurrence; } @Override public String toString() { return String.format("EventFrequency=[timeWindow=%d, eventNumOccurrence=%d]", timeWindow, eventNumOccurrence); } } /** * Parse a pair of event throttle thresholds of the form "time window in ms,occurrences" * into {@link EventFrequency} * @param s String to be parsed in the form of "time window in ms,occurrences" * @param defaultTimeWindow The time window to return if parsing failed. * @param defaultOccurrences The occurrence to return if parsing failed. * @return timeWindow and occurrence wrapped in EventFrequency */ @VisibleForTesting public EventFrequency parseSlidingWindowCounterThreshold(String s, long defaultTimeWindow, int defaultOccurrences) { EventFrequency defaultValue = new EventFrequency(defaultTimeWindow, defaultOccurrences); if (TextUtils.isEmpty(s)) return defaultValue; final String[] pair = s.split(","); if (pair.length != 2) { loge("Invalid format: " + s + "Format should be in \"time window in ms,occurrences\". " + "Using default instead."); return defaultValue; } long windowSpan; int occurrence; try { windowSpan = Long.parseLong(pair[0].trim()); } catch (NumberFormatException e) { loge("Exception parsing SlidingWindow window span " + pair[0] + ": " + e); return defaultValue; } try { occurrence = Integer.parseInt(pair[1].trim()); } catch (NumberFormatException e) { loge("Exception parsing SlidingWindow occurrence as integer " + pair[1] + ": " + e); return defaultValue; } return new EventFrequency(windowSpan, occurrence); } /** * @return Get rules for handover between IWLAN and cellular networks. * Loading Loading @@ -981,8 +1174,12 @@ public class DataConfigManager extends Handler { pw.increaseIndent(); mDataHandoverRetryRules.forEach(pw::println); pw.decreaseIndent(); pw.println("IMS request release throttle anomaly window in ms=" + mImsRequestReleaseThrottleAnomalyWindowMs); pw.println("mSetupDataCallAnomalyReport=" + mSetupDataCallAnomalyReportThreshold); pw.println("mNetworkUnwantedAnomalyReport=" + mNetworkUnwantedAnomalyReportThreshold); pw.println("mImsReleaseRequestAnomalyReport=" + mImsReleaseRequestAnomalyReportThreshold); pw.println("mNetworkConnectingTimeout=" + mNetworkConnectingTimeout); pw.println("mNetworkDisconnectingTimeout=" + mNetworkDisconnectingTimeout); pw.println("mNetworkHandoverTimeout=" + mNetworkHandoverTimeout); pw.println("Metered APN types=" + mMeteredApnTypes.stream() .map(ApnSetting::getApnTypeString).collect(Collectors.joining(","))); pw.println("Roaming metered APN types=" + mRoamingMeteredApnTypes.stream() Loading src/java/com/android/internal/telephony/data/DataNetwork.java +31 −22 Original line number Diff line number Diff line Loading @@ -207,8 +207,10 @@ public class DataNetwork extends StateMachine { /** * Event for data network stuck in transient (i.e. connecting/disconnecting/handover) state for * too long time. Timeout value specified in {@link #MAXIMUM_CONNECTING_DURATION_MILLIS}, * {@link #MAXIMUM_DISCONNECTING_DURATION_MILLIS}, {@link #MAXIMUM_HANDOVER_DURATION_MILLIS}. * too long time. Timeout value specified in * {@link DataConfigManager#getAnomalyNetworkConnectingTimeoutMs()}, * {@link DataConfigManager#getAnomalyNetworkDisconnectingTimeoutMs()}, * {@link DataConfigManager#getNetworkHandoverTimeoutMs()}. */ private static final int EVENT_STUCK_IN_TRANSIENT_STATE = 20; Loading @@ -227,18 +229,6 @@ public class DataNetwork extends StateMachine { /** Invalid context id. */ private static final int INVALID_CID = -1; /** The maximum time the data network can stay in {@link ConnectingState}. */ private static final long MAXIMUM_CONNECTING_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** The maximum time the data network can stay in {@link DisconnectingState}. */ private static final long MAXIMUM_DISCONNECTING_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** The maximum time the data network can stay in {@link HandoverState}. */ private static final long MAXIMUM_HANDOVER_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** * The data network providing default internet will have a higher score of 50. Other network * will have a slightly lower score of 45. The intention is other connections will not cause Loading Loading @@ -781,6 +771,13 @@ public class DataNetwork extends StateMachine { * @param dataNetwork The data network. */ public abstract void onNetworkCapabilitiesChanged(@NonNull DataNetwork dataNetwork); /** * Called when attempt to tear down a data network * * @param dataNetwork The data network. */ public abstract void onTrackNetworkUnwanted(@NonNull DataNetwork dataNetwork); } /** Loading Loading @@ -1046,7 +1043,7 @@ public class DataNetwork extends StateMachine { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_CONNECTING_DURATION_MILLIS); mDataConfigManager.getAnomalyNetworkConnectingTimeoutMs()); // Need to calculate the initial capabilities before creating the network agent. updateNetworkCapabilities(); mNetworkAgent = createNetworkAgent(); Loading Loading @@ -1103,7 +1100,8 @@ public class DataNetwork extends StateMachine { case EVENT_STUCK_IN_TRANSIENT_STATE: String message = "Data network stuck in connecting state for " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_CONNECTING_DURATION_MILLIS) + " seconds."; mDataConfigManager.getAnomalyNetworkConnectingTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("58c56403-7ea7-4e56-a0c7-e467114d09b8"), message); Loading Loading @@ -1235,7 +1233,8 @@ public class DataNetwork extends StateMachine { private final class HandoverState extends State { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_HANDOVER_DURATION_MILLIS); sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, mDataConfigManager.getNetworkHandoverTimeoutMs()); notifyPreciseDataConnectionState(); } Loading Loading @@ -1277,10 +1276,10 @@ public class DataNetwork extends StateMachine { case EVENT_STUCK_IN_TRANSIENT_STATE: String message = "Data service did not respond the handover request within " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_HANDOVER_DURATION_MILLIS) + " seconds."; mDataConfigManager.getNetworkHandoverTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("15f60e1d-c985-48a9-abc4-be76e343864f"), message); UUID.fromString("1afe68cb-8b41-4964-a737-4f34372429ea"), message); // Handover failed. Use the retry logic defined in // CarrierConfigManager.KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY. Loading Loading @@ -1346,7 +1345,7 @@ public class DataNetwork extends StateMachine { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_DISCONNECTING_DURATION_MILLIS); mDataConfigManager.getAnomalyNetworkDisconnectingTimeoutMs()); notifyPreciseDataConnectionState(); } Loading Loading @@ -1378,7 +1377,8 @@ public class DataNetwork extends StateMachine { String message = "RIL did not send data call list changed event after " + "deactivate data call request within " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_DISCONNECTING_DURATION_MILLIS) + " seconds."; mDataConfigManager.getAnomalyNetworkDisconnectingTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("d0e4fa1c-c57b-4ba5-b4b6-8955487012cc"), message); Loading Loading @@ -2253,6 +2253,14 @@ public class DataNetwork extends StateMachine { return; } //track frequent networkUnwanted call of IMS and INTERNET if ((isConnected()) && (mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) || mNetworkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET))) { mDataNetworkCallback.onTrackNetworkUnwanted(this); } // TODO: Need to support DataService.REQUEST_REASON_SHUTDOWN mDataServiceManagers.get(mTransport).deactivateDataCall(mCid.get(mTransport), DataService.REQUEST_REASON_NORMAL, Loading @@ -2268,7 +2276,8 @@ public class DataNetwork extends StateMachine { return mDataConfigManager.isImsDelayTearDownEnabled() && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) && mPhone.getImsPhone() != null && mPhone.getImsPhone().getCallTracker().getState() != PhoneConstants.State.IDLE; && mPhone.getImsPhone().getCallTracker().getState() != PhoneConstants.State.IDLE; } /** Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +62 −7 File changed.Preview size limit exceeded, changes collapsed. Show changes src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java +0 −39 Original line number Diff line number Diff line Loading @@ -22,29 +22,24 @@ import android.annotation.Nullable; import android.net.KeepalivePacketData; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; import android.net.NetworkScore; import android.net.QosFilter; import android.net.QosSessionAttributes; import android.net.Uri; import android.os.Looper; import android.telephony.AnomalyReporter; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.LocalLog; import com.android.internal.telephony.Phone; import com.android.internal.telephony.SlidingWindowEventCounter; import com.android.telephony.Rlog; import java.io.FileDescriptor; import java.io.PrintWriter; import java.time.Duration; import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; /** * TelephonyNetworkAgent class represents a single PDN (Packet Data Network). It is an agent Loading @@ -56,13 +51,6 @@ public class TelephonyNetworkAgent extends NetworkAgent implements NotifyQosSess private final Phone mPhone; private final LocalLog mLocalLog = new LocalLog(128); /** Event counter for unwanted network within time window, is used to trigger anomaly report. */ private static final long NETWORK_UNWANTED_ANOMALY_WINDOW_MS = TimeUnit.MINUTES.toMillis(5); private static final int NETWORK_UNWANTED_ANOMALY_NUM_OCCURRENCES = 12; private static final SlidingWindowEventCounter sNetworkUnwantedCounter = new SlidingWindowEventCounter(NETWORK_UNWANTED_ANOMALY_WINDOW_MS, NETWORK_UNWANTED_ANOMALY_NUM_OCCURRENCES); /** The parent data network. */ private final @NonNull DataNetwork mDataNetwork; Loading Loading @@ -189,36 +177,9 @@ public class TelephonyNetworkAgent extends NetworkAgent implements NotifyQosSess return; } NetworkCapabilities capabilities = mDataNetwork.getNetworkCapabilities(); if ((mDataNetwork.isConnected() || mDataNetwork.isHandoverInProgress()) && (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))) { trackNetworkUnwanted(); } mDataNetwork.tearDown(DataNetwork.TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED); } /** * There have been several bugs where a RECONNECT loop kicks off where a DataConnection * connects to the Network, ConnectivityService indicates that the Network is unwanted, * and then the DataConnection reconnects. By the time we get the bug report it's too late * because there have already been hundreds of RECONNECTS. This is meant to capture the issue * when it first starts. * * The unwanted counter is configured to only take an anomaly report in extreme cases. * This is to avoid having the anomaly message show up on several devices. * */ private void trackNetworkUnwanted() { if (sNetworkUnwantedCounter.addOccurrence()) { AnomalyReporter.reportAnomaly( UUID.fromString("9f3bc55b-bfa6-4e26-afaa-5031426a66d2"), "Network Unwanted called 12 times in 5 minutes."); } } /** * @return The unique id of the agent. */ Loading Loading
src/java/com/android/internal/telephony/SlidingWindowEventCounter.java +22 −1 Original line number Diff line number Diff line Loading @@ -81,7 +81,28 @@ public class SlidingWindowEventCounter { } @VisibleForTesting int getNumOccurrences() { int getQueuedNumOccurrences() { return mTimestampQueueMillis.size(); } /** * @return the time span in ms of the sliding window. */ public synchronized long getWindowSizeMillis() { return mWindowSizeMillis; } /** * @return the least number of occurrences for {@link #isInWindow} to be true. */ public synchronized int getNumOccurrences() { return mNumOccurrences; } @Override public String toString() { return String.format("SlidingWindowEventCounter=[windowSizeMillis=" + mWindowSizeMillis + ", numOccurrences=" + mNumOccurrences + ", timestampQueueMillis=" + mTimestampQueueMillis + "]"); } }
src/java/com/android/internal/telephony/data/DataConfigManager.java +214 −17 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.telephony.data.ApnSetting; import android.text.TextUtils; import android.util.IndentingPrintWriter; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.Phone; import com.android.internal.telephony.data.DataNetworkController.HandoverRule; import com.android.internal.telephony.data.DataRetryManager.DataHandoverRetryRule; Loading Loading @@ -72,6 +73,9 @@ public class DataConfigManager extends Handler { /** Event for carrier config changed. */ private static final int EVENT_CARRIER_CONFIG_CHANGED = 1; /** Event for device config changed. */ private static final int EVENT_DEVICE_CONFIG_CHANGED = 2; /** Indicates the bandwidth estimation source is from the modem. */ private static final String BANDWIDTH_SOURCE_MODEM_STRING_VALUE = "modem"; Loading Loading @@ -185,13 +189,52 @@ public class DataConfigManager extends Handler { @Retention(RetentionPolicy.SOURCE) private @interface DataConfigNetworkType {} /** DeviceConfig key of anomaly report threshold for back to back ims release-request. */ private static final String KEY_ANOMALY_IMS_RELEASE_REQUEST = "anomaly_ims_release_request"; /** DeviceConfig key of anomaly report threshold for frequent setup data failure. */ private static final String KEY_ANOMALY_SETUP_DATA_CALL_FAILURE = "anomaly_setup_data_call_failure"; /** DeviceConfig key of anomaly report threshold for frequent network-unwanted call. */ private static final String KEY_ANOMALY_NETWORK_UNWANTED = "anomaly_network_unwanted"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in connecting state. */ private static final String KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT = "anomaly_network_connecting_timeout"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in disconnecting state.*/ private static final String KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT = "anomaly_network_disconnecting_timeout"; /** DeviceConfig key of anomaly report threshold for DataNetwork stuck in handover state. */ private static final String KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT = "anomaly_network_handover_timeout"; /** Anomaly report thresholds for frequent setup data call failure. */ private EventFrequency mSetupDataCallAnomalyReportThreshold; /** Anomaly report thresholds for back to back release-request of IMS. */ private EventFrequency mImsReleaseRequestAnomalyReportThreshold; /** * Anomaly report thresholds for frequent network unwanted call * at {@link TelephonyNetworkAgent#onNetworkUnwanted} */ private EventFrequency mNetworkUnwantedAnomalyReportThreshold; /** * The minimal time window for duplicate release-request for IMS, the violation of which * triggers anomaly report in {@link DataNetworkController}. * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#ConnectingState}. */ private final long mImsRequestReleaseThrottleAnomalyWindowMs = DeviceConfig.getInt(DeviceConfig.NAMESPACE_TELEPHONY, "ims_release_request_window", 0); private int mNetworkConnectingTimeout; /** * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#DisconnectingState}. */ private int mNetworkDisconnectingTimeout; /** * Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#HandoverState}. */ private int mNetworkHandoverTimeout; private @NonNull final Phone mPhone; private @NonNull final String mLogTag; Loading Loading @@ -247,6 +290,7 @@ public class DataConfigManager extends Handler { mCarrierConfigManager = mPhone.getContext().getSystemService(CarrierConfigManager.class); // Register for carrier configs update IntentFilter filter = new IntentFilter(); filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); mPhone.getContext().registerReceiver(new BroadcastReceiver() { Loading @@ -262,8 +306,20 @@ public class DataConfigManager extends Handler { } }, filter, null, mPhone); // Register for device config update DeviceConfig.addOnPropertiesChangedListener( DeviceConfig.NAMESPACE_TELEPHONY, this::post, properties -> { if (TextUtils.equals(DeviceConfig.NAMESPACE_TELEPHONY, properties.getNamespace())) { sendEmptyMessage(EVENT_DEVICE_CONFIG_CHANGED); } }); // Must be called to set mCarrierConfig and mResources to non-null values updateConfig(); updateCarrierConfig(); updateDeviceConfig(); mConfigUpdateRegistrants.notifyRegistrants(); } @Override Loading @@ -271,13 +327,44 @@ public class DataConfigManager extends Handler { switch (msg.what) { case EVENT_CARRIER_CONFIG_CHANGED: log("EVENT_CARRIER_CONFIG_CHANGED"); updateConfig(); updateCarrierConfig(); mConfigUpdateRegistrants.notifyRegistrants(); break; case EVENT_DEVICE_CONFIG_CHANGED: log("EVENT_DEVICE_CONFIG_CHANGED"); updateDeviceConfig(); mConfigUpdateRegistrants.notifyRegistrants(); break; default: loge("Unexpected message " + msg.what); } } /** Update local properties from {@link DeviceConfig} */ private void updateDeviceConfig() { DeviceConfig.Properties properties = //read all telephony properties DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TELEPHONY); mImsReleaseRequestAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_IMS_RELEASE_REQUEST, null), 300000, 12); mNetworkUnwantedAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_NETWORK_UNWANTED, null), 300000, 12); mSetupDataCallAnomalyReportThreshold = parseSlidingWindowCounterThreshold( properties.getString(KEY_ANOMALY_SETUP_DATA_CALL_FAILURE, null), 0, 2); mNetworkConnectingTimeout = properties.getInt( KEY_ANOMALY_NETWORK_CONNECTING_TIMEOUT, 86400000); mNetworkDisconnectingTimeout = properties.getInt( KEY_ANOMALY_NETWORK_DISCONNECTING_TIMEOUT, 86400000); mNetworkHandoverTimeout = properties.getInt( KEY_ANOMALY_NETWORK_HANDOVER_TIMEOUT, 86400000); } /** * @return {@code true} if the configuration is carrier specific. {@code false} if the * configuration is the default (i.e. SIM not inserted). Loading @@ -287,9 +374,9 @@ public class DataConfigManager extends Handler { } /** * Update the configuration. * Update the configuration from carrier configs and resources. */ private void updateConfig() { private void updateCarrierConfig() { if (mCarrierConfigManager != null) { mCarrierConfig = mCarrierConfigManager.getConfigForSubId(mPhone.getSubId()); } Loading @@ -310,8 +397,6 @@ public class DataConfigManager extends Handler { log("Data config updated. Config is " + (isConfigCarrierSpecific() ? "" : "not ") + "carrier specific."); mConfigUpdateRegistrants.notifyRegistrants(); } /** Loading Loading @@ -666,10 +751,52 @@ public class DataConfigManager extends Handler { } /** * @return The IMS back to back request/release minimal interval. * Anomaly report thresholds for frequent setup data call failure. * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalySetupDataCallThreshold() { return mSetupDataCallAnomalyReportThreshold; } /** * Anomaly report thresholds for frequent network unwanted call * at {@link TelephonyNetworkAgent#onNetworkUnwanted} * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalyNetworkUnwantedThreshold() { return mNetworkUnwantedAnomalyReportThreshold; } /** * Anomaly report thresholds for back to back release-request of IMS. * @return EventFrequency to trigger the anomaly report */ public @NonNull EventFrequency getAnomalyImsReleaseRequestThreshold() { return mImsReleaseRequestAnomalyReportThreshold; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#ConnectingState}. */ public long getImsRequestReleaseThrottleAnomalyWindowMs() { return mImsRequestReleaseThrottleAnomalyWindowMs; public int getAnomalyNetworkConnectingTimeoutMs() { return mNetworkConnectingTimeout; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#DisconnectingState}. */ public int getAnomalyNetworkDisconnectingTimeoutMs() { return mNetworkDisconnectingTimeout; } /** * @return Timeout in ms before creating an anomaly report for a DataNetwork stuck in * {@link DataNetwork#HandoverState}. */ public int getNetworkHandoverTimeoutMs() { return mNetworkHandoverTimeout; } /** Loading Loading @@ -794,6 +921,72 @@ public class DataConfigManager extends Handler { } } /** * Describe an event occurs eventNumOccurrence within a time span timeWindow */ public static class EventFrequency { /** The time window in ms within which event occurs. */ public final long timeWindow; /** The number of time the event occurs. */ public final int eventNumOccurrence; /** * Constructor * * @param timeWindow The time window in ms within which event occurs. * @param eventNumOccurrence The number of time the event occurs. */ public EventFrequency(long timeWindow, int eventNumOccurrence) { this.timeWindow = timeWindow; this.eventNumOccurrence = eventNumOccurrence; } @Override public String toString() { return String.format("EventFrequency=[timeWindow=%d, eventNumOccurrence=%d]", timeWindow, eventNumOccurrence); } } /** * Parse a pair of event throttle thresholds of the form "time window in ms,occurrences" * into {@link EventFrequency} * @param s String to be parsed in the form of "time window in ms,occurrences" * @param defaultTimeWindow The time window to return if parsing failed. * @param defaultOccurrences The occurrence to return if parsing failed. * @return timeWindow and occurrence wrapped in EventFrequency */ @VisibleForTesting public EventFrequency parseSlidingWindowCounterThreshold(String s, long defaultTimeWindow, int defaultOccurrences) { EventFrequency defaultValue = new EventFrequency(defaultTimeWindow, defaultOccurrences); if (TextUtils.isEmpty(s)) return defaultValue; final String[] pair = s.split(","); if (pair.length != 2) { loge("Invalid format: " + s + "Format should be in \"time window in ms,occurrences\". " + "Using default instead."); return defaultValue; } long windowSpan; int occurrence; try { windowSpan = Long.parseLong(pair[0].trim()); } catch (NumberFormatException e) { loge("Exception parsing SlidingWindow window span " + pair[0] + ": " + e); return defaultValue; } try { occurrence = Integer.parseInt(pair[1].trim()); } catch (NumberFormatException e) { loge("Exception parsing SlidingWindow occurrence as integer " + pair[1] + ": " + e); return defaultValue; } return new EventFrequency(windowSpan, occurrence); } /** * @return Get rules for handover between IWLAN and cellular networks. * Loading Loading @@ -981,8 +1174,12 @@ public class DataConfigManager extends Handler { pw.increaseIndent(); mDataHandoverRetryRules.forEach(pw::println); pw.decreaseIndent(); pw.println("IMS request release throttle anomaly window in ms=" + mImsRequestReleaseThrottleAnomalyWindowMs); pw.println("mSetupDataCallAnomalyReport=" + mSetupDataCallAnomalyReportThreshold); pw.println("mNetworkUnwantedAnomalyReport=" + mNetworkUnwantedAnomalyReportThreshold); pw.println("mImsReleaseRequestAnomalyReport=" + mImsReleaseRequestAnomalyReportThreshold); pw.println("mNetworkConnectingTimeout=" + mNetworkConnectingTimeout); pw.println("mNetworkDisconnectingTimeout=" + mNetworkDisconnectingTimeout); pw.println("mNetworkHandoverTimeout=" + mNetworkHandoverTimeout); pw.println("Metered APN types=" + mMeteredApnTypes.stream() .map(ApnSetting::getApnTypeString).collect(Collectors.joining(","))); pw.println("Roaming metered APN types=" + mRoamingMeteredApnTypes.stream() Loading
src/java/com/android/internal/telephony/data/DataNetwork.java +31 −22 Original line number Diff line number Diff line Loading @@ -207,8 +207,10 @@ public class DataNetwork extends StateMachine { /** * Event for data network stuck in transient (i.e. connecting/disconnecting/handover) state for * too long time. Timeout value specified in {@link #MAXIMUM_CONNECTING_DURATION_MILLIS}, * {@link #MAXIMUM_DISCONNECTING_DURATION_MILLIS}, {@link #MAXIMUM_HANDOVER_DURATION_MILLIS}. * too long time. Timeout value specified in * {@link DataConfigManager#getAnomalyNetworkConnectingTimeoutMs()}, * {@link DataConfigManager#getAnomalyNetworkDisconnectingTimeoutMs()}, * {@link DataConfigManager#getNetworkHandoverTimeoutMs()}. */ private static final int EVENT_STUCK_IN_TRANSIENT_STATE = 20; Loading @@ -227,18 +229,6 @@ public class DataNetwork extends StateMachine { /** Invalid context id. */ private static final int INVALID_CID = -1; /** The maximum time the data network can stay in {@link ConnectingState}. */ private static final long MAXIMUM_CONNECTING_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** The maximum time the data network can stay in {@link DisconnectingState}. */ private static final long MAXIMUM_DISCONNECTING_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** The maximum time the data network can stay in {@link HandoverState}. */ private static final long MAXIMUM_HANDOVER_DURATION_MILLIS = TimeUnit.SECONDS.toMillis(60); /** * The data network providing default internet will have a higher score of 50. Other network * will have a slightly lower score of 45. The intention is other connections will not cause Loading Loading @@ -781,6 +771,13 @@ public class DataNetwork extends StateMachine { * @param dataNetwork The data network. */ public abstract void onNetworkCapabilitiesChanged(@NonNull DataNetwork dataNetwork); /** * Called when attempt to tear down a data network * * @param dataNetwork The data network. */ public abstract void onTrackNetworkUnwanted(@NonNull DataNetwork dataNetwork); } /** Loading Loading @@ -1046,7 +1043,7 @@ public class DataNetwork extends StateMachine { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_CONNECTING_DURATION_MILLIS); mDataConfigManager.getAnomalyNetworkConnectingTimeoutMs()); // Need to calculate the initial capabilities before creating the network agent. updateNetworkCapabilities(); mNetworkAgent = createNetworkAgent(); Loading Loading @@ -1103,7 +1100,8 @@ public class DataNetwork extends StateMachine { case EVENT_STUCK_IN_TRANSIENT_STATE: String message = "Data network stuck in connecting state for " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_CONNECTING_DURATION_MILLIS) + " seconds."; mDataConfigManager.getAnomalyNetworkConnectingTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("58c56403-7ea7-4e56-a0c7-e467114d09b8"), message); Loading Loading @@ -1235,7 +1233,8 @@ public class DataNetwork extends StateMachine { private final class HandoverState extends State { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_HANDOVER_DURATION_MILLIS); sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, mDataConfigManager.getNetworkHandoverTimeoutMs()); notifyPreciseDataConnectionState(); } Loading Loading @@ -1277,10 +1276,10 @@ public class DataNetwork extends StateMachine { case EVENT_STUCK_IN_TRANSIENT_STATE: String message = "Data service did not respond the handover request within " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_HANDOVER_DURATION_MILLIS) + " seconds."; mDataConfigManager.getNetworkHandoverTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("15f60e1d-c985-48a9-abc4-be76e343864f"), message); UUID.fromString("1afe68cb-8b41-4964-a737-4f34372429ea"), message); // Handover failed. Use the retry logic defined in // CarrierConfigManager.KEY_TELEPHONY_DATA_HANDOVER_RETRY_RULES_STRING_ARRAY. Loading Loading @@ -1346,7 +1345,7 @@ public class DataNetwork extends StateMachine { @Override public void enter() { sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE, MAXIMUM_DISCONNECTING_DURATION_MILLIS); mDataConfigManager.getAnomalyNetworkDisconnectingTimeoutMs()); notifyPreciseDataConnectionState(); } Loading Loading @@ -1378,7 +1377,8 @@ public class DataNetwork extends StateMachine { String message = "RIL did not send data call list changed event after " + "deactivate data call request within " + TimeUnit.MILLISECONDS.toSeconds( MAXIMUM_DISCONNECTING_DURATION_MILLIS) + " seconds."; mDataConfigManager.getAnomalyNetworkDisconnectingTimeoutMs()) + " seconds."; logl(message); AnomalyReporter.reportAnomaly( UUID.fromString("d0e4fa1c-c57b-4ba5-b4b6-8955487012cc"), message); Loading Loading @@ -2253,6 +2253,14 @@ public class DataNetwork extends StateMachine { return; } //track frequent networkUnwanted call of IMS and INTERNET if ((isConnected()) && (mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) || mNetworkCapabilities.hasCapability( NetworkCapabilities.NET_CAPABILITY_INTERNET))) { mDataNetworkCallback.onTrackNetworkUnwanted(this); } // TODO: Need to support DataService.REQUEST_REASON_SHUTDOWN mDataServiceManagers.get(mTransport).deactivateDataCall(mCid.get(mTransport), DataService.REQUEST_REASON_NORMAL, Loading @@ -2268,7 +2276,8 @@ public class DataNetwork extends StateMachine { return mDataConfigManager.isImsDelayTearDownEnabled() && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) && mPhone.getImsPhone() != null && mPhone.getImsPhone().getCallTracker().getState() != PhoneConstants.State.IDLE; && mPhone.getImsPhone().getCallTracker().getState() != PhoneConstants.State.IDLE; } /** Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +62 −7 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/java/com/android/internal/telephony/data/TelephonyNetworkAgent.java +0 −39 Original line number Diff line number Diff line Loading @@ -22,29 +22,24 @@ import android.annotation.Nullable; import android.net.KeepalivePacketData; import android.net.NetworkAgent; import android.net.NetworkAgentConfig; import android.net.NetworkCapabilities; import android.net.NetworkProvider; import android.net.NetworkScore; import android.net.QosFilter; import android.net.QosSessionAttributes; import android.net.Uri; import android.os.Looper; import android.telephony.AnomalyReporter; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.LocalLog; import com.android.internal.telephony.Phone; import com.android.internal.telephony.SlidingWindowEventCounter; import com.android.telephony.Rlog; import java.io.FileDescriptor; import java.io.PrintWriter; import java.time.Duration; import java.util.Set; import java.util.UUID; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; /** * TelephonyNetworkAgent class represents a single PDN (Packet Data Network). It is an agent Loading @@ -56,13 +51,6 @@ public class TelephonyNetworkAgent extends NetworkAgent implements NotifyQosSess private final Phone mPhone; private final LocalLog mLocalLog = new LocalLog(128); /** Event counter for unwanted network within time window, is used to trigger anomaly report. */ private static final long NETWORK_UNWANTED_ANOMALY_WINDOW_MS = TimeUnit.MINUTES.toMillis(5); private static final int NETWORK_UNWANTED_ANOMALY_NUM_OCCURRENCES = 12; private static final SlidingWindowEventCounter sNetworkUnwantedCounter = new SlidingWindowEventCounter(NETWORK_UNWANTED_ANOMALY_WINDOW_MS, NETWORK_UNWANTED_ANOMALY_NUM_OCCURRENCES); /** The parent data network. */ private final @NonNull DataNetwork mDataNetwork; Loading Loading @@ -189,36 +177,9 @@ public class TelephonyNetworkAgent extends NetworkAgent implements NotifyQosSess return; } NetworkCapabilities capabilities = mDataNetwork.getNetworkCapabilities(); if ((mDataNetwork.isConnected() || mDataNetwork.isHandoverInProgress()) && (capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS) || capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET))) { trackNetworkUnwanted(); } mDataNetwork.tearDown(DataNetwork.TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED); } /** * There have been several bugs where a RECONNECT loop kicks off where a DataConnection * connects to the Network, ConnectivityService indicates that the Network is unwanted, * and then the DataConnection reconnects. By the time we get the bug report it's too late * because there have already been hundreds of RECONNECTS. This is meant to capture the issue * when it first starts. * * The unwanted counter is configured to only take an anomaly report in extreme cases. * This is to avoid having the anomaly message show up on several devices. * */ private void trackNetworkUnwanted() { if (sNetworkUnwantedCounter.addOccurrence()) { AnomalyReporter.reportAnomaly( UUID.fromString("9f3bc55b-bfa6-4e26-afaa-5031426a66d2"), "Network Unwanted called 12 times in 5 minutes."); } } /** * @return The unique id of the agent. */ Loading