Merge "Fix nascent timer never get removed" into sc-dev
diff --git a/framework/api/current.txt b/framework/api/current.txt
index 9c77c85..13ecb12 100644
--- a/framework/api/current.txt
+++ b/framework/api/current.txt
@@ -68,7 +68,6 @@
method public boolean bindProcessToNetwork(@Nullable android.net.Network);
method @NonNull public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull android.net.IpSecManager.UdpEncapsulationSocket, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network getActiveNetwork();
- method @Nullable @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public android.net.Network getActiveNetworkForUid(int);
method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo getActiveNetworkInfo();
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.NetworkInfo[] getAllNetworkInfo();
method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public android.net.Network[] getAllNetworks();
@@ -412,6 +411,8 @@
}
public class ParseException extends java.lang.RuntimeException {
+ ctor public ParseException(@NonNull String);
+ ctor public ParseException(@NonNull String, @NonNull Throwable);
field public String response;
}
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 2065559..4719772 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -26,6 +26,7 @@
method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void startCaptivePortalApp(@NonNull android.net.Network);
method public void systemReady();
+ field public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
field public static final String ACTION_PROMPT_LOST_VALIDATION = "android.net.action.PROMPT_LOST_VALIDATION";
field public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY = "android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
field public static final String ACTION_PROMPT_UNVALIDATED = "android.net.action.PROMPT_UNVALIDATED";
@@ -107,7 +108,6 @@
}
public final class NetworkCapabilities implements android.os.Parcelable {
- ctor public NetworkCapabilities(@Nullable android.net.NetworkCapabilities, long);
method @Nullable public java.util.Set<android.util.Range<java.lang.Integer>> getUids();
method public boolean hasUnwantedCapability(int);
field public static final long REDACT_ALL = -1L; // 0xffffffffffffffffL
@@ -133,21 +133,6 @@
method @NonNull public android.net.NetworkRequest.Builder setUids(@Nullable java.util.Set<android.util.Range<java.lang.Integer>>);
}
- public class ParseException extends java.lang.RuntimeException {
- ctor public ParseException(@NonNull String);
- ctor public ParseException(@NonNull String, @NonNull Throwable);
- }
-
- public final class TcpRepairWindow {
- ctor public TcpRepairWindow(int, int, int, int, int, int);
- field public final int maxWindow;
- field public final int rcvWnd;
- field public final int rcvWndScale;
- field public final int rcvWup;
- field public final int sndWl1;
- field public final int sndWnd;
- }
-
public final class TestNetworkInterface implements android.os.Parcelable {
ctor public TestNetworkInterface(@NonNull android.os.ParcelFileDescriptor, @NonNull String);
method public int describeContents();
@@ -158,10 +143,10 @@
}
public class TestNetworkManager {
- method @NonNull public android.net.TestNetworkInterface createTapInterface();
- method @NonNull public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
- method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
- method public void teardownTestNetwork(@NonNull android.net.Network);
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTapInterface();
+ method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public android.net.TestNetworkInterface createTunInterface(@NonNull java.util.Collection<android.net.LinkAddress>);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_TEST_NETWORKS) public void teardownTestNetwork(@NonNull android.net.Network);
field public static final String TEST_TAP_PREFIX = "testtap";
}
diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt
index 847bcbc..63e0fe9 100644
--- a/framework/api/system-current.txt
+++ b/framework/api/system-current.txt
@@ -260,15 +260,15 @@
public static final class NetworkAgentConfig.Builder {
ctor public NetworkAgentConfig.Builder();
method @NonNull public android.net.NetworkAgentConfig build();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableNat64Detection();
- method @NonNull public android.net.NetworkAgentConfig.Builder disableProvisioningNotification();
method @NonNull public android.net.NetworkAgentConfig.Builder setExplicitlySelected(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyExtraInfo(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacySubTypeName(@NonNull String);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyType(int);
method @NonNull public android.net.NetworkAgentConfig.Builder setLegacyTypeName(@NonNull String);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setNat64DetectionEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setPartialConnectivityAcceptable(boolean);
+ method @NonNull public android.net.NetworkAgentConfig.Builder setProvisioningNotificationEnabled(boolean);
method @NonNull public android.net.NetworkAgentConfig.Builder setUnvalidatedConnectivityAcceptable(boolean);
}
@@ -471,14 +471,14 @@
public final class TcpKeepalivePacketData extends android.net.KeepalivePacketData implements android.os.Parcelable {
ctor public TcpKeepalivePacketData(@NonNull java.net.InetAddress, int, @NonNull java.net.InetAddress, int, @NonNull byte[], int, int, int, int, int, int) throws android.net.InvalidPacketException;
method public int describeContents();
+ method public int getIpTos();
+ method public int getIpTtl();
+ method public int getTcpAck();
+ method public int getTcpSeq();
+ method public int getTcpWindow();
+ method public int getTcpWindowScale();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.TcpKeepalivePacketData> CREATOR;
- field public final int ipTos;
- field public final int ipTtl;
- field public final int tcpAck;
- field public final int tcpSeq;
- field public final int tcpWindow;
- field public final int tcpWindowScale;
}
}
diff --git a/framework/src/android/net/ConnectivityManager.java b/framework/src/android/net/ConnectivityManager.java
index 350b47f..c4a0d69 100644
--- a/framework/src/android/net/ConnectivityManager.java
+++ b/framework/src/android/net/ConnectivityManager.java
@@ -44,6 +44,7 @@
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.net.ConnectivityDiagnosticsManager.DataStallReport.DetectionMethod;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.SocketKeepalive.Callback;
import android.net.TetheringManager.StartTetheringCallback;
@@ -450,6 +451,15 @@
"android.net.action.PROMPT_PARTIAL_CONNECTIVITY";
/**
+ * Clear DNS Cache Action: This is broadcast when networks have changed and old
+ * DNS entries should be cleared.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
+ public static final String ACTION_CLEAR_DNS_CACHE = "android.net.action.CLEAR_DNS_CACHE";
+
+ /**
* Invalid tethering type.
* @see #startTethering(int, boolean, OnStartTetheringCallback)
* @hide
@@ -1193,7 +1203,8 @@
*
* @return a {@link Network} object for the current default network for the
* given UID or {@code null} if no default network is currently active
- * TODO: b/183465229 Cleanup getActiveNetworkForUid once b/165835257 is fixed
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
@Nullable
@@ -3143,18 +3154,27 @@
}
/**
- * Set a network-independent global http proxy. This is not normally what you want
- * for typical HTTP proxies - they are general network dependent. However if you're
- * doing something unusual like general internal filtering this may be useful. On
- * a private network where the proxy is not accessible, you may break HTTP using this.
+ * Set a network-independent global HTTP proxy.
*
- * @param p A {@link ProxyInfo} object defining the new global
- * HTTP proxy. A {@code null} value will clear the global HTTP proxy.
+ * This sets an HTTP proxy that applies to all networks and overrides any network-specific
+ * proxy. If set, HTTP libraries that are proxy-aware will use this global proxy when
+ * accessing any network, regardless of what the settings for that network are.
+ *
+ * Note that HTTP proxies are by nature typically network-dependent, and setting a global
+ * proxy is likely to break networking on multiple networks. This method is only meant
+ * for device policy clients looking to do general internal filtering or similar use cases.
+ *
+ * {@see #getGlobalProxy}
+ * {@see LinkProperties#getHttpProxy}
+ *
+ * @param p A {@link ProxyInfo} object defining the new global HTTP proxy. Calling this
+ * method with a {@code null} value will clear the global HTTP proxy.
* @hide
*/
+ // Used by Device Policy Manager to set the global proxy.
@SystemApi(client = MODULE_LIBRARIES)
@RequiresPermission(android.Manifest.permission.NETWORK_STACK)
- public void setGlobalProxy(@Nullable ProxyInfo p) {
+ public void setGlobalProxy(@Nullable final ProxyInfo p) {
try {
mService.setGlobalProxy(p);
} catch (RemoteException e) {
@@ -3466,6 +3486,8 @@
* not include location sensitive info.
* </p>
*/
+ // Note: Some existing fields which are location sensitive may still be included without
+ // this flag if the app targets SDK < S (to maintain backwards compatibility).
public static final int FLAG_INCLUDE_LOCATION_INFO = 1 << 0;
/** @hide */
@@ -5138,10 +5160,13 @@
*
* <p>This method should only be used for tests.
*
- * <p>The caller must be the owner of the specified Network.
+ * <p>The caller must be the owner of the specified Network. This simulates a data stall to
+ * have the system behave as if it had happened, but does not actually stall connectivity.
*
* @param detectionMethod The detection method used to identify the Data Stall.
- * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds.
+ * See ConnectivityDiagnosticsManager.DataStallReport.DETECTION_METHOD_*.
+ * @param timestampMillis The timestamp at which the stall 'occurred', in milliseconds, as per
+ * SystemClock.elapsedRealtime.
* @param network The Network for which a Data Stall is being simluated.
* @param extras The PersistableBundle of extras included in the Data Stall notification.
* @throws SecurityException if the caller is not the owner of the given network.
@@ -5150,7 +5175,7 @@
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_TEST_NETWORKS,
android.Manifest.permission.NETWORK_STACK})
- public void simulateDataStall(int detectionMethod, long timestampMillis,
+ public void simulateDataStall(@DetectionMethod int detectionMethod, long timestampMillis,
@NonNull Network network, @NonNull PersistableBundle extras) {
try {
mService.simulateDataStall(detectionMethod, timestampMillis, network, extras);
diff --git a/framework/src/android/net/DnsResolver.java b/framework/src/android/net/DnsResolver.java
index 3f7660f..dac88ad 100644
--- a/framework/src/android/net/DnsResolver.java
+++ b/framework/src/android/net/DnsResolver.java
@@ -500,7 +500,7 @@
try {
resp = resNetworkResult(fd); // Closes fd, marks it invalid.
} catch (ErrnoException e) {
- Log.e(TAG, "resNetworkResult:" + e.toString());
+ Log.w(TAG, "resNetworkResult:" + e.toString());
exception = e;
}
}
diff --git a/framework/src/android/net/NetworkAgentConfig.java b/framework/src/android/net/NetworkAgentConfig.java
index 3f058d8..ad8396b 100644
--- a/framework/src/android/net/NetworkAgentConfig.java
+++ b/framework/src/android/net/NetworkAgentConfig.java
@@ -311,26 +311,28 @@
}
/**
- * Disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to save power
- * and reduce idle traffic on networks that are known to be IPv6-only without a NAT64.
+ * Enables or disables active detection of NAT64 (e.g., via RFC 7050 DNS lookups). Used to
+ * save power and reduce idle traffic on networks that are known to be IPv6-only without a
+ * NAT64. By default, NAT64 detection is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableNat64Detection() {
- mConfig.skip464xlat = true;
+ public Builder setNat64DetectionEnabled(boolean enabled) {
+ mConfig.skip464xlat = !enabled;
return this;
}
/**
- * Disables the "Sign in to network" notification. Used if the network transport will
- * perform its own carrier-specific provisioning procedure.
+ * Enables or disables the "Sign in to network" notification. Used if the network transport
+ * will perform its own carrier-specific provisioning procedure. By default, the
+ * notification is enabled.
*
* @return this builder, to facilitate chaining.
*/
@NonNull
- public Builder disableProvisioningNotification() {
- mConfig.provisioningNotificationDisabled = true;
+ public Builder setProvisioningNotificationEnabled(boolean enabled) {
+ mConfig.provisioningNotificationDisabled = !enabled;
return this;
}
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index a54696f..c4277c3 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -162,7 +162,6 @@
* {@link NetworkCapabilities}.
* @hide
*/
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public NetworkCapabilities(@Nullable NetworkCapabilities nc, @RedactionType long redactions) {
mRedactions = redactions;
if (nc != null) {
@@ -601,8 +600,9 @@
// TODO: Consider adding unwanted capabilities to the public API and mention this
// in the documentation.
checkValidCapability(capability);
- mNetworkCapabilities |= 1 << capability;
- mUnwantedNetworkCapabilities &= ~(1 << capability); // remove from unwanted capability list
+ mNetworkCapabilities |= 1L << capability;
+ // remove from unwanted capability list
+ mUnwantedNetworkCapabilities &= ~(1L << capability);
return this;
}
@@ -621,8 +621,8 @@
*/
public void addUnwantedCapability(@NetCapability int capability) {
checkValidCapability(capability);
- mUnwantedNetworkCapabilities |= 1 << capability;
- mNetworkCapabilities &= ~(1 << capability); // remove from requested capabilities
+ mUnwantedNetworkCapabilities |= 1L << capability;
+ mNetworkCapabilities &= ~(1L << capability); // remove from requested capabilities
}
/**
@@ -635,7 +635,7 @@
*/
public @NonNull NetworkCapabilities removeCapability(@NetCapability int capability) {
checkValidCapability(capability);
- final long mask = ~(1 << capability);
+ final long mask = ~(1L << capability);
mNetworkCapabilities &= mask;
return this;
}
@@ -650,7 +650,7 @@
*/
public @NonNull NetworkCapabilities removeUnwantedCapability(@NetCapability int capability) {
checkValidCapability(capability);
- mUnwantedNetworkCapabilities &= ~(1 << capability);
+ mUnwantedNetworkCapabilities &= ~(1L << capability);
return this;
}
@@ -718,14 +718,14 @@
*/
public boolean hasCapability(@NetCapability int capability) {
return isValidCapability(capability)
- && ((mNetworkCapabilities & (1 << capability)) != 0);
+ && ((mNetworkCapabilities & (1L << capability)) != 0);
}
/** @hide */
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean hasUnwantedCapability(@NetCapability int capability) {
return isValidCapability(capability)
- && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0);
+ && ((mUnwantedNetworkCapabilities & (1L << capability)) != 0);
}
/**
@@ -1127,7 +1127,9 @@
* app needs to hold {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission. If the
* app targets SDK version greater than or equal to {@link Build.VERSION_CODES#S}, then they
* also need to use {@link NetworkCallback#FLAG_INCLUDE_LOCATION_INFO} to get the info in their
- * callback. The app will be blamed for location access if this field is included.
+ * callback. If the apps targets SDK version equal to {{@link Build.VERSION_CODES#R}, this field
+ * will always be included. The app will be blamed for location access if this field is
+ * included.
* </p>
*/
public int getOwnerUid() {
diff --git a/framework/src/android/net/NetworkScore.java b/framework/src/android/net/NetworkScore.java
index 0dee225..b0752e9 100644
--- a/framework/src/android/net/NetworkScore.java
+++ b/framework/src/android/net/NetworkScore.java
@@ -93,6 +93,10 @@
mKeepConnectedReason = in.readInt();
}
+ /**
+ * Get the legacy int score embedded in this NetworkScore.
+ * @see Builder#setLegacyInt(int)
+ */
public int getLegacyInt() {
return mLegacyInt;
}
@@ -212,7 +216,9 @@
/**
* Sets the legacy int for this score.
*
- * Do not rely on this. It will be gone by the time S is released.
+ * This will be used for measurements and logs, but will no longer be used for ranking
+ * networks against each other. Callers that existed before Android S should send what
+ * they used to send as the int score.
*
* @param score the legacy int
* @return this
diff --git a/framework/src/android/net/OemNetworkPreferences.java b/framework/src/android/net/OemNetworkPreferences.java
index 5a76cd6..2bb006d 100644
--- a/framework/src/android/net/OemNetworkPreferences.java
+++ b/framework/src/android/net/OemNetworkPreferences.java
@@ -40,6 +40,23 @@
*/
@SystemApi
public final class OemNetworkPreferences implements Parcelable {
+ // Valid production preferences must be > 0, negative values reserved for testing
+ /**
+ * This preference is only to be used for testing and nothing else.
+ * Use only TRANSPORT_TEST transport networks.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_TEST_ONLY = -2;
+
+ /**
+ * This preference is only to be used for testing and nothing else.
+ * If an unmetered network is available, use it.
+ * Otherwise, if a network with the TRANSPORT_TEST transport is available, use it.
+ * Otherwise, use the general default network.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_TEST = -1;
+
/**
* Default in case this value is not set. Using it will result in an error.
*/
@@ -69,6 +86,12 @@
*/
public static final int OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY = 4;
+ /**
+ * The max allowed value for an OEM network preference.
+ * @hide
+ */
+ public static final int OEM_NETWORK_PREFERENCE_MAX = OEM_NETWORK_PREFERENCE_OEM_PRIVATE_ONLY;
+
@NonNull
private final Bundle mNetworkMappings;
@@ -96,7 +119,7 @@
@Override
public String toString() {
- return "OemNetworkPreferences{" + "mNetworkMappings=" + mNetworkMappings + '}';
+ return "OemNetworkPreferences{" + "mNetworkMappings=" + getNetworkPreferences() + '}';
}
@Override
@@ -185,6 +208,8 @@
/** @hide */
@IntDef(prefix = "OEM_NETWORK_PREFERENCE_", value = {
+ OEM_NETWORK_PREFERENCE_TEST_ONLY,
+ OEM_NETWORK_PREFERENCE_TEST,
OEM_NETWORK_PREFERENCE_UNINITIALIZED,
OEM_NETWORK_PREFERENCE_OEM_PAID,
OEM_NETWORK_PREFERENCE_OEM_PAID_NO_FALLBACK,
@@ -205,6 +230,10 @@
@NonNull
public static String oemNetworkPreferenceToString(@OemNetworkPreference int value) {
switch (value) {
+ case OEM_NETWORK_PREFERENCE_TEST_ONLY:
+ return "OEM_NETWORK_PREFERENCE_TEST_ONLY";
+ case OEM_NETWORK_PREFERENCE_TEST:
+ return "OEM_NETWORK_PREFERENCE_TEST";
case OEM_NETWORK_PREFERENCE_UNINITIALIZED:
return "OEM_NETWORK_PREFERENCE_UNINITIALIZED";
case OEM_NETWORK_PREFERENCE_OEM_PAID:
diff --git a/framework/src/android/net/ParseException.java b/framework/src/android/net/ParseException.java
index ca6d012..9d4727a 100644
--- a/framework/src/android/net/ParseException.java
+++ b/framework/src/android/net/ParseException.java
@@ -17,7 +17,6 @@
package android.net;
import android.annotation.NonNull;
-import android.annotation.SystemApi;
/**
* Thrown when parsing failed.
@@ -26,15 +25,11 @@
public class ParseException extends RuntimeException {
public String response;
- /** @hide */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public ParseException(@NonNull String response) {
super(response);
this.response = response;
}
- /** @hide */
- @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public ParseException(@NonNull String response, @NonNull Throwable cause) {
super(response, cause);
this.response = response;
diff --git a/framework/src/android/net/TcpKeepalivePacketData.java b/framework/src/android/net/TcpKeepalivePacketData.java
index ddb3a6a..c2c4f32 100644
--- a/framework/src/android/net/TcpKeepalivePacketData.java
+++ b/framework/src/android/net/TcpKeepalivePacketData.java
@@ -32,22 +32,39 @@
public final class TcpKeepalivePacketData extends KeepalivePacketData implements Parcelable {
private static final String TAG = "TcpKeepalivePacketData";
- /** TCP sequence number. */
+ /**
+ * TCP sequence number.
+ * @hide
+ */
public final int tcpSeq;
- /** TCP ACK number. */
+ /**
+ * TCP ACK number.
+ * @hide
+ */
public final int tcpAck;
- /** TCP RCV window. */
+ /**
+ * TCP RCV window.
+ * @hide
+ */
public final int tcpWindow;
- /** TCP RCV window scale. */
+ /** TCP RCV window scale.
+ * @hide
+ */
public final int tcpWindowScale;
- /** IP TOS. */
+ /**
+ * IP TOS.
+ * @hide
+ */
public final int ipTos;
- /** IP TTL. */
+ /**
+ * IP TTL.
+ * @hide
+ */
public final int ipTtl;
public TcpKeepalivePacketData(@NonNull final InetAddress srcAddress, int srcPort,
@@ -63,6 +80,56 @@
this.ipTtl = ipTtl;
}
+ /**
+ * Get the TCP sequence number.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpSeq() {
+ return tcpSeq;
+ }
+
+ /**
+ * Get the TCP ACK number.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpAck() {
+ return tcpAck;
+ }
+
+ /**
+ * Get the TCP RCV window.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpWindow() {
+ return tcpWindow;
+ }
+
+ /**
+ * Get the TCP RCV window scale.
+ *
+ * See https://tools.ietf.org/html/rfc793#page-15.
+ */
+ public int getTcpWindowScale() {
+ return tcpWindowScale;
+ }
+
+ /**
+ * Get the IP type of service.
+ */
+ public int getIpTos() {
+ return ipTos;
+ }
+
+ /**
+ * Get the IP TTL.
+ */
+ public int getIpTtl() {
+ return ipTtl;
+ }
+
@Override
public boolean equals(@Nullable final Object o) {
if (!(o instanceof TcpKeepalivePacketData)) return false;
diff --git a/framework/src/android/net/TcpRepairWindow.java b/framework/src/android/net/TcpRepairWindow.java
index f062fa9..86034f0 100644
--- a/framework/src/android/net/TcpRepairWindow.java
+++ b/framework/src/android/net/TcpRepairWindow.java
@@ -16,15 +16,12 @@
package android.net;
-import android.annotation.SystemApi;
-
/**
* Corresponds to C's {@code struct tcp_repair_window} from
* include/uapi/linux/tcp.h
*
* @hide
*/
-@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public final class TcpRepairWindow {
public final int sndWl1;
public final int sndWnd;
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index a7a6235..9ddd2f5 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -15,8 +15,10 @@
*/
package android.net;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.os.IBinder;
import android.os.RemoteException;
@@ -58,6 +60,7 @@
* @param network The test network that should be torn down
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void teardownTestNetwork(@NonNull Network network) {
try {
@@ -103,6 +106,7 @@
* @param binder A binder object guarding the lifecycle of this test network.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
setupTestNetwork(iface, null, true, new int[0], binder);
@@ -145,6 +149,7 @@
* TUN interface.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
@@ -163,6 +168,7 @@
* TAP interface.
* @hide
*/
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
@NonNull
public TestNetworkInterface createTapInterface() {
diff --git a/service/Android.bp b/service/Android.bp
index 518f198..20ccf06 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -113,7 +113,6 @@
],
jarjar_rules: "jarjar-rules.txt",
apex_available: [
- "//apex_available:platform", // For arc-services
"com.android.tethering",
],
}
diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml
index 9ff2a22..82d8e4f 100644
--- a/service/ServiceConnectivityResources/res/values/config.xml
+++ b/service/ServiceConnectivityResources/res/values/config.xml
@@ -123,4 +123,8 @@
<string-array translatable="false" name="config_networkNotifySwitches">
</string-array>
+ <!-- Whether to use an ongoing notification for signing in to captive portals, instead of a
+ notification that can be dismissed. -->
+ <bool name="config_ongoingSignInNotification">false</bool>
+
</resources>
diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml
index 717d08e..568deca 100644
--- a/service/ServiceConnectivityResources/res/values/overlayable.xml
+++ b/service/ServiceConnectivityResources/res/values/overlayable.xml
@@ -32,6 +32,7 @@
<item type="integer" name="config_networkWakeupPacketMask"/>
<item type="integer" name="config_networkNotifySwitchType"/>
<item type="array" name="config_networkNotifySwitches"/>
+ <item type="bool" name="config_ongoingSignInNotification"/>
</policy>
</overlayable>
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index eb383ea..9539494 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2279,7 +2279,9 @@
netId = nai.network.getNetId();
}
boolean ok = addLegacyRouteToHost(lp, addr, netId, uid);
- if (DBG) log("requestRouteToHostAddress ok=" + ok);
+ if (DBG) {
+ log("requestRouteToHostAddress " + addr + nai.toShortString() + " ok=" + ok);
+ }
return ok;
} finally {
Binder.restoreCallingIdentity(token);
@@ -2903,13 +2905,13 @@
pw.println();
pw.println("mNetworkRequestInfoLogs (most recent first):");
pw.increaseIndent();
- mNetworkRequestInfoLogs.reverseDump(fd, pw, args);
+ mNetworkRequestInfoLogs.reverseDump(pw);
pw.decreaseIndent();
pw.println();
pw.println("mNetworkInfoBlockingLogs (most recent first):");
pw.increaseIndent();
- mNetworkInfoBlockingLogs.reverseDump(fd, pw, args);
+ mNetworkInfoBlockingLogs.reverseDump(pw);
pw.decreaseIndent();
pw.println();
@@ -2923,7 +2925,7 @@
long duration = SystemClock.elapsedRealtime() - mLastWakeLockAcquireTimestamp;
pw.println("currently holding WakeLock for: " + (duration / 1000) + "s");
}
- mWakelockLogs.reverseDump(fd, pw, args);
+ mWakelockLogs.reverseDump(pw);
pw.println();
pw.println("bandwidth update requests (by uid):");
@@ -2935,7 +2937,12 @@
}
}
pw.decreaseIndent();
+ pw.decreaseIndent();
+ pw.println();
+ pw.println("mOemNetworkPreferencesLogs (most recent first):");
+ pw.increaseIndent();
+ mOemNetworkPreferencesLogs.reverseDump(pw);
pw.decreaseIndent();
}
@@ -3789,6 +3796,10 @@
private void destroyNativeNetwork(@NonNull NetworkAgentInfo networkAgent) {
try {
mNetd.networkDestroy(networkAgent.network.getNetId());
+ } catch (RemoteException | ServiceSpecificException e) {
+ loge("Exception destroying network(networkDestroy): " + e);
+ }
+ try {
mDnsResolver.destroyNetworkCache(networkAgent.network.getNetId());
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception destroying network: " + e);
@@ -4220,7 +4231,7 @@
// network, we should respect the user's option and don't need to popup the
// PARTIAL_CONNECTIVITY notification to user again.
nai.networkAgentConfig.acceptPartialConnectivity = accept;
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
@@ -4288,6 +4299,7 @@
}
if (!nai.avoidUnvalidated) {
nai.avoidUnvalidated = true;
+ nai.updateScoreForNetworkAgentUpdate();
rematchAllNetworksAndRequests();
}
}
@@ -4395,7 +4407,7 @@
private void updateAvoidBadWifi() {
for (final NetworkAgentInfo nai : mNetworkAgentInfos) {
- nai.updateScoreForNetworkAgentConfigUpdate();
+ nai.updateScoreForNetworkAgentUpdate();
}
rematchAllNetworksAndRequests();
}
@@ -4985,7 +4997,7 @@
}
@Override
- public void setGlobalProxy(final ProxyInfo proxyProperties) {
+ public void setGlobalProxy(@Nullable final ProxyInfo proxyProperties) {
PermissionUtils.enforceNetworkStackPermission(mContext);
mProxyTracker.setGlobalProxy(proxyProperties);
}
@@ -5683,7 +5695,7 @@
+ mNetworkRequestForCallback.requestId
+ " " + mRequests
+ (mPendingIntent == null ? "" : " to trigger " + mPendingIntent)
- + "callback flags: " + mCallbackFlags;
+ + " callback flags: " + mCallbackFlags;
}
}
@@ -6233,6 +6245,12 @@
@NonNull
private ProfileNetworkPreferences mProfileNetworkPreferences = new ProfileNetworkPreferences();
+ // OemNetworkPreferences activity String log entries.
+ private static final int MAX_OEM_NETWORK_PREFERENCE_LOGS = 20;
+ @NonNull
+ private final LocalLog mOemNetworkPreferencesLogs =
+ new LocalLog(MAX_OEM_NETWORK_PREFERENCE_LOGS);
+
/**
* Determine whether a given package has a mapping in the current OemNetworkPreferences.
* @param packageName the package name to check existence of a mapping for.
@@ -6597,7 +6615,7 @@
@NonNull final INetworkOfferCallback callback) {
ensureRunningOnConnectivityServiceThread();
for (final NetworkOfferInfo noi : mNetworkOffers) {
- if (noi.offer.callback.equals(callback)) return noi;
+ if (noi.offer.callback.asBinder().equals(callback.asBinder())) return noi;
}
return null;
}
@@ -7155,6 +7173,7 @@
final NetworkCapabilities prevNc = nai.getAndSetNetworkCapabilities(newNc);
updateUids(nai, prevNc, newNc);
+ nai.updateScoreForNetworkAgentUpdate();
if (nai.getCurrentScore() == oldScore && newNc.equalRequestableCapabilities(prevNc)) {
// If the requestable capabilities haven't changed, and the score hasn't changed, then
@@ -7681,7 +7700,7 @@
}
void addRequestReassignment(@NonNull final RequestReassignment reassignment) {
- if (Build.IS_DEBUGGABLE) {
+ if (Build.isDebuggable()) {
// The code is never supposed to add two reassignments of the same request. Make
// sure this stays true, but without imposing this expensive check on all
// reassignments on all user devices.
@@ -9737,6 +9756,7 @@
return;
}
+ mOemNetworkPreferencesLogs.log("UPDATE INITIATED: " + preference);
final ArraySet<NetworkRequestInfo> nris =
new OemNetworkRequestFactory().createNrisFromOemNetworkPreferences(preference);
replaceDefaultNetworkRequestsForPreference(nris);
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index ffeb77d..cf4fe1e 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -420,7 +420,7 @@
/*
* Tell the VMs to toss their DNS caches
*/
- final Intent intent = new Intent(Intent.ACTION_CLEAR_DNS_CACHE);
+ final Intent intent = new Intent(ConnectivityManager.ACTION_CLEAR_DNS_CACHE);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
/*
* Connectivity events can happen before boot has completed ...
diff --git a/services/core/java/com/android/server/connectivity/FullScore.java b/services/core/java/com/android/server/connectivity/FullScore.java
index a8a83fc..52da566 100644
--- a/services/core/java/com/android/server/connectivity/FullScore.java
+++ b/services/core/java/com/android/server/connectivity/FullScore.java
@@ -91,17 +91,26 @@
/** @hide */
public static final int POLICY_IS_INVINCIBLE = 58;
+ // This network has been validated at least once since it was connected, but not explicitly
+ // avoided in UI.
+ // TODO : remove setAvoidUnvalidated and instead disconnect the network when the user
+ // chooses to move away from this network, and remove this flag.
+ /** @hide */
+ public static final int POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD = 57;
+
// To help iterate when printing
@VisibleForTesting
- static final int MIN_CS_MANAGED_POLICY = POLICY_IS_INVINCIBLE;
+ static final int MIN_CS_MANAGED_POLICY = POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
@VisibleForTesting
static final int MAX_CS_MANAGED_POLICY = POLICY_IS_VALIDATED;
// Mask for policies in NetworkScore. This should have all bits managed by NetworkScore set
// and all bits managed by FullScore unset. As bits are handled from 0 up in NetworkScore and
- // from 63 down in FullScore, cut at the 32rd bit for simplicity, but change this if some day
+ // from 63 down in FullScore, cut at the 32nd bit for simplicity, but change this if some day
// there are more than 32 bits handled on either side.
- private static final int EXTERNAL_POLICIES_MASK = 0x0000FFFF;
+ // YIELD_TO_BAD_WIFI is temporarily handled by ConnectivityService.
+ private static final long EXTERNAL_POLICIES_MASK =
+ 0x00000000FFFFFFFFL & ~(1L << POLICY_YIELD_TO_BAD_WIFI);
@VisibleForTesting
static @NonNull String policyNameOf(final int policy) {
@@ -115,6 +124,7 @@
case POLICY_TRANSPORT_PRIMARY: return "TRANSPORT_PRIMARY";
case POLICY_EXITING: return "EXITING";
case POLICY_IS_INVINCIBLE: return "INVINCIBLE";
+ case POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD: return "EVER_VALIDATED";
}
throw new IllegalArgumentException("Unknown policy : " + policy);
}
@@ -137,6 +147,7 @@
* @param score the score supplied by the agent
* @param caps the NetworkCapabilities of the network
* @param config the NetworkAgentConfig of the network
+ * @param everValidated whether this network has ever validated
* @param yieldToBadWiFi whether this network yields to a previously validated wifi gone bad
* @return a FullScore that is appropriate to use for ranking.
*/
@@ -145,12 +156,13 @@
// connectivity for backward compatibility.
public static FullScore fromNetworkScore(@NonNull final NetworkScore score,
@NonNull final NetworkCapabilities caps, @NonNull final NetworkAgentConfig config,
- final boolean yieldToBadWiFi) {
+ final boolean everValidated, final boolean yieldToBadWiFi) {
return withPolicies(score.getLegacyInt(), score.getPolicies(),
score.getKeepConnectedReason(),
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWiFi,
@@ -179,6 +191,8 @@
// Prospective scores are always unmetered, because unmetered networks are stronger
// than metered networks, and it's not known in advance whether the network is metered.
final boolean unmetered = true;
+ // If the offer may validate, then it should be considered to have validated at some point
+ final boolean everValidated = mayValidate;
// The network hasn't been chosen by the user (yet, at least).
final boolean everUserSelected = false;
// Don't assume the user will accept unvalidated connectivity.
@@ -189,8 +203,8 @@
// score.
final boolean invincible = score.getLegacyInt() > NetworkRanker.LEGACY_INT_MAX;
return withPolicies(score.getLegacyInt(), score.getPolicies(), KEEP_CONNECTED_NONE,
- mayValidate, vpn, unmetered, everUserSelected, acceptUnvalidated, yieldToBadWiFi,
- invincible);
+ mayValidate, vpn, unmetered, everValidated, everUserSelected, acceptUnvalidated,
+ yieldToBadWiFi, invincible);
}
/**
@@ -204,11 +218,14 @@
// telephony factory, so that it depends on the carrier. For now this is handled by
// connectivity for backward compatibility.
public FullScore mixInScore(@NonNull final NetworkCapabilities caps,
- @NonNull final NetworkAgentConfig config, final boolean yieldToBadWifi) {
+ @NonNull final NetworkAgentConfig config,
+ final boolean everValidated,
+ final boolean yieldToBadWifi) {
return withPolicies(mLegacyInt, mPolicies, mKeepConnectedReason,
caps.hasCapability(NET_CAPABILITY_VALIDATED),
caps.hasTransport(TRANSPORT_VPN),
caps.hasCapability(NET_CAPABILITY_NOT_METERED),
+ everValidated,
config.explicitlySelected,
config.acceptUnvalidated,
yieldToBadWifi,
@@ -224,6 +241,7 @@
final boolean isValidated,
final boolean isVpn,
final boolean isUnmetered,
+ final boolean everValidated,
final boolean everUserSelected,
final boolean acceptUnvalidated,
final boolean yieldToBadWiFi,
@@ -232,6 +250,7 @@
| (isValidated ? 1L << POLICY_IS_VALIDATED : 0)
| (isVpn ? 1L << POLICY_IS_VPN : 0)
| (isUnmetered ? 1L << POLICY_IS_UNMETERED : 0)
+ | (everValidated ? 1L << POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD : 0)
| (everUserSelected ? 1L << POLICY_EVER_USER_SELECTED : 0)
| (acceptUnvalidated ? 1L << POLICY_ACCEPT_UNVALIDATED : 0)
| (yieldToBadWiFi ? 1L << POLICY_YIELD_TO_BAD_WIFI : 0)
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 5d793fd..4d310cb 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -707,7 +707,8 @@
@NonNull final NetworkCapabilities nc) {
final NetworkCapabilities oldNc = networkCapabilities;
networkCapabilities = nc;
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, everValidatedForYield(),
+ yieldToBadWiFi());
final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
nm.notifyNetworkCapabilitiesChanged(nc);
@@ -893,7 +894,7 @@
// Caller must not mutate. This method is called frequently and making a defensive copy
// would be too expensive. This is used by NetworkRanker.Scoreable, so it can be compared
// against other scoreables.
- @Override public NetworkCapabilities getCaps() {
+ @Override public NetworkCapabilities getCapsNoCopy() {
return networkCapabilities;
}
@@ -919,7 +920,7 @@
*/
public void setScore(final NetworkScore score) {
mScore = FullScore.fromNetworkScore(score, networkCapabilities, networkAgentConfig,
- yieldToBadWiFi());
+ everValidatedForYield(), yieldToBadWiFi());
}
/**
@@ -927,8 +928,13 @@
*
* Call this after updating the network agent config.
*/
- public void updateScoreForNetworkAgentConfigUpdate() {
- mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig, yieldToBadWiFi());
+ public void updateScoreForNetworkAgentUpdate() {
+ mScore = mScore.mixInScore(networkCapabilities, networkAgentConfig,
+ everValidatedForYield(), yieldToBadWiFi());
+ }
+
+ private boolean everValidatedForYield() {
+ return everValidated && !avoidUnvalidated;
}
/**
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index b57ad5d..3dc79c5 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -280,7 +280,11 @@
.setContentTitle(title)
.setContentIntent(intent)
.setLocalOnly(true)
- .setOnlyAlertOnce(true);
+ .setOnlyAlertOnce(true)
+ // TODO: consider having action buttons to disconnect on the sign-in notification
+ // especially if it is ongoing
+ .setOngoing(notifyType == NotificationType.SIGN_IN
+ && r.getBoolean(R.bool.config_ongoingSignInNotification));
if (notifyType == NotificationType.NETWORK_SWITCH) {
builder.setStyle(new Notification.BigTextStyle().bigText(details));
diff --git a/services/core/java/com/android/server/connectivity/NetworkOffer.java b/services/core/java/com/android/server/connectivity/NetworkOffer.java
index 5336593..8285e7a 100644
--- a/services/core/java/com/android/server/connectivity/NetworkOffer.java
+++ b/services/core/java/com/android/server/connectivity/NetworkOffer.java
@@ -76,7 +76,7 @@
/**
* Get the capabilities filter of this offer
*/
- @Override @NonNull public NetworkCapabilities getCaps() {
+ @Override @NonNull public NetworkCapabilities getCapsNoCopy() {
return caps;
}
@@ -133,7 +133,7 @@
* @param previousOffer the previous offer
*/
public void migrateFrom(@NonNull final NetworkOffer previousOffer) {
- if (!callback.equals(previousOffer.callback)) {
+ if (!callback.asBinder().equals(previousOffer.callback.asBinder())) {
throw new IllegalArgumentException("Can only migrate from a previous version of"
+ " the same offer");
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java
index 3aaff59..c123ea7 100644
--- a/services/core/java/com/android/server/connectivity/NetworkRanker.java
+++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java
@@ -26,6 +26,7 @@
import static com.android.server.connectivity.FullScore.POLICY_ACCEPT_UNVALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_EVER_USER_SELECTED;
+import static com.android.server.connectivity.FullScore.POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD;
import static com.android.server.connectivity.FullScore.POLICY_IS_INVINCIBLE;
import static com.android.server.connectivity.FullScore.POLICY_IS_VALIDATED;
import static com.android.server.connectivity.FullScore.POLICY_IS_VPN;
@@ -58,7 +59,7 @@
/** Get score of this scoreable */
FullScore getScore();
/** Get capabilities of this scoreable */
- NetworkCapabilities getCaps();
+ NetworkCapabilities getCapsNoCopy();
}
private static final boolean USE_POLICY_RANKING = false;
@@ -158,11 +159,12 @@
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) candidates = new ArrayList<>(accepted);
- // Yield to bad wifi policy : if any wifi has ever been validated, keep only networks
- // that don't yield to such a wifi network.
+ // Yield to bad wifi policy : if any wifi has ever been validated (even if it's now
+ // unvalidated), and unless it's been explicitly avoided when bad in UI, then keep only
+ // networks that don't yield to such a wifi network.
final boolean anyWiFiEverValidated = CollectionUtils.any(candidates,
- nai -> nai.getScore().hasPolicy(POLICY_EVER_USER_SELECTED)
- && nai.getCaps().hasTransport(TRANSPORT_WIFI));
+ nai -> nai.getScore().hasPolicy(POLICY_EVER_VALIDATED_NOT_AVOIDED_WHEN_BAD)
+ && nai.getCapsNoCopy().hasTransport(TRANSPORT_WIFI));
if (anyWiFiEverValidated) {
partitionInto(candidates, nai -> !nai.getScore().hasPolicy(POLICY_YIELD_TO_BAD_WIFI),
accepted, rejected);
@@ -206,18 +208,18 @@
for (final Scoreable defaultSubNai : accepted) {
// Remove all networks without the DEFAULT_SUBSCRIPTION policy and the same transports
// as a network that has it.
- final int[] transports = defaultSubNai.getCaps().getTransportTypes();
+ final int[] transports = defaultSubNai.getCapsNoCopy().getTransportTypes();
candidates.removeIf(nai -> !nai.getScore().hasPolicy(POLICY_TRANSPORT_PRIMARY)
- && Arrays.equals(transports, nai.getCaps().getTransportTypes()));
+ && Arrays.equals(transports, nai.getCapsNoCopy().getTransportTypes()));
}
if (1 == candidates.size()) return candidates.get(0);
- // It's guaranteed candidates.size() > 0 because there is at least one with DEFAULT_SUB
- // policy and only those without it were removed.
+ // It's guaranteed candidates.size() > 0 because there is at least one with the
+ // TRANSPORT_PRIMARY policy and only those without it were removed.
// If some of the networks have a better transport than others, keep only the ones with
// the best transports.
for (final int transport : PREFERRED_TRANSPORTS_ORDER) {
- partitionInto(candidates, nai -> nai.getCaps().hasTransport(transport),
+ partitionInto(candidates, nai -> nai.getCapsNoCopy().hasTransport(transport),
accepted, rejected);
if (accepted.size() == 1) return accepted.get(0);
if (accepted.size() > 0 && rejected.size() > 0) {
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 3711679..e952ee5 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -133,7 +133,7 @@
* Get device first sdk version.
*/
public int getDeviceFirstSdkInt() {
- return Build.VERSION.FIRST_SDK_INT;
+ return Build.VERSION.DEVICE_INITIAL_SDK_INT;
}
}
diff --git a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
index 1e54093..db939f9 100644
--- a/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
+++ b/tests/net/common/java/android/net/NetworkAgentConfigTest.kt
@@ -63,8 +63,8 @@
setPartialConnectivityAcceptable(false)
setUnvalidatedConnectivityAcceptable(true)
setLegacyTypeName("TEST_NETWORK")
- disableNat64Detection()
- disableProvisioningNotification()
+ setNat64DetectionEnabled(false)
+ setProvisioningNotificationEnabled(false)
}.build()
assertTrue(config.isExplicitlySelected())
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index e7718b5..6d852bf 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -48,6 +48,7 @@
import static com.android.modules.utils.build.SdkLevel.isAtLeastR;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
+import static com.android.net.module.util.NetworkCapabilitiesUtils.TRANSPORT_USB;
import static com.android.testutils.MiscAsserts.assertEmpty;
import static com.android.testutils.MiscAsserts.assertThrows;
import static com.android.testutils.ParcelUtils.assertParcelSane;
@@ -959,6 +960,11 @@
assertNotEquals(512, nc.getLinkUpstreamBandwidthKbps());
}
+ private int getMaxTransport() {
+ if (!isAtLeastS() && MAX_TRANSPORT == TRANSPORT_USB) return MAX_TRANSPORT - 1;
+ return MAX_TRANSPORT;
+ }
+
@Test
public void testSignalStrength() {
final NetworkCapabilities nc = new NetworkCapabilities();
@@ -970,7 +976,7 @@
}
private void assertNoTransport(NetworkCapabilities nc) {
- for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+ for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) {
assertFalse(nc.hasTransport(i));
}
}
@@ -987,7 +993,7 @@
assertFalse(nc.hasTransport(i));
}
}
- for (int i = MAX_TRANSPORT; i > maxTransportType; i--) {
+ for (int i = getMaxTransport(); i > maxTransportType; i--) {
if (positiveSequence) {
assertFalse(nc.hasTransport(i));
} else {
@@ -1001,12 +1007,12 @@
final NetworkCapabilities nc = new NetworkCapabilities();
assertNoTransport(nc);
// Test adding multiple transport types.
- for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+ for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) {
nc.addTransportType(i);
checkCurrentTransportTypes(nc, i, true /* positiveSequence */);
}
// Test removing multiple transport types.
- for (int i = MIN_TRANSPORT; i <= MAX_TRANSPORT; i++) {
+ for (int i = MIN_TRANSPORT; i <= getMaxTransport(); i++) {
nc.removeTransportType(i);
checkCurrentTransportTypes(nc, i, false /* positiveSequence */);
}
diff --git a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
index 6770066..7a18bb0 100644
--- a/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
+++ b/tests/net/common/java/android/net/TcpKeepalivePacketDataTest.kt
@@ -92,12 +92,12 @@
assertTrue(str.contains(data.dstAddress.hostAddress))
assertTrue(str.contains(data.dstPort.toString()))
// .packet not included in toString()
- assertTrue(str.contains(data.tcpSeq.toString()))
- assertTrue(str.contains(data.tcpAck.toString()))
- assertTrue(str.contains(data.tcpWindow.toString()))
- assertTrue(str.contains(data.tcpWindowScale.toString()))
- assertTrue(str.contains(data.ipTos.toString()))
- assertTrue(str.contains(data.ipTtl.toString()))
+ assertTrue(str.contains(data.getTcpSeq().toString()))
+ assertTrue(str.contains(data.getTcpAck().toString()))
+ assertTrue(str.contains(data.getTcpWindow().toString()))
+ assertTrue(str.contains(data.getTcpWindowScale().toString()))
+ assertTrue(str.contains(data.getIpTos().toString()))
+ assertTrue(str.contains(data.getIpTtl().toString()))
// Update above assertions if field is added
assertFieldCountEquals(5, KeepalivePacketData::class.java)
diff --git a/tests/net/java/android/net/IpSecAlgorithmTest.java b/tests/net/java/android/net/IpSecAlgorithmTest.java
index 3a8d600..5bd2214 100644
--- a/tests/net/java/android/net/IpSecAlgorithmTest.java
+++ b/tests/net/java/android/net/IpSecAlgorithmTest.java
@@ -121,7 +121,7 @@
@Test
public void testValidationForAlgosAddedInS() throws Exception {
- if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.R) {
+ if (Build.VERSION.DEVICE_INITIAL_SDK_INT <= Build.VERSION_CODES.R) {
return;
}
@@ -194,13 +194,13 @@
private static Set<String> getMandatoryAlgos() {
return CollectionUtils.filter(
ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
- i -> Build.VERSION.FIRST_SDK_INT >= ALGO_TO_REQUIRED_FIRST_SDK.get(i));
+ i -> Build.VERSION.DEVICE_INITIAL_SDK_INT >= ALGO_TO_REQUIRED_FIRST_SDK.get(i));
}
private static Set<String> getOptionalAlgos() {
return CollectionUtils.filter(
ALGO_TO_REQUIRED_FIRST_SDK.keySet(),
- i -> Build.VERSION.FIRST_SDK_INT < ALGO_TO_REQUIRED_FIRST_SDK.get(i));
+ i -> Build.VERSION.DEVICE_INITIAL_SDK_INT < ALGO_TO_REQUIRED_FIRST_SDK.get(i));
}
@Test
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index ada20d3..47e4b5e 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -18,6 +18,7 @@
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.DUMP;
import static android.Manifest.permission.NETWORK_FACTORY;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
@@ -63,6 +64,7 @@
import static android.net.INetworkMonitor.NETWORK_VALIDATION_PROBE_PRIVDNS;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL;
import static android.net.INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_BIP;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
@@ -89,6 +91,7 @@
import static android.net.NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VSIM;
import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
import static android.net.NetworkCapabilities.NET_CAPABILITY_XCAP;
import static android.net.NetworkCapabilities.REDACT_FOR_ACCESS_FINE_LOCATION;
@@ -354,6 +357,8 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;
import java.util.function.Supplier;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import kotlin.reflect.KClass;
@@ -3030,10 +3035,11 @@
// Verify NOT_RESTRICTED is set appropriately
final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
.build().networkCapabilities;
- if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN ||
- capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA ||
- capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS ||
- capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
+ if (capability == NET_CAPABILITY_CBS || capability == NET_CAPABILITY_DUN
+ || capability == NET_CAPABILITY_EIMS || capability == NET_CAPABILITY_FOTA
+ || capability == NET_CAPABILITY_IA || capability == NET_CAPABILITY_IMS
+ || capability == NET_CAPABILITY_RCS || capability == NET_CAPABILITY_XCAP
+ || capability == NET_CAPABILITY_VSIM || capability == NET_CAPABILITY_BIP
|| capability == NET_CAPABILITY_ENTERPRISE) {
assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
} else {
@@ -3168,6 +3174,8 @@
tryNetworkFactoryRequests(NET_CAPABILITY_INTERNET);
tryNetworkFactoryRequests(NET_CAPABILITY_TRUSTED);
tryNetworkFactoryRequests(NET_CAPABILITY_NOT_VPN);
+ tryNetworkFactoryRequests(NET_CAPABILITY_VSIM);
+ tryNetworkFactoryRequests(NET_CAPABILITY_BIP);
// Skipping VALIDATED and CAPTIVE_PORTAL as they're disallowed.
}
@@ -9250,7 +9258,7 @@
final int expectedOwnerUidWithoutIncludeFlag =
shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag
- ? Process.myUid() : INVALID_UID;
+ ? myUid : INVALID_UID;
assertEquals(expectedOwnerUidWithoutIncludeFlag, getOwnerUidNetCapsPermission(
myUid, myUid, false /* includeLocationSensitiveInfo */));
@@ -9269,22 +9277,26 @@
}
+ private void verifyOwnerUidAndTransportInfoNetCapsPermissionPreS() {
+ verifyOwnerUidAndTransportInfoNetCapsPermission(
+ // Ensure that owner uid is included even if the request asks to remove it (which is
+ // the default) since the app has necessary permissions and targetSdk < S.
+ true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
+ true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
+ // Ensure that location info is removed if the request asks to remove it even if the
+ // app has necessary permissions.
+ false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
+ true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
+ );
+ }
+
@Test
- public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQ()
+ public void testCreateWithLocationInfoSanitizedWithFineLocationAfterQPreS()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- verifyOwnerUidAndTransportInfoNetCapsPermission(
- // Ensure that we include owner uid even if the request asks to remove it since the
- // app has necessary permissions and targetSdk < S.
- true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- // Ensure that we remove location info if the request asks to remove it even if the
- // app has necessary permissions.
- true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
- );
+ verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
}
@Test
@@ -9293,16 +9305,7 @@
setupLocationPermissions(Build.VERSION_CODES.R, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- verifyOwnerUidAndTransportInfoNetCapsPermission(
- // Ensure that we include owner uid even if the request asks to remove it since the
- // app has necessary permissions and targetSdk < S.
- true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- // Ensure that we remove location info if the request asks to remove it even if the
- // app has necessary permissions.
- true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
- );
+ verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
}
@Test
@@ -9313,13 +9316,13 @@
Manifest.permission.ACCESS_FINE_LOCATION);
verifyOwnerUidAndTransportInfoNetCapsPermission(
- // Ensure that we owner UID if the request asks us to remove it even if the app
- // has necessary permissions since targetSdk >= S.
+ // Ensure that the owner UID is removed if the request asks us to remove it even
+ // if the app has necessary permissions since targetSdk >= S.
false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- // Ensure that we remove location info if the request asks to remove it even if the
+ // Ensure that location info is removed if the request asks to remove it even if the
// app has necessary permissions.
+ false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
);
}
@@ -9330,15 +9333,15 @@
setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
+ verifyOwnerUidAndTransportInfoNetCapsPermissionPreS();
+ }
+
+ private void verifyOwnerUidAndTransportInfoNetCapsNotIncluded() {
verifyOwnerUidAndTransportInfoNetCapsPermission(
- // Ensure that we owner UID if the request asks us to remove it even if the app
- // has necessary permissions since targetSdk >= S.
- true, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- true, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
+ false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
+ false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- // Ensure that we remove location info if the request asks to remove it even if the
- // app has necessary permissions.
- true /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
+ false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
);
}
@@ -9348,12 +9351,7 @@
setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
- verifyOwnerUidAndTransportInfoNetCapsPermission(
- false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
- );
+ verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
}
@Test
@@ -9375,26 +9373,17 @@
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
- verifyOwnerUidAndTransportInfoNetCapsPermission(
- false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
- );
+ verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
}
@Test
- public void testCreateWithLocationInfoSanitizedWithoutLocationPermission()
+ public void testCreateWithLocationInfoSanitizedWithCoarseLocationAfterS()
throws Exception {
// Test that not having fine location permission leads to sanitization.
- setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
+ setupLocationPermissions(Build.VERSION_CODES.S, true, AppOpsManager.OPSTR_COARSE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION);
- verifyOwnerUidAndTransportInfoNetCapsPermission(
- false, /* shouldInclLocationSensitiveOwnerUidWithoutIncludeFlag */
- false, /* shouldInclLocationSensitiveOwnerUidWithIncludeFlag */
- false, /* shouldInclLocationSensitiveTransportInfoWithoutIncludeFlag */
- false /* shouldInclLocationSensitiveTransportInfoWithIncludeFlag */
- );
+ verifyOwnerUidAndTransportInfoNetCapsNotIncluded();
}
@Test
@@ -10062,6 +10051,7 @@
@Test
public void testDumpDoesNotCrash() {
+ mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
// Filing a couple requests prior to testing the dump.
final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
@@ -12011,6 +12001,33 @@
}
@Test
+ public void testSetOemNetworkPreferenceLogsRequest() throws Exception {
+ mServiceContext.setPermission(DUMP, PERMISSION_GRANTED);
+ @OemNetworkPreferences.OemNetworkPreference final int networkPref =
+ OEM_NETWORK_PREFERENCE_OEM_PAID;
+ final StringWriter stringWriter = new StringWriter();
+ final String logIdentifier = "UPDATE INITIATED: OemNetworkPreferences";
+ final Pattern pattern = Pattern.compile(logIdentifier);
+
+ final int expectedNumLogs = 2;
+ final UidRangeParcel[] uidRanges =
+ toUidRangeStableParcels(uidRangesForUids(TEST_PACKAGE_UID));
+
+ // Call twice to generate two logs.
+ setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+ setupSetOemNetworkPreferenceForPreferenceTest(networkPref, uidRanges, TEST_PACKAGE_NAME);
+ mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
+
+ final String dumpOutput = stringWriter.toString();
+ final Matcher matcher = pattern.matcher(dumpOutput);
+ int count = 0;
+ while (matcher.find()) {
+ count++;
+ }
+ assertEquals(expectedNumLogs, count);
+ }
+
+ @Test
public void testGetAllNetworkStateSnapshot() throws Exception {
verifyNoNetwork();
diff --git a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
index f0d7d86..45b575a 100644
--- a/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
+++ b/tests/net/java/com/android/server/connectivity/FullScoreTest.kt
@@ -56,7 +56,7 @@
if (vpn) addTransportType(NetworkCapabilities.TRANSPORT_VPN)
if (validated) addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
}.build()
- return mixInScore(nc, nac, false /* avoidBadWifi */)
+ return mixInScore(nc, nac, validated, false /* yieldToBadWifi */)
}
@Test
diff --git a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
index 2f3ee68..c353cea 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
+++ b/tests/net/java/com/android/server/connectivity/NetworkNotificationManagerTest.java
@@ -16,8 +16,16 @@
package com.android.server.connectivity;
-import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.*;
+import static android.app.Notification.FLAG_ONGOING_EVENT;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.LOST_INTERNET;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NETWORK_SWITCH;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.NO_INTERNET;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PARTIAL_CONNECTIVITY;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.PRIVATE_DNS_BROKEN;
+import static com.android.server.connectivity.NetworkNotificationManager.NotificationType.SIGN_IN;
+
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.clearInvocations;
@@ -230,19 +238,47 @@
verify(mNotificationManager, never()).notify(any(), anyInt(), any());
}
+ private void assertNotification(NotificationType type, boolean ongoing) {
+ final int id = 101;
+ final String tag = NetworkNotificationManager.tagFor(id);
+ final ArgumentCaptor<Notification> noteCaptor = ArgumentCaptor.forClass(Notification.class);
+ mManager.showNotification(id, type, mWifiNai, mCellNai, null, false);
+ verify(mNotificationManager, times(1)).notify(eq(tag), eq(type.eventId),
+ noteCaptor.capture());
+
+ assertEquals("Notification ongoing flag should be " + (ongoing ? "set" : "unset"),
+ ongoing, (noteCaptor.getValue().flags & FLAG_ONGOING_EVENT) != 0);
+ }
+
@Test
public void testDuplicatedNotificationsNoInternetThenSignIn() {
final int id = 101;
final String tag = NetworkNotificationManager.tagFor(id);
// Show first NO_INTERNET
- mManager.showNotification(id, NO_INTERNET, mWifiNai, mCellNai, null, false);
- verify(mNotificationManager, times(1)).notify(eq(tag), eq(NO_INTERNET.eventId), any());
+ assertNotification(NO_INTERNET, false /* ongoing */);
// Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
- mManager.showNotification(id, SIGN_IN, mWifiNai, mCellNai, null, false);
+ assertNotification(SIGN_IN, false /* ongoing */);
verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
- verify(mNotificationManager, times(1)).notify(eq(tag), eq(SIGN_IN.eventId), any());
+
+ // Network disconnects
+ mManager.clearNotification(id);
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(SIGN_IN.eventId));
+ }
+
+ @Test
+ public void testOngoingSignInNotification() {
+ doReturn(true).when(mResources).getBoolean(R.bool.config_ongoingSignInNotification);
+ final int id = 101;
+ final String tag = NetworkNotificationManager.tagFor(id);
+
+ // Show first NO_INTERNET
+ assertNotification(NO_INTERNET, false /* ongoing */);
+
+ // Captive portal detection triggers SIGN_IN a bit later, clearing the previous NO_INTERNET
+ assertNotification(SIGN_IN, true /* ongoing */);
+ verify(mNotificationManager, times(1)).cancel(eq(tag), eq(NO_INTERNET.eventId));
// Network disconnects
mManager.clearNotification(id);