Add SkipNativeNetworkCreation flag in NetworkAgentConfig
This flag allows ConnectivityService to skip native network creation, deferring this responsibility to Tethering. This is necessary because: - ConnectivityService requires the NetworkAgent to be in the CONNECTED state to configure routing and invokes NetworkCallback#onAvailable once ready. - Tethering requires lower-layer interactions to be completed before notifying applications. This approach ensures proper synchronization between ConnectivityService and Tethering during network setup. Long-term, all netd operations should be handled by ConnectivityService when it supports early native network creation in the CONNECTING state. As a mid-term solution, this flag enables Tethering to manage native network creation within the IpServer. Test: atest ConnectivityCoverageTests:android.net.connectivity.android.net.NetworkAgentConfigTest Bug: 349487600 Change-Id: I84da9c74dc4d40c7cd36c6657f17a158affed689
This commit is contained in:
parent
04783040d5
commit
fef111ce47
2 changed files with 84 additions and 27 deletions
|
|
@ -272,6 +272,27 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
return mVpnRequiresValidation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the native network creation should be skipped.
|
||||
*
|
||||
* If set, the native network and routes should be maintained by the caller.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
private boolean mSkipNativeNetworkCreation = false;
|
||||
|
||||
|
||||
/**
|
||||
* @return Whether the native network creation should be skipped.
|
||||
* @hide
|
||||
*/
|
||||
// TODO: Expose API when ready.
|
||||
// @FlaggedApi(Flags.FLAG_TETHERING_NETWORK_AGENT)
|
||||
// @SystemApi(client = MODULE_LIBRARIES) when ready.
|
||||
public boolean shouldSkipNativeNetworkCreation() {
|
||||
return mSkipNativeNetworkCreation;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public NetworkAgentConfig() {
|
||||
}
|
||||
|
|
@ -293,6 +314,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
mLegacyExtraInfo = nac.mLegacyExtraInfo;
|
||||
excludeLocalRouteVpn = nac.excludeLocalRouteVpn;
|
||||
mVpnRequiresValidation = nac.mVpnRequiresValidation;
|
||||
mSkipNativeNetworkCreation = nac.mSkipNativeNetworkCreation;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -483,6 +505,26 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the native network creation should be skipped.
|
||||
*
|
||||
* @return this builder, to facilitate chaining.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
// TODO: Expose API when ready.
|
||||
// @FlaggedApi(Flags.FLAG_TETHERING_NETWORK_AGENT)
|
||||
// @SystemApi(client = MODULE_LIBRARIES) when ready.
|
||||
public Builder setSkipNativeNetworkCreation(boolean skipNativeNetworkCreation) {
|
||||
if (!SdkLevel.isAtLeastV()) {
|
||||
// Local agents are supported starting on U on TVs and on V on everything else.
|
||||
// Thus, only support this flag on V+.
|
||||
throw new UnsupportedOperationException("Method is not supported");
|
||||
}
|
||||
mConfig.mSkipNativeNetworkCreation = skipNativeNetworkCreation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the constructed {@link NetworkAgentConfig} object.
|
||||
*/
|
||||
|
|
@ -510,7 +552,8 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
&& Objects.equals(legacySubTypeName, that.legacySubTypeName)
|
||||
&& Objects.equals(mLegacyExtraInfo, that.mLegacyExtraInfo)
|
||||
&& excludeLocalRouteVpn == that.excludeLocalRouteVpn
|
||||
&& mVpnRequiresValidation == that.mVpnRequiresValidation;
|
||||
&& mVpnRequiresValidation == that.mVpnRequiresValidation
|
||||
&& mSkipNativeNetworkCreation == that.mSkipNativeNetworkCreation;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -518,7 +561,8 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
return Objects.hash(allowBypass, explicitlySelected, acceptUnvalidated,
|
||||
acceptPartialConnectivity, provisioningNotificationDisabled, subscriberId,
|
||||
skip464xlat, legacyType, legacySubType, legacyTypeName, legacySubTypeName,
|
||||
mLegacyExtraInfo, excludeLocalRouteVpn, mVpnRequiresValidation);
|
||||
mLegacyExtraInfo, excludeLocalRouteVpn, mVpnRequiresValidation,
|
||||
mSkipNativeNetworkCreation);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -539,6 +583,7 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
+ ", legacyExtraInfo = '" + mLegacyExtraInfo + '\''
|
||||
+ ", excludeLocalRouteVpn = '" + excludeLocalRouteVpn + '\''
|
||||
+ ", vpnRequiresValidation = '" + mVpnRequiresValidation + '\''
|
||||
+ ", skipNativeNetworkCreation = '" + mSkipNativeNetworkCreation + '\''
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
|
@ -563,33 +608,35 @@ public final class NetworkAgentConfig implements Parcelable {
|
|||
out.writeString(mLegacyExtraInfo);
|
||||
out.writeInt(excludeLocalRouteVpn ? 1 : 0);
|
||||
out.writeInt(mVpnRequiresValidation ? 1 : 0);
|
||||
out.writeInt(mSkipNativeNetworkCreation ? 1 : 0);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<NetworkAgentConfig> CREATOR =
|
||||
new Creator<NetworkAgentConfig>() {
|
||||
@Override
|
||||
public NetworkAgentConfig createFromParcel(Parcel in) {
|
||||
NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
|
||||
networkAgentConfig.allowBypass = in.readInt() != 0;
|
||||
networkAgentConfig.explicitlySelected = in.readInt() != 0;
|
||||
networkAgentConfig.acceptUnvalidated = in.readInt() != 0;
|
||||
networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0;
|
||||
networkAgentConfig.subscriberId = in.readString();
|
||||
networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0;
|
||||
networkAgentConfig.skip464xlat = in.readInt() != 0;
|
||||
networkAgentConfig.legacyType = in.readInt();
|
||||
networkAgentConfig.legacyTypeName = in.readString();
|
||||
networkAgentConfig.legacySubType = in.readInt();
|
||||
networkAgentConfig.legacySubTypeName = in.readString();
|
||||
networkAgentConfig.mLegacyExtraInfo = in.readString();
|
||||
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
|
||||
networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0;
|
||||
return networkAgentConfig;
|
||||
}
|
||||
@Override
|
||||
public NetworkAgentConfig createFromParcel(Parcel in) {
|
||||
NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
|
||||
networkAgentConfig.allowBypass = in.readInt() != 0;
|
||||
networkAgentConfig.explicitlySelected = in.readInt() != 0;
|
||||
networkAgentConfig.acceptUnvalidated = in.readInt() != 0;
|
||||
networkAgentConfig.acceptPartialConnectivity = in.readInt() != 0;
|
||||
networkAgentConfig.subscriberId = in.readString();
|
||||
networkAgentConfig.provisioningNotificationDisabled = in.readInt() != 0;
|
||||
networkAgentConfig.skip464xlat = in.readInt() != 0;
|
||||
networkAgentConfig.legacyType = in.readInt();
|
||||
networkAgentConfig.legacyTypeName = in.readString();
|
||||
networkAgentConfig.legacySubType = in.readInt();
|
||||
networkAgentConfig.legacySubTypeName = in.readString();
|
||||
networkAgentConfig.mLegacyExtraInfo = in.readString();
|
||||
networkAgentConfig.excludeLocalRouteVpn = in.readInt() != 0;
|
||||
networkAgentConfig.mVpnRequiresValidation = in.readInt() != 0;
|
||||
networkAgentConfig.mSkipNativeNetworkCreation = in.readInt() != 0;
|
||||
return networkAgentConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkAgentConfig[] newArray(int size) {
|
||||
return new NetworkAgentConfig[size];
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public NetworkAgentConfig[] newArray(int size) {
|
||||
return new NetworkAgentConfig[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import androidx.test.filters.SmallTest
|
|||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.modules.utils.build.SdkLevel.isAtLeastS
|
||||
import com.android.modules.utils.build.SdkLevel.isAtLeastT
|
||||
import com.android.modules.utils.build.SdkLevel.isAtLeastV
|
||||
import com.android.testutils.ConnectivityModuleTest
|
||||
import com.android.testutils.assertParcelingIsLossless
|
||||
import org.junit.Assert.assertEquals
|
||||
|
|
@ -47,6 +48,9 @@ class NetworkAgentConfigTest {
|
|||
setLocalRoutesExcludedForVpn(true)
|
||||
setVpnRequiresValidation(true)
|
||||
}
|
||||
if (isAtLeastV()) {
|
||||
setSkipNativeNetworkCreation(true)
|
||||
}
|
||||
}.build()
|
||||
assertParcelingIsLossless(config)
|
||||
}
|
||||
|
|
@ -71,6 +75,9 @@ class NetworkAgentConfigTest {
|
|||
setLocalRoutesExcludedForVpn(true)
|
||||
setVpnRequiresValidation(true)
|
||||
}
|
||||
if (isAtLeastV()) {
|
||||
setSkipNativeNetworkCreation(true)
|
||||
}
|
||||
}.build()
|
||||
|
||||
assertTrue(config.isExplicitlySelected())
|
||||
|
|
@ -79,6 +86,9 @@ class NetworkAgentConfigTest {
|
|||
assertFalse(config.isPartialConnectivityAcceptable())
|
||||
assertTrue(config.isUnvalidatedConnectivityAcceptable())
|
||||
assertEquals("TEST_NETWORK", config.getLegacyTypeName())
|
||||
if (isAtLeastV()) {
|
||||
assertTrue(config.shouldSkipNativeNetworkCreation())
|
||||
}
|
||||
if (isAtLeastT()) {
|
||||
assertTrue(config.areLocalRoutesExcludedForVpn())
|
||||
assertTrue(config.isVpnValidationRequired())
|
||||
|
|
|
|||
Loading…
Reference in a new issue