Loading common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java +75 −16 Original line number Diff line number Diff line Loading @@ -16,14 +16,20 @@ package android.net.captiveportal; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTP; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTPS; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Result of calling isCaptivePortal(). * @hide */ public final class CaptivePortalProbeResult { public class CaptivePortalProbeResult { public static final int SUCCESS_CODE = 204; public static final int FAILED_CODE = 599; public static final int PORTAL_CODE = 302; Loading @@ -42,18 +48,17 @@ public final class CaptivePortalProbeResult { // be FAILED if one of the probes returns this status. // This logic is only used if the config_force_dns_probe_private_ip_no_internet flag is set. public static final int DNS_PRIVATE_IP_RESPONSE_CODE = -2; @NonNull public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); @NonNull public static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); public static final CaptivePortalProbeResult PARTIAL = new CaptivePortalProbeResult(PARTIAL_CODE); // The private IP logic only applies to the HTTP probe. public static final CaptivePortalProbeResult PRIVATE_IP = new CaptivePortalProbeResult(DNS_PRIVATE_IP_RESPONSE_CODE); new CaptivePortalProbeResult(DNS_PRIVATE_IP_RESPONSE_CODE, 1 << PROBE_HTTP); // Partial connectivity should be concluded from both HTTP and HTTPS probes. @NonNull public static final CaptivePortalProbeResult PARTIAL = new CaptivePortalProbeResult( PARTIAL_CODE, 1 << PROBE_HTTP | 1 << PROBE_HTTPS); // Probe type that is used for unspecified probe result. public static final int PROBE_UNKNOWN = 0; private final int mHttpResponseCode; // HTTP response code returned from Internet probe. final int mHttpResponseCode; // HTTP response code returned from Internet probe. @Nullable public final String redirectUrl; // Redirect destination returned from Internet probe. @Nullable Loading @@ -62,21 +67,39 @@ public final class CaptivePortalProbeResult { @Nullable public final CaptivePortalProbeSpec probeSpec; public CaptivePortalProbeResult(int httpResponseCode) { this(httpResponseCode, null, null); // Indicate what kind of probe this is. This is a bitmask constructed by // bitwise-or-ing(i.e. {@code |}) the {@code ValidationProbeEvent.PROBE_HTTP} or // {@code ValidationProbeEvent.PROBE_HTTPS} values. Set it as {@code PROBE_UNKNOWN} if the probe // type is unspecified. @ProbeType public final int probeType; @IntDef(value = { PROBE_UNKNOWN, 1 << PROBE_HTTP, 1 << PROBE_HTTPS, }) @Retention(RetentionPolicy.SOURCE) public @interface ProbeType { } public CaptivePortalProbeResult(int httpResponseCode, @ProbeType int probeType) { this(httpResponseCode, null, null, null, probeType); } public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl) { this(httpResponseCode, redirectUrl, detectUrl, null); @Nullable String detectUrl, @ProbeType int probeType) { this(httpResponseCode, redirectUrl, detectUrl, null, probeType); } public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec) { @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec, @ProbeType int probeType) { mHttpResponseCode = httpResponseCode; this.redirectUrl = redirectUrl; this.detectUrl = detectUrl; this.probeSpec = probeSpec; this.probeType = probeType; } public boolean isSuccessful() { Loading @@ -98,4 +121,40 @@ public final class CaptivePortalProbeResult { public boolean isDnsPrivateIpResponse() { return mHttpResponseCode == DNS_PRIVATE_IP_RESPONSE_CODE; } /** * Make a failed {@code this} for either HTTPS or HTTP determined by {@param isHttps}. * @param probeType probe type of the result. * @return a failed {@link CaptivePortalProbeResult} */ public static CaptivePortalProbeResult failed(@ProbeType int probeType) { return new CaptivePortalProbeResult(FAILED_CODE, probeType); } /** * Make a success {@code this} for either HTTPS or HTTP determined by {@param isHttps}. * @param probeType probe type of the result. * @return a success {@link CaptivePortalProbeResult} */ public static CaptivePortalProbeResult success(@ProbeType int probeType) { return new CaptivePortalProbeResult(SUCCESS_CODE, probeType); } /** * As {@code this} is the result of calling isCaptivePortal(), the result may be determined from * one or more probes depending on the configuration of detection probes. Return if HTTPS probe * is one of the probes that concludes it. */ public boolean isConcludedFromHttps() { return (probeType & (1 << PROBE_HTTPS)) != 0; } /** * As {@code this} is the result of calling isCaptivePortal(), the result may be determined from * one or more probes depending on the configuration of detection probes. Return if HTTP probe * is one of the probes that concludes it. */ public boolean isConcludedFromHttp() { return (probeType & (1 << PROBE_HTTP)) != 0; } } common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeSpec.java +15 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.net.captiveportal; import static android.net.captiveportal.CaptivePortalProbeResult.PORTAL_CODE; import static android.net.captiveportal.CaptivePortalProbeResult.SUCCESS_CODE; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTP; import android.text.TextUtils; import android.util.Log; Loading @@ -40,6 +41,7 @@ public abstract class CaptivePortalProbeSpec { private static final String TAG = CaptivePortalProbeSpec.class.getSimpleName(); private static final String REGEX_SEPARATOR = "@@/@@"; private static final String SPEC_SEPARATOR = "@@,@@"; private static final String PROTOCOL_HTTP = "http"; private final String mEncodedSpec; private final URL mUrl; Loading Loading @@ -138,7 +140,7 @@ public abstract class CaptivePortalProbeSpec { } /** * Get the probe result from HTTP status and location header. * Get the HTTP probe result from HTTP status and location header. */ @NonNull public abstract CaptivePortalProbeResult getResult(int status, @Nullable String locationHeader); Loading @@ -157,6 +159,7 @@ public abstract class CaptivePortalProbeSpec { * Implementation of {@link CaptivePortalProbeSpec} that is based on configurable regular * expressions for the HTTP status code and location header (if any). Matches indicate that * the page is not a portal. * @throws IllegalArgumentException The protocol of the url is not http. * This probe cannot fail: it always returns SUCCESS_CODE or PORTAL_CODE */ private static class RegexMatchProbeSpec extends CaptivePortalProbeSpec { Loading @@ -165,9 +168,17 @@ public abstract class CaptivePortalProbeSpec { @Nullable final Pattern mLocationHeaderRegex; RegexMatchProbeSpec( String spec, URL url, Pattern statusRegex, Pattern locationHeaderRegex) { RegexMatchProbeSpec(@NonNull String spec, @NonNull URL url, @Nullable Pattern statusRegex, @Nullable Pattern locationHeaderRegex) throws ParseException { super(spec, url); final String protocol = url.getProtocol(); if (!PROTOCOL_HTTP.equals(protocol)) { // The probe type taken in the result is hard-coded as PROBE_HTTP currently, so the // probe type taken into the result of {@code getResult} have to change if other // kind of probes are used. throw new IllegalArgumentException("Protocol for probe spec should be http but was" + protocol); } mStatusRegex = statusRegex; mLocationHeaderRegex = locationHeaderRegex; } Loading @@ -178,7 +189,7 @@ public abstract class CaptivePortalProbeSpec { final boolean locationMatch = safeMatch(locationHeader, mLocationHeaderRegex); final int returnCode = statusMatch && locationMatch ? SUCCESS_CODE : PORTAL_CODE; return new CaptivePortalProbeResult( returnCode, locationHeader, getUrl().toString(), this); returnCode, locationHeader, getUrl().toString(), this, PROBE_HTTP); } } Loading common/networkstackclient/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,10 @@ aidl_interface { ], backend: { java: { apex_available: ["com.android.wifi",], apex_available: [ "//apex_available:platform", "com.android.wifi", ], }, ndk: { enabled: false, Loading src/android/net/captiveportal/CapportApiProbeResult.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.captiveportal; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.networkstack.apishim.CaptivePortalDataShim; /** * Captive portal probe detection result including capport API detection result. * @hide */ public class CapportApiProbeResult extends CaptivePortalProbeResult { @NonNull private final CaptivePortalDataShim mCapportData; public CapportApiProbeResult(@NonNull CaptivePortalProbeResult result, @NonNull CaptivePortalDataShim capportData) { this(result.mHttpResponseCode, result.redirectUrl, result.detectUrl, capportData, result.probeType); } public CapportApiProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl, @Nullable CaptivePortalDataShim capportData, int probeType) { super(httpResponseCode, redirectUrl, detectUrl, probeType); mCapportData = capportData; } public CaptivePortalDataShim getCaptivePortalData() { return mCapportData; } } src/android/net/dhcp/DhcpClient.java +1 −0 Original line number Diff line number Diff line Loading @@ -1717,6 +1717,7 @@ public class DhcpClient extends StateMachine { Log.d(TAG, "Renewed lease not for our current IP address!"); notifyFailure(); transitionTo(mDhcpInitState); return; } setDhcpLeaseExpiry(packet); // Updating our notion of DhcpResults here only causes the Loading Loading
common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeResult.java +75 −16 Original line number Diff line number Diff line Loading @@ -16,14 +16,20 @@ package android.net.captiveportal; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTP; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTPS; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Result of calling isCaptivePortal(). * @hide */ public final class CaptivePortalProbeResult { public class CaptivePortalProbeResult { public static final int SUCCESS_CODE = 204; public static final int FAILED_CODE = 599; public static final int PORTAL_CODE = 302; Loading @@ -42,18 +48,17 @@ public final class CaptivePortalProbeResult { // be FAILED if one of the probes returns this status. // This logic is only used if the config_force_dns_probe_private_ip_no_internet flag is set. public static final int DNS_PRIVATE_IP_RESPONSE_CODE = -2; @NonNull public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE); @NonNull public static final CaptivePortalProbeResult SUCCESS = new CaptivePortalProbeResult(SUCCESS_CODE); public static final CaptivePortalProbeResult PARTIAL = new CaptivePortalProbeResult(PARTIAL_CODE); // The private IP logic only applies to the HTTP probe. public static final CaptivePortalProbeResult PRIVATE_IP = new CaptivePortalProbeResult(DNS_PRIVATE_IP_RESPONSE_CODE); new CaptivePortalProbeResult(DNS_PRIVATE_IP_RESPONSE_CODE, 1 << PROBE_HTTP); // Partial connectivity should be concluded from both HTTP and HTTPS probes. @NonNull public static final CaptivePortalProbeResult PARTIAL = new CaptivePortalProbeResult( PARTIAL_CODE, 1 << PROBE_HTTP | 1 << PROBE_HTTPS); // Probe type that is used for unspecified probe result. public static final int PROBE_UNKNOWN = 0; private final int mHttpResponseCode; // HTTP response code returned from Internet probe. final int mHttpResponseCode; // HTTP response code returned from Internet probe. @Nullable public final String redirectUrl; // Redirect destination returned from Internet probe. @Nullable Loading @@ -62,21 +67,39 @@ public final class CaptivePortalProbeResult { @Nullable public final CaptivePortalProbeSpec probeSpec; public CaptivePortalProbeResult(int httpResponseCode) { this(httpResponseCode, null, null); // Indicate what kind of probe this is. This is a bitmask constructed by // bitwise-or-ing(i.e. {@code |}) the {@code ValidationProbeEvent.PROBE_HTTP} or // {@code ValidationProbeEvent.PROBE_HTTPS} values. Set it as {@code PROBE_UNKNOWN} if the probe // type is unspecified. @ProbeType public final int probeType; @IntDef(value = { PROBE_UNKNOWN, 1 << PROBE_HTTP, 1 << PROBE_HTTPS, }) @Retention(RetentionPolicy.SOURCE) public @interface ProbeType { } public CaptivePortalProbeResult(int httpResponseCode, @ProbeType int probeType) { this(httpResponseCode, null, null, null, probeType); } public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl) { this(httpResponseCode, redirectUrl, detectUrl, null); @Nullable String detectUrl, @ProbeType int probeType) { this(httpResponseCode, redirectUrl, detectUrl, null, probeType); } public CaptivePortalProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec) { @Nullable String detectUrl, @Nullable CaptivePortalProbeSpec probeSpec, @ProbeType int probeType) { mHttpResponseCode = httpResponseCode; this.redirectUrl = redirectUrl; this.detectUrl = detectUrl; this.probeSpec = probeSpec; this.probeType = probeType; } public boolean isSuccessful() { Loading @@ -98,4 +121,40 @@ public final class CaptivePortalProbeResult { public boolean isDnsPrivateIpResponse() { return mHttpResponseCode == DNS_PRIVATE_IP_RESPONSE_CODE; } /** * Make a failed {@code this} for either HTTPS or HTTP determined by {@param isHttps}. * @param probeType probe type of the result. * @return a failed {@link CaptivePortalProbeResult} */ public static CaptivePortalProbeResult failed(@ProbeType int probeType) { return new CaptivePortalProbeResult(FAILED_CODE, probeType); } /** * Make a success {@code this} for either HTTPS or HTTP determined by {@param isHttps}. * @param probeType probe type of the result. * @return a success {@link CaptivePortalProbeResult} */ public static CaptivePortalProbeResult success(@ProbeType int probeType) { return new CaptivePortalProbeResult(SUCCESS_CODE, probeType); } /** * As {@code this} is the result of calling isCaptivePortal(), the result may be determined from * one or more probes depending on the configuration of detection probes. Return if HTTPS probe * is one of the probes that concludes it. */ public boolean isConcludedFromHttps() { return (probeType & (1 << PROBE_HTTPS)) != 0; } /** * As {@code this} is the result of calling isCaptivePortal(), the result may be determined from * one or more probes depending on the configuration of detection probes. Return if HTTP probe * is one of the probes that concludes it. */ public boolean isConcludedFromHttp() { return (probeType & (1 << PROBE_HTTP)) != 0; } }
common/captiveportal/src/android/net/captiveportal/CaptivePortalProbeSpec.java +15 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package android.net.captiveportal; import static android.net.captiveportal.CaptivePortalProbeResult.PORTAL_CODE; import static android.net.captiveportal.CaptivePortalProbeResult.SUCCESS_CODE; import static android.net.metrics.ValidationProbeEvent.PROBE_HTTP; import android.text.TextUtils; import android.util.Log; Loading @@ -40,6 +41,7 @@ public abstract class CaptivePortalProbeSpec { private static final String TAG = CaptivePortalProbeSpec.class.getSimpleName(); private static final String REGEX_SEPARATOR = "@@/@@"; private static final String SPEC_SEPARATOR = "@@,@@"; private static final String PROTOCOL_HTTP = "http"; private final String mEncodedSpec; private final URL mUrl; Loading Loading @@ -138,7 +140,7 @@ public abstract class CaptivePortalProbeSpec { } /** * Get the probe result from HTTP status and location header. * Get the HTTP probe result from HTTP status and location header. */ @NonNull public abstract CaptivePortalProbeResult getResult(int status, @Nullable String locationHeader); Loading @@ -157,6 +159,7 @@ public abstract class CaptivePortalProbeSpec { * Implementation of {@link CaptivePortalProbeSpec} that is based on configurable regular * expressions for the HTTP status code and location header (if any). Matches indicate that * the page is not a portal. * @throws IllegalArgumentException The protocol of the url is not http. * This probe cannot fail: it always returns SUCCESS_CODE or PORTAL_CODE */ private static class RegexMatchProbeSpec extends CaptivePortalProbeSpec { Loading @@ -165,9 +168,17 @@ public abstract class CaptivePortalProbeSpec { @Nullable final Pattern mLocationHeaderRegex; RegexMatchProbeSpec( String spec, URL url, Pattern statusRegex, Pattern locationHeaderRegex) { RegexMatchProbeSpec(@NonNull String spec, @NonNull URL url, @Nullable Pattern statusRegex, @Nullable Pattern locationHeaderRegex) throws ParseException { super(spec, url); final String protocol = url.getProtocol(); if (!PROTOCOL_HTTP.equals(protocol)) { // The probe type taken in the result is hard-coded as PROBE_HTTP currently, so the // probe type taken into the result of {@code getResult} have to change if other // kind of probes are used. throw new IllegalArgumentException("Protocol for probe spec should be http but was" + protocol); } mStatusRegex = statusRegex; mLocationHeaderRegex = locationHeaderRegex; } Loading @@ -178,7 +189,7 @@ public abstract class CaptivePortalProbeSpec { final boolean locationMatch = safeMatch(locationHeader, mLocationHeaderRegex); final int returnCode = statusMatch && locationMatch ? SUCCESS_CODE : PORTAL_CODE; return new CaptivePortalProbeResult( returnCode, locationHeader, getUrl().toString(), this); returnCode, locationHeader, getUrl().toString(), this, PROBE_HTTP); } } Loading
common/networkstackclient/Android.bp +4 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,10 @@ aidl_interface { ], backend: { java: { apex_available: ["com.android.wifi",], apex_available: [ "//apex_available:platform", "com.android.wifi", ], }, ndk: { enabled: false, Loading
src/android/net/captiveportal/CapportApiProbeResult.java 0 → 100644 +47 −0 Original line number Diff line number Diff line /* * Copyright (C) 2020 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.captiveportal; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.networkstack.apishim.CaptivePortalDataShim; /** * Captive portal probe detection result including capport API detection result. * @hide */ public class CapportApiProbeResult extends CaptivePortalProbeResult { @NonNull private final CaptivePortalDataShim mCapportData; public CapportApiProbeResult(@NonNull CaptivePortalProbeResult result, @NonNull CaptivePortalDataShim capportData) { this(result.mHttpResponseCode, result.redirectUrl, result.detectUrl, capportData, result.probeType); } public CapportApiProbeResult(int httpResponseCode, @Nullable String redirectUrl, @Nullable String detectUrl, @Nullable CaptivePortalDataShim capportData, int probeType) { super(httpResponseCode, redirectUrl, detectUrl, probeType); mCapportData = capportData; } public CaptivePortalDataShim getCaptivePortalData() { return mCapportData; } }
src/android/net/dhcp/DhcpClient.java +1 −0 Original line number Diff line number Diff line Loading @@ -1717,6 +1717,7 @@ public class DhcpClient extends StateMachine { Log.d(TAG, "Renewed lease not for our current IP address!"); notifyFailure(); transitionTo(mDhcpInitState); return; } setDhcpLeaseExpiry(packet); // Updating our notion of DhcpResults here only causes the Loading