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

Commit 00b06f5b authored by Sangyun Yun's avatar Sangyun Yun Committed by Android (Google) Code Review
Browse files

Merge changes from topic "DataServiceValidationAPI" into main

* changes:
  [Data Validation Api] Add Unit test coverage
  Adds request and response for handling network validation feature.
parents 80114228 177d2862
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -41,3 +41,11 @@ flag {
  description: "Expose apn setting supporting field"
  bug: "307038091"
}

flag {
  name: "network_validation"
  namespace: "telephony"
  description: "Request network validation for data networks and response status."
  bug:"286171724"
}
+15 −1
Original line number Diff line number Diff line
@@ -441,9 +441,23 @@ public class TelephonyComponentFactory {
     * @param phone The phone instance
     * @param looper Looper for the handler.
     * @return The access networks manager
     * @deprecated {@link #makeAccessNetworksManager(Phone, Looper, FeatureFlags)} instead
     */
    public AccessNetworksManager makeAccessNetworksManager(Phone phone, Looper looper) {
        return new AccessNetworksManager(phone, looper);
        return new AccessNetworksManager(phone, looper, new FeatureFlagsImpl());
    }

    /**
     * Make access networks manager
     *
     * @param phone The phone instance
     * @param looper Looper for the handler.
     * @param featureFlags feature flags.
     * @return The access networks manager
     */
    public AccessNetworksManager makeAccessNetworksManager(Phone phone, Looper looper,
            @NonNull FeatureFlags featureFlags) {
        return new AccessNetworksManager(phone, looper, featureFlags);
    }

    public CdmaSubscriptionSourceManager
+47 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.telephony.Annotation.NetCapability;
import android.telephony.AnomalyReporter;
import android.telephony.CarrierConfigManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataServiceCallback;
import android.telephony.data.IQualifiedNetworksService;
import android.telephony.data.IQualifiedNetworksServiceCallback;
import android.telephony.data.QualifiedNetworksService;
@@ -51,8 +52,11 @@ import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.SparseArray;

import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.SlidingWindowEventCounter;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.FunctionalUtils;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
@@ -65,6 +69,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
@@ -133,6 +138,8 @@ public class AccessNetworksManager extends Handler {
    private final @NonNull Set<AccessNetworksManagerCallback> mAccessNetworksManagerCallbacks =
            new ArraySet<>();

    private final FeatureFlags mFeatureFlags;

    /**
     * Represents qualified network types list on a specific APN type.
     */
@@ -294,6 +301,43 @@ public class AccessNetworksManager extends Handler {
                mQualifiedNetworksChangedRegistrants.notifyResult(qualifiedNetworksList);
            }
        }

        /**
         * Called when QualifiedNetworksService requests network validation.
         *
         * Since the data network in the connected state corresponding to the given network
         * capability must be validated, a request is tossed to the data network controller.
         * @param networkCapability network capability
         */
        @Override
        public void onNetworkValidationRequested(@NetCapability int networkCapability,
                @NonNull IIntegerConsumer resultCodeCallback) {
            DataNetworkController dnc = mPhone.getDataNetworkController();
            if (!mFeatureFlags.networkValidation()) {
                FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
                        .accept(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
                return;
            }

            log("onNetworkValidationRequested: networkCapability = ["
                    + DataUtils.networkCapabilityToString(networkCapability) + "]");

            dnc.requestNetworkValidation(networkCapability, new Consumer<Integer>() {
                @Override
                public void accept(Integer result) {
                    post(() -> {
                        try {
                            log("onNetworkValidationRequestDone:"
                                    + DataServiceCallback.resultCodeToString(result));
                            resultCodeCallback.accept(result.intValue());
                        } catch (RemoteException e) {
                            // Ignore if the remote process is no longer available to call back.
                            loge("onNetworkValidationRequestDone RemoteException" + e);
                        }
                    });
                }
            });
        }
    }

    private void onEmergencyDataNetworkPreferredTransportChanged(
@@ -337,7 +381,8 @@ public class AccessNetworksManager extends Handler {
     * @param phone The phone object.
     * @param looper Looper for the handler.
     */
    public AccessNetworksManager(@NonNull Phone phone, @NonNull Looper looper) {
    public AccessNetworksManager(@NonNull Phone phone, @NonNull Looper looper,
            @NonNull FeatureFlags featureFlags) {
        super(looper);
        mPhone = phone;
        mCarrierConfigManager = (CarrierConfigManager) phone.getContext().getSystemService(
@@ -346,6 +391,7 @@ public class AccessNetworksManager extends Handler {
        mApnTypeToQnsChangeNetworkCounter = new SparseArray<>();
        mAvailableTransports = new int[]{AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
                AccessNetworkConstants.TRANSPORT_TYPE_WLAN};
        mFeatureFlags = featureFlags;

        // bindQualifiedNetworksService posts real work to handler thread. So here we can
        // let the callback execute in binder thread to avoid post twice.
+116 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.metrics.DataCallSessionStats;
import com.android.internal.telephony.metrics.TelephonyMetrics;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FunctionalUtils;
import com.android.internal.util.IState;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -256,6 +257,12 @@ public class DataNetwork extends StateMachine {
     */
    private static final int EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE = 27;

    /** Event for data network validation request from the AccessNetworksManager. */
    private static final int EVENT_DATA_NETWORK_VALIDATION_REQUESTED = 28;

    /** Event for response to data network validation request. */
    private static final int EVENT_DATA_NETWORK_VALIDATION_RESPONSE = 29;

    /** Invalid context id. */
    private static final int INVALID_CID = -1;

@@ -718,6 +725,19 @@ public class DataNetwork extends StateMachine {
     */
    private @Nullable DataConfigManagerCallback mDataConfigManagerCallback;

    /**
     * Network validation status for this data network. If the data service provider does not
     * support the network validation feature, should be UNSUPPORTED.
     */
    private @PreciseDataConnectionState.NetworkValidationStatus int mNetworkValidationStatus =
            PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED;

    /**
     * Callback used to respond to a network validation request to determine whether the request is
     * successfully submitted. If the request has been submitted, change it to null.
     */
    private @Nullable Consumer<Integer> mNetworkValidationResultCodeCallback;

    /**
     * The network bandwidth.
     */
@@ -1277,6 +1297,14 @@ public class DataNetwork extends StateMachine {
                    loge(eventToString(msg.what) + ": transition to disconnected state");
                    transitionTo(mDisconnectedState);
                    break;
                case EVENT_DATA_NETWORK_VALIDATION_REQUESTED:
                    // If the data network is not connected, the request should be ignored.
                    handleErrorDataNetworkValidationRequest((Consumer<Integer>) msg.obj);
                    break;
                case EVENT_DATA_NETWORK_VALIDATION_RESPONSE:
                    // handle the resultCode in response for the request.
                    handleDataNetworkValidationRequestResultCode(msg.arg1 /* resultCode */);
                    break;
                default:
                    loge("Unhandled event " + eventToString(msg.what));
                    break;
@@ -1622,6 +1650,10 @@ public class DataNetwork extends StateMachine {
                    updateSuspendState();
                    updateNetworkCapabilities();
                    break;
                case EVENT_DATA_NETWORK_VALIDATION_REQUESTED:
                    // Network validation request can be accepted if the data is in connected state
                    handleDataNetworkValidationRequest((Consumer<Integer>) msg.obj);
                    break;
                default:
                    return NOT_HANDLED;
            }
@@ -1676,6 +1708,7 @@ public class DataNetwork extends StateMachine {
                case EVENT_CSS_INDICATOR_CHANGED:
                case EVENT_VOICE_CALL_ENDED:
                case EVENT_VOICE_CALL_STARTED:
                case EVENT_DATA_NETWORK_VALIDATION_REQUESTED:
                    // Defer the request until handover succeeds or fails.
                    log("Defer message " + eventToString(msg.what));
                    deferMessage(msg);
@@ -1810,6 +1843,8 @@ public class DataNetwork extends StateMachine {

            if (mEverConnected) {
                mLinkStatus = DataCallResponse.LINK_STATUS_INACTIVE;
                mNetworkValidationStatus =
                        PreciseDataConnectionState.NETWORK_VALIDATION_UNSUPPORTED;
                mDataNetworkCallback.invokeFromExecutor(() -> mDataNetworkCallback
                        .onLinkStatusChanged(DataNetwork.this, mLinkStatus));
                mDataNetworkCallback.invokeFromExecutor(() -> mDataNetworkCallback
@@ -2601,6 +2636,7 @@ public class DataNetwork extends StateMachine {
        }

        updateNetworkCapabilities();
        updateValidationStatus(response.getNetworkValidationStatus());
    }

    /**
@@ -3245,6 +3281,7 @@ public class DataNetwork extends StateMachine {
                .setNetworkType(getDataNetworkType())
                .setFailCause(mFailCause)
                .setDefaultQos(mDefaultQos)
                .setNetworkValidationStatus(mNetworkValidationStatus)
                .build();
    }

@@ -3514,6 +3551,81 @@ public class DataNetwork extends StateMachine {
                request -> request.hasCapability(netCapability));
    }

    /**
     * The network validation requests moves to process on the statemachich handler. A request is
     * processed according to state of the data network.
     */
    public void requestNetworkValidation(@NonNull Consumer<Integer> resultCodeCallback) {
        // request a network validation by DataNetwork state
        sendMessage(EVENT_DATA_NETWORK_VALIDATION_REQUESTED, resultCodeCallback);
    }

    /**
     * Request network validation to data service provider.
     */
    private void handleDataNetworkValidationRequest(@NonNull Consumer<Integer> resultCodeCallback) {
        if (mNetworkValidationResultCodeCallback != null) {
            loge("requestNetworkValidation: previous networkValidationRequest is in progress.");
            FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
                    .accept(DataServiceCallback.RESULT_ERROR_BUSY);
            return;
        }

        mNetworkValidationResultCodeCallback = resultCodeCallback;

        // Request validation directly from the data service.
        mDataServiceManagers.get(mTransport).requestValidation(
                mCid.get(mTransport), obtainMessage(EVENT_DATA_NETWORK_VALIDATION_RESPONSE));
        log("handleDataNetworkValidationRequest, network validation requested");
    }

    private void handleErrorDataNetworkValidationRequest(
            @NonNull Consumer<Integer> resultCodeCallback) {
        loge("handleErrorDataNetworkValidationRequest: DataNetwork is not in Connected state");
        FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
                .accept(DataServiceCallback.RESULT_ERROR_ILLEGAL_STATE);
    }

    /**
     * handle the resultCode in response for the request.
     *
     * @param resultCode {@link DataServiceCallback.ResultCode}
     */
    private void handleDataNetworkValidationRequestResultCode(
            @DataServiceCallback.ResultCode int resultCode) {
        if (mNetworkValidationResultCodeCallback != null) {
            log("handleDataNetworkValidationRequestResultCode, resultCode:"
                    + DataServiceCallback.resultCodeToString(resultCode));
            FunctionalUtils.ignoreRemoteException(mNetworkValidationResultCodeCallback::accept)
                    .accept(resultCode);
            mNetworkValidationResultCodeCallback = null;
        }
    }

    /**
     * Update the validation status from {@link DataCallResponse}, convert to network validation
     * status {@link PreciseDataConnectionState.NetworkValidationStatus} and notify to
     * {@link PreciseDataConnectionState} if status was changed.
     *
     * @param networkValidationStatus {@link PreciseDataConnectionState.NetworkValidationStatus}
     */
    private void updateValidationStatus(
            @PreciseDataConnectionState.NetworkValidationStatus int networkValidationStatus) {
        if (!mFlags.networkValidation()) {
            // Do nothing, if network validation feature is disabled
            return;
        }

        // if network validation status is changed, notify preciseDataConnectionState.
        if (mNetworkValidationStatus != networkValidationStatus) {
            log("updateValidationStatus:"
                    + PreciseDataConnectionState.networkValidationStatusToString(
                    networkValidationStatus));
            mNetworkValidationStatus = networkValidationStatus;
            notifyPreciseDataConnectionState();
        }
    }

    /**
     * Convert the data tear down reason to string.
     *
@@ -3647,6 +3759,10 @@ public class DataNetwork extends StateMachine {
                return "EVENT_NOTIFY_HANDOVER_STARTED_RESPONSE";
            case EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE:
                return "EVENT_NOTIFY_HANDOVER_CANCELLED_RESPONSE";
            case EVENT_DATA_NETWORK_VALIDATION_REQUESTED:
                return "EVENT_DATA_NETWORK_VALIDATION_REQUESTED";
            case EVENT_DATA_NETWORK_VALIDATION_RESPONSE:
                return "EVENT_DATA_NETWORK_VALIDATION_RESPONSE";
            default:
                return "Unknown(" + event + ")";
        }
+41 −0
Original line number Diff line number Diff line
@@ -60,10 +60,12 @@ import android.telephony.TelephonyManager;
import android.telephony.TelephonyManager.DataState;
import android.telephony.TelephonyManager.SimState;
import android.telephony.TelephonyRegistryManager;
import android.telephony.data.ApnSetting;
import android.telephony.data.DataCallResponse;
import android.telephony.data.DataCallResponse.HandoverFailureMode;
import android.telephony.data.DataCallResponse.LinkStatus;
import android.telephony.data.DataProfile;
import android.telephony.data.DataServiceCallback;
import android.telephony.ims.ImsException;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsReasonInfo;
@@ -104,6 +106,7 @@ import com.android.internal.telephony.ims.ImsResolver;
import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
import com.android.internal.telephony.subscription.SubscriptionManagerService;
import com.android.internal.telephony.util.TelephonyUtils;
import com.android.internal.util.FunctionalUtils;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
@@ -126,6 +129,7 @@ import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

@@ -3886,6 +3890,43 @@ public class DataNetworkController extends Handler {
        return true;
    }

    /**
     * Request network validation.
     *
     * Nnetwork validation request is sent to the DataNetwork that matches the network capability
     * in the list of DataNetwork owned by the DNC.
     *
     * @param capability network capability {@link NetCapability}
     */
    public void requestNetworkValidation(@NetCapability int capability,
            @NonNull Consumer<Integer> resultCodeCallback) {

        if (DataUtils.networkCapabilityToApnType(capability) == ApnSetting.TYPE_NONE) {
            // If the capability is not an apn type based capability, sent an invalid argument.
            loge("requestNetworkValidation: the capability is not an apn type based. capability:"
                    + capability);
            FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
                    .accept(DataServiceCallback.RESULT_ERROR_INVALID_ARG);
            return;
        }

        // Find DataNetwork that matches the capability.
        List<DataNetwork> list = mDataNetworkList.stream()
                .filter(dataNetwork ->
                        dataNetwork.getNetworkCapabilities().hasCapability(capability))
                .toList();

        if (!list.isEmpty()) {
            // request network validation.
            list.forEach(dataNetwork -> dataNetwork.requestNetworkValidation(resultCodeCallback));
        } else {
            // If not found, sent an invalid argument.
            loge("requestNetworkValidation: No matching DataNetwork was found");
            FunctionalUtils.ignoreRemoteException(resultCodeCallback::accept)
                    .accept(DataServiceCallback.RESULT_ERROR_INVALID_ARG);
        }
    }

    /**
     * Log debug messages.
     * @param s debug messages
Loading