Loading core/java/android/net/vcn/VcnTransportInfo.java +88 −12 Original line number Original line Diff line number Diff line Loading @@ -16,14 +16,23 @@ package android.net.vcn; package android.net.vcn; import static android.net.NetworkCapabilities.REDACT_ALL; import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.net.NetworkCapabilities; import android.net.TransportInfo; import android.net.TransportInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcel; import android.os.Parcelable; import android.os.Parcelable; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; import java.util.Objects; /** /** Loading @@ -37,28 +46,41 @@ import java.util.Objects; * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo * will be {@code null}. * will be {@code null}. * * * <p>Receipt of a VcnTransportInfo requires the NETWORK_SETTINGS permission; else the entire * VcnTransportInfo instance will be redacted. * * @hide * @hide */ */ public class VcnTransportInfo implements TransportInfo, Parcelable { public class VcnTransportInfo implements TransportInfo, Parcelable { @Nullable private final WifiInfo mWifiInfo; @Nullable private final WifiInfo mWifiInfo; private final int mSubId; private final int mSubId; /** * The redaction scheme to use when parcelling. * * <p>The TransportInfo/NetworkCapabilities redaction mechanisms rely on redaction being * performed at parcelling time. This means that the redaction scheme must be stored for later * use. * * <p>Since the redaction scheme itself is not parcelled, this field is listed as a transient. * * <p>Defaults to REDACT_ALL when constructed using public constructors, or creating from * parcels. */ private final transient long mRedactions; public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID); this(wifiInfo, INVALID_SUBSCRIPTION_ID, REDACT_ALL); } } public VcnTransportInfo(int subId) { public VcnTransportInfo(int subId) { this(null /* wifiInfo */, subId); this(null /* wifiInfo */, subId, REDACT_ALL); } private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) { if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { throw new IllegalArgumentException( "VcnTransportInfo requires either non-null WifiInfo or valid subId"); } } private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId, long redactions) { mWifiInfo = wifiInfo; mWifiInfo = wifiInfo; mSubId = subId; mSubId = subId; mRedactions = redactions; } } /** /** Loading Loading @@ -86,8 +108,19 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { return mSubId; return mSubId; } } /** * Gets the redaction scheme * * @hide */ @VisibleForTesting(visibility = PRIVATE) public long getRedaction() { return mRedactions; } @Override @Override public int hashCode() { public int hashCode() { // mRedactions not hashed, as it is a transient, for control of parcelling return Objects.hash(mWifiInfo, mSubId); return Objects.hash(mWifiInfo, mSubId); } } Loading @@ -96,6 +129,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { if (!(o instanceof VcnTransportInfo)) return false; if (!(o instanceof VcnTransportInfo)) return false; final VcnTransportInfo that = (VcnTransportInfo) o; final VcnTransportInfo that = (VcnTransportInfo) o; // mRedactions not compared, as it is a transient, for control of parcelling return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; } } Loading @@ -105,19 +139,61 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { return 0; return 0; } } @Override @NonNull public TransportInfo makeCopy(long redactions) { return new VcnTransportInfo( mWifiInfo == null ? null : mWifiInfo.makeCopy(redactions), mSubId, redactions); } @Override public long getApplicableRedactions() { long redactions = REDACT_FOR_NETWORK_SETTINGS; // Add additional wifi redactions if necessary if (mWifiInfo != null) { redactions |= mWifiInfo.getApplicableRedactions(); } return redactions; } private boolean shouldParcelNetworkSettingsFields() { return (mRedactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) == 0; } /** {@inheritDoc} */ /** {@inheritDoc} */ @Override @Override public void writeToParcel(@NonNull Parcel dest, int flags) {} public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(shouldParcelNetworkSettingsFields() ? mSubId : INVALID_SUBSCRIPTION_ID); dest.writeParcelable( shouldParcelNetworkSettingsFields() ? (Parcelable) mWifiInfo : null, flags); } @Override public String toString() { return "VcnTransportInfo { mWifiInfo = " + mWifiInfo + ", mSubId = " + mSubId + " }"; } /** Implement the Parcelable interface */ /** Implement the Parcelable interface */ public static final @NonNull Creator<VcnTransportInfo> CREATOR = public static final @NonNull Creator<VcnTransportInfo> CREATOR = new Creator<VcnTransportInfo>() { new Creator<VcnTransportInfo>() { public VcnTransportInfo createFromParcel(Parcel in) { public VcnTransportInfo createFromParcel(Parcel in) { // return null instead of a default VcnTransportInfo to avoid leaking final int subId = in.readInt(); // information about this being a VCN Network (instead of macro cellular, etc) final WifiInfo wifiInfo = in.readParcelable(null); // If all fields are their null values, return null TransportInfo to avoid // leaking information about this being a VCN Network (instead of macro // cellular, etc) if (wifiInfo == null && subId == INVALID_SUBSCRIPTION_ID) { return null; return null; } } // Prevent further forwarding by redacting everything in future parcels from // this VcnTransportInfo return new VcnTransportInfo(wifiInfo, subId, REDACT_ALL); } public VcnTransportInfo[] newArray(int size) { public VcnTransportInfo[] newArray(int size) { return new VcnTransportInfo[size]; return new VcnTransportInfo[size]; } } Loading tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java +41 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.net.vcn; package android.net.vcn; import static android.net.NetworkCapabilities.REDACT_ALL; import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; Loading @@ -36,6 +38,12 @@ public class VcnTransportInfoTest { private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID); private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID); private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); @Test public void testRedactionDefaults() { assertEquals(REDACT_ALL, CELL_UNDERLYING_INFO.getRedaction()); assertEquals(REDACT_ALL, WIFI_UNDERLYING_INFO.getRedaction()); } @Test @Test public void testGetWifiInfo() { public void testGetWifiInfo() { assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); Loading @@ -50,6 +58,18 @@ public class VcnTransportInfoTest { assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId()); assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId()); } } @Test public void testMakeCopySetsRedactions() { assertEquals( REDACT_FOR_NETWORK_SETTINGS, ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) .getRedaction()); assertEquals( REDACT_FOR_NETWORK_SETTINGS, ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) .getRedaction()); } @Test @Test public void testEquals() { public void testEquals() { assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO); assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO); Loading @@ -64,8 +84,29 @@ public class VcnTransportInfoTest { } } private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { // Verify redacted by default Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain(); vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); parcel.setDataPosition(0); assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); } } @Test public void testParcelUnparcelNotRedactedForSysUi() { verifyParcelingForSysUi(CELL_UNDERLYING_INFO); verifyParcelingForSysUi(WIFI_UNDERLYING_INFO); } private void verifyParcelingForSysUi(VcnTransportInfo vcnTransportInfo) { // Allow fully unredacted; SysUI will have all the relevant permissions. final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(0); final Parcel parcel = Parcel.obtain(); unRedacted.writeToParcel(parcel, 0 /* flags */); parcel.setDataPosition(0); final VcnTransportInfo unparceled = VcnTransportInfo.CREATOR.createFromParcel(parcel); assertEquals(vcnTransportInfo, unparceled); assertEquals(REDACT_ALL, unparceled.getRedaction()); } } } Loading
core/java/android/net/vcn/VcnTransportInfo.java +88 −12 Original line number Original line Diff line number Diff line Loading @@ -16,14 +16,23 @@ package android.net.vcn; package android.net.vcn; import static android.net.NetworkCapabilities.REDACT_ALL; import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static com.android.internal.annotations.VisibleForTesting.Visibility.PRIVATE; import android.annotation.NonNull; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.Nullable; import android.net.NetworkCapabilities; import android.net.TransportInfo; import android.net.TransportInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiInfo; import android.os.Parcel; import android.os.Parcel; import android.os.Parcelable; import android.os.Parcelable; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager; import com.android.internal.annotations.VisibleForTesting; import java.util.Objects; import java.util.Objects; /** /** Loading @@ -37,28 +46,41 @@ import java.util.Objects; * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo * will be {@code null}. * will be {@code null}. * * * <p>Receipt of a VcnTransportInfo requires the NETWORK_SETTINGS permission; else the entire * VcnTransportInfo instance will be redacted. * * @hide * @hide */ */ public class VcnTransportInfo implements TransportInfo, Parcelable { public class VcnTransportInfo implements TransportInfo, Parcelable { @Nullable private final WifiInfo mWifiInfo; @Nullable private final WifiInfo mWifiInfo; private final int mSubId; private final int mSubId; /** * The redaction scheme to use when parcelling. * * <p>The TransportInfo/NetworkCapabilities redaction mechanisms rely on redaction being * performed at parcelling time. This means that the redaction scheme must be stored for later * use. * * <p>Since the redaction scheme itself is not parcelled, this field is listed as a transient. * * <p>Defaults to REDACT_ALL when constructed using public constructors, or creating from * parcels. */ private final transient long mRedactions; public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { public VcnTransportInfo(@NonNull WifiInfo wifiInfo) { this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID); this(wifiInfo, INVALID_SUBSCRIPTION_ID, REDACT_ALL); } } public VcnTransportInfo(int subId) { public VcnTransportInfo(int subId) { this(null /* wifiInfo */, subId); this(null /* wifiInfo */, subId, REDACT_ALL); } private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) { if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { throw new IllegalArgumentException( "VcnTransportInfo requires either non-null WifiInfo or valid subId"); } } private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId, long redactions) { mWifiInfo = wifiInfo; mWifiInfo = wifiInfo; mSubId = subId; mSubId = subId; mRedactions = redactions; } } /** /** Loading Loading @@ -86,8 +108,19 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { return mSubId; return mSubId; } } /** * Gets the redaction scheme * * @hide */ @VisibleForTesting(visibility = PRIVATE) public long getRedaction() { return mRedactions; } @Override @Override public int hashCode() { public int hashCode() { // mRedactions not hashed, as it is a transient, for control of parcelling return Objects.hash(mWifiInfo, mSubId); return Objects.hash(mWifiInfo, mSubId); } } Loading @@ -96,6 +129,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { if (!(o instanceof VcnTransportInfo)) return false; if (!(o instanceof VcnTransportInfo)) return false; final VcnTransportInfo that = (VcnTransportInfo) o; final VcnTransportInfo that = (VcnTransportInfo) o; // mRedactions not compared, as it is a transient, for control of parcelling return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId; } } Loading @@ -105,19 +139,61 @@ public class VcnTransportInfo implements TransportInfo, Parcelable { return 0; return 0; } } @Override @NonNull public TransportInfo makeCopy(long redactions) { return new VcnTransportInfo( mWifiInfo == null ? null : mWifiInfo.makeCopy(redactions), mSubId, redactions); } @Override public long getApplicableRedactions() { long redactions = REDACT_FOR_NETWORK_SETTINGS; // Add additional wifi redactions if necessary if (mWifiInfo != null) { redactions |= mWifiInfo.getApplicableRedactions(); } return redactions; } private boolean shouldParcelNetworkSettingsFields() { return (mRedactions & NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS) == 0; } /** {@inheritDoc} */ /** {@inheritDoc} */ @Override @Override public void writeToParcel(@NonNull Parcel dest, int flags) {} public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(shouldParcelNetworkSettingsFields() ? mSubId : INVALID_SUBSCRIPTION_ID); dest.writeParcelable( shouldParcelNetworkSettingsFields() ? (Parcelable) mWifiInfo : null, flags); } @Override public String toString() { return "VcnTransportInfo { mWifiInfo = " + mWifiInfo + ", mSubId = " + mSubId + " }"; } /** Implement the Parcelable interface */ /** Implement the Parcelable interface */ public static final @NonNull Creator<VcnTransportInfo> CREATOR = public static final @NonNull Creator<VcnTransportInfo> CREATOR = new Creator<VcnTransportInfo>() { new Creator<VcnTransportInfo>() { public VcnTransportInfo createFromParcel(Parcel in) { public VcnTransportInfo createFromParcel(Parcel in) { // return null instead of a default VcnTransportInfo to avoid leaking final int subId = in.readInt(); // information about this being a VCN Network (instead of macro cellular, etc) final WifiInfo wifiInfo = in.readParcelable(null); // If all fields are their null values, return null TransportInfo to avoid // leaking information about this being a VCN Network (instead of macro // cellular, etc) if (wifiInfo == null && subId == INVALID_SUBSCRIPTION_ID) { return null; return null; } } // Prevent further forwarding by redacting everything in future parcels from // this VcnTransportInfo return new VcnTransportInfo(wifiInfo, subId, REDACT_ALL); } public VcnTransportInfo[] newArray(int size) { public VcnTransportInfo[] newArray(int size) { return new VcnTransportInfo[size]; return new VcnTransportInfo[size]; } } Loading
tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java +41 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,8 @@ package android.net.vcn; package android.net.vcn; import static android.net.NetworkCapabilities.REDACT_ALL; import static android.net.NetworkCapabilities.REDACT_FOR_NETWORK_SETTINGS; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; Loading @@ -36,6 +38,12 @@ public class VcnTransportInfoTest { private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID); private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID); private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO); @Test public void testRedactionDefaults() { assertEquals(REDACT_ALL, CELL_UNDERLYING_INFO.getRedaction()); assertEquals(REDACT_ALL, WIFI_UNDERLYING_INFO.getRedaction()); } @Test @Test public void testGetWifiInfo() { public void testGetWifiInfo() { assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo()); Loading @@ -50,6 +58,18 @@ public class VcnTransportInfoTest { assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId()); assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId()); } } @Test public void testMakeCopySetsRedactions() { assertEquals( REDACT_FOR_NETWORK_SETTINGS, ((VcnTransportInfo) CELL_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) .getRedaction()); assertEquals( REDACT_FOR_NETWORK_SETTINGS, ((VcnTransportInfo) WIFI_UNDERLYING_INFO.makeCopy(REDACT_FOR_NETWORK_SETTINGS)) .getRedaction()); } @Test @Test public void testEquals() { public void testEquals() { assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO); assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO); Loading @@ -64,8 +84,29 @@ public class VcnTransportInfoTest { } } private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) { // Verify redacted by default Parcel parcel = Parcel.obtain(); Parcel parcel = Parcel.obtain(); vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); vcnTransportInfo.writeToParcel(parcel, 0 /* flags */); parcel.setDataPosition(0); assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel)); } } @Test public void testParcelUnparcelNotRedactedForSysUi() { verifyParcelingForSysUi(CELL_UNDERLYING_INFO); verifyParcelingForSysUi(WIFI_UNDERLYING_INFO); } private void verifyParcelingForSysUi(VcnTransportInfo vcnTransportInfo) { // Allow fully unredacted; SysUI will have all the relevant permissions. final VcnTransportInfo unRedacted = (VcnTransportInfo) vcnTransportInfo.makeCopy(0); final Parcel parcel = Parcel.obtain(); unRedacted.writeToParcel(parcel, 0 /* flags */); parcel.setDataPosition(0); final VcnTransportInfo unparceled = VcnTransportInfo.CREATOR.createFromParcel(parcel); assertEquals(vcnTransportInfo, unparceled); assertEquals(REDACT_ALL, unparceled.getRedaction()); } } }