Snap for 11154822 from 4cdc32bd2129380ed311e7439281bdef16976796 to mainline-healthfitness-release

Change-Id: Iedf560efd4f6b4afaad2e6309e508016d3462f8a
diff --git a/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
index df98c1c..632d1d6 100644
--- a/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
+++ b/common/networkstackclient/src/android/net/shared/PrivateDnsConfig.java
@@ -22,6 +22,8 @@
 import static android.net.shared.ParcelableUtil.fromParcelableArray;
 import static android.net.shared.ParcelableUtil.toParcelableArray;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.net.PrivateDnsConfigParcel;
 import android.text.TextUtils;
 
@@ -31,16 +33,20 @@
 /** @hide */
 public class PrivateDnsConfig {
     // These fields store the private DNS configuration from setting.
-    // TODO(b/261404136): Replace this `boolean useTls` with `int mode`.
-    public final boolean useTls;
+    public final int mode;
+    @NonNull
     public final String hostname;
 
     // Stores the DoT server IP addresses resolved from A/AAAA lookups.
+    @NonNull
     public final InetAddress[] ips;
 
     // These fields store the DoH information discovered from SVCB lookups.
+    @NonNull
     public final String dohName;
+    @NonNull
     public final InetAddress[] dohIps;
+    @NonNull
     public final String dohPath;
     public final int dohPort;
 
@@ -60,8 +66,9 @@
      * A constructor for off/opportunistic mode private DNS configuration depending on `useTls`.
      */
     public PrivateDnsConfig(boolean useTls) {
-        this(useTls, null /* hostname */ , null /* ips */, null /* dohName */, null /* dohIps */,
-                null /* dohPath */, -1 /* dohPort */);
+        this(useTls ? PRIVATE_DNS_MODE_OPPORTUNISTIC : PRIVATE_DNS_MODE_OFF, null /* hostname */,
+                null /* ips */, null /* dohName */, null /* dohIps */, null /* dohPath */,
+                -1 /* dohPort */);
     }
 
     /**
@@ -69,17 +76,21 @@
      * If `hostname` is empty or null, this constructor creates a PrivateDnsConfig for off mode;
      * otherwise, it creates a PrivateDnsConfig for strict mode.
      */
-    public PrivateDnsConfig(String hostname, InetAddress[] ips) {
-        this(!TextUtils.isEmpty(hostname), hostname, ips, null /* dohName */, null /* dohIps */,
-                null /* dohPath */, -1 /* dohPort */);
+    public PrivateDnsConfig(@Nullable String hostname, @Nullable InetAddress[] ips) {
+        this(TextUtils.isEmpty(hostname) ? PRIVATE_DNS_MODE_OFF :
+                PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, hostname, ips, null /* dohName */,
+                null /* dohIps */, null /* dohPath */, -1 /* dohPort */);
     }
 
     /**
      * A constructor for all kinds of private DNS configuration with given DoH information.
+     * It treats both null values and empty strings as equivalent. Similarly, treats null values
+     * and empty arrays as equivalent.
      */
-    public PrivateDnsConfig(boolean useTls, String hostname, InetAddress[] ips, String dohName,
-            InetAddress[] dohIps, String dohPath, int dohPort) {
-        this.useTls = useTls;
+    public PrivateDnsConfig(int mode, @Nullable String hostname, @Nullable InetAddress[] ips,
+            @Nullable String dohName, @Nullable InetAddress[] dohIps, @Nullable String dohPath,
+            int dohPort) {
+        this.mode = mode;
         this.hostname = (hostname != null) ? hostname : "";
         this.ips = (ips != null) ? ips.clone() : new InetAddress[0];
         this.dohName = (dohName != null) ? dohName : "";
@@ -89,7 +100,7 @@
     }
 
     public PrivateDnsConfig(PrivateDnsConfig cfg) {
-        useTls = cfg.useTls;
+        mode = cfg.mode;
         hostname = cfg.hostname;
         ips = cfg.ips;
         dohName = cfg.dohName;
@@ -102,20 +113,20 @@
      * Indicates whether this is a strict mode private DNS configuration.
      */
     public boolean inStrictMode() {
-        return useTls && !TextUtils.isEmpty(hostname);
+        return mode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
     }
 
     /**
      * Indicates whether this is an opportunistic mode private DNS configuration.
      */
     public boolean inOpportunisticMode() {
-        return useTls && TextUtils.isEmpty(hostname);
+        return mode == PRIVATE_DNS_MODE_OPPORTUNISTIC;
     }
 
     @Override
     public String toString() {
         return PrivateDnsConfig.class.getSimpleName()
-                + "{" + useTls + ":" + hostname + "/" + Arrays.toString(ips)
+                + "{" + modeAsString(mode) + ":" + hostname + "/" + Arrays.toString(ips)
                 + ", dohName=" + dohName
                 + ", dohIps=" + Arrays.toString(dohIps)
                 + ", dohPath=" + dohPath
@@ -123,6 +134,16 @@
                 + "}";
     }
 
+    @NonNull
+    private static String modeAsString(int mode) {
+        switch (mode) {
+            case PRIVATE_DNS_MODE_OFF: return "off";
+            case PRIVATE_DNS_MODE_OPPORTUNISTIC: return "opportunistic";
+            case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME: return "strict";
+            default: return "unknown";
+        }
+    }
+
     /**
      * Create a stable AIDL-compatible parcel from the current instance.
      */
@@ -131,9 +152,7 @@
         parcel.hostname = hostname;
         parcel.ips = toParcelableArray(
                 Arrays.asList(ips), IpConfigurationParcelableUtil::parcelAddress, String.class);
-        parcel.privateDnsMode = !useTls ? PRIVATE_DNS_MODE_OFF
-                : TextUtils.isEmpty(hostname)
-                        ? PRIVATE_DNS_MODE_OPPORTUNISTIC : PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+        parcel.privateDnsMode = mode;
         parcel.dohName = dohName;
         parcel.dohIps = toParcelableArray(
                 Arrays.asList(dohIps), IpConfigurationParcelableUtil::parcelAddress, String.class);
@@ -152,7 +171,7 @@
 
         // For compatibility. If the sender (Tethering module) is using an old version (< 19) of
         // NetworkStack AIDL that `privateDnsMode` field is not present, `privateDnsMode` will be
-        // assigned from the default value -1. Let `useTls` assigned based on the hostname.
+        // assigned from the default value -1. Let `privateDnsMode` assigned based on the hostname.
         // In this case, there is a harmless bug that the receiver (NetworkStack module) can't
         // convert the parcel to a PrivateDnsConfig that indicates opportunistic mode.
         // The bug is harmless because 1) the bug exists for years without any problems and
@@ -165,11 +184,10 @@
             return new PrivateDnsConfig(parcel.hostname, ips);
         }
 
-        final boolean useTls = parcel.privateDnsMode != PRIVATE_DNS_MODE_OFF;
         InetAddress[] dohIps = new InetAddress[parcel.dohIps.length];
         dohIps = fromParcelableArray(parcel.dohIps,
                 IpConfigurationParcelableUtil::unparcelAddress).toArray(dohIps);
-        return new PrivateDnsConfig(useTls, parcel.hostname, ips, parcel.dohName, dohIps,
-                parcel.dohPath, parcel.dohPort);
+        return new PrivateDnsConfig(parcel.privateDnsMode, parcel.hostname, ips, parcel.dohName,
+                dohIps, parcel.dohPath, parcel.dohPort);
     }
 }
diff --git a/src/com/android/networkstack/netlink/TcpInfo.java b/src/com/android/networkstack/netlink/TcpInfo.java
index 73d206e..de450e9 100644
--- a/src/com/android/networkstack/netlink/TcpInfo.java
+++ b/src/com/android/networkstack/netlink/TcpInfo.java
@@ -170,7 +170,8 @@
         }
     }
 
-    private static String decodeWscale(byte num) {
+    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
+    static String decodeWscale(byte num) {
         return String.valueOf((num >> 4) & 0x0f)  + ":" + String.valueOf(num & 0x0f);
     }
 
diff --git a/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java b/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java
index 60da0b0..94f04d5 100644
--- a/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java
+++ b/tests/unit/src/android/net/shared/PrivateDnsConfigTest.java
@@ -22,9 +22,6 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.net.PrivateDnsConfigParcel;
 
@@ -36,6 +33,10 @@
 
 @RunWith(JUnit4.class)
 public final class PrivateDnsConfigTest {
+    private static final int OFF_MODE = PRIVATE_DNS_MODE_OFF;
+    private static final int OPPORTUNISTIC_MODE = PRIVATE_DNS_MODE_OPPORTUNISTIC;
+    private static final int STRICT_MODE = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
+
     private static final InetAddress[] TEST_ADDRS = new InetAddress[] {
         InetAddress.parseNumericAddress("1.2.3.4"),
         InetAddress.parseNumericAddress("2001:db8::2"),
@@ -51,7 +52,7 @@
     }
 
     private void assertPrivateDnsConfigEquals(PrivateDnsConfig a, PrivateDnsConfig b) {
-        assertEquals(a.useTls, b.useTls);
+        assertEquals(a.mode, b.mode);
         assertEquals(a.hostname, b.hostname);
         assertArrayEquals(a.ips, b.ips);
         assertEquals(a.dohName, b.dohName);
@@ -61,24 +62,9 @@
     }
 
     private void assertParcelEquals(PrivateDnsConfig cfg, PrivateDnsConfigParcel parcel) {
+        assertEquals(parcel.privateDnsMode, cfg.mode);
         assertEquals(parcel.hostname, cfg.hostname);
         assertArrayEquals(parcel.ips, toStringArray(cfg.ips));
-        switch (parcel.privateDnsMode) {
-            case PRIVATE_DNS_MODE_OFF:
-                assertFalse(cfg.useTls);
-                assertTrue(cfg.hostname.isEmpty());
-                break;
-            case PRIVATE_DNS_MODE_OPPORTUNISTIC:
-                assertTrue(cfg.useTls);
-                assertTrue(cfg.hostname.isEmpty());
-                break;
-            case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
-                assertTrue(cfg.useTls);
-                assertFalse(cfg.hostname.isEmpty());
-                break;
-            default:
-                fail("Unexpected private DNS mode");
-        }
         assertEquals(parcel.dohName, cfg.dohName);
         assertEquals(parcel.dohPath, cfg.dohPath);
         assertEquals(parcel.dohPort, cfg.dohPort);
@@ -94,6 +80,8 @@
         assertPrivateDnsConfigEquals(cfg, convertedCfg);
     }
 
+    // Tests that a PrivateDnsConfig and a PrivateDnsConfig that is converted from
+    // PrivateDnsConfigParcel are equal.
     @Test
     public void testParcelableConversion() {
         // Test the constructor: PrivateDnsConfig()
@@ -110,25 +98,31 @@
         testPrivateDnsConfigConversion(new PrivateDnsConfig("dns.com", TEST_ADDRS));
 
         // Test the constructor:
-        // PrivateDnsConfig(boolean useTls, String hostname, InetAddress[] ips, String dohName,
-        //                  InetAddress[] dohIps, String dohPath, int dohPort)
-        testPrivateDnsConfigConversion(new PrivateDnsConfig(true, "dns.com", TEST_ADDRS, null,
-                null, null, -1));
-        testPrivateDnsConfigConversion(new PrivateDnsConfig(true, "dns.com", TEST_ADDRS, "doh.com",
-                null, null, -1));
-        testPrivateDnsConfigConversion(new PrivateDnsConfig(true, "dns.com", TEST_ADDRS, "doh.com",
-                TEST_ADDRS, null, -1));
-        testPrivateDnsConfigConversion(new PrivateDnsConfig(true, "dns.com", TEST_ADDRS, "doh.com",
-                TEST_ADDRS, "dohpath=/some-path{?dns}", -1));
-        testPrivateDnsConfigConversion(new PrivateDnsConfig(true, "dns.com", TEST_ADDRS, "doh.com",
-                TEST_ADDRS, "dohpath=/some-path{?dns}", 443));
+        // PrivateDnsConfig(int mode, String hostname, InetAddress[] ips,
+        //                  String dohName, InetAddress[] dohIps, String dohPath, int dohPort)
+        for (int mode : new int[] { OFF_MODE, OPPORTUNISTIC_MODE, STRICT_MODE }) {
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, null, null,
+                    null, null, null, -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", null,
+                    null, null, null, -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS,
+                    null, null, null, -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS,
+                    "doh.com", null, null, -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS,
+                    "doh.com", TEST_ADDRS, null, -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS,
+                    "doh.com", TEST_ADDRS, "dohpath=/some-path{?dns}", -1));
+            testPrivateDnsConfigConversion(new PrivateDnsConfig(mode, "dns.com", TEST_ADDRS,
+                    "doh.com", TEST_ADDRS, "dohpath=/some-path{?dns}", 443));
+        }
     }
 
     @Test
     public void testIpAddressArrayIsCopied() {
         final InetAddress ip = InetAddress.parseNumericAddress("1.2.3.4");
         final InetAddress[] ipArray = new InetAddress[] { ip };
-        final PrivateDnsConfig cfg = new PrivateDnsConfig(true /* useTls */, null /* hostname */,
+        final PrivateDnsConfig cfg = new PrivateDnsConfig(OPPORTUNISTIC_MODE, null /* hostname */,
                 ipArray /* ips */, null /* dohName */, ipArray /* dohIps */, null /* dohPath */,
                 -1 /* dohPort */);
 
diff --git a/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java b/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java
index 380f4ec..ff56f5f 100644
--- a/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java
+++ b/tests/unit/src/com/android/networkstack/netlink/TcpInfoTest.java
@@ -242,4 +242,20 @@
 
         return info;
     }
+
+    @Test
+    public void testHashCode() {
+        final TcpInfo info = new TcpInfo(2, 1, 5);
+        final TcpInfo info2 = new TcpInfo(2, 1, 5);
+
+        assertEquals(info, info2);
+        assertEquals(info.hashCode(), info2.hashCode());
+    }
+
+    @Test
+    public void testDecodeWscale() {
+        assertEquals("0:0", TcpInfo.decodeWscale((byte) 0));
+        assertEquals("15:15", TcpInfo.decodeWscale((byte) 255));
+        assertEquals("15:0", TcpInfo.decodeWscale((byte) 240));
+    }
 }