Expose vpn bypassability in VpnTransportInfo

Bug: 256775913
Test: m framework-connectivity.stubs.source.system-update-current-api
Test: m lint-check
Test: atest FrameworksNetTests
Change-Id: I6aaad7b4372aa4f91df4bed89caea674031a6367
This commit is contained in:
chiachangwang 2022-11-10 10:25:25 +00:00
commit d12d2011cb
4 changed files with 113 additions and 21 deletions

View file

@ -228,13 +228,9 @@ package android.net {
}
public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
ctor public VpnTransportInfo(int, @Nullable String);
method public int describeContents();
ctor @Deprecated public VpnTransportInfo(int, @Nullable String);
method @Nullable public String getSessionId();
method public int getType();
method @NonNull public android.net.VpnTransportInfo makeCopy(long);
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
}
}

View file

@ -511,6 +511,15 @@ package android.net {
field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
}
public final class VpnTransportInfo implements android.os.Parcelable android.net.TransportInfo {
ctor public VpnTransportInfo(int, @Nullable String, boolean);
method public int describeContents();
method public boolean getBypassable();
method public int getType();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.VpnTransportInfo> CREATOR;
}
}
package android.net.apf {

View file

@ -17,6 +17,7 @@
package android.net;
import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.annotation.SystemApi.Client.PRIVILEGED_APPS;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import android.annotation.NonNull;
@ -27,6 +28,10 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import androidx.annotation.RequiresApi;
import com.android.modules.utils.build.SdkLevel;
import java.util.Objects;
/**
@ -37,7 +42,7 @@ import java.util.Objects;
*
* @hide
*/
@SystemApi(client = MODULE_LIBRARIES)
@SystemApi(client = PRIVILEGED_APPS)
public final class VpnTransportInfo implements TransportInfo, Parcelable {
/** Type of this VPN. */
private final int mType;
@ -45,6 +50,13 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable {
@Nullable
private final String mSessionId;
private final boolean mBypassable;
// TODO: Refer to Build.VERSION_CODES when it's available in every branch.
private static final int UPSIDE_DOWN_CAKE = 34;
/** @hide */
@SystemApi(client = MODULE_LIBRARIES)
@Override
public @RedactionType long getApplicableRedactions() {
return REDACT_FOR_NETWORK_SETTINGS;
@ -52,21 +64,58 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable {
/**
* Create a copy of a {@link VpnTransportInfo} with the sessionId redacted if necessary.
* @hide
*/
@NonNull
@SystemApi(client = MODULE_LIBRARIES)
public VpnTransportInfo makeCopy(@RedactionType long redactions) {
return new VpnTransportInfo(mType,
((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : mSessionId);
((redactions & REDACT_FOR_NETWORK_SETTINGS) != 0) ? null : mSessionId, mBypassable);
}
/**
* @deprecated please use {@link VpnTransportInfo(int,String,boolean)} instead.
* @hide
*/
@Deprecated
@SystemApi(client = MODULE_LIBRARIES)
public VpnTransportInfo(int type, @Nullable String sessionId) {
// When the module runs on older SDKs, |bypassable| will always be false since the old Vpn
// code will call this constructor. For Settings VPNs, this is always correct as they are
// never bypassable. For VpnManager and VpnService types, this may be wrong since both of
// them have a choice. However, on these SDKs VpnTransportInfo#getBypassable is not
// available anyway, so this should be harmless. False is a better choice than true here
// regardless because it is the default value for both VpnManager and VpnService if the app
// does not do anything about it.
this(type, sessionId, false /* bypassable */);
}
public VpnTransportInfo(int type, @Nullable String sessionId, boolean bypassable) {
this.mType = type;
this.mSessionId = sessionId;
this.mBypassable = bypassable;
}
/**
* Returns whether the VPN is allowing bypass.
*
* This method is not supported in SDK below U, and will throw
* {@code UnsupportedOperationException} if called.
*/
@RequiresApi(UPSIDE_DOWN_CAKE)
public boolean getBypassable() {
if (!SdkLevel.isAtLeastU()) {
throw new UnsupportedOperationException("Not supported before U");
}
return mBypassable;
}
/**
* Returns the session Id of this VpnTransportInfo.
* @hide
*/
@SystemApi(client = MODULE_LIBRARIES)
@Nullable
public String getSessionId() {
return mSessionId;
@ -84,17 +133,19 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable {
if (!(o instanceof VpnTransportInfo)) return false;
VpnTransportInfo that = (VpnTransportInfo) o;
return (this.mType == that.mType) && TextUtils.equals(this.mSessionId, that.mSessionId);
return (this.mType == that.mType) && TextUtils.equals(this.mSessionId, that.mSessionId)
&& (this.mBypassable == that.mBypassable);
}
@Override
public int hashCode() {
return Objects.hash(mType, mSessionId);
return Objects.hash(mType, mSessionId, mBypassable);
}
@Override
public String toString() {
return String.format("VpnTransportInfo{type=%d, sessionId=%s}", mType, mSessionId);
return String.format("VpnTransportInfo{type=%d, sessionId=%s, bypassable=%b}",
mType, mSessionId, mBypassable);
}
@Override
@ -106,12 +157,13 @@ public final class VpnTransportInfo implements TransportInfo, Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mType);
dest.writeString(mSessionId);
dest.writeBoolean(mBypassable);
}
public static final @NonNull Creator<VpnTransportInfo> CREATOR =
new Creator<VpnTransportInfo>() {
public VpnTransportInfo createFromParcel(Parcel in) {
return new VpnTransportInfo(in.readInt(), in.readString());
return new VpnTransportInfo(in.readInt(), in.readString(), in.readBoolean());
}
public VpnTransportInfo[] newArray(int size) {
return new VpnTransportInfo[size];

View file

@ -19,10 +19,13 @@ package android.net;
import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS;
import static android.net.NetworkCapabilities.REDACT_NONE;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.ParcelUtils.assertParcelSane;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import android.os.Build;
@ -31,6 +34,7 @@ import androidx.test.filters.SmallTest;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -38,36 +42,67 @@ import org.junit.runner.RunWith;
@SmallTest
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
public class VpnTransportInfoTest {
@Rule
public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
@Test
public void testParceling() {
VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
assertParcelSane(v, 2 /* fieldCount */);
final VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
assertParcelSane(v, 3 /* fieldCount */);
final VpnTransportInfo v2 =
new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345", true);
assertParcelSane(v2, 3 /* fieldCount */);
}
@Test
public void testEqualsAndHashCode() {
String session1 = "12345";
String session2 = "6789";
VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
final VpnTransportInfo v11 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
final VpnTransportInfo v12 = new VpnTransportInfo(VpnManager.TYPE_VPN_SERVICE, session1);
final VpnTransportInfo v13 = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, session1);
final VpnTransportInfo v14 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session1);
final VpnTransportInfo v15 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1);
final VpnTransportInfo v16 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1, true);
final VpnTransportInfo v17 = new VpnTransportInfo(VpnManager.TYPE_VPN_OEM, session1, true);
final VpnTransportInfo v21 = new VpnTransportInfo(VpnManager.TYPE_VPN_LEGACY, session2);
VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
final VpnTransportInfo v31 = v11.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
final VpnTransportInfo v32 = v13.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
final VpnTransportInfo v33 = v16.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
final VpnTransportInfo v34 = v17.makeCopy(REDACT_FOR_NETWORK_SETTINGS);
assertNotEquals(v11, v12);
assertNotEquals(v13, v14);
assertNotEquals(v14, v15);
assertNotEquals(v14, v21);
assertNotEquals(v15, v16);
assertEquals(v11, v13);
assertEquals(v31, v32);
assertEquals(v33, v34);
assertEquals(v11.hashCode(), v13.hashCode());
assertEquals(v16.hashCode(), v17.hashCode());
assertEquals(REDACT_FOR_NETWORK_SETTINGS, v32.getApplicableRedactions());
assertEquals(session1, v15.makeCopy(REDACT_NONE).getSessionId());
}
@DevSdkIgnoreRule.IgnoreAfter(Build.VERSION_CODES.TIRAMISU)
@Test
public void testGetBypassable_beforeU() {
final VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
assertThrows(UnsupportedOperationException.class, () -> v.getBypassable());
}
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
@Test
public void testGetBypassable_afterU() {
final VpnTransportInfo v = new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345");
assertFalse(v.getBypassable());
final VpnTransportInfo v2 =
new VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, "12345", true);
assertTrue(v2.getBypassable());
}
}