Loading core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -5965,6 +5965,7 @@ package android.net { method public long getExpiryTimeMillis(); method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method @Nullable public String getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public boolean isCaptive(); method public boolean isSessionExtendable(); Loading @@ -5982,6 +5983,7 @@ package android.net { 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 setVenueFriendlyName(@Nullable String); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); } Loading core/java/android/net/CaptivePortalData.java +32 −6 Original line number Diff line number Diff line Loading @@ -39,9 +39,11 @@ public final class CaptivePortalData implements Parcelable { private final long mByteLimit; private final long mExpiryTimeMillis; private final boolean mCaptive; private final String mVenueFriendlyName; private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive) { boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, String venueFriendlyName) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; Loading @@ -49,11 +51,12 @@ public final class CaptivePortalData implements Parcelable { mByteLimit = byteLimit; mExpiryTimeMillis = expiryTimeMillis; mCaptive = captive; mVenueFriendlyName = venueFriendlyName; } private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), p.readLong(), p.readLong(), p.readBoolean()); p.readLong(), p.readLong(), p.readBoolean(), p.readString()); } @Override Loading @@ -70,6 +73,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mByteLimit); dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); dest.writeString(mVenueFriendlyName); } /** Loading @@ -83,6 +87,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; private String mVenueFriendlyName; /** * Create an empty builder. Loading @@ -100,7 +105,8 @@ public final class CaptivePortalData implements Parcelable { .setSessionExtendable(data.mIsSessionExtendable) .setBytesRemaining(data.mByteLimit) .setExpiryTime(data.mExpiryTimeMillis) .setCaptive(data.mCaptive); .setCaptive(data.mCaptive) .setVenueFriendlyName(data.mVenueFriendlyName); } /** Loading Loading @@ -166,13 +172,23 @@ public final class CaptivePortalData implements Parcelable { return this; } /** * Set the venue friendly name. */ @NonNull public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } /** * Create a new {@link CaptivePortalData}. */ @NonNull public CaptivePortalData build() { return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive); mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, mVenueFriendlyName); } } Loading Loading @@ -232,6 +248,14 @@ public final class CaptivePortalData implements Parcelable { return mCaptive; } /** * Get the venue friendly name */ @Nullable public String getVenueFriendlyName() { return mVenueFriendlyName; } @NonNull public static final Creator<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() { @Override Loading @@ -248,7 +272,7 @@ public final class CaptivePortalData implements Parcelable { @Override public int hashCode() { return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive); mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName); } @Override Loading @@ -261,7 +285,8 @@ public final class CaptivePortalData implements Parcelable { && mIsSessionExtendable == other.mIsSessionExtendable && mByteLimit == other.mByteLimit && mExpiryTimeMillis == other.mExpiryTimeMillis && mCaptive == other.mCaptive; && mCaptive == other.mCaptive && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName); } @Override Loading @@ -274,6 +299,7 @@ public final class CaptivePortalData implements Parcelable { + ", byteLimit: " + mByteLimit + ", expiryTime: " + mExpiryTimeMillis + ", captive: " + mCaptive + ", venueFriendlyName: " + mVenueFriendlyName + "}"; } } services/core/java/com/android/server/ConnectivityService.java +60 −6 Original line number Diff line number Diff line Loading @@ -2973,7 +2973,7 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_CAPPORT_DATA_CHANGED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; handleCaptivePortalDataUpdate(nai, (CaptivePortalData) msg.obj); handleCapportApiDataUpdate(nai, (CaptivePortalData) msg.obj); break; } } Loading Loading @@ -3311,9 +3311,9 @@ public class ConnectivityService extends IConnectivityManager.Stub handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); } private void handleCaptivePortalDataUpdate(@NonNull final NetworkAgentInfo nai, private void handleCapportApiDataUpdate(@NonNull final NetworkAgentInfo nai, @Nullable final CaptivePortalData data) { nai.captivePortalData = data; nai.capportApiData = data; // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); } Loading Loading @@ -6123,6 +6123,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { lp.ensureDirectlyConnectedRoutes(); nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix()); nai.networkAgentPortalData = lp.getCaptivePortalData(); } private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, Loading Loading @@ -6166,9 +6167,11 @@ public class ConnectivityService extends IConnectivityManager.Stub updateWakeOnLan(newLp); // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo, // it is not contained in LinkProperties sent from NetworkAgents so needs to be merged here. newLp.setCaptivePortalData(networkAgent.captivePortalData); // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo. // It is not always contained in the LinkProperties sent from NetworkAgents, and if it // does, it needs to be merged here. newLp.setCaptivePortalData(mergeCaptivePortalData(networkAgent.networkAgentPortalData, networkAgent.capportApiData)); // TODO - move this check to cover the whole function if (!Objects.equals(newLp, oldLp)) { Loading @@ -6188,6 +6191,57 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent); } /** * @param naData captive portal data from NetworkAgent * @param apiData captive portal data from capport API */ @Nullable private CaptivePortalData mergeCaptivePortalData(CaptivePortalData naData, CaptivePortalData apiData) { if (naData == null || apiData == null) { return naData == null ? apiData : naData; } final CaptivePortalData.Builder captivePortalBuilder = new CaptivePortalData.Builder(naData); if (apiData.isCaptive()) { captivePortalBuilder.setCaptive(true); } if (apiData.isSessionExtendable()) { captivePortalBuilder.setSessionExtendable(true); } if (apiData.getExpiryTimeMillis() >= 0 || apiData.getByteLimit() >= 0) { // Expiry time, bytes remaining, refresh time all need to come from the same source, // otherwise data would be inconsistent. Prefer the capport API info if present, // as it can generally be refreshed more often. captivePortalBuilder.setExpiryTime(apiData.getExpiryTimeMillis()); captivePortalBuilder.setBytesRemaining(apiData.getByteLimit()); captivePortalBuilder.setRefreshTime(apiData.getRefreshTimeMillis()); } else if (naData.getExpiryTimeMillis() < 0 && naData.getByteLimit() < 0) { // No source has time / bytes remaining information: surface the newest refresh time // for other fields captivePortalBuilder.setRefreshTime( Math.max(naData.getRefreshTimeMillis(), apiData.getRefreshTimeMillis())); } // Prioritize the user portal URL from the network agent. if (apiData.getUserPortalUrl() != null && (naData.getUserPortalUrl() == null || TextUtils.isEmpty(naData.getUserPortalUrl().toSafeString()))) { captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl()); } // Prioritize the venue information URL from the network agent. if (apiData.getVenueInfoUrl() != null && (naData.getVenueInfoUrl() == null || TextUtils.isEmpty(naData.getVenueInfoUrl().toSafeString()))) { captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl()); // Note that venue friendly name can only come from the network agent because it is not // in use in RFC8908. However, if using the Capport venue URL, make sure that the // friendly name is not set from the network agent. captivePortalBuilder.setVenueFriendlyName(null); } return captivePortalBuilder.build(); } private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) { // Marks are only available on WiFi interfaces. Checking for // marks on unsupported interfaces is harmless. Loading services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +7 −2 Original line number Diff line number Diff line Loading @@ -189,13 +189,18 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // Set to true when partial connectivity was detected. public boolean partialConnectivity; // Captive portal info of the network, if any. // Captive portal info of the network from RFC8908, if any. // Obtained by ConnectivityService and merged into NetworkAgent-provided information. public CaptivePortalData captivePortalData; public CaptivePortalData capportApiData; // The UID of the remote entity that created this Network. public final int creatorUid; // Network agent portal info of the network, if any. This information is provided from // non-RFC8908 sources, such as Wi-Fi Passpoint, which can provide information such as Venue // URL, Terms & Conditions URL, and network friendly name. public CaptivePortalData networkAgentPortalData; // Networks are lingered when they become unneeded as a result of their NetworkRequests being // satisfied by a higher-scoring network. so as to allow communication to wrap up before the // network is taken down. This usually only happens to the default network. Lingering ends with Loading tests/net/common/java/android/net/CaptivePortalDataTest.kt +9 −1 Original line number Diff line number Diff line Loading @@ -41,13 +41,14 @@ class CaptivePortalDataTest { .setBytesRemaining(456L) .setExpiryTime(789L) .setCaptive(true) .setVenueFriendlyName("venue friendly name") .build() private fun makeBuilder() = CaptivePortalData.Builder(data) @Test fun testParcelUnparcel() { assertParcelSane(data, fieldCount = 7) assertParcelSane(data, fieldCount = 8) assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build()) assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build()) Loading @@ -66,6 +67,8 @@ class CaptivePortalDataTest { assertNotEqualsAfterChange { it.setBytesRemaining(789L) } assertNotEqualsAfterChange { it.setExpiryTime(12L) } assertNotEqualsAfterChange { it.setCaptive(false) } assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } } @Test Loading Loading @@ -108,6 +111,11 @@ class CaptivePortalDataTest { assertFalse(makeBuilder().setCaptive(false).build().isCaptive) } @Test fun testVenueFriendlyName() { assertEquals("venue friendly name", data.venueFriendlyName) } private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) = CaptivePortalData.Builder(this).apply { mutator(this) }.build() Loading Loading
core/api/system-current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -5965,6 +5965,7 @@ package android.net { method public long getExpiryTimeMillis(); method public long getRefreshTimeMillis(); method @Nullable public android.net.Uri getUserPortalUrl(); method @Nullable public String getVenueFriendlyName(); method @Nullable public android.net.Uri getVenueInfoUrl(); method public boolean isCaptive(); method public boolean isSessionExtendable(); Loading @@ -5982,6 +5983,7 @@ package android.net { 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 setVenueFriendlyName(@Nullable String); method @NonNull public android.net.CaptivePortalData.Builder setVenueInfoUrl(@Nullable android.net.Uri); } Loading
core/java/android/net/CaptivePortalData.java +32 −6 Original line number Diff line number Diff line Loading @@ -39,9 +39,11 @@ public final class CaptivePortalData implements Parcelable { private final long mByteLimit; private final long mExpiryTimeMillis; private final boolean mCaptive; private final String mVenueFriendlyName; private CaptivePortalData(long refreshTimeMillis, Uri userPortalUrl, Uri venueInfoUrl, boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive) { boolean isSessionExtendable, long byteLimit, long expiryTimeMillis, boolean captive, String venueFriendlyName) { mRefreshTimeMillis = refreshTimeMillis; mUserPortalUrl = userPortalUrl; mVenueInfoUrl = venueInfoUrl; Loading @@ -49,11 +51,12 @@ public final class CaptivePortalData implements Parcelable { mByteLimit = byteLimit; mExpiryTimeMillis = expiryTimeMillis; mCaptive = captive; mVenueFriendlyName = venueFriendlyName; } private CaptivePortalData(Parcel p) { this(p.readLong(), p.readParcelable(null), p.readParcelable(null), p.readBoolean(), p.readLong(), p.readLong(), p.readBoolean()); p.readLong(), p.readLong(), p.readBoolean(), p.readString()); } @Override Loading @@ -70,6 +73,7 @@ public final class CaptivePortalData implements Parcelable { dest.writeLong(mByteLimit); dest.writeLong(mExpiryTimeMillis); dest.writeBoolean(mCaptive); dest.writeString(mVenueFriendlyName); } /** Loading @@ -83,6 +87,7 @@ public final class CaptivePortalData implements Parcelable { private long mBytesRemaining = -1; private long mExpiryTime = -1; private boolean mCaptive; private String mVenueFriendlyName; /** * Create an empty builder. Loading @@ -100,7 +105,8 @@ public final class CaptivePortalData implements Parcelable { .setSessionExtendable(data.mIsSessionExtendable) .setBytesRemaining(data.mByteLimit) .setExpiryTime(data.mExpiryTimeMillis) .setCaptive(data.mCaptive); .setCaptive(data.mCaptive) .setVenueFriendlyName(data.mVenueFriendlyName); } /** Loading Loading @@ -166,13 +172,23 @@ public final class CaptivePortalData implements Parcelable { return this; } /** * Set the venue friendly name. */ @NonNull public Builder setVenueFriendlyName(@Nullable String venueFriendlyName) { mVenueFriendlyName = venueFriendlyName; return this; } /** * Create a new {@link CaptivePortalData}. */ @NonNull public CaptivePortalData build() { return new CaptivePortalData(mRefreshTime, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive); mIsSessionExtendable, mBytesRemaining, mExpiryTime, mCaptive, mVenueFriendlyName); } } Loading Loading @@ -232,6 +248,14 @@ public final class CaptivePortalData implements Parcelable { return mCaptive; } /** * Get the venue friendly name */ @Nullable public String getVenueFriendlyName() { return mVenueFriendlyName; } @NonNull public static final Creator<CaptivePortalData> CREATOR = new Creator<CaptivePortalData>() { @Override Loading @@ -248,7 +272,7 @@ public final class CaptivePortalData implements Parcelable { @Override public int hashCode() { return Objects.hash(mRefreshTimeMillis, mUserPortalUrl, mVenueInfoUrl, mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive); mIsSessionExtendable, mByteLimit, mExpiryTimeMillis, mCaptive, mVenueFriendlyName); } @Override Loading @@ -261,7 +285,8 @@ public final class CaptivePortalData implements Parcelable { && mIsSessionExtendable == other.mIsSessionExtendable && mByteLimit == other.mByteLimit && mExpiryTimeMillis == other.mExpiryTimeMillis && mCaptive == other.mCaptive; && mCaptive == other.mCaptive && Objects.equals(mVenueFriendlyName, other.mVenueFriendlyName); } @Override Loading @@ -274,6 +299,7 @@ public final class CaptivePortalData implements Parcelable { + ", byteLimit: " + mByteLimit + ", expiryTime: " + mExpiryTimeMillis + ", captive: " + mCaptive + ", venueFriendlyName: " + mVenueFriendlyName + "}"; } }
services/core/java/com/android/server/ConnectivityService.java +60 −6 Original line number Diff line number Diff line Loading @@ -2973,7 +2973,7 @@ public class ConnectivityService extends IConnectivityManager.Stub case EVENT_CAPPORT_DATA_CHANGED: { final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2); if (nai == null) break; handleCaptivePortalDataUpdate(nai, (CaptivePortalData) msg.obj); handleCapportApiDataUpdate(nai, (CaptivePortalData) msg.obj); break; } } Loading Loading @@ -3311,9 +3311,9 @@ public class ConnectivityService extends IConnectivityManager.Stub handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); } private void handleCaptivePortalDataUpdate(@NonNull final NetworkAgentInfo nai, private void handleCapportApiDataUpdate(@NonNull final NetworkAgentInfo nai, @Nullable final CaptivePortalData data) { nai.captivePortalData = data; nai.capportApiData = data; // CaptivePortalData will be merged into LinkProperties from NetworkAgentInfo handleUpdateLinkProperties(nai, new LinkProperties(nai.linkProperties)); } Loading Loading @@ -6123,6 +6123,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private void processLinkPropertiesFromAgent(NetworkAgentInfo nai, LinkProperties lp) { lp.ensureDirectlyConnectedRoutes(); nai.clatd.setNat64PrefixFromRa(lp.getNat64Prefix()); nai.networkAgentPortalData = lp.getCaptivePortalData(); } private void updateLinkProperties(NetworkAgentInfo networkAgent, LinkProperties newLp, Loading Loading @@ -6166,9 +6167,11 @@ public class ConnectivityService extends IConnectivityManager.Stub updateWakeOnLan(newLp); // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo, // it is not contained in LinkProperties sent from NetworkAgents so needs to be merged here. newLp.setCaptivePortalData(networkAgent.captivePortalData); // Captive portal data is obtained from NetworkMonitor and stored in NetworkAgentInfo. // It is not always contained in the LinkProperties sent from NetworkAgents, and if it // does, it needs to be merged here. newLp.setCaptivePortalData(mergeCaptivePortalData(networkAgent.networkAgentPortalData, networkAgent.capportApiData)); // TODO - move this check to cover the whole function if (!Objects.equals(newLp, oldLp)) { Loading @@ -6188,6 +6191,57 @@ public class ConnectivityService extends IConnectivityManager.Stub mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent); } /** * @param naData captive portal data from NetworkAgent * @param apiData captive portal data from capport API */ @Nullable private CaptivePortalData mergeCaptivePortalData(CaptivePortalData naData, CaptivePortalData apiData) { if (naData == null || apiData == null) { return naData == null ? apiData : naData; } final CaptivePortalData.Builder captivePortalBuilder = new CaptivePortalData.Builder(naData); if (apiData.isCaptive()) { captivePortalBuilder.setCaptive(true); } if (apiData.isSessionExtendable()) { captivePortalBuilder.setSessionExtendable(true); } if (apiData.getExpiryTimeMillis() >= 0 || apiData.getByteLimit() >= 0) { // Expiry time, bytes remaining, refresh time all need to come from the same source, // otherwise data would be inconsistent. Prefer the capport API info if present, // as it can generally be refreshed more often. captivePortalBuilder.setExpiryTime(apiData.getExpiryTimeMillis()); captivePortalBuilder.setBytesRemaining(apiData.getByteLimit()); captivePortalBuilder.setRefreshTime(apiData.getRefreshTimeMillis()); } else if (naData.getExpiryTimeMillis() < 0 && naData.getByteLimit() < 0) { // No source has time / bytes remaining information: surface the newest refresh time // for other fields captivePortalBuilder.setRefreshTime( Math.max(naData.getRefreshTimeMillis(), apiData.getRefreshTimeMillis())); } // Prioritize the user portal URL from the network agent. if (apiData.getUserPortalUrl() != null && (naData.getUserPortalUrl() == null || TextUtils.isEmpty(naData.getUserPortalUrl().toSafeString()))) { captivePortalBuilder.setUserPortalUrl(apiData.getUserPortalUrl()); } // Prioritize the venue information URL from the network agent. if (apiData.getVenueInfoUrl() != null && (naData.getVenueInfoUrl() == null || TextUtils.isEmpty(naData.getVenueInfoUrl().toSafeString()))) { captivePortalBuilder.setVenueInfoUrl(apiData.getVenueInfoUrl()); // Note that venue friendly name can only come from the network agent because it is not // in use in RFC8908. However, if using the Capport venue URL, make sure that the // friendly name is not set from the network agent. captivePortalBuilder.setVenueFriendlyName(null); } return captivePortalBuilder.build(); } private void wakeupModifyInterface(String iface, NetworkCapabilities caps, boolean add) { // Marks are only available on WiFi interfaces. Checking for // marks on unsupported interfaces is harmless. Loading
services/core/java/com/android/server/connectivity/NetworkAgentInfo.java +7 −2 Original line number Diff line number Diff line Loading @@ -189,13 +189,18 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> { // Set to true when partial connectivity was detected. public boolean partialConnectivity; // Captive portal info of the network, if any. // Captive portal info of the network from RFC8908, if any. // Obtained by ConnectivityService and merged into NetworkAgent-provided information. public CaptivePortalData captivePortalData; public CaptivePortalData capportApiData; // The UID of the remote entity that created this Network. public final int creatorUid; // Network agent portal info of the network, if any. This information is provided from // non-RFC8908 sources, such as Wi-Fi Passpoint, which can provide information such as Venue // URL, Terms & Conditions URL, and network friendly name. public CaptivePortalData networkAgentPortalData; // Networks are lingered when they become unneeded as a result of their NetworkRequests being // satisfied by a higher-scoring network. so as to allow communication to wrap up before the // network is taken down. This usually only happens to the default network. Lingering ends with Loading
tests/net/common/java/android/net/CaptivePortalDataTest.kt +9 −1 Original line number Diff line number Diff line Loading @@ -41,13 +41,14 @@ class CaptivePortalDataTest { .setBytesRemaining(456L) .setExpiryTime(789L) .setCaptive(true) .setVenueFriendlyName("venue friendly name") .build() private fun makeBuilder() = CaptivePortalData.Builder(data) @Test fun testParcelUnparcel() { assertParcelSane(data, fieldCount = 7) assertParcelSane(data, fieldCount = 8) assertParcelingIsLossless(makeBuilder().setUserPortalUrl(null).build()) assertParcelingIsLossless(makeBuilder().setVenueInfoUrl(null).build()) Loading @@ -66,6 +67,8 @@ class CaptivePortalDataTest { assertNotEqualsAfterChange { it.setBytesRemaining(789L) } assertNotEqualsAfterChange { it.setExpiryTime(12L) } assertNotEqualsAfterChange { it.setCaptive(false) } assertNotEqualsAfterChange { it.setVenueFriendlyName("another friendly name") } assertNotEqualsAfterChange { it.setVenueFriendlyName(null) } } @Test Loading Loading @@ -108,6 +111,11 @@ class CaptivePortalDataTest { assertFalse(makeBuilder().setCaptive(false).build().isCaptive) } @Test fun testVenueFriendlyName() { assertEquals("venue friendly name", data.venueFriendlyName) } private fun CaptivePortalData.mutate(mutator: (CaptivePortalData.Builder) -> Unit) = CaptivePortalData.Builder(this).apply { mutator(this) }.build() Loading