Merge changes from topic "trafficctrl_coverage"

* changes:
  Extend unit test for dump function
  Add unit test for getFirewallType
  Add unit test for dump function
diff --git a/service/ServiceConnectivityResources/res/values-sq/strings.xml b/service/ServiceConnectivityResources/res/values-sq/strings.xml
index 385c75c..85bd84f 100644
--- a/service/ServiceConnectivityResources/res/values-sq/strings.xml
+++ b/service/ServiceConnectivityResources/res/values-sq/strings.xml
@@ -35,7 +35,7 @@
   <string-array name="network_switch_type_name">
     <item msgid="3004933964374161223">"të dhënat celulare"</item>
     <item msgid="5624324321165953608">"Wi-Fi"</item>
-    <item msgid="5667906231066981731">"Bluetooth"</item>
+    <item msgid="5667906231066981731">"Bluetooth-i"</item>
     <item msgid="346574747471703768">"Eternet"</item>
     <item msgid="5734728378097476003">"VPN"</item>
   </string-array>
diff --git a/service/native/libs/libclat/clatutils_test.cpp b/service/native/libs/libclat/clatutils_test.cpp
index 4153e19..8cca1f4 100644
--- a/service/native/libs/libclat/clatutils_test.cpp
+++ b/service/native/libs/libclat/clatutils_test.cpp
@@ -19,6 +19,7 @@
 #include <gtest/gtest.h>
 #include <linux/if_packet.h>
 #include <linux/if_tun.h>
+#include <netinet/in.h>
 #include "tun_interface.h"
 
 extern "C" {
@@ -182,6 +183,31 @@
     v6Iface.destroy();
 }
 
+// This is not a realistic test because we can't test generateIPv6Address here since it requires
+// manipulating routing, which we can't do without talking to the real netd on the system.
+// See test MakeChecksumNeutral.
+// TODO: remove this test once EthernetTetheringTest can test on mainline test coverage branch.
+TEST_F(ClatUtils, GenerateIpv6AddressFailWithUlaSocketAddress) {
+    // Create an interface for generateIpv6Address to connect to.
+    TunInterface tun;
+    ASSERT_EQ(0, tun.init());
+
+    // Unused because v6 address is ULA and makeChecksumNeutral has never called.
+    in_addr v4 = {inet_addr(kIPv4LocalAddr)};
+    // Not a NAT64 prefix because test can't connect to in generateIpv6Address.
+    // Used to be a fake address from the tun interface for generating an IPv6 socket address.
+    // nat64Prefix won't be used in MakeChecksumNeutral because MakeChecksumNeutral has never
+    // be called.
+    in6_addr nat64Prefix = tun.dstAddr();  // not realistic
+    in6_addr v6;
+    EXPECT_EQ(1, inet_pton(AF_INET6, "::", &v6));  // initialize as zero
+
+    EXPECT_EQ(-ENETUNREACH, generateIpv6Address(tun.name().c_str(), v4, nat64Prefix, &v6));
+    EXPECT_TRUE(IN6_IS_ADDR_ULA(&v6));
+
+    tun.destroy();
+}
+
 }  // namespace clat
 }  // namespace net
 }  // namespace android
diff --git a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
index bd1b74a..6dfadc7 100644
--- a/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
+++ b/tests/cts/tethering/src/android/tethering/cts/TetheringManagerTest.java
@@ -26,8 +26,13 @@
 import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
 import static android.net.TetheringManager.TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
+import static android.net.TetheringManager.TETHER_ERROR_PROVISIONING_FAILED;
 import static android.net.cts.util.CtsTetheringUtils.isAnyIfaceMatch;
 
+import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL;
+import static com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
+import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -68,14 +73,19 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.TestCarrierConfigReceiver;
+
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.CompletableFuture;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
@@ -84,6 +94,9 @@
 @RunWith(AndroidJUnit4.class)
 public class TetheringManagerTest {
 
+    @Rule
+    public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule();
+
     private Context mContext;
 
     private ConnectivityManager mCm;
@@ -392,7 +405,7 @@
         // Override carrier config to ignore entitlement check.
         final PersistableBundle bundle = new PersistableBundle();
         bundle.putBoolean(CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, false);
-        overrideCarrierConfig(bundle);
+        overrideCarrierConfig(bundle, CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
 
         // Verify that requestLatestTetheringEntitlementResult() can get entitlement
         // result TETHER_ERROR_NO_ERROR due to provisioning bypassed.
@@ -400,14 +413,112 @@
                 TETHERING_WIFI, false, c -> c.run(), listener), TETHER_ERROR_NO_ERROR);
 
         // Reset carrier config.
-        overrideCarrierConfig(null);
+        overrideCarrierConfig(null, "");
     }
 
-    private void overrideCarrierConfig(PersistableBundle bundle) {
-        final CarrierConfigManager configManager = (CarrierConfigManager) mContext
-                .getSystemService(Context.CARRIER_CONFIG_SERVICE);
-        final int subId = SubscriptionManager.getDefaultSubscriptionId();
-        configManager.overrideConfig(subId, bundle);
+    @Test
+    @IgnoreUpTo(SC_V2)
+    public void testEnableTethering_carrierUnsupported_noTetheringActive() throws Exception {
+        assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
+
+        final TestTetheringEventCallback tetherEventCallback =
+                mCtsTetheringUtils.registerTetheringEventCallback();
+        boolean previousWifiEnabledState = false;
+        try {
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
+            // Avoid device connected to Wifi network.
+            previousWifiEnabledState = ensureCurrentNetworkIsCellular();
+            final PersistableBundle bundle = new PersistableBundle();
+            bundle.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, false);
+            // Override carrier config to make carrier not support.
+            overrideCarrierConfig(bundle, KEY_CARRIER_SUPPORTS_TETHERING_BOOL);
+
+            mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+            mCtsTetheringUtils.expectSoftApDisabled();
+            tetherEventCallback.expectNoTetheringActive();
+        } finally {
+            overrideCarrierConfig(null, "");
+            mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
+            if (previousWifiEnabledState) {
+                mCtsNetUtils.connectToWifi();
+            }
+        }
+    }
+
+    @Test
+    @IgnoreUpTo(SC_V2)
+    public void testEnableTethering_carrierUnsupportByConfigChange_noTetheringActive()
+            throws Exception {
+        assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
+
+        final TestTetheringEventCallback tetherEventCallback =
+                mCtsTetheringUtils.registerTetheringEventCallback();
+        boolean previousWifiEnabledState = false;
+        try {
+            tetherEventCallback.assumeWifiTetheringSupported(mContext);
+            // Avoid device connected to Wifi network.
+            previousWifiEnabledState = ensureCurrentNetworkIsCellular();
+            mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
+
+            final PersistableBundle bundle = new PersistableBundle();
+            bundle.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, false);
+            // Override carrier config to make carrier not support.
+            overrideCarrierConfig(bundle, KEY_CARRIER_SUPPORTS_TETHERING_BOOL);
+
+            mCtsTetheringUtils.expectSoftApDisabled();
+            tetherEventCallback.expectNoTetheringActive();
+        } finally {
+            overrideCarrierConfig(null, "");
+            mCtsTetheringUtils.unregisterTetheringEventCallback(tetherEventCallback);
+            if (previousWifiEnabledState) {
+                mCtsNetUtils.connectToWifi();
+            }
+        }
+    }
+
+    @Test
+    @IgnoreUpTo(SC_V2)
+    public void testRequestLatestEntitlementResult_carrierUnsupported() throws Exception {
+        assumeTrue(mTM.isTetheringSupported());
+        assumeTrue(mPm.hasSystemFeature(FEATURE_TELEPHONY));
+
+        final PersistableBundle bundle = new PersistableBundle();
+        bundle.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, false);
+        try {
+            // Override carrier config to make carrier not support.
+            overrideCarrierConfig(bundle, KEY_CARRIER_SUPPORTS_TETHERING_BOOL);
+
+            // Verify that requestLatestTetheringEntitlementResult() can get entitlement
+            // result TETHER_ERROR_PROVISIONING_FAILED due to carrier unsupported
+            assertEntitlementResult(listener -> mTM.requestLatestTetheringEntitlementResult(
+                    TETHERING_WIFI,
+                    false,
+                    c -> c.run(),
+                    listener),
+                    TETHER_ERROR_PROVISIONING_FAILED);
+        } finally {
+            // Reset carrier config.
+            overrideCarrierConfig(null, "");
+        }
+    }
+
+    private void overrideCarrierConfig(PersistableBundle bundle, String configName)
+            throws Exception {
+        final int timeoutMs = 5_000;
+        final int currentSubId = SubscriptionManager.getDefaultSubscriptionId();
+        TestCarrierConfigReceiver configListener =
+                new TestCarrierConfigReceiver(mContext, currentSubId, timeoutMs, bundle,
+                        (configs) -> {
+                            if (bundle == null) {
+                                // This is to restore carrier config and means no need to do match.
+                                return true;
+                            }
+                            boolean requestConfigValue = bundle.getBoolean(configName);
+                            boolean receiveConfigValue = configs.getBoolean(configName);
+                            return Objects.equals(receiveConfigValue, requestConfigValue);
+                        });
+        configListener.overrideCarrierConfigForTest();
     }
 
     @Test
@@ -421,30 +532,8 @@
         try {
             tetherEventCallback.assumeWifiTetheringSupported(mContext);
             tetherEventCallback.expectNoTetheringActive();
-
-            previousWifiEnabledState = mWm.isWifiEnabled();
-            if (previousWifiEnabledState) {
-                mCtsNetUtils.ensureWifiDisconnected(null);
-            }
-
-            final TestNetworkCallback networkCallback = new TestNetworkCallback();
-            Network activeNetwork = null;
-            try {
-                mCm.registerDefaultNetworkCallback(networkCallback);
-                activeNetwork = networkCallback.waitForAvailable();
-            } finally {
-                mCm.unregisterNetworkCallback(networkCallback);
-            }
-
-            assertNotNull("No active network. Please ensure the device has working mobile data.",
-                    activeNetwork);
-            final NetworkCapabilities activeNetCap = mCm.getNetworkCapabilities(activeNetwork);
-
-            // If active nework is ETHERNET, tethering may not use cell network as upstream.
-            assumeFalse(activeNetCap.hasTransport(TRANSPORT_ETHERNET));
-
-            assertTrue(activeNetCap.hasTransport(TRANSPORT_CELLULAR));
-
+            // Avoid device connected to Wifi network.
+            previousWifiEnabledState = ensureCurrentNetworkIsCellular();
             mCtsTetheringUtils.startWifiTethering(tetherEventCallback);
 
             final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
@@ -464,4 +553,36 @@
             }
         }
     }
+
+    /**
+     * Make sure current network is cellular data.
+     * @return true Previous Wifi state is enabled, false is disabled.
+     */
+    private boolean ensureCurrentNetworkIsCellular() throws Exception {
+        final boolean previousWifiEnabledState = mWm.isWifiEnabled();
+        if (previousWifiEnabledState) {
+            mCtsNetUtils.ensureWifiDisconnected(null);
+        }
+
+        final TestNetworkCallback networkCallback = new TestNetworkCallback();
+        Network activeNetwork = null;
+        try {
+            mCm.registerDefaultNetworkCallback(networkCallback);
+            activeNetwork = networkCallback.waitForAvailable();
+        } finally {
+            mCm.unregisterNetworkCallback(networkCallback);
+        }
+
+        assertNotNull("No active network. Please ensure the device has working mobile data.",
+                activeNetwork);
+
+        final NetworkCapabilities activeNetCap = mCm.getNetworkCapabilities(activeNetwork);
+
+        // If active nework is ETHERNET, tethering may not use cell network as upstream.
+        assumeFalse(activeNetCap.hasTransport(TRANSPORT_ETHERNET));
+
+        assertTrue(activeNetCap.hasTransport(TRANSPORT_CELLULAR));
+
+        return previousWifiEnabledState;
+    }
 }