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

Commit 144519f4 authored by Remi NGUYEN VAN's avatar Remi NGUYEN VAN Committed by Gerrit Code Review
Browse files

Merge "Add API for CaptivePortalData"

parents 385afc99 ead1ef41
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -4307,6 +4307,32 @@ package android.net {
    field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
  }
  public final class CaptivePortalData implements android.os.Parcelable {
    method public int describeContents();
    method public long getByteLimit();
    method public long getExpiryTimeMillis();
    method public long getRefreshTimeMillis();
    method @Nullable public android.net.Uri getUserPortalUrl();
    method @Nullable public android.net.Uri getVenueInfoUrl();
    method public boolean isCaptive();
    method public boolean isSessionExtendable();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
  }
  public static class CaptivePortalData.Builder {
    ctor public CaptivePortalData.Builder();
    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
    method @NonNull public android.net.CaptivePortalData build();
    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
  }
  public class ConnectivityManager {
    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
    method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
@@ -4438,6 +4464,8 @@ package android.net {
    method @NonNull public java.util.List<java.lang.String> getAllInterfaceNames();
    method @NonNull public java.util.List<android.net.LinkAddress> getAllLinkAddresses();
    method @NonNull public java.util.List<android.net.RouteInfo> getAllRoutes();
    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
    method @Nullable public String getTcpBufferSizes();
    method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -4451,9 +4479,12 @@ package android.net {
    method public boolean isIpv6Provisioned();
    method public boolean isProvisioned();
    method public boolean isReachable(@NonNull java.net.InetAddress);
    method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
    method public boolean removeDnsServer(@NonNull java.net.InetAddress);
    method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
    method public boolean removeRoute(@NonNull android.net.RouteInfo);
    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
    method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
    method public void setPrivateDnsServerName(@Nullable String);
    method public void setTcpBufferSizes(@Nullable String);
+31 −0
Original line number Diff line number Diff line
@@ -1361,6 +1361,32 @@ package android.net {
    field public static final int APP_RETURN_WANTED_AS_IS = 2; // 0x2
  }

  public final class CaptivePortalData implements android.os.Parcelable {
    method public int describeContents();
    method public long getByteLimit();
    method public long getExpiryTimeMillis();
    method public long getRefreshTimeMillis();
    method @Nullable public android.net.Uri getUserPortalUrl();
    method @Nullable public android.net.Uri getVenueInfoUrl();
    method public boolean isCaptive();
    method public boolean isSessionExtendable();
    method public void writeToParcel(@NonNull android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.net.CaptivePortalData> CREATOR;
  }

  public static class CaptivePortalData.Builder {
    ctor public CaptivePortalData.Builder();
    ctor public CaptivePortalData.Builder(@Nullable android.net.CaptivePortalData);
    method @NonNull public android.net.CaptivePortalData build();
    method @NonNull public android.net.CaptivePortalData.Builder setBytesRemaining(long);
    method @NonNull public android.net.CaptivePortalData.Builder setCaptive(boolean);
    method @NonNull public android.net.CaptivePortalData.Builder setExpiryTime(long);
    method @NonNull public android.net.CaptivePortalData.Builder setRefreshTime(long);
    method @NonNull public android.net.CaptivePortalData.Builder setSessionExtendable(boolean);
    method @NonNull public android.net.CaptivePortalData.Builder setUserPortalUrl(@Nullable android.net.Uri);
    method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri);
  }

  public class ConnectivityManager {
    method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
    field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
@@ -1391,6 +1417,8 @@ package android.net {
    ctor public LinkProperties(@Nullable android.net.LinkProperties);
    method public boolean addDnsServer(@NonNull java.net.InetAddress);
    method public boolean addLinkAddress(@NonNull android.net.LinkAddress);
    method @Nullable public android.net.Uri getCaptivePortalApiUrl();
    method @Nullable public android.net.CaptivePortalData getCaptivePortalData();
    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
    method @Nullable public String getTcpBufferSizes();
    method @NonNull public java.util.List<java.net.InetAddress> getValidatedPrivateDnsServers();
@@ -1401,9 +1429,12 @@ package android.net {
    method public boolean isIpv6Provisioned();
    method public boolean isProvisioned();
    method public boolean isReachable(@NonNull java.net.InetAddress);
    method @NonNull public android.net.LinkProperties makeSensitiveFieldsParcelingCopy();
    method public boolean removeDnsServer(@NonNull java.net.InetAddress);
    method public boolean removeLinkAddress(@NonNull android.net.LinkAddress);
    method public boolean removeRoute(@NonNull android.net.RouteInfo);
    method public void setCaptivePortalApiUrl(@Nullable android.net.Uri);
    method public void setCaptivePortalData(@Nullable android.net.CaptivePortalData);
    method public void setPcscfServers(@NonNull java.util.Collection<java.net.InetAddress>);
    method public void setPrivateDnsServerName(@Nullable String);
    method public void setTcpBufferSizes(@Nullable String);
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

@JavaOnlyStableParcelable parcelable CaptivePortalData;
+281 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.net;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.os.Parcel;
import android.os.Parcelable;

import java.util.Objects;

/**
 * Metadata sent by captive portals, see https://www.ietf.org/id/draft-ietf-capport-api-03.txt.
 * @hide
 */
@SystemApi
@TestApi
public final class CaptivePortalData implements Parcelable {
    private final long mRefreshTimeMillis;
    @Nullable
    private final Uri mUserPortalUrl;
    @Nullable
    private final Uri mVenueInfoUrl;
    private final boolean mIsSessionExtendable;
    private final long mByteLimit;
    private final long mExpiryTimeMillis;
    private final boolean mCaptive;

    private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl,
            boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive) {
        mRefreshTimeMillis = refreshTimeMillis;
        mUserPortalUrl = userPortalUrl;
        mVenueInfoUrl = venueInfoUrl;
        mIsSessionExtendable = isSessionExtendable;
        mByteLimit = byteLimit;
        mExpiryTimeMillis = expiryTimeMillis;
        mCaptive = captive;
    }

    private CaptivePortalData(Parcel p) {
        this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(),
                p.readLong(), p.readLong(), p.readBoolean());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        dest.writeLong(mRefreshTimeMillis);
        dest.writeParcelable(mUserPortalUrl, 0);
        dest.writeParcelable(mVenueInfoUrl, 0);
        dest.writeBoolean(mIsSessionExtendable);
        dest.writeLong(mByteLimit);
        dest.writeLong(mExpiryTimeMillis);
        dest.writeBoolean(mCaptive);
    }

    /**
     * A builder to create new {@link CaptivePortalData}.
     */
    public static class Builder {
        private long mRefreshTime;
        private Uri mUserPortalUrl;
        private Uri mVenueInfoUrl;
        private boolean mIsSessionExtendable;
        private long mBytesRemaining = -1;
        private long mExpiryTime = -1;
        private boolean mCaptive;

        /**
         * Create an empty builder.
         */
        public Builder() {}

        /**
         * Create a builder copying all data from existing {@link CaptivePortalData}.
         */
        public Builder(@Nullable CaptivePortalData data) {
            if (data == null) return;
            setRefreshTime(data.mRefreshTimeMillis)
                    .setUserPortalUrl(data.mUserPortalUrl)
                    .setVenueInfoUrl(data.mVenueInfoUrl)
                    .setSessionExtendable(data.mIsSessionExtendable)
                    .setBytesRemaining(data.mByteLimit)
                    .setExpiryTime(data.mExpiryTimeMillis)
                    .setCaptive(data.mCaptive);
        }

        /**
         * Set the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
         */
        @NonNull
        public Builder setRefreshTime(long refreshTime) {
            mRefreshTime = refreshTime;
            return this;
        }

        /**
         * Set the URL to be used for users to login to the portal, if captive.
         */
        @NonNull
        public Builder setUserPortalUrl(@Nullable Uri userPortalUrl) {
            mUserPortalUrl = userPortalUrl;
            return this;
        }

        /**
         * Set the URL that can be used by users to view information about the network venue.
         */
        @NonNull
        public Builder setVenueInfoUrl(@Nullable Uri venueInfoUrl) {
            mVenueInfoUrl = venueInfoUrl;
            return this;
        }

        /**
         * Set whether the portal supports extending a user session on the portal URL page.
         */
        @NonNull
        public Builder setSessionExtendable(boolean sessionExtendable) {
            mIsSessionExtendable = sessionExtendable;
            return this;
        }

        /**
         * Set the number of bytes remaining on the network before the portal closes.
         */
        @NonNull
        public Builder setBytesRemaining(long bytesRemaining) {
            mBytesRemaining = bytesRemaining;
            return this;
        }

        /**
         * Set the time at the session will expire, as per {@link System#currentTimeMillis()}.
         */
        @NonNull
        public Builder setExpiryTime(long expiryTime) {
            mExpiryTime = expiryTime;
            return this;
        }

        /**
         * Set whether the network is captive (portal closed).
         */
        @NonNull
        public Builder setCaptive(boolean captive) {
            mCaptive = captive;
            return this;
        }

        /**
         * Create a new {@link CaptivePortalData}.
         */
        @NonNull
        public CaptivePortalData build() {
            return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl,
                    mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive);
        }
    }

    /**
     * Get the time at which data was last refreshed, as per {@link System#currentTimeMillis()}.
     */
    public long getRefreshTimeMillis() {
        return mRefreshTimeMillis;
    }

    /**
     * Get the URL to be used for users to login to the portal, or extend their session if
     * {@link #isSessionExtendable()} is true.
     */
    @Nullable
    public Uri getUserPortalUrl() {
        return mUserPortalUrl;
    }

    /**
     * Get the URL that can be used by users to view information about the network venue.
     */
    @Nullable
    public Uri getVenueInfoUrl() {
        return mVenueInfoUrl;
    }

    /**
     * Indicates whether the user portal URL can be used to extend sessions, when the user is logged
     * in and the session has a time or byte limit.
     */
    public boolean isSessionExtendable() {
        return mIsSessionExtendable;
    }

    /**
     * Get the remaining bytes on the captive portal session, at the time {@link CaptivePortalData}
     * was refreshed. This may be different from the limit currently enforced by the portal.
     * @return The byte limit, or -1 if not set.
     */
    public long getByteLimit() {
        return mByteLimit;
    }

    /**
     * Get the time at the session will expire, as per {@link System#currentTimeMillis()}.
     * @return The expiry time, or -1 if unset.
     */
    public long getExpiryTimeMillis() {
        return mExpiryTimeMillis;
    }

    /**
     * Get whether the network is captive (portal closed).
     */
    public boolean isCaptive() {
        return mCaptive;
    }

    @NonNull
    public static final Creator<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() {
        @Override
        public CaptivePortalData createFromParcel(Parcel source) {
            return new CaptivePortalData(source);
        }

        @Override
        public CaptivePortalData[] newArray(int size) {
            return new CaptivePortalData[size];
        }
    };

    @Override
    public int hashCode() {
        return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl,
                mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive);
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof CaptivePortalData)) return false;
        final CaptivePortalData other = (CaptivePortalData) obj;
        return mRefreshTimeMillis == other.mRefreshTimeMillis
                && Objects.equals(mUserPortalUrl, other.mUserPortalUrl)
                && Objects.equals(mVenueInfoUrl, other.mVenueInfoUrl)
                && mIsSessionExtendable == other.mIsSessionExtendable
                && mByteLimit == other.mByteLimit
                && mExpiryTimeMillis == other.mExpiryTimeMillis
                && mCaptive == other.mCaptive;
    }

    @Override
    public String toString() {
        return "CaptivePortalData {"
                + "refreshTime: " + mRefreshTimeMillis
                + ", userPortalUrl: " + mUserPortalUrl
                + ", venueInfoUrl: " + mVenueInfoUrl
                + ", isSessionExtendable: " + mIsSessionExtendable
                + ", byteLimit: " + mByteLimit
                + ", expiryTime: " + mExpiryTimeMillis
                + ", captive: " + mCaptive
                + "}";
    }
}
+148 −21
Original line number Diff line number Diff line
@@ -70,6 +70,14 @@ public final class LinkProperties implements Parcelable {
    private String mTcpBufferSizes;
    private IpPrefix mNat64Prefix;
    private boolean mWakeOnLanSupported;
    private Uri mCaptivePortalApiUrl;
    private CaptivePortalData mCaptivePortalData;

    /**
     * Indicates whether parceling should preserve fields that are set based on permissions of
     * the process receiving the {@link LinkProperties}.
     */
    private final transient boolean mParcelSensitiveFields;

    private static final int MIN_MTU    = 68;
    private static final int MIN_MTU_V6 = 1280;
@@ -174,6 +182,7 @@ public final class LinkProperties implements Parcelable {
     * Constructs a new {@code LinkProperties} with default values.
     */
    public LinkProperties() {
        mParcelSensitiveFields = false;
    }

    /**
@@ -182,7 +191,12 @@ public final class LinkProperties implements Parcelable {
    @SystemApi
    @TestApi
    public LinkProperties(@Nullable LinkProperties source) {
        if (source != null) {
        this(source, false /* parcelSensitiveFields */);
    }

    private LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
        mParcelSensitiveFields = parcelSensitiveFields;
        if (source == null) return;
        mIfaceName = source.mIfaceName;
        mLinkAddresses.addAll(source.mLinkAddresses);
        mDnses.addAll(source.mDnses);
@@ -201,7 +215,8 @@ public final class LinkProperties implements Parcelable {
        mTcpBufferSizes = source.mTcpBufferSizes;
        mNat64Prefix = source.mNat64Prefix;
        mWakeOnLanSupported = source.mWakeOnLanSupported;
        }
        mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
        mCaptivePortalData = source.mCaptivePortalData;
    }

    /**
@@ -860,6 +875,11 @@ public final class LinkProperties implements Parcelable {
     * Clears this object to its initial state.
     */
    public void clear() {
        if (mParcelSensitiveFields) {
            throw new UnsupportedOperationException(
                    "Cannot clear LinkProperties when parcelSensitiveFields is set");
        }

        mIfaceName = null;
        mLinkAddresses.clear();
        mDnses.clear();
@@ -875,6 +895,8 @@ public final class LinkProperties implements Parcelable {
        mTcpBufferSizes = null;
        mNat64Prefix = null;
        mWakeOnLanSupported = false;
        mCaptivePortalApiUrl = null;
        mCaptivePortalData = null;
    }

    /**
@@ -945,6 +967,14 @@ public final class LinkProperties implements Parcelable {
            resultJoiner.add(mDhcpServerAddress.toString());
        }

        if (mCaptivePortalApiUrl != null) {
            resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl);
        }

        if (mCaptivePortalData != null) {
            resultJoiner.add("CaptivePortalData: " + mCaptivePortalData);
        }

        if (mTcpBufferSizes != null) {
            resultJoiner.add("TcpBufferSizes:");
            resultJoiner.add(mTcpBufferSizes);
@@ -1478,6 +1508,28 @@ public final class LinkProperties implements Parcelable {
        return isWakeOnLanSupported() == target.isWakeOnLanSupported();
    }

    /**
     * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target.
     *
     * @param target LinkProperties to compare.
     * @return {@code true} if both are identical, {@code false} otherwise.
     * @hide
     */
    public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) {
        return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl);
    }

    /**
     * Compares this {@code LinkProperties}'s CaptivePortalData against the target.
     *
     * @param target LinkProperties to compare.
     * @return {@code true} if both are identical, {@code false} otherwise.
     * @hide
     */
    public boolean isIdenticalCaptivePortalData(LinkProperties target) {
        return Objects.equals(mCaptivePortalData, target.mCaptivePortalData);
    }

    /**
     * Set whether the network interface supports WakeOnLAN
     *
@@ -1498,6 +1550,73 @@ public final class LinkProperties implements Parcelable {
        return mWakeOnLanSupported;
    }

    /**
     * Set the URL of the captive portal API endpoint to get more information about the network.
     * @hide
     */
    @SystemApi
    @TestApi
    public void setCaptivePortalApiUrl(@Nullable Uri url) {
        mCaptivePortalApiUrl = url;
    }

    /**
     * Get the URL of the captive portal API endpoint to get more information about the network.
     *
     * <p>This is null unless the application has
     * {@link android.Manifest.permission.NETWORK_SETTINGS} or
     * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided
     * the URL.
     * @hide
     */
    @SystemApi
    @TestApi
    @Nullable
    public Uri getCaptivePortalApiUrl() {
        return mCaptivePortalApiUrl;
    }

    /**
     * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis).
     * @hide
     */
    @SystemApi
    @TestApi
    public void setCaptivePortalData(@Nullable CaptivePortalData data) {
        mCaptivePortalData = data;
    }

    /**
     * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis).
     *
     * <p>This is null unless the application has
     * {@link android.Manifest.permission.NETWORK_SETTINGS} or
     * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions.
     * @hide
     */
    @SystemApi
    @TestApi
    @Nullable
    public CaptivePortalData getCaptivePortalData() {
        return mCaptivePortalData;
    }

    /**
     * Create a copy of this {@link LinkProperties} that will preserve fields that were set
     * based on the permissions of the process that received this {@link LinkProperties}.
     *
     * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
     * they should not be shared outside of the process that receives them without appropriate
     * checks.
     * @hide
     */
    @SystemApi
    @TestApi
    @NonNull
    public LinkProperties makeSensitiveFieldsParcelingCopy() {
        return new LinkProperties(this, true /* parcelSensitiveFields */);
    }

    /**
     * Compares this {@code LinkProperties} instance against the target
     * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
@@ -1537,7 +1656,9 @@ public final class LinkProperties implements Parcelable {
                && isIdenticalMtu(target)
                && isIdenticalTcpBufferSizes(target)
                && isIdenticalNat64Prefix(target)
                && isIdenticalWakeOnLan(target);
                && isIdenticalWakeOnLan(target)
                && isIdenticalCaptivePortalApiUrl(target)
                && isIdenticalCaptivePortalData(target);
    }

    /**
@@ -1655,7 +1776,8 @@ public final class LinkProperties implements Parcelable {
                + mPcscfs.size() * 67
                + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
                + Objects.hash(mNat64Prefix)
                + (mWakeOnLanSupported ? 71 : 0);
                + (mWakeOnLanSupported ? 71 : 0)
                + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData);
    }

    /**
@@ -1694,6 +1816,8 @@ public final class LinkProperties implements Parcelable {
        dest.writeList(stackedLinks);

        dest.writeBoolean(mWakeOnLanSupported);
        dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0);
        dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0);
    }

    private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
@@ -1785,6 +1909,9 @@ public final class LinkProperties implements Parcelable {
                    netProp.addStackedLink(stackedLink);
                }
                netProp.setWakeOnLanSupported(in.readBoolean());

                netProp.setCaptivePortalApiUrl(in.readParcelable(null));
                netProp.setCaptivePortalData(in.readParcelable(null));
                return netProp;
            }

Loading