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

Commit 913ae2b8 authored by Benedict Wong's avatar Benedict Wong
Browse files

Allow VcnTransportInfo to be parcelled

Allows VCN transport info to be parcelled for purposes of sysUI

Bug: 186025257
Test: atest FrameworksVcnTests
Change-Id: I5a5d9b88659c8dcaa9ded16d491b2bac0529169a
parent 47f27e64
Loading
Loading
Loading
Loading
+88 −12
Original line number Diff line number Diff line
@@ -16,14 +16,23 @@

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.Nullable;
import android.net.NetworkCapabilities;
import android.net.TransportInfo;
import android.net.wifi.WifiInfo;
import android.os.Parcel;
import android.os.Parcelable;
import android.telephony.SubscriptionManager;

import com.android.internal.annotations.VisibleForTesting;

import java.util.Objects;

/**
@@ -37,28 +46,41 @@ import java.util.Objects;
 * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo
 * will be {@code null}.
 *
 * <p>Receipt of a VcnTransportInfo requires the NETWORK_SETTINGS permission; else the entire
 * VcnTransportInfo instance will be redacted.
 *
 * @hide
 */
public class VcnTransportInfo implements TransportInfo, Parcelable {
    @Nullable private final WifiInfo mWifiInfo;
    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) {
        this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
        this(wifiInfo, INVALID_SUBSCRIPTION_ID, REDACT_ALL);
    }

    public VcnTransportInfo(int subId) {
        this(null /* wifiInfo */, subId);
    }

    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");
        this(null /* wifiInfo */, subId, REDACT_ALL);
    }

    private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId, long redactions) {
        mWifiInfo = wifiInfo;
        mSubId = subId;
        mRedactions = redactions;
    }

    /**
@@ -86,8 +108,19 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
        return mSubId;
    }

    /**
     * Gets the redaction scheme
     *
     * @hide
     */
    @VisibleForTesting(visibility = PRIVATE)
    public long getRedaction() {
        return mRedactions;
    }

    @Override
    public int hashCode() {
        // mRedactions not hashed, as it is a transient, for control of parcelling
        return Objects.hash(mWifiInfo, mSubId);
    }

@@ -96,6 +129,7 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
        if (!(o instanceof VcnTransportInfo)) return false;
        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;
    }

@@ -105,19 +139,61 @@ public class VcnTransportInfo implements TransportInfo, Parcelable {
        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} */
    @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 */
    public static final @NonNull Creator<VcnTransportInfo> CREATOR =
            new Creator<VcnTransportInfo>() {
                public VcnTransportInfo createFromParcel(Parcel in) {
                    // return null instead of a default VcnTransportInfo to avoid leaking
                    // information about this being a VCN Network (instead of macro cellular, etc)
                    final int subId = in.readInt();
                    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;
                    }

                    // Prevent further forwarding by redacting everything in future parcels from
                    // this VcnTransportInfo
                    return new VcnTransportInfo(wifiInfo, subId, REDACT_ALL);
                }

                public VcnTransportInfo[] newArray(int size) {
                    return new VcnTransportInfo[size];
                }
+41 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

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 org.junit.Assert.assertEquals;
@@ -36,6 +38,12 @@ public class VcnTransportInfoTest {
    private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID);
    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
    public void testGetWifiInfo() {
        assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
@@ -50,6 +58,18 @@ public class VcnTransportInfoTest {
        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
    public void testEquals() {
        assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO);
@@ -64,8 +84,29 @@ public class VcnTransportInfoTest {
    }

    private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
        // Verify redacted by default
        Parcel parcel = Parcel.obtain();
        vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
        parcel.setDataPosition(0);

        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());
    }
}