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

Commit 39f0f234 authored by Jack Yu's avatar Jack Yu Committed by Gerrit Code Review
Browse files

Merge changes from topic "fail_cause_to_string"

* changes:
  Make IMS anomaly report trigger only on release-request
  Fixed unnecessary network request removal
  Fixed out of boundary exception
  Add anomaly report for frequent setup data call failure
  Update constant thresholds for trigger anomaly report
  Improved data fail cause debug message
  [DSRM] Fix issues
  Delayed IMS tear down when voice call is ongoing
parents b3a80437 ab5e8bbf
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.internal.telephony;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.os.SystemClock;
import android.util.LongArrayQueue;

@@ -81,7 +82,37 @@ 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;
    }

    /**
     * Get the event frequency description.
     *
     * @return A string describing the anomaly event
     */
    public @NonNull String getFrequencyString() {
        return String.format("%d times within %d ms.", mNumOccurrences, mWindowSizeMillis);
    }

    @Override
    public String toString() {
        return String.format("SlidingWindowEventCounter=[windowSizeMillis=" + mWindowSizeMillis
                + ", numOccurrences=" + mNumOccurrences
                + ", timestampQueueMillis=" + mTimestampQueueMillis + "]");
    }
}
+214 −17
Original line number Diff line number Diff line
@@ -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;
@@ -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";

@@ -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;
@@ -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() {
@@ -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
@@ -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).
@@ -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());
        }
@@ -310,8 +397,6 @@ public class DataConfigManager extends Handler {

        log("Data config updated. Config is " + (isConfigCarrierSpecific() ? "" : "not ")
                + "carrier specific.");

        mConfigUpdateRegistrants.notifyRegistrants();
    }

    /**
@@ -665,10 +750,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;
    }

    /**
@@ -796,6 +923,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.
     *
@@ -983,8 +1176,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()
+41 −26
Original line number Diff line number Diff line
@@ -208,8 +208,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;

@@ -228,18 +230,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
@@ -785,6 +775,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);
    }

    /**
@@ -1051,7 +1048,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();
@@ -1108,7 +1105,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);
@@ -1240,7 +1238,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();
        }

@@ -1282,10 +1281,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.
@@ -1351,7 +1350,7 @@ public class DataNetwork extends StateMachine {
        @Override
        public void enter() {
            sendMessageDelayed(EVENT_STUCK_IN_TRANSIENT_STATE,
                    MAXIMUM_DISCONNECTING_DURATION_MILLIS);
                    mDataConfigManager.getAnomalyNetworkDisconnectingTimeoutMs());
            notifyPreciseDataConnectionState();
        }

@@ -1383,7 +1382,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);
@@ -2224,15 +2224,19 @@ public class DataNetwork extends StateMachine {

    private void onTearDown(@TearDownReason int reason) {
        logl("onTearDown: reason=" + tearDownReasonToString(reason));
        if (mDataConfigManager.isImsDelayTearDownEnabled()
                && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
                && reason == TEAR_DOWN_REASON_CONNECTIVITY_SERVICE_UNWANTED
                && mPhone.getImsPhone() != null
                && mPhone.getImsPhone().getCallTracker().getState() != PhoneConstants.State.IDLE) {
        if (shouldDelayTearDown()) {
            logl("onTearDown: Delay IMS tear down until call ends.");
            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,
@@ -2241,6 +2245,17 @@ public class DataNetwork extends StateMachine {
        mInvokedDataDeactivation = true;
    }

    /**
     * @return {@code true} if this tear down should be delayed on this data network.
     */
    public boolean shouldDelayTearDown() {
        return mDataConfigManager.isImsDelayTearDownEnabled()
                && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)
                && mPhone.getImsPhone() != null
                && mPhone.getImsPhone().getCallTracker().getState()
                != PhoneConstants.State.IDLE;
    }

    /**
     * Tear down the data network when condition is met or timed out. Data network will enter
     * {@link DisconnectingState} immediately and waiting for condition met. When condition is met,
+164 −29

File changed.

Preview size limit exceeded, changes collapsed.

+3 −2
Original line number Diff line number Diff line
@@ -1042,7 +1042,7 @@ public class DataRetryManager extends Handler {
    private void onEvaluateDataSetupRetry(@NonNull DataProfile dataProfile,
            @TransportType int transport, @NonNull NetworkRequestList requestList,
            @DataFailureCause int cause, long retryDelayMillis) {
        logl("onEvaluateDataRetry: " + dataProfile + ", transport="
        logl("onEvaluateDataSetupRetry: " + dataProfile + ", transport="
                + AccessNetworkConstants.transportTypeToString(transport) + ", cause="
                + DataFailCause.toString(cause) + ", retryDelayMillis=" + retryDelayMillis + "ms"
                + ", " + requestList);
@@ -1128,7 +1128,8 @@ public class DataRetryManager extends Handler {
            }

            if (!retryScheduled) {
                log("onEvaluateDataRetry: Did not match any retry rule. Stop timer-based retry.");
                log("onEvaluateDataSetupRetry: Did not match any retry rule. Stop timer-based "
                        + "retry.");
            }
        }
    }
Loading