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

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

Merge changes from topic "refactor_data_stall"

* changes:
  Implement the Functions for DataConfigManager
  Add the Skip Recovery Action Mechanism
  Replaced NetworkRequest with TelephonyNetworkRequest
  [DataStallRecoveryManagerTest] Fix the test fail
  Replaced DcRequest with TelephonyNetworkRequest
parents e4eeabd0 cffda0b4
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -793,6 +793,26 @@ public class DataConfigManager extends Handler {
        }
    }

    /**
     * @return Get recovery action delay in milliseconds between recovery actions.
     *
     * @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY
     */
    public @NonNull long[] getDataStallRecoveryDelayMillis() {
        return mCarrierConfig.getLongArray(
            CarrierConfigManager.KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY);
    }

    /**
     * @return Get the data stall recovery should skip boolean array.
     *
     * @see CarrierConfigManager#KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY
     */
    public @NonNull boolean[] getDataStallRecoveryShouldSkipArray() {
        return mCarrierConfig.getBooleanArray(
            CarrierConfigManager.KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY);
    }

    /**
     * Registration point for subscription info ready
     *
+1 −1
Original line number Diff line number Diff line
@@ -1215,7 +1215,7 @@ public class DataNetwork extends StateMachine {
        TelephonyNetworkRequest networkRequest = mAttachedNetworkRequestList.get(0);

        mPreferredTransport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
                networkRequest.getHighestPriorityNetworkCapability());
                networkRequest.getApnTypeNetworkCapability());
        if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
            mTransport = mPreferredTransport;
        }
+11 −28
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkAgent;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
@@ -803,7 +802,7 @@ public class DataNetworkController extends Handler {
                onReevaluateExistingDataNetworks(reason);
                break;
            case EVENT_REMOVE_NETWORK_REQUEST:
                onRemoveNetworkRequest((NetworkRequest) msg.obj);
                onRemoveNetworkRequest((TelephonyNetworkRequest) msg.obj);
                break;
            case EVENT_VOICE_CALL_ENDED:
                sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
@@ -869,16 +868,13 @@ public class DataNetworkController extends Handler {

    /**
     * Add a network request, which is originated from the apps. Note that add a network request
     * is not necessarily setting up a net {@link DataNetwork}.
     * is not necessarily setting up a {@link DataNetwork}.
     *
     * @param networkRequest Network request
     *
     */
    public void addNetworkRequest(@NonNull NetworkRequest networkRequest) {
        // TODO: TelephonyNetworkRequest should be created in TelephonyNetworkFactory after
        //       DcTracker and other legacy data stacks are removed.
        sendMessage(obtainMessage(EVENT_ADD_NETWORK_REQUEST,
                new TelephonyNetworkRequest(networkRequest, mPhone)));
    public void addNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
        sendMessage(obtainMessage(EVENT_ADD_NETWORK_REQUEST, networkRequest));
    }

    /**
@@ -1013,7 +1009,7 @@ public class DataNetworkController extends Handler {
            @NonNull TelephonyNetworkRequest networkRequest, DataEvaluationReason reason) {
        DataEvaluation evaluation = new DataEvaluation(reason);
        int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
                networkRequest.getHighestPriorityNetworkCapability());
                networkRequest.getApnTypeNetworkCapability());

        // Bypass all checks for emergency network request.
        if (networkRequest.hasCapability(NetworkCapabilities.NET_CAPABILITY_EIMS)) {
@@ -1091,7 +1087,7 @@ public class DataNetworkController extends Handler {


        if (!mDataSettingsManager.isDataEnabled(DataUtils.networkCapabilityToApnType(
                networkRequest.getHighestPriorityNetworkCapability()))) {
                networkRequest.getApnTypeNetworkCapability()))) {
            evaluation.addDataDisallowedReason(DataDisallowedReason.DATA_DISABLED);
        }

@@ -1110,7 +1106,7 @@ public class DataNetworkController extends Handler {
                evaluation.addDataAllowedReason(DataAllowedReason.UNMETERED_USAGE);
            } else if (transport == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
                int apnType = DataUtils.networkCapabilityToApnType(
                        networkRequest.getHighestPriorityNetworkCapability());
                        networkRequest.getApnTypeNetworkCapability());
                Set<Integer> meteredApns = mServiceState.getDataRoaming()
                        ? mDataConfigManager.getMeteredApnTypesWhenRoaming()
                        : mDataConfigManager.getMeteredApnTypes();
@@ -1349,24 +1345,11 @@ public class DataNetworkController extends Handler {
     *
     * @param networkRequest Network request
     */
    // TODO: TelephonyNetworkRequest should be used after DcTracker and other legacy data stacks are
    //  removed.
    public void removeNetworkRequest(@NonNull NetworkRequest networkRequest) {
    public void removeNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
        sendMessage(obtainMessage(EVENT_REMOVE_NETWORK_REQUEST, networkRequest));
    }

    private void onRemoveNetworkRequest(@NonNull NetworkRequest request) {
        // TODO: TelephonyNetworkRequest should be used after DcTracker and other legacy data stacks
        //  are removed.
        // temp solution: find the original telephony network request.
        TelephonyNetworkRequest networkRequest = mAllNetworkRequestList.stream()
                .filter(nr -> nr.getNativeNetworkRequest().equals(request))
                .findFirst()
                .orElse(null);
        if (networkRequest == null) {
            return;
        }

    private void onRemoveNetworkRequest(@NonNull TelephonyNetworkRequest networkRequest) {
        if (!mAllNetworkRequestList.remove(networkRequest)) {
            loge("onRemoveNetworkRequest: Network request does not exist. " + networkRequest);
            return;
@@ -1624,7 +1607,7 @@ public class DataNetworkController extends Handler {
        }

        int transport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
                networkRequestList.get(0).getHighestPriorityNetworkCapability());
                networkRequestList.get(0).getApnTypeNetworkCapability());
        logl("Creating data network on "
                + AccessNetworkConstants.transportTypeToString(transport) + " with " + dataProfile
                + ", and attaching " + networkRequestList.size() + " network requests to it.");
@@ -1759,7 +1742,7 @@ public class DataNetworkController extends Handler {
            dataSetupRetryEntry.setState(DataRetryEntry.RETRY_STATE_CANCELLED);
            return;
        }
        int networkCapability = telephonyNetworkRequest.getHighestPriorityNetworkCapability();
        int networkCapability = telephonyNetworkRequest.getApnTypeNetworkCapability();
        int preferredTransport = mAccessNetworksManager.getPreferredTransportByNetworkCapability(
                networkCapability);
        if (preferredTransport != dataSetupRetryEntry.transport) {
+2 −2
Original line number Diff line number Diff line
@@ -859,7 +859,7 @@ public class DataRetryManager extends Handler {
            List<NetworkRequestList> groupedNetworkRequestLists =
                    DataUtils.getGroupedNetworkRequestList(requestList);
            for (NetworkRequestList networkRequestList : groupedNetworkRequestLists) {
                int capability = networkRequestList.get(0).getHighestPriorityNetworkCapability();
                int capability = networkRequestList.get(0).getApnTypeNetworkCapability();

                for (DataSetupRetryRule retryRule : mDataSetupRetryRuleList) {
                    if (retryRule.canBeMatched(capability, cause)) {
@@ -1035,7 +1035,7 @@ public class DataRetryManager extends Handler {
                // count towards the last succeeded data setup.
                if (entry.setupRetryType == DataSetupRetryEntry.RETRY_TYPE_NETWORK_REQUESTS
                        && entry.networkRequestList.get(0)
                        .getHighestPriorityNetworkCapability() == networkCapability
                        .getApnTypeNetworkCapability() == networkCapability
                        && entry.appliedDataRetryRule.equals(dataRetryRule)) {
                    if (entry.getState() == DataRetryEntry.RETRY_STATE_SUCCEEDED
                            || entry.getState() == DataRetryEntry.RETRY_STATE_CANCELLED) {
+149 −44
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.data.DataNetworkController.DataNetworkControllerCallback;
import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
import com.android.internal.telephony.metrics.DataStallRecoveryStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.telephony.Rlog;
@@ -46,6 +47,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.concurrent.Executor;

/**
@@ -91,15 +93,11 @@ public class DataStallRecoveryManager extends Handler {
    /** Event for data config updated. */
    private static final int EVENT_DATA_CONFIG_UPDATED = 1;


    /** Event for triggering recovery action. */
    private static final int EVENT_DO_RECOVERY = 2;

    /** Event for mobile data setting changed. */
    private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 3;

    /** Event for radio state changed. */
    private static final int EVENT_RADIO_STATE_CHANGED = 4;
    private static final int EVENT_RADIO_STATE_CHANGED = 3;

    private final @NonNull Phone mPhone;
    private final @NonNull String mLogTag;
@@ -132,8 +130,17 @@ public class DataStallRecoveryManager extends Handler {
    private @RadioPowerState int mRadioPowerState;
    /** Whether the NetworkCheckTimer start. */
    private boolean mNetworkCheckTimerStarted = false;
    /** Whether radio state changed during data stall. */
    private boolean mRadioStateChangedDuringDataStall;
    /** Whether mobile data change to Enabled during data stall. */
    private boolean mMobileDataChangedToEnabledDuringDataStall;

    /** The array for the timers between recovery actions. */
    private @NonNull long[] mDataStallRecoveryDelayMillisArray;
    /** The boolean array for the flags. They are used to skip the recovery actions if needed. */
    private @NonNull boolean[] mSkipRecoveryActionArray;

    private @NonNull DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback;
    private DataStallRecoveryManagerCallback mDataStallRecoveryManagerCallback;

    /**
     * The data stall recovery manager callback. Note this is only used for passing information
@@ -175,11 +182,24 @@ public class DataStallRecoveryManager extends Handler {
        super(looper);
        mPhone = phone;
        mLogTag = "DSRM-" + mPhone.getPhoneId();
        log("DataStallRecoveryManager created.");
        mDataNetworkController = dataNetworkController;
        mWwanDataServiceManager = dataServiceManager;
        mDataConfigManager = mDataNetworkController.getDataConfigManager();
        mDataNetworkController
                .getDataSettingsManager()
                .registerCallback(
                        new DataSettingsManagerCallback(this::post) {
                            @Override
                            public void onDataEnabledChanged(
                                    boolean enabled,
                                    @TelephonyManager.DataEnabledChangedReason int reason) {
                                onMobileDataEnabledChanged(enabled);
                            }
                        });
        mDataStallRecoveryManagerCallback = callback;
        mRadioPowerState = mPhone.getRadioPowerState();
        updateDataStallRecoveryConfigs();

        registerAllEvents();
    }
@@ -197,12 +217,12 @@ public class DataStallRecoveryManager extends Handler {

                    @Override
                    public void onInternetDataNetworkConnected() {
                        // onInternetDataNetworkConnected();
                        // onInternetNetworkConnected();
                    }

                    @Override
                    public void onInternetDataNetworkDisconnected() {
                        // onInternetDataNetworkDisconnected();
                        // onInternetNetworkDisconnected();
                    }
                });
        mPhone.mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
@@ -218,11 +238,12 @@ public class DataStallRecoveryManager extends Handler {
            case EVENT_DO_RECOVERY:
                doRecovery();
                break;
            case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
                onMobileDataSettingsChanged();
                break;
            case EVENT_RADIO_STATE_CHANGED:
                mRadioPowerState = mPhone.getRadioPowerState();
                if (mDataStalled) {
                    // Store the radio state changed flag only when data stall occurred.
                    mRadioStateChangedDuringDataStall = true;
                }
                break;
            default:
                loge("Unexpected message = " + msg);
@@ -230,9 +251,49 @@ public class DataStallRecoveryManager extends Handler {
        }
    }

    /** Update the data stall recovery configs from DataConfigManager. */
    private void updateDataStallRecoveryConfigs() {
        mDataStallRecoveryDelayMillisArray = mDataConfigManager.getDataStallRecoveryDelayMillis();
        mSkipRecoveryActionArray = mDataConfigManager.getDataStallRecoveryShouldSkipArray();
    }

    /**
     * Get the duration for specific data stall recovery action.
     *
     * @param recoveryAction The recovery action to query.
     * @return the delay in milliseconds for the specific recovery action.
     */
    private long getDataStallRecoveryDelayMillis(@RecoveryAction int recoveryAction) {
        return mDataStallRecoveryDelayMillisArray[recoveryAction];
    }

    /**
     * Check if the recovery action needs to be skipped.
     *
     * @param recoveryAction The recovery action.
     * @return {@code true} if the action needs to be skipped.
     */
    private boolean shouldSkipRecoveryAction(@RecoveryAction int recoveryAction) {
        return mSkipRecoveryActionArray[recoveryAction];
    }

    /** Called when data config was updated. */
    private void onDataConfigUpdated() {
        // TODO: (b/178670629): Get the new config from DataConfigManager.
        updateDataStallRecoveryConfigs();
    }

    /**
     * Called when mobile data setting changed.
     *
     * @param enabled true for mobile data settings enabled & false for disabled.
     */
    private void onMobileDataEnabledChanged(boolean enabled) {
        logl("onMobileDataEnabledChanged: DataEnabled:" + enabled + ",DataStalled:" + mDataStalled);
        // Store the mobile data changed flag (from disabled to enabled) as TRUE
        // during data stalled.
        if (mDataStalled && enabled) {
            mMobileDataChangedToEnabledDuringDataStall = true;
        }
    }

    /**
@@ -260,15 +321,11 @@ public class DataStallRecoveryManager extends Handler {
        }
    }

    /** Called when mobile data setiings changed. */
    private void onMobileDataSettingsChanged() {
        logv("onMobileDataSettingsChanged");
        // TODO: (b/178670629): Get mobile data settings from DataSettingsManager.
    }

    /** Reset the action to initial step. */
    private void resetAction() {
        mTimeLastRecoveryStartMs = 0;
        mMobileDataChangedToEnabledDuringDataStall = false;
        mRadioStateChangedDuringDataStall = false;
        setRecoveryAction(RECOVERY_ACTION_GET_DATA_CALL_LIST);
    }

@@ -292,6 +349,38 @@ public class DataStallRecoveryManager extends Handler {
    @VisibleForTesting
    public void setRecoveryAction(@RecoveryAction int action) {
        mRecovryAction = action;

        // Check if the mobile data enabled is TRUE, it means that the mobile data setting changed
        // from DISABLED to ENABLED, we will set the next recovery action to
        // RECOVERY_ACTION_RADIO_RESTART due to already did the RECOVERY_ACTION_CLEANUP.
        if (mMobileDataChangedToEnabledDuringDataStall
                && mRecovryAction < RECOVERY_ACTION_RADIO_RESTART) {
            mRecovryAction = RECOVERY_ACTION_RADIO_RESTART;
        }
        // Check if the radio state changed from off to on, it means that the modem already
        // did the radio restart, we will set the next action to RECOVERY_ACTION_RESET_MODEM.
        if (mRadioStateChangedDuringDataStall
                && mRadioPowerState == TelephonyManager.RADIO_POWER_ON) {
            mRecovryAction = RECOVERY_ACTION_RESET_MODEM;
        }
        // To check the flag from DataConfigManager if we need to skip the step.
        if (shouldSkipRecoveryAction(mRecovryAction)) {
            switch (mRecovryAction) {
                case RECOVERY_ACTION_GET_DATA_CALL_LIST:
                    setRecoveryAction(RECOVERY_ACTION_CLEANUP);
                    break;
                case RECOVERY_ACTION_CLEANUP:
                    setRecoveryAction(RECOVERY_ACTION_RADIO_RESTART);
                    break;
                case RECOVERY_ACTION_RADIO_RESTART:
                    setRecoveryAction(RECOVERY_ACTION_RESET_MODEM);
                    break;
                case RECOVERY_ACTION_RESET_MODEM:
                    resetAction();
                    break;
            }
        }

        log("setRecoveryAction: " + recoveryActionToString(mRecovryAction));
    }

@@ -313,16 +402,6 @@ public class DataStallRecoveryManager extends Handler {
        return (SystemClock.elapsedRealtime() - mTimeLastRecoveryStartMs);
    }

    /**
     * Get duration between recovery from DataStallRecoveryConfig.
     *
     * @return the time in milliseconds between recovery action.
     */
    private long getMinDurationBetweenRecovery() {
        // TODO: (b/178670629): Get the duration from DataConfigManager
        return 3 * 60 * 1000;
    }

    /**
     * Broadcast intent when data stall occurred.
     *
@@ -361,12 +440,19 @@ public class DataStallRecoveryManager extends Handler {
        mPhone.rebootModem(null);
    }

    /** Initialize the network check timer. */
    private void startNetworkCheckTimer() {
        log("startNetworkCheckTimer()");
    /**
     * Initialize the network check timer.
     *
     * @param action The recovery action to start the network check timer.
     */
    private void startNetworkCheckTimer(@RecoveryAction int action) {
        // Ignore send message delayed due to reached the last action.
        if (action == RECOVERY_ACTION_RESET_MODEM) return;
        log("startNetworkCheckTimer(): " + getDataStallRecoveryDelayMillis(action) + "ms");
        if (!mNetworkCheckTimerStarted) {
            mNetworkCheckTimerStarted = true;
            sendMessageDelayed(obtainMessage(EVENT_DO_RECOVERY), getMinDurationBetweenRecovery());
            sendMessageDelayed(
                    obtainMessage(EVENT_DO_RECOVERY), getDataStallRecoveryDelayMillis(action));
        }
    }

@@ -388,7 +474,7 @@ public class DataStallRecoveryManager extends Handler {
    private boolean isRecoveryNeeded() {
        logv("enter: isRecoveryNeeded()");
        // To avoid back to back recovery, wait for a grace period
        if (getElapsedTimeSinceRecoveryMs() < getMinDurationBetweenRecovery()) {
        if (getElapsedTimeSinceRecoveryMs() < getDataStallRecoveryDelayMillis(mLastAction)) {
            log("skip back to back data stall recovery");
            return false;
        }
@@ -407,8 +493,6 @@ public class DataStallRecoveryManager extends Handler {
            return false;
        }

        // TODO: (b/178670629): check the customized carrier config to skip the recovery action

        return true;
    }

@@ -488,7 +572,26 @@ public class DataStallRecoveryManager extends Handler {
                                + recoveryActionToString(recoveryAction));
        }

        startNetworkCheckTimer();
        startNetworkCheckTimer(mLastAction);
    }

    /**
     * Convert RadioPowerState to string
     *
     * @param state The radio power state
     * @return The radio power state in string format.
     */
    private static @NonNull String radioPowerStateToString(@RadioPowerState int state) {
        switch (state) {
            case TelephonyManager.RADIO_POWER_OFF:
                return "RADIO_POWER_OFF";
            case TelephonyManager.RADIO_POWER_ON:
                return "RADIO_POWER_ON";
            case TelephonyManager.RADIO_POWER_UNAVAILABLE:
                return "RADIO_POWER_UNAVAILABLE";
            default:
                return "Unknown(" + state + ")";
        }
    }

    /**
@@ -512,13 +615,6 @@ public class DataStallRecoveryManager extends Handler {
        }
    }

    /** The data stall recovery config. */
    public static final class DataStallRecoveryConfig {
        DataStallRecoveryConfig(String stringConfig) {
            // TODO: (b/178670629): Parsing the config string.
        }
    }

    /**
     * Log debug messages.
     *
@@ -572,10 +668,19 @@ public class DataStallRecoveryManager extends Handler {
        pw.println("mIsValidNetwork=" + mIsValidNetwork);
        pw.println("mDataStalled=" + mDataStalled);
        pw.println("mDataStallStartMs=" + mDataStallStartMs);
        pw.println("mRadioPowerState=" + mRadioPowerState);
        pw.println("mRadioPowerState=" + radioPowerStateToString(mRadioPowerState));
        pw.println("mLastActionReported=" + mLastActionReported);
        pw.println("mTimeLastRecoveryStartMs=" + mTimeLastRecoveryStartMs);
        pw.println("getRecoveryAction()=" + recoveryActionToString(getRecoveryAction()));
        pw.println("mRadioStateChangedDuringDataStall=" + mRadioStateChangedDuringDataStall);
        pw.println(
                "mMobileDataChangedToEnabledDuringDataStall="
                        + mMobileDataChangedToEnabledDuringDataStall);
        pw.println(
                "DataStallRecoveryDelayMillisArray="
                        + Arrays.toString(mDataStallRecoveryDelayMillisArray));
        pw.println("SkipRecoveryActionArray=" + Arrays.toString(mSkipRecoveryActionArray));
        pw.decreaseIndent();
        pw.println("");

        pw.println("Local logs:");
Loading