Merge "Import translations. DO NOT MERGE ANYWHERE"
diff --git a/Android.bp b/Android.bp
index 26e7165..4b3c22d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -314,6 +314,7 @@
         ":framework-telecomm-sources",
         ":framework-telephony-common-sources",
         ":framework-telephony-sources",
+        ":framework-vcn-util-sources",
         ":framework-wifi-annotations",
         ":framework-wifi-non-updatable-sources",
         ":PacProcessor-aidl-sources",
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index fb01283..95a2f2e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -31,6 +31,7 @@
 import android.net.ProxyInfo;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.Messenger;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
@@ -233,4 +234,10 @@
                 in PersistableBundle extras);
 
     void systemReady();
+
+    void registerNetworkActivityListener(in INetworkActivityListener l);
+
+    void unregisterNetworkActivityListener(in INetworkActivityListener l);
+
+    boolean isDefaultNetworkActive();
 }
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 0941e7d..486e2d7 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -20,12 +20,13 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.LinkPropertiesUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
 
+import com.android.net.module.util.LinkPropertiesUtils;
+
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
diff --git a/core/java/android/net/MacAddress.java b/core/java/android/net/MacAddress.java
index 178183d..c7116b4 100644
--- a/core/java/android/net/MacAddress.java
+++ b/core/java/android/net/MacAddress.java
@@ -20,13 +20,13 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.MacAddressUtils;
 import android.net.wifi.WifiInfo;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
 import com.android.internal.util.Preconditions;
+import com.android.net.module.util.MacAddressUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 6166a75..94f849f 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -21,11 +21,12 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.NetUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.net.module.util.NetUtils;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.net.Inet4Address;
diff --git a/core/java/android/net/vcn/VcnConfig.java b/core/java/android/net/vcn/VcnConfig.java
index 148acf1..d4a3fa7 100644
--- a/core/java/android/net/vcn/VcnConfig.java
+++ b/core/java/android/net/vcn/VcnConfig.java
@@ -15,30 +15,104 @@
  */
 package android.net.vcn;
 
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
 
 /**
  * This class represents a configuration for a Virtual Carrier Network.
  *
+ * <p>Each {@link VcnGatewayConnectionConfig} instance added represents a connection that will be
+ * brought up on demand based on active {@link NetworkRequest}(s).
+ *
+ * @see VcnManager for more information on the Virtual Carrier Network feature
  * @hide
  */
 public final class VcnConfig implements Parcelable {
     @NonNull private static final String TAG = VcnConfig.class.getSimpleName();
 
-    private VcnConfig() {
+    private static final String GATEWAY_CONNECTION_CONFIGS_KEY = "mGatewayConnectionConfigs";
+    @NonNull private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs;
+
+    private VcnConfig(@NonNull Set<VcnGatewayConnectionConfig> tunnelConfigs) {
+        mGatewayConnectionConfigs = Collections.unmodifiableSet(tunnelConfigs);
+
         validate();
     }
-    // TODO: Implement getters, validators, etc
 
     /**
-     * Validates this configuration.
+     * Deserializes a VcnConfig from a PersistableBundle.
      *
      * @hide
      */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnConfig(@NonNull PersistableBundle in) {
+        final PersistableBundle gatewayConnectionConfigsBundle =
+                in.getPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY);
+        mGatewayConnectionConfigs =
+                new ArraySet<>(
+                        PersistableBundleUtils.toList(
+                                gatewayConnectionConfigsBundle, VcnGatewayConnectionConfig::new));
+
+        validate();
+    }
+
     private void validate() {
-        // TODO: implement validation logic
+        Preconditions.checkCollectionNotEmpty(
+                mGatewayConnectionConfigs, "gatewayConnectionConfigs");
+    }
+
+    /** Retrieves the set of configured tunnels. */
+    @NonNull
+    public Set<VcnGatewayConnectionConfig> getGatewayConnectionConfigs() {
+        return Collections.unmodifiableSet(mGatewayConnectionConfigs);
+    }
+
+    /**
+     * Serializes this object to a PersistableBundle.
+     *
+     * @hide
+     */
+    @NonNull
+    public PersistableBundle toPersistableBundle() {
+        final PersistableBundle result = new PersistableBundle();
+
+        final PersistableBundle gatewayConnectionConfigsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mGatewayConnectionConfigs),
+                        VcnGatewayConnectionConfig::toPersistableBundle);
+        result.putPersistableBundle(GATEWAY_CONNECTION_CONFIGS_KEY, gatewayConnectionConfigsBundle);
+
+        return result;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mGatewayConnectionConfigs);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (!(other instanceof VcnConfig)) {
+            return false;
+        }
+
+        final VcnConfig rhs = (VcnConfig) other;
+        return mGatewayConnectionConfigs.equals(rhs.mGatewayConnectionConfigs);
     }
 
     // Parcelable methods
@@ -49,15 +123,16 @@
     }
 
     @Override
-    public void writeToParcel(Parcel out, int flags) {}
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeParcelable(toPersistableBundle(), flags);
+    }
 
     @NonNull
     public static final Parcelable.Creator<VcnConfig> CREATOR =
             new Parcelable.Creator<VcnConfig>() {
                 @NonNull
                 public VcnConfig createFromParcel(Parcel in) {
-                    // TODO: Ensure all methods are pulled from the parcels
-                    return new VcnConfig();
+                    return new VcnConfig((PersistableBundle) in.readParcelable(null));
                 }
 
                 @NonNull
@@ -68,7 +143,23 @@
 
     /** This class is used to incrementally build {@link VcnConfig} objects. */
     public static class Builder {
-        // TODO: Implement this builder
+        @NonNull
+        private final Set<VcnGatewayConnectionConfig> mGatewayConnectionConfigs = new ArraySet<>();
+
+        /**
+         * Adds a configuration for an individual gateway connection.
+         *
+         * @param gatewayConnectionConfig the configuration for an individual gateway connection
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        public Builder addGatewayConnectionConfig(
+                @NonNull VcnGatewayConnectionConfig gatewayConnectionConfig) {
+            Objects.requireNonNull(gatewayConnectionConfig, "gatewayConnectionConfig was null");
+
+            mGatewayConnectionConfigs.add(gatewayConnectionConfig);
+            return this;
+        }
 
         /**
          * Builds and validates the VcnConfig.
@@ -77,7 +168,7 @@
          */
         @NonNull
         public VcnConfig build() {
-            return new VcnConfig();
+            return new VcnConfig(mGatewayConnectionConfigs);
         }
     }
 }
diff --git a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
index 8160edc..039360a 100644
--- a/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
+++ b/core/java/android/net/vcn/VcnGatewayConnectionConfig.java
@@ -15,7 +15,27 @@
  */
 package android.net.vcn;
 
+import static android.net.NetworkCapabilities.NetCapability;
+
+import static com.android.internal.annotations.VisibleForTesting.Visibility;
+
+import android.annotation.IntRange;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
+import android.os.PersistableBundle;
+import android.util.ArraySet;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.Preconditions;
+import com.android.server.vcn.util.PersistableBundleUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 /**
  * This class represents a configuration for a connection to a Virtual Carrier Network gateway.
@@ -49,38 +69,399 @@
  *   <li>{@link android.net.NetworkCapabilities.NET_CAPABILITY_MCX}
  * </ul>
  *
+ * <p>The meteredness and roaming of the VCN {@link Network} will be determined by that of the
+ * underlying Network(s).
+ *
  * @hide
  */
 public final class VcnGatewayConnectionConfig {
-    private VcnGatewayConnectionConfig() {
+    // TODO: Use MIN_MTU_V6 once it is public, @hide
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int MIN_MTU_V6 = 1280;
+
+    private static final Set<Integer> ALLOWED_CAPABILITIES;
+
+    static {
+        Set<Integer> allowedCaps = new ArraySet<>();
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_SUPL);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_DUN);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_FOTA);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_CBS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_IA);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_RCS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_XCAP);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_EIMS);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_INTERNET);
+        allowedCaps.add(NetworkCapabilities.NET_CAPABILITY_MCX);
+
+        ALLOWED_CAPABILITIES = Collections.unmodifiableSet(allowedCaps);
+    }
+
+    private static final int DEFAULT_MAX_MTU = 1500;
+
+    /**
+     * The maximum number of retry intervals that may be specified.
+     *
+     * <p>Limited to ensure an upper bound on config sizes.
+     */
+    private static final int MAX_RETRY_INTERVAL_COUNT = 10;
+
+    /**
+     * The minimum allowable repeating retry interval
+     *
+     * <p>To ensure the device is not constantly being woken up, this retry interval MUST be greater
+     * than this value.
+     *
+     * @see {@link Builder#setRetryInterval()}
+     */
+    private static final long MINIMUM_REPEATING_RETRY_INTERVAL_MS = TimeUnit.MINUTES.toMillis(15);
+
+    private static final long[] DEFAULT_RETRY_INTERVALS_MS =
+            new long[] {
+                TimeUnit.SECONDS.toMillis(1),
+                TimeUnit.SECONDS.toMillis(2),
+                TimeUnit.SECONDS.toMillis(5),
+                TimeUnit.SECONDS.toMillis(30),
+                TimeUnit.MINUTES.toMillis(1),
+                TimeUnit.MINUTES.toMillis(5),
+                TimeUnit.MINUTES.toMillis(15)
+            };
+
+    private static final String EXPOSED_CAPABILITIES_KEY = "mExposedCapabilities";
+    @NonNull private final Set<Integer> mExposedCapabilities;
+
+    private static final String UNDERLYING_CAPABILITIES_KEY = "mUnderlyingCapabilities";
+    @NonNull private final Set<Integer> mUnderlyingCapabilities;
+
+    // TODO: Add Ike/ChildSessionParams as a subclass - maybe VcnIkeGatewayConnectionConfig
+
+    private static final String MAX_MTU_KEY = "mMaxMtu";
+    private final int mMaxMtu;
+
+    private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
+    @NonNull private final long[] mRetryIntervalsMs;
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnGatewayConnectionConfig(
+            @NonNull Set<Integer> exposedCapabilities,
+            @NonNull Set<Integer> underlyingCapabilities,
+            @NonNull long[] retryIntervalsMs,
+            @IntRange(from = MIN_MTU_V6) int maxMtu) {
+        mExposedCapabilities = exposedCapabilities;
+        mUnderlyingCapabilities = underlyingCapabilities;
+        mRetryIntervalsMs = retryIntervalsMs;
+        mMaxMtu = maxMtu;
+
         validate();
     }
 
-    // TODO: Implement getters, validators, etc
+    /** @hide */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public VcnGatewayConnectionConfig(@NonNull PersistableBundle in) {
+        final PersistableBundle exposedCapsBundle =
+                in.getPersistableBundle(EXPOSED_CAPABILITIES_KEY);
+        final PersistableBundle underlyingCapsBundle =
+                in.getPersistableBundle(UNDERLYING_CAPABILITIES_KEY);
+
+        mExposedCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+                exposedCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+        mUnderlyingCapabilities = new ArraySet<>(PersistableBundleUtils.toList(
+                underlyingCapsBundle, PersistableBundleUtils.INTEGER_DESERIALIZER));
+        mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
+        mMaxMtu = in.getInt(MAX_MTU_KEY);
+
+        validate();
+    }
+
+    private void validate() {
+        Preconditions.checkArgument(
+                mExposedCapabilities != null && !mExposedCapabilities.isEmpty(),
+                "exposedCapsBundle was null or empty");
+        for (Integer cap : getAllExposedCapabilities()) {
+            checkValidCapability(cap);
+        }
+
+        Preconditions.checkArgument(
+                mUnderlyingCapabilities != null && !mUnderlyingCapabilities.isEmpty(),
+                "underlyingCapabilities was null or empty");
+        for (Integer cap : getAllUnderlyingCapabilities()) {
+            checkValidCapability(cap);
+        }
+
+        Objects.requireNonNull(mRetryIntervalsMs, "retryIntervalsMs was null");
+        validateRetryInterval(mRetryIntervalsMs);
+
+        Preconditions.checkArgument(
+                mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+    }
+
+    private static void checkValidCapability(int capability) {
+        Preconditions.checkArgument(
+                ALLOWED_CAPABILITIES.contains(capability),
+                "NetworkCapability " + capability + "out of range");
+    }
+
+    private static void validateRetryInterval(@Nullable long[] retryIntervalsMs) {
+        Preconditions.checkArgument(
+                retryIntervalsMs != null
+                        && retryIntervalsMs.length > 0
+                        && retryIntervalsMs.length <= MAX_RETRY_INTERVAL_COUNT,
+                "retryIntervalsMs was null, empty or exceed max interval count");
+
+        final long repeatingInterval = retryIntervalsMs[retryIntervalsMs.length - 1];
+        if (repeatingInterval < MINIMUM_REPEATING_RETRY_INTERVAL_MS) {
+            throw new IllegalArgumentException(
+                    "Repeating retry interval was too short, must be a minimum of 15 minutes: "
+                            + repeatingInterval);
+        }
+    }
 
     /**
-     * Validates this configuration
+     * Returns all exposed capabilities.
      *
      * @hide
      */
-    private void validate() {
-        // TODO: implement validation logic
+    @NonNull
+    public Set<Integer> getAllExposedCapabilities() {
+        return Collections.unmodifiableSet(mExposedCapabilities);
     }
 
-    // Parcelable methods
+    /**
+     * Checks if this config is configured to support/expose a specific capability.
+     *
+     * @param capability the capability to check for
+     */
+    public boolean hasExposedCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
 
-    /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects */
+        return mExposedCapabilities.contains(capability);
+    }
+
+    /**
+     * Returns all capabilities required of underlying networks.
+     *
+     * @hide
+     */
+    @NonNull
+    public Set<Integer> getAllUnderlyingCapabilities() {
+        return Collections.unmodifiableSet(mUnderlyingCapabilities);
+    }
+
+    /**
+     * Checks if this config requires an underlying network to have the specified capability.
+     *
+     * @param capability the capability to check for
+     */
+    public boolean requiresUnderlyingCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
+
+        return mUnderlyingCapabilities.contains(capability);
+    }
+
+    /** Retrieves the configured retry intervals. */
+    @NonNull
+    public long[] getRetryIntervalsMs() {
+        return Arrays.copyOf(mRetryIntervalsMs, mRetryIntervalsMs.length);
+    }
+
+    /** Retrieves the maximum MTU allowed for this Gateway Connection. */
+    @IntRange(from = MIN_MTU_V6)
+    public int getMaxMtu() {
+        return mMaxMtu;
+    }
+
+    /**
+     * Converts this config to a PersistableBundle.
+     *
+     * @hide
+     */
+    @NonNull
+    @VisibleForTesting(visibility = Visibility.PROTECTED)
+    public PersistableBundle toPersistableBundle() {
+        final PersistableBundle result = new PersistableBundle();
+
+        final PersistableBundle exposedCapsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mExposedCapabilities),
+                        PersistableBundleUtils.INTEGER_SERIALIZER);
+        final PersistableBundle underlyingCapsBundle =
+                PersistableBundleUtils.fromList(
+                        new ArrayList<>(mUnderlyingCapabilities),
+                        PersistableBundleUtils.INTEGER_SERIALIZER);
+
+        result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
+        result.putPersistableBundle(UNDERLYING_CAPABILITIES_KEY, underlyingCapsBundle);
+        result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
+        result.putInt(MAX_MTU_KEY, mMaxMtu);
+
+        return result;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(
+                mExposedCapabilities,
+                mUnderlyingCapabilities,
+                Arrays.hashCode(mRetryIntervalsMs),
+                mMaxMtu);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object other) {
+        if (!(other instanceof VcnGatewayConnectionConfig)) {
+            return false;
+        }
+
+        final VcnGatewayConnectionConfig rhs = (VcnGatewayConnectionConfig) other;
+        return mExposedCapabilities.equals(rhs.mExposedCapabilities)
+                && mUnderlyingCapabilities.equals(rhs.mUnderlyingCapabilities)
+                && Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
+                && mMaxMtu == rhs.mMaxMtu;
+    }
+
+    /** This class is used to incrementally build {@link VcnGatewayConnectionConfig} objects. */
     public static class Builder {
-        // TODO: Implement this builder
+        @NonNull private final Set<Integer> mExposedCapabilities = new ArraySet();
+        @NonNull private final Set<Integer> mUnderlyingCapabilities = new ArraySet();
+        @NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
+        private int mMaxMtu = DEFAULT_MAX_MTU;
+
+        // TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
+        //       Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
+        //       when on Cell.
 
         /**
-         * Builds and validates the VcnGatewayConnectionConfig
+         * Add a capability that this VCN Gateway Connection will support.
+         *
+         * @param exposedCapability the app-facing capability to be exposed by this VCN Gateway
+         *     Connection (i.e., the capabilities that this VCN Gateway Connection will support).
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+         *     Connection
+         */
+        public Builder addExposedCapability(@NetCapability int exposedCapability) {
+            checkValidCapability(exposedCapability);
+
+            mExposedCapabilities.add(exposedCapability);
+            return this;
+        }
+
+        /**
+         * Remove a capability that this VCN Gateway Connection will support.
+         *
+         * @param exposedCapability the app-facing capability to not be exposed by this VCN Gateway
+         *     Connection (i.e., the capabilities that this VCN Gateway Connection will support)
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be exposed by a Gateway
+         *     Connection
+         */
+        public Builder removeExposedCapability(@NetCapability int exposedCapability) {
+            checkValidCapability(exposedCapability);
+
+            mExposedCapabilities.remove(exposedCapability);
+            return this;
+        }
+
+        /**
+         * Require a capability for Networks underlying this VCN Gateway Connection.
+         *
+         * @param underlyingCapability the capability that a network MUST have in order to be an
+         *     underlying network for this VCN Gateway Connection.
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+         *     networks
+         */
+        public Builder addRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+            checkValidCapability(underlyingCapability);
+
+            mUnderlyingCapabilities.add(underlyingCapability);
+            return this;
+        }
+
+        /**
+         * Remove a requirement of a capability for Networks underlying this VCN Gateway Connection.
+         *
+         * <p>Calling this method will allow Networks that do NOT have this capability to be
+         * selected as an underlying network for this VCN Gateway Connection. However, underlying
+         * networks MAY still have the removed capability.
+         *
+         * @param underlyingCapability the capability that a network DOES NOT need to have in order
+         *     to be an underlying network for this VCN Gateway Connection.
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnGatewayConnectionConfig for a list of capabilities may be required of underlying
+         *     networks
+         */
+        public Builder removeRequiredUnderlyingCapability(@NetCapability int underlyingCapability) {
+            checkValidCapability(underlyingCapability);
+
+            mUnderlyingCapabilities.remove(underlyingCapability);
+            return this;
+        }
+
+        /**
+         * Set the retry interval between VCN establishment attempts upon successive failures.
+         *
+         * <p>The last retry interval will be repeated until safe mode is entered, or a connection
+         * is successfully established, at which point the retry timers will be reset. For power
+         * reasons, the last (repeated) retry interval MUST be at least 15 minutes.
+         *
+         * <p>Retry intervals MAY be subject to system power saving modes. That is to say that if
+         * the system enters a power saving mode, the retry may not occur until the device leaves
+         * the specified power saving mode. Intervals are sequential, and intervals will NOT be
+         * skipped if system power saving results in delaying retries (even if it exceed multiple
+         * retry intervals).
+         *
+         * <p>Each Gateway Connection will retry according to the retry intervals configured, but if
+         * safe mode is enabled, all Gateway Connection(s) will be disabled.
+         *
+         * @param retryIntervalsMs an array of between 1 and 10 millisecond intervals after which
+         *     the VCN will attempt to retry a session initiation. The last (repeating) retry
+         *     interval must be at least 15 minutes. Defaults to: {@code [1s, 2s, 5s, 30s, 1m, 5m,
+         *     15m]}
+         * @return this {@link Builder} instance, for chaining
+         * @see VcnManager for additional discussion on fail-safe mode
+         */
+        @NonNull
+        public Builder setRetryInterval(@NonNull long[] retryIntervalsMs) {
+            validateRetryInterval(retryIntervalsMs);
+
+            mRetryIntervalsMs = retryIntervalsMs;
+            return this;
+        }
+
+        /**
+         * Sets the maximum MTU allowed for this VCN Gateway Connection.
+         *
+         * <p>This MTU is applied to the VCN Gateway Connection exposed Networks, and represents the
+         * MTU of the virtualized network.
+         *
+         * <p>The system may reduce the MTU below the maximum specified based on signals such as the
+         * MTU of the underlying networks (and adjusted for Gateway Connection overhead).
+         *
+         * @param maxMtu the maximum MTU allowed for this Gateway Connection. Must be greater than
+         *     the IPv6 minimum MTU of 1280. Defaults to 1500.
+         * @return this {@link Builder} instance, for chaining
+         */
+        @NonNull
+        public Builder setMaxMtu(@IntRange(from = MIN_MTU_V6) int maxMtu) {
+            Preconditions.checkArgument(
+                    maxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
+
+            mMaxMtu = maxMtu;
+            return this;
+        }
+
+        /**
+         * Builds and validates the VcnGatewayConnectionConfig.
          *
          * @return an immutable VcnGatewayConnectionConfig instance
          */
         @NonNull
         public VcnGatewayConnectionConfig build() {
-            return new VcnGatewayConnectionConfig();
+            return new VcnGatewayConnectionConfig(
+                    mExposedCapabilities, mUnderlyingCapabilities, mRetryIntervalsMs, mMaxMtu);
         }
     }
 }
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 6769b9e..46d1c1c 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -23,6 +23,9 @@
 import android.content.Context;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.ServiceSpecificException;
+
+import java.io.IOException;
 
 /**
  * VcnManager publishes APIs for applications to configure and manage Virtual Carrier Networks.
@@ -63,15 +66,20 @@
      * @param config the configuration parameters for the VCN
      * @throws SecurityException if the caller does not have carrier privileges, or is not running
      *     as the primary user
+     * @throws IOException if the configuration failed to be persisted. A caller encountering this
+     *     exception should attempt to retry (possibly after a delay).
      * @hide
      */
     @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
-    public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config) {
+    public void setVcnConfig(@NonNull ParcelUuid subscriptionGroup, @NonNull VcnConfig config)
+            throws IOException {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
         requireNonNull(config, "config was null");
 
         try {
             mService.setVcnConfig(subscriptionGroup, config);
+        } catch (ServiceSpecificException e) {
+            throw new IOException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -88,14 +96,18 @@
      * @param subscriptionGroup the subscription group that the configuration should be applied to
      * @throws SecurityException if the caller does not have carrier privileges, or is not running
      *     as the primary user
+     * @throws IOException if the configuration failed to be cleared. A caller encountering this
+     *     exception should attempt to retry (possibly after a delay).
      * @hide
      */
     @RequiresPermission("carrier privileges") // TODO (b/72967236): Define a system-wide constant
-    public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) {
+    public void clearVcnConfig(@NonNull ParcelUuid subscriptionGroup) throws IOException {
         requireNonNull(subscriptionGroup, "subscriptionGroup was null");
 
         try {
             mService.clearVcnConfig(subscriptionGroup);
+        } catch (ServiceSpecificException e) {
+            throw new IOException(e);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 57f2d6a..d41868e 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -20,12 +20,12 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="byteShort" msgid="202579285008794431">"B"</string>
+    <string name="byteShort" msgid="202579285008794431">"ባ"</string>
     <string name="kilobyteShort" msgid="2214285521564195803">"ኪባ"</string>
-    <string name="megabyteShort" msgid="6649361267635823443">"MB"</string>
-    <string name="gigabyteShort" msgid="7515809460261287991">"GB"</string>
-    <string name="terabyteShort" msgid="1822367128583886496">"TB"</string>
-    <string name="petabyteShort" msgid="5651571254228534832">"PB"</string>
+    <string name="megabyteShort" msgid="6649361267635823443">"ሜባ"</string>
+    <string name="gigabyteShort" msgid="7515809460261287991">"ጊባ"</string>
+    <string name="terabyteShort" msgid="1822367128583886496">"ቴባ"</string>
+    <string name="petabyteShort" msgid="5651571254228534832">"ፔባ"</string>
     <string name="fileSizeSuffix" msgid="4233671691980131257">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="untitled" msgid="3381766946944136678">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="emptyPhoneNumber" msgid="5812172618020360048">"(ምንም ስልክ ቁጥር የለም)"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 7b6dea3..13f1b56 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -823,7 +823,7 @@
     <string name="keyguard_password_enter_pin_password_code" msgid="7792964196473964340">"Introduce el código PIN para desbloquear."</string>
     <string name="keyguard_password_wrong_pin_code" msgid="8583732939138432793">"Código PIN incorrecto"</string>
     <string name="keyguard_label_text" msgid="3841953694564168384">"Para desbloquear el teléfono, pulsa la tecla de menú y, a continuación, pulsa 0."</string>
-    <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Llamada de emergencia"</string>
+    <string name="emergency_call_dialog_number_for_display" msgid="2978165477085612673">"Número de emergencia"</string>
     <string name="lockscreen_carrier_default" msgid="6192313772955399160">"Sin servicio"</string>
     <string name="lockscreen_screen_locked" msgid="7364905540516041817">"Pantalla bloqueada"</string>
     <string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pulsa la tecla de menú para desbloquear el teléfono o realizar una llamada de emergencia."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index fe283ab..03a1456 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1878,7 +1878,7 @@
     <string name="language_selection_title" msgid="52674936078683285">"افزودن زبان"</string>
     <string name="country_selection_title" msgid="5221495687299014379">"اولویت‌های منطقه"</string>
     <string name="search_language_hint" msgid="7004225294308793583">"نام زبان را تایپ کنید"</string>
-    <string name="language_picker_section_suggested" msgid="6556199184638990447">"پیشنهادشده"</string>
+    <string name="language_picker_section_suggested" msgid="6556199184638990447">"پیشنهادی"</string>
     <string name="language_picker_section_all" msgid="1985809075777564284">"همه زبان‌ها"</string>
     <string name="region_picker_section_all" msgid="756441309928774155">"همه منطقه‌ها"</string>
     <string name="locale_search_menu" msgid="6258090710176422934">"جستجو"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index e8d6408..29fe136 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -52,7 +52,6 @@
     <string name="enablePin" msgid="2543771964137091212">"Opération infructueuse. Activez le verrouillage SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée.</item>
-      <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM soit verrouillée.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"Code IIEM"</string>
@@ -180,7 +179,6 @@
     <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">Autorité de certification installée</item>
-      <item quantity="many">Certificate authorities installed</item>
       <item quantity="other">Autorités de certification installées</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -253,7 +251,6 @@
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bogue. Aucune capture d\'écran supplémentaire ne peut être capturée, et vous ne pouvez entrer aucune autre information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
       <item quantity="one">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde.</item>
-      <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">Saisie d\'écran pour le rapport de bogue dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran prise avec le rapport de bogue"</string>
@@ -997,7 +994,6 @@
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
       <item quantity="one">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Le dernier <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1020,82 +1016,66 @@
     <string name="now_string_shortest" msgid="3684914126941650330">"maintenant"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
       <item quantity="one">il y a<xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other">il y a<xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1466,7 +1446,6 @@
     <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
       <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"Terminé"</string>
@@ -1603,7 +1582,6 @@
     <string name="kg_wrong_pin" msgid="3680925703673166482">"NIP incorrect."</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
       <item quantity="one">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
-      <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1790,7 +1768,6 @@
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le NIP est trop court. Il doit comporter au moins 4 chiffres."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
-      <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Réessayez plus tard"</string>
@@ -1822,42 +1799,34 @@
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
       <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
       <item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
       <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
       <item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
       <item quantity="one">Pendant %d minute</item>
-      <item quantity="many">For %d minutes</item>
       <item quantity="other">Pendant %d minutes</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
       <item quantity="one">Pendant %d min</item>
-      <item quantity="many">For %d min</item>
       <item quantity="other">Pendant %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
       <item quantity="one">Pendant %d heure</item>
-      <item quantity="many">For %d hours</item>
       <item quantity="other">Pendant %d heures</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
       <item quantity="one">Pendant %d h</item>
-      <item quantity="many">For %d hr</item>
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="2250286190237669079">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1898,7 +1867,6 @@
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1966,7 +1934,6 @@
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de remplissage automatique"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de remplissage automatique</item>
-      <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de remplissage automatique</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
@@ -2060,7 +2027,6 @@
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement en cours…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
-      <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index fc91c47..a5b1626 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -52,7 +52,6 @@
     <string name="enablePin" msgid="2543771964137091212">"Échec de l\'opération. Veuillez activer le verrouillage de la carte SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
       <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée.</item>
-      <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"Code IMEI"</string>
@@ -180,7 +179,6 @@
     <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">Autorité de certification installée</item>
-      <item quantity="many">Certificate authorities installed</item>
       <item quantity="other">Autorités de certification installées</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string>
@@ -253,7 +251,6 @@
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bug. Aucune capture d\'écran supplémentaire ne peut être prise, et vous ne pouvez saisir aucune autre information."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
       <item quantity="one">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> seconde</item>
-      <item quantity="many">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">Capture d\'écran pour le rapport de bug dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran avec rapport de bug effectuée"</string>
@@ -997,7 +994,6 @@
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
       <item quantity="one">Le dernier jour (<xliff:g id="COUNT_1">%d</xliff:g>)</item>
-      <item quantity="many">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Les <xliff:g id="COUNT_1">%d</xliff:g> derniers jours</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string>
@@ -1020,82 +1016,66 @@
     <string name="now_string_shortest" msgid="3684914126941650330">"mainten."</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
       <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> j</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
       <item quantity="one">il y a <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other">il y a <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> minute</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> heure</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> heures</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> jour</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> jours</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
       <item quantity="one">dans <xliff:g id="COUNT_1">%d</xliff:g> an</item>
-      <item quantity="many">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">dans <xliff:g id="COUNT_1">%d</xliff:g> ans</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string>
@@ -1466,7 +1446,6 @@
     <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
       <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="many"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> sur <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"OK"</string>
@@ -1603,7 +1582,6 @@
     <string name="kg_wrong_pin" msgid="3680925703673166482">"Code PIN incorrect."</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
       <item quantity="one">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
-      <item quantity="many">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="8366024510502517748">"Dessinez votre schéma."</string>
@@ -1790,7 +1768,6 @@
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Le code PIN est trop court. Il doit comporter au moins 4 chiffres."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="one">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> seconde</item>
-      <item quantity="many">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Réessayer dans <xliff:g id="COUNT">%d</xliff:g> secondes</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Veuillez réessayer ultérieurement."</string>
@@ -1822,42 +1799,34 @@
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
       <item quantity="one">Pendant %1$d minute (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d minutes (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
       <item quantity="one">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d min (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
       <item quantity="one">Pendant %1$d heure (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d heures (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
       <item quantity="one">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="many">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Pendant %1$d h (jusqu\'à <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
       <item quantity="one">Pendant %d minute</item>
-      <item quantity="many">For %d minutes</item>
       <item quantity="other">Pendant %d minutes</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
       <item quantity="one">Pendant %d min</item>
-      <item quantity="many">For %d min</item>
       <item quantity="other">Pendant %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
       <item quantity="one">Pendant %d heure</item>
-      <item quantity="many">For %d hours</item>
       <item quantity="other">Pendant %d heures</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
       <item quantity="one">Pendant %d h</item>
-      <item quantity="many">For %d hr</item>
       <item quantity="other">Pendant %d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="2250286190237669079">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1898,7 +1867,6 @@
     <string name="notification_messaging_title_template" msgid="772857526770251989">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g> : <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
       <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sans catégorie"</string>
@@ -1966,7 +1934,6 @@
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de saisie automatique"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
       <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> suggestion de saisie automatique</item>
-      <item quantity="many"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggestions de saisie automatique</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string>
@@ -2060,7 +2027,6 @@
     <string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
       <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichier</item>
-      <item quantity="many"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> files</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> fichiers</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 95e1a48..054344e 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1441,7 +1441,7 @@
     <string name="car_mode_disable_notification_message" msgid="8954550232288567515">"Tocca per uscire dall\'app di guida."</string>
     <string name="back_button_label" msgid="4078224038025043387">"Indietro"</string>
     <string name="next_button_label" msgid="6040209156399907780">"Avanti"</string>
-    <string name="skip_button_label" msgid="3566599811326688389">"Ignora"</string>
+    <string name="skip_button_label" msgid="3566599811326688389">"Salta"</string>
     <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string>
     <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 6723e66..e2cf7f9 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1956,7 +1956,7 @@
     <string name="autofill_save_type_debit_card" msgid="3169397504133097468">"डेबिट कार्ड"</string>
     <string name="autofill_save_type_payment_card" msgid="6555012156728690856">"भुक्तानी कार्ड"</string>
     <string name="autofill_save_type_generic_card" msgid="1019367283921448608">"कार्ड"</string>
-    <string name="autofill_save_type_username" msgid="1018816929884640882">"प्रयोगकर्ताको नाम"</string>
+    <string name="autofill_save_type_username" msgid="1018816929884640882">"युजरनेम"</string>
     <string name="autofill_save_type_email_address" msgid="1303262336895591924">"इमेल ठेगाना"</string>
     <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"शान्त रहनुहोस् र नजिकै आश्रयस्थल खोज्नुहोस्।"</string>
     <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"तटीय क्षेत्र र नदीछेउका ठाउँहरू छाडी उच्च सतहमा अवस्थित कुनै अझ सुरक्षित ठाउँमा जानुहोस्।"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index bae44fd..594ea61 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -954,7 +954,7 @@
     <string name="permdesc_readHistoryBookmarks" msgid="2323799501008967852">"Hiermee kan de app de geschiedenis lezen van alle URL\'s die in de systeemeigen browser zijn bezocht, en alle bookmarks in de systeemeigen browser. Let op: deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
     <string name="permlab_writeHistoryBookmarks" msgid="6090259925187986937">"webbookmarks en -geschiedenis schrijven"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tablet" msgid="573341025292489065">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je tablet. Deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
-    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Hiermee kan de app de browsergeschiedenis of opgeslagen bookmarks bewerken op je Android TV-apparaat. Hierdoor kan de app mogelijk browsergegevens wissen of aanpassen. Opmerking: Dit recht kan niet worden afgedwongen door andere browsers of andere apps met internetmogelijkheden."</string>
+    <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="88642768580408561">"Hiermee kan de app de browsergeschiedenis of opgeslagen bookmarks bewerken op je Android TV-apparaat. Hierdoor kan de app mogelijk browsegegevens wissen of aanpassen. Opmerking: Dit recht kan niet worden afgedwongen door andere browsers of andere apps met internetmogelijkheden."</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="2245203087160913652">"Hiermee kan de app de webgeschiedenis wijzigen in de systeemeigen browser en de bookmarks die zijn opgeslagen op je telefoon. Deze rechten kunnen niet worden geforceerd door andere browsers of andere apps met internetmogelijkheden."</string>
     <string name="permlab_setAlarm" msgid="1158001610254173567">"een wekker instellen"</string>
     <string name="permdesc_setAlarm" msgid="2185033720060109640">"Hiermee kan de app een wekker instellen in een geïnstalleerde wekker-app. Deze functie wordt door sommige wekker-apps niet geïmplementeerd."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index df5cdac..624d554 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -162,7 +162,7 @@
     <string name="httpErrorAuth" msgid="469553140922938968">"Nepodarilo sa overiť totožnosť."</string>
     <string name="httpErrorProxyAuth" msgid="7229662162030113406">"Overenie pomocou servera proxy bolo neúspešné."</string>
     <string name="httpErrorConnect" msgid="3295081579893205617">"K serveru sa nepodarilo pripojiť."</string>
-    <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to znova neskôr."</string>
+    <string name="httpErrorIO" msgid="3860318696166314490">"Nepodarilo sa nadviazať komunikáciu so serverom. Skúste to neskôr."</string>
     <string name="httpErrorTimeout" msgid="7446272815190334204">"Časový limit pripojenia na server vypršal."</string>
     <string name="httpErrorRedirectLoop" msgid="8455757777509512098">"Stránka obsahuje príliš veľa presmerovaní servera."</string>
     <string name="httpErrorUnsupportedScheme" msgid="2664108769858966374">"Protokol nie je podporovaný."</string>
@@ -563,7 +563,7 @@
     <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string>
     <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string>
     <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string>
-    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+    <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string>
     <string name="fingerprint_error_lockout_permanent" msgid="3895478283943513746">"Príliš veľa pokusov. Senzor odtlačkov prstov bol deaktivovaný."</string>
     <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string>
     <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string>
@@ -607,7 +607,7 @@
     <string name="face_error_no_space" msgid="5649264057026021723">"Nové údaje o tvári sa nedajú uložiť. Najprv odstráňte jeden zo starých záznamov."</string>
     <string name="face_error_canceled" msgid="2164434737103802131">"Operácia týkajúca sa tváre bola zrušená"</string>
     <string name="face_error_user_canceled" msgid="8553045452825849843">"Odomknutie tvárou zrušil používateľ."</string>
-    <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to znova neskôr."</string>
+    <string name="face_error_lockout" msgid="7864408714994529437">"Príliš veľa pokusov. Skúste to neskôr."</string>
     <string name="face_error_lockout_permanent" msgid="8277853602168960343">"Príliš veľa pokusov. Odomknutie tvárou bolo zakázané."</string>
     <string name="face_error_unable_to_process" msgid="5723292697366130070">"Nedá sa overiť tvár. Skúste to znova."</string>
     <string name="face_error_not_enrolled" msgid="7369928733504691611">"Nenastavili ste odomknutie tvárou."</string>
@@ -1816,7 +1816,7 @@
       <item quantity="other">Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> sekúnd</item>
       <item quantity="one">Skúste to znova o 1 sekundu</item>
     </plurals>
-    <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to znova neskôr"</string>
+    <string name="restr_pin_try_later" msgid="5897719962541636727">"Skúste to neskôr"</string>
     <string name="immersive_cling_title" msgid="2307034298721541791">"Zobrazenie na celú obrazovku"</string>
     <string name="immersive_cling_description" msgid="7092737175345204832">"Ukončíte potiahnutím zhora nadol."</string>
     <string name="immersive_cling_positive" msgid="7047498036346489883">"Dobre"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index e8449c3..2b83c82 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1765,7 +1765,7 @@
     <string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Yangi PIN kodni tasdiqlash"</string>
     <string name="restr_pin_create_pin" msgid="917067613896366033">"Cheklovlarni o‘zgartirish uchun PIN-kod yaratish"</string>
     <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"PIN-kod mos kelmadi. Qayta urinib ko‘ring."</string>
-    <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod kamida 4 ta raqamdan iborat bo‘lishi shart."</string>
+    <string name="restr_pin_error_too_short" msgid="1547007808237941065">"PIN kod juda qisqa, kamida 4 ta raqam kiriting."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
       <item quantity="other"><xliff:g id="COUNT">%d</xliff:g> soniyadan so‘ng qayta urinib ko‘ring</item>
       <item quantity="one">1 soniyadan so‘ng qayta urinib ko‘ring</item>
diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
index 082c148..3b7775a 100644
--- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml
+++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml
@@ -57,7 +57,6 @@
     <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
       <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvées</item>
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -78,7 +77,6 @@
     <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
       <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
-      <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
       <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
     </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> en cours…"</string>
diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml
index 560c5dc..f6e901d 100644
--- a/packages/PrintSpooler/res/values-fr/strings.xml
+++ b/packages/PrintSpooler/res/values-fr/strings.xml
@@ -57,7 +57,6 @@
     <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string>
     <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868">
       <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes trouvées</item>
     </plurals>
     <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string>
@@ -78,7 +77,6 @@
     <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string>
     <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138">
       <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item>
-      <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item>
       <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item>
     </plurals>
     <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 671461b..e4ba93a 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Greška u konfiguraciji IP-a"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Niste povezani zbog slabog kvaliteta mreže"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Greška pri povezivanju na WiFi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji."</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problem pri autentifikaciji"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Nije se moguće povezati"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Nije se moguće povezati na aplikaciju \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Provjerite lozinku i pokušajte ponovo"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 121da7b..19ba5d0 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -34,7 +34,7 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"گذرواژه را بررسی و دوباره امتحان کنید"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"در محدوده نیست"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"اتصال به‌صورت خودکار انجام نمی‌شود"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"بدون دسترسی به اینترنت"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"دسترسی به اینترنت ندارد"</string>
     <string name="saved_network" msgid="7143698034077223645">"ذخیره‌شده توسط <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"‏اتصال خودکار ازطریق %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"اتصال خودکار ازطریق ارائه‌دهنده رتبه‌بندی شبکه"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6bb1a3a..bdbfbc6 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -488,7 +488,6 @@
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Les adresses MAC sont randomisées"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="one">%1$d appareil connecté</item>
-      <item quantity="many">%1$d devices connected</item>
       <item quantity="other">%1$d appareils connectés</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 8690dd8..4509b09 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Échec de configuration de l\'adresse IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Non connecté en raison de la faible qualité du réseau"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Échec de la connexion Wi-Fi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification."</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problème d\'authentification"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Connexion impossible"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Impossible de se connecter au réseau \"<xliff:g id="AP_NAME">%1$s</xliff:g>\""</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Vérifiez le mot de passe et réessayez"</string>
@@ -251,7 +251,7 @@
     <string name="wifi_display_certification" msgid="1805579519992520381">"Certification affichage sans fil"</string>
     <string name="wifi_verbose_logging" msgid="1785910450009679371">"Autoriser l\'enregistrement d\'infos Wi-Fi détaillées"</string>
     <string name="wifi_scan_throttling" msgid="2985624788509913617">"Limiter la recherche Wi‑Fi"</string>
-    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Chgt aléatoire d\'adresse MAC en Wi-Fi"</string>
+    <string name="wifi_enhanced_mac_randomization" msgid="5437378364995776979">"Changement aléatoire d\'adresse MAC en Wi-Fi"</string>
     <string name="mobile_data_always_on" msgid="8275958101875563572">"Données mobiles toujours actives"</string>
     <string name="tethering_hardware_offload" msgid="4116053719006939161">"Accélération matérielle pour le partage de connexion"</string>
     <string name="bluetooth_show_devices_without_names" msgid="923584526471885819">"Afficher les appareils Bluetooth sans nom"</string>
@@ -488,7 +488,6 @@
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"La sélection des adresses MAC est aléatoire"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
       <item quantity="one">%1$d appareil connecté</item>
-      <item quantity="many">%1$d devices connected</item>
       <item quantity="other">%1$d appareils connectés</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Plus longtemps."</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index 6e734bc..4ba2961 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP कॉन्‍फ़िगरेशन की विफलता"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"खराब नेटवर्क होने के कारण कनेक्ट नहीं हुआ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"वाईफ़ाई कनेक्‍शन विफलता"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"प्रमाणीकरण समस्या"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"पुष्टि नहीं हो सकी"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"कनेक्ट नहीं हो पा रहा है"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' से कनेक्ट नहीं हो पा रहा है"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"पासवर्ड जाँचें और दोबारा कोशिश करें"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index ec2429b..3e06a3a 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -207,7 +207,7 @@
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB tersambung"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Cabut otorisasi debug USB"</string>
     <string name="enable_adb_wireless" msgid="6973226350963971018">"Proses debug nirkabel"</string>
-    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode debug saat Wi-Fi tersambung"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode debug saat Wi-Fi terhubung"</string>
     <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
     <string name="adb_wireless_settings" msgid="2295017847215680229">"Proses debug nirkabel"</string>
     <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Untuk melihat dan menggunakan perangkat yang tersedia, aktifkan proses debug nirkabel"</string>
@@ -225,13 +225,13 @@
     <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sambungkan dengan perangkat"</string>
     <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kode penyambungan Wi-Fi"</string>
     <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Penyambungan perangkat gagal"</string>
-    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan perangkat tersambung ke jaringan yang sama."</string>
-    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Menyambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan perangkat terhubung ke jaringan yang sama."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
     <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Menyambungkan perangkat…"</string>
     <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak tersambung ke jaringan yang sama."</string>
     <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP &amp; Port"</string>
     <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Memindai kode QR"</string>
-    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Menyambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"Sambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Harap sambungkan ke jaringan Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan bug"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index 3729a83..d62d944 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP ပြုပြင်ခြင်း မအောင်မြင်ပါ"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ကွန်ရက်ချိတ်ဆက်မှု အားနည်းသည့်အတွက် ချိတ်ဆက်ထားခြင်း မရှိပါ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"WiFi ချိတ်ဆက်မှု မအောင်မြင်ပါ"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"စစ်မှန်ကြောင်းအတည်ပြုရန်၌ ပြသနာရှိခြင်း"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"အထောက်အထားစိစစ်မှု ပြဿနာ"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"ချိတ်ဆက်၍ မရပါ"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' နှင့် ချိတ်ဆက်၍ မရပါ"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"စကားဝှက်ကို စစ်ဆေးပြီး ထပ်လုပ်ကြည့်ပါ"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0e0e761..d567ee2 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -34,7 +34,7 @@
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Sjekk passordet og prøv igjen"</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Utenfor område"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Kobler ikke til automatisk"</string>
-    <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen Internett-tilgang"</string>
+    <string name="wifi_no_internet" msgid="1774198889176926299">"Ingen internettilgang"</string>
     <string name="saved_network" msgid="7143698034077223645">"Lagret av <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="connected_via_network_scorer" msgid="7665725527352893558">"Automatisk tilkoblet via %1$s"</string>
     <string name="connected_via_network_scorer_default" msgid="7973529709744526285">"Automatisk tilkoblet via leverandør av nettverksvurdering"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index d200f50..c9bbe71 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP କନଫିଗରେଶନ ବିଫଳ ହୋଇଛି"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"ନିମ୍ନ ମାନର ନେଟ୍‌ୱର୍କ କାରଣରୁ ସଂଯୁକ୍ତ ହୋଇନାହିଁ"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"ୱାଇଫାଇ ସଂଯୋଗ ବିଫଳ ହୋଇଛି"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ସତ୍ୟାପନରେ ସମସ୍ୟା"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"ପ୍ରମାଣୀକରଣରେ ସମସ୍ୟା"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"ସଂଯୋଗ କରିପାରିବ ନାହିଁ"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\'<xliff:g id="AP_NAME">%1$s</xliff:g>\' ସହିତ ସଂଯୁକ୍ତ ହୋଇପାରୁନାହିଁ"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"ପାସ୍‌ୱର୍ଡ ଯାଞ୍ଚ କରନ୍ତୁ ଏବଂ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index cc1626c..737c000 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Zlyhanie konfigurácie adresy IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Nepripojené z dôvodu siete nízkej kvality"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Zlyhanie pripojenia Wi‑Fi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením totožnosti"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problém s overením"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Nedá sa pripojiť"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"K sieti <xliff:g id="AP_NAME">%1$s</xliff:g> sa nedá pripojiť"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Skontrolujte heslo a skúste to znova"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 5d4e975..1a2d5e2 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"Pagkabigo ng Configuration ng IP"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Hindi nakakonekta dahil mababa ang kalidad ng network"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Pagkabigo ng Koneksyon sa WiFi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pagpapatotoo"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Problema sa pag-authenticate"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Hindi makakonekta"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"Hindi makakonekta sa \'<xliff:g id="AP_NAME">%1$s</xliff:g>\'"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Suriin ang password at subukang muli"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 2ae55fe..2325efd 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -28,7 +28,7 @@
     <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"IP manzilini sozlab bo‘lmadi"</string>
     <string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"Sifatsiz tarmoq sababli ulanib bo‘lmadi"</string>
     <string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"Wi-Fi ulanishini o‘rnatib bo‘lmadi"</string>
-    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tasdiqdan o‘tishda muammo"</string>
+    <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Tekshiruvda muammo"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Tarmoqqa ulanilmadi"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"“<xliff:g id="AP_NAME">%1$s</xliff:g>” nomli tarmoqqa ulanilmadi"</string>
     <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Parolni tekshirib, qaytadan urining"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 9e9eb85..6baa848 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -325,7 +325,6 @@
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
     </plurals>
     <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g> : <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
@@ -401,7 +400,6 @@
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="one">%d appareil</item>
-      <item quantity="many">%d devices</item>
       <item quantity="other">%d appareils</item>
     </plurals>
     <string name="quick_settings_notifications_label" msgid="3379631363952582758">"Notifications"</string>
@@ -494,7 +492,6 @@
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite d\'utilisateurs atteinte"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
       <item quantity="one">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateur.</item>
-      <item quantity="many">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
       <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> utilisateurs.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur?"</string>
@@ -761,12 +758,10 @@
     <string name="snoozed_for_time" msgid="7586689374860469469">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
       <item quantity="one">%d heure</item>
-      <item quantity="many">%d hours</item>
       <item quantity="other">%d heures</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
       <item quantity="one">%d minute</item>
-      <item quantity="many">%d minutes</item>
       <item quantity="other">%d minutes</item>
     </plurals>
     <string name="battery_panel_title" msgid="5931157246673665963">"Utilisation de la pile"</string>
@@ -1045,7 +1040,6 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'application pour laquelle ajouter des commandes"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> commande ajoutée.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5d1b3a1..ad258b2 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -325,7 +325,6 @@
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> autres"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> autre notification à l\'intérieur.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> autres notifications à l\'intérieur.</item>
     </plurals>
     <string name="notification_summary_message_format" msgid="5158219088501909966">"<xliff:g id="CONTACT_NAME">%1$s</xliff:g> : <xliff:g id="MESSAGE_CONTENT">%2$s</xliff:g>"</string>
@@ -401,7 +400,6 @@
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
       <item quantity="one">%d appareil</item>
-      <item quantity="many">%d devices</item>
       <item quantity="other">%d appareils</item>
     </plurals>
     <string name="quick_settings_notifications_label" msgid="3379631363952582758">"Notifications"</string>
@@ -494,7 +492,6 @@
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite nombre utilisateurs atteinte"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
       <item quantity="one">Vous pouvez ajouter <xliff:g id="COUNT">%d</xliff:g> profil utilisateur.</item>
-      <item quantity="many">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
       <item quantity="other">Vous pouvez ajouter jusqu\'à <xliff:g id="COUNT">%d</xliff:g> profils utilisateur.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur ?"</string>
@@ -761,12 +758,10 @@
     <string name="snoozed_for_time" msgid="7586689374860469469">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
       <item quantity="one">%d heure</item>
-      <item quantity="many">%d hours</item>
       <item quantity="other">%d heures</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
       <item quantity="one">%d minute</item>
-      <item quantity="many">%d minutes</item>
       <item quantity="other">%d minutes</item>
     </plurals>
     <string name="battery_panel_title" msgid="5931157246673665963">"Utilisation batterie"</string>
@@ -1045,7 +1040,6 @@
     <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'appli pour laquelle ajouter des commandes"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
       <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> commande ajoutée.</item>
-      <item quantity="many"><xliff:g id="NUMBER_1">%s</xliff:g> controls added.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> commandes ajoutées.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index cc8b5fe..f6b71e4 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -776,7 +776,7 @@
     <string name="keyboard_key_dpad_left" msgid="8329738048908755640">"Зүүн"</string>
     <string name="keyboard_key_dpad_right" msgid="6282105433822321767">"Баруун"</string>
     <string name="keyboard_key_dpad_center" msgid="4079412840715672825">"Гол хэсэг"</string>
-    <string name="keyboard_key_tab" msgid="4592772350906496730">"Чихтэй хуудас"</string>
+    <string name="keyboard_key_tab" msgid="4592772350906496730">"Таб"</string>
     <string name="keyboard_key_space" msgid="6980847564173394012">"Зай"</string>
     <string name="keyboard_key_enter" msgid="8633362970109751646">"Оруулах"</string>
     <string name="keyboard_key_backspace" msgid="4095278312039628074">"Арилгах"</string>
@@ -826,7 +826,7 @@
     <string name="switch_bar_on" msgid="1770868129120096114">"Идэвхтэй"</string>
     <string name="switch_bar_off" msgid="5669805115416379556">"Идэвхгүй"</string>
     <string name="tile_unavailable" msgid="3095879009136616920">"Боломжгүй"</string>
-    <string name="nav_bar" msgid="4642708685386136807">"Навигацийн самбар"</string>
+    <string name="nav_bar" msgid="4642708685386136807">"Навигацын самбар"</string>
     <string name="nav_bar_layout" msgid="4716392484772899544">"Бүдүүвч"</string>
     <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Нэмэлт зүүн товчлуураар шивэх"</string>
     <string name="right_nav_bar_button_type" msgid="4472566498647364715">"Нэмэлт баруун товчлуураар шивэх"</string>
@@ -848,7 +848,7 @@
     <string name="reset" msgid="8715144064608810383">"Шинэчлэх"</string>
     <string name="adjust_button_width" msgid="8313444823666482197">"Товчлуурын өргөнг тохируулах"</string>
     <string name="clipboard" msgid="8517342737534284617">"Түр санах ой"</string>
-    <string name="accessibility_key" msgid="3471162841552818281">"Навигацийн товчлуурыг өөрчлөх"</string>
+    <string name="accessibility_key" msgid="3471162841552818281">"Навигацын товчлуурыг өөрчлөх"</string>
     <string name="left_keycode" msgid="8211040899126637342">"Зүүн түлхүүрийн код"</string>
     <string name="right_keycode" msgid="2480715509844798438">"Баруун түлхүүрийн код"</string>
     <string name="left_icon" msgid="5036278531966897006">"Зүүн дүрс тэмдэг"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 9c69703..555b1c0 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -563,9 +563,9 @@
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"Abrir as definições de VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"Abrir credenciais fidedignas"</string>
-    <string name="monitoring_description_network_logging" msgid="577305979174002252">"O seu gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o gestor."</string>
+    <string name="monitoring_description_network_logging" msgid="577305979174002252">"O seu gestor ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara mais informações, contacte o gestor."</string>
     <string name="monitoring_description_vpn" msgid="1685428000684586870">"Concedeu autorização a uma app para configurar uma ligação VPN.\n\nEsta app pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Sites."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu gestor tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara obter mais informações, contacte o gestor.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu gestor tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara mais informações, contacte o gestor.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
     <string name="monitoring_description_app" msgid="376868879287922929">"Está associado à app <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_app_personal" msgid="1970094872688265987">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string>
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 184f1bf..2e1fbb7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -136,8 +136,6 @@
 import android.net.metrics.NetworkEvent;
 import android.net.netlink.InetDiagMessage;
 import android.net.shared.PrivateDnsConfig;
-import android.net.util.LinkPropertiesUtils.CompareOrUpdateResult;
-import android.net.util.LinkPropertiesUtils.CompareResult;
 import android.net.util.MultinetworkPolicyTracker;
 import android.net.util.NetdService;
 import android.os.Binder;
@@ -146,6 +144,7 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
+import android.os.INetworkActivityListener;
 import android.os.INetworkManagementService;
 import android.os.Looper;
 import android.os.Message;
@@ -191,6 +190,8 @@
 import com.android.internal.util.MessageUtils;
 import com.android.internal.util.XmlUtils;
 import com.android.modules.utils.BasicShellCommandHandler;
+import com.android.net.module.util.LinkPropertiesUtils.CompareOrUpdateResult;
+import com.android.net.module.util.LinkPropertiesUtils.CompareResult;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.AutodestructReference;
 import com.android.server.connectivity.DataConnectionStats;
@@ -1380,8 +1381,11 @@
             return;
         }
         final String action = blocked ? "BLOCKED" : "UNBLOCKED";
+        final NetworkRequest satisfiedRequest = nri.getSatisfiedRequest();
+        final int requestId =  satisfiedRequest != null
+                ? satisfiedRequest.requestId : nri.mRequests.get(0).requestId;
         mNetworkInfoBlockingLogs.log(String.format(
-                "%s %d(%d) on netId %d", action, nri.mUid, nri.request.requestId, net.getNetId()));
+                "%s %d(%d) on netId %d", action, nri.mUid, requestId, net.getNetId()));
     }
 
     /**
@@ -1709,16 +1713,17 @@
             return newNc;
         }
 
-        Binder.withCleanCallingIdentity(
-                () -> {
-                    if (!mLocationPermissionChecker.checkLocationPermission(
-                            callerPkgName, null /* featureId */, callerUid, null /* message */)) {
-                        // Caller does not have the requisite location permissions. Reset the
-                        // owner's UID in the NetworkCapabilities.
-                        newNc.setOwnerUid(INVALID_UID);
-                    }
-                }
-        );
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (!mLocationPermissionChecker.checkLocationPermission(
+                    callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+                // Caller does not have the requisite location permissions. Reset the
+                // owner's UID in the NetworkCapabilities.
+                newNc.setOwnerUid(INVALID_UID);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         return newNc;
     }
@@ -2336,6 +2341,31 @@
     }
 
     /**
+     * Start listening for default data network activity state changes.
+     */
+    @Override
+    public void registerNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Stop listening for default data network activity state changes.
+     */
+    @Override
+    public void unregisterNetworkActivityListener(@NonNull INetworkActivityListener l) {
+        // TODO: Replace network activity listener registry in ConnectivityManager from NMS to here
+    }
+
+    /**
+     * Check whether the default network radio is currently active.
+     */
+    @Override
+    public boolean isDefaultNetworkActive() {
+        // TODO: Replace isNetworkActive() in NMS.
+        return false;
+    }
+
+    /**
      * Setup data activity tracking for the given network.
      *
      * Every {@code setupDataActivityTracking} should be paired with a
@@ -2705,7 +2735,7 @@
      * Return an array of all current NetworkRequest sorted by request id.
      */
     @VisibleForTesting
-    protected NetworkRequestInfo[] requestsSortedById() {
+    NetworkRequestInfo[] requestsSortedById() {
         NetworkRequestInfo[] requests = new NetworkRequestInfo[0];
         requests = mNetworkRequests.values().toArray(requests);
         // Sort the array based off the NRI containing the min requestId in its requests.
@@ -3555,30 +3585,58 @@
             return false;
         }
         for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-            if (reason == UnneededFor.LINGER && nri.request.isBackgroundRequest()) {
+            if (reason == UnneededFor.LINGER
+                    && !nri.isMultilayerRequest()
+                    && nri.mRequests.get(0).isBackgroundRequest()) {
                 // Background requests don't affect lingering.
                 continue;
             }
 
-            // If this Network is already the highest scoring Network for a request, or if
-            // there is hope for it to become one if it validated, then it is needed.
-            if (nri.request.isRequest() && nai.satisfies(nri.request) &&
-                    (nai.isSatisfyingRequest(nri.request.requestId) ||
-                    // Note that this catches two important cases:
-                    // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
-                    //    is currently satisfying the request.  This is desirable when
-                    //    cellular ends up validating but WiFi does not.
-                    // 2. Unvalidated WiFi will not be reaped when validated cellular
-                    //    is currently satisfying the request.  This is desirable when
-                    //    WiFi ends up validating and out scoring cellular.
-                    nri.mSatisfier.getCurrentScore()
-                            < nai.getCurrentScoreAsValidated())) {
+            if (isNetworkPotentialSatisfier(nai, nri)) {
                 return false;
             }
         }
         return true;
     }
 
+    private boolean isNetworkPotentialSatisfier(
+            @NonNull final NetworkAgentInfo candidate, @NonNull final NetworkRequestInfo nri) {
+        // listen requests won't keep up a network satisfying it. If this is not a multilayer
+        // request, we can return immediately. For multilayer requests, we have to check to see if
+        // any of the multilayer requests may have a potential satisfier.
+        if (!nri.isMultilayerRequest() && nri.mRequests.get(0).isListen()) {
+            return false;
+        }
+        for (final NetworkRequest req : nri.mRequests) {
+            // As non-multilayer listen requests have already returned, the below would only happen
+            // for a multilayer request therefore continue to the next request if available.
+            if (req.isListen()) {
+                continue;
+            }
+            // If this Network is already the highest scoring Network for a request, or if
+            // there is hope for it to become one if it validated, then it is needed.
+            if (candidate.satisfies(req)) {
+                // As soon as a network is found that satisfies a request, return. Specifically for
+                // multilayer requests, returning as soon as a NetworkAgentInfo satisfies a request
+                // is important so as to not evaluate lower priority requests further in
+                // nri.mRequests.
+                final boolean isNetworkNeeded = candidate.isSatisfyingRequest(req.requestId)
+                        // Note that this catches two important cases:
+                        // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
+                        //    is currently satisfying the request.  This is desirable when
+                        //    cellular ends up validating but WiFi does not.
+                        // 2. Unvalidated WiFi will not be reaped when validated cellular
+                        //    is currently satisfying the request.  This is desirable when
+                        //    WiFi ends up validating and out scoring cellular.
+                        || nri.mSatisfier.getCurrentScore()
+                        < candidate.getCurrentScoreAsValidated();
+                return isNetworkNeeded;
+            }
+        }
+
+        return false;
+    }
+
     private NetworkRequestInfo getNriForAppRequest(
             NetworkRequest request, int callingUid, String requestedOperation) {
         final NetworkRequestInfo nri = mNetworkRequests.get(request);
@@ -3875,8 +3933,12 @@
                 new CaptivePortal(new CaptivePortalImpl(network).asBinder()));
         appIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK);
 
-        Binder.withCleanCallingIdentity(() ->
-                mContext.startActivityAsUser(appIntent, UserHandle.CURRENT));
+        final long token = Binder.clearCallingIdentity();
+        try {
+            mContext.startActivityAsUser(appIntent, UserHandle.CURRENT);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private class CaptivePortalImpl extends ICaptivePortal.Stub {
@@ -5464,6 +5526,10 @@
             this(r, null);
         }
 
+        boolean isMultilayerRequest() {
+            return mRequests.size() > 1;
+        }
+
         private List<NetworkRequest> initializeRequests(NetworkRequest r) {
             final ArrayList<NetworkRequest> tempRequests = new ArrayList<>();
             tempRequests.add(new NetworkRequest(r));
@@ -5505,7 +5571,7 @@
         public void binderDied() {
             log("ConnectivityService NetworkRequestInfo binderDied(" +
                     mRequests + ", " + mBinder + ")");
-            releaseNetworkRequest(mRequests);
+            releaseNetworkRequests(mRequests);
         }
 
         @Override
@@ -5538,13 +5604,15 @@
         mAppOpsManager.checkPackage(callerUid, callerPackageName);
     }
 
-    private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
+    private ArrayList<Integer> getSignalStrengthThresholds(@NonNull final NetworkAgentInfo nai) {
         final SortedSet<Integer> thresholds = new TreeSet<>();
         synchronized (nai) {
-            for (NetworkRequestInfo nri : mNetworkRequests.values()) {
-                if (nri.request.networkCapabilities.hasSignalStrength() &&
-                        nai.satisfiesImmutableCapabilitiesOf(nri.request)) {
-                    thresholds.add(nri.request.networkCapabilities.getSignalStrength());
+            for (final NetworkRequestInfo nri : mNetworkRequests.values()) {
+                for (final NetworkRequest req : nri.mRequests) {
+                    if (req.networkCapabilities.hasSignalStrength()
+                            && nai.satisfiesImmutableCapabilitiesOf(req)) {
+                        thresholds.add(req.networkCapabilities.getSignalStrength());
+                    }
                 }
             }
         }
@@ -5831,7 +5899,7 @@
         return mNextNetworkProviderId.getAndIncrement();
     }
 
-    private void releaseNetworkRequest(List<NetworkRequest> networkRequests) {
+    private void releaseNetworkRequests(List<NetworkRequest> networkRequests) {
         for (int i = 0; i < networkRequests.size(); i++) {
             releaseNetworkRequest(networkRequests.get(i));
         }
@@ -7763,10 +7831,13 @@
 
         final int userId = UserHandle.getCallingUserId();
 
-        Binder.withCleanCallingIdentity(() -> {
+        final long token = Binder.clearCallingIdentity();
+        try {
             final IpMemoryStore ipMemoryStore = IpMemoryStore.getMemoryStore(mContext);
             ipMemoryStore.factoryReset();
-        });
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
 
         // Turn airplane mode off
         setAirplaneMode(false);
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 4a1820a..d907505 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -25,7 +25,6 @@
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
 import android.net.nsd.NsdServiceInfo;
-import android.net.util.nsd.DnsSdTxtRecord;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Message;
@@ -42,6 +41,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.net.module.util.DnsSdTxtRecord;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index 655d8ab..e8687e5 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -107,23 +107,23 @@
 
         String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
         String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
-        return Binder.withCleanCallingIdentity(
-                () -> {
-                    try {
-                        ParcelFileDescriptor tunIntf =
-                                ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
-                        for (LinkAddress addr : linkAddrs) {
-                            mNetd.interfaceAddAddress(
-                                    iface,
-                                    addr.getAddress().getHostAddress(),
-                                    addr.getPrefixLength());
-                        }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            ParcelFileDescriptor tunIntf =
+                    ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
+            for (LinkAddress addr : linkAddrs) {
+                mNetd.interfaceAddAddress(
+                        iface,
+                        addr.getAddress().getHostAddress(),
+                        addr.getPrefixLength());
+            }
 
-                        return new TestNetworkInterface(tunIntf, iface);
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
-                });
+            return new TestNetworkInterface(tunIntf, iface);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     /**
@@ -317,7 +317,12 @@
 
         try {
             // This requires NETWORK_STACK privileges.
-            Binder.withCleanCallingIdentity(() -> mNMS.setInterfaceUp(iface));
+            final long token = Binder.clearCallingIdentity();
+            try {
+                mNMS.setInterfaceUp(iface);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
 
             // Synchronize all accesses to mTestNetworkTracker to prevent the case where:
             // 1. TestNetworkAgent successfully binds to death of binder
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index e9f17ff..5e85409 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -26,20 +26,31 @@
 import android.net.vcn.IVcnManagementService;
 import android.net.vcn.VcnConfig;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.ParcelUuid;
+import android.os.PersistableBundle;
 import android.os.Process;
+import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
+import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.util.PersistableBundleUtils;
 
+import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 /**
  * VcnManagementService manages Virtual Carrier Network profiles and lifecycles.
@@ -101,20 +112,72 @@
 
     public static final boolean VDBG = false; // STOPSHIP: if true
 
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final String VCN_CONFIG_FILE = "/data/system/vcn/configs.xml";
+
     /* Binder context for this service */
     @NonNull private final Context mContext;
     @NonNull private final Dependencies mDeps;
 
     @NonNull private final Looper mLooper;
+    @NonNull private final Handler mHandler;
     @NonNull private final VcnNetworkProvider mNetworkProvider;
 
+    @GuardedBy("mLock")
+    @NonNull
+    private final Map<ParcelUuid, VcnConfig> mConfigs = new ArrayMap<>();
+
+    @NonNull private final Object mLock = new Object();
+
+    @NonNull private final PersistableBundleUtils.LockingReadWriteHelper mConfigDiskRwHelper;
+
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     VcnManagementService(@NonNull Context context, @NonNull Dependencies deps) {
         mContext = requireNonNull(context, "Missing context");
         mDeps = requireNonNull(deps, "Missing dependencies");
 
         mLooper = mDeps.getLooper();
+        mHandler = new Handler(mLooper);
         mNetworkProvider = new VcnNetworkProvider(mContext, mLooper);
+
+        mConfigDiskRwHelper = mDeps.newPersistableBundleLockingReadWriteHelper(VCN_CONFIG_FILE);
+
+        // Run on handler to ensure I/O does not block system server startup
+        mHandler.post(() -> {
+            PersistableBundle configBundle = null;
+            try {
+                configBundle = mConfigDiskRwHelper.readFromDisk();
+            } catch (IOException e1) {
+                Slog.e(TAG, "Failed to read configs from disk; retrying", e1);
+
+                // Retry immediately. The IOException may have been transient.
+                try {
+                    configBundle = mConfigDiskRwHelper.readFromDisk();
+                } catch (IOException e2) {
+                    Slog.wtf(TAG, "Failed to read configs from disk", e2);
+                    return;
+                }
+            }
+
+            if (configBundle != null) {
+                final Map<ParcelUuid, VcnConfig> configs =
+                        PersistableBundleUtils.toMap(
+                                configBundle,
+                                PersistableBundleUtils::toParcelUuid,
+                                VcnConfig::new);
+
+                synchronized (mLock) {
+                    for (Entry<ParcelUuid, VcnConfig> entry : configs.entrySet()) {
+                        // Ensure no new configs are overwritten; a carrier app may have added a new
+                        // config.
+                        if (!mConfigs.containsKey(entry.getKey())) {
+                            mConfigs.put(entry.getKey(), entry.getValue());
+                        }
+                    }
+                    // TODO: Trigger re-evaluation of active VCNs; start/stop VCNs as needed.
+                }
+            }
+        });
     }
 
     // Package-visibility for SystemServer to create instances.
@@ -151,12 +214,21 @@
         public int getBinderCallingUid() {
             return Binder.getCallingUid();
         }
+
+        /**
+         * Creates and returns a new {@link PersistableBundle.LockingReadWriteHelper}
+         *
+         * @param path the file path to read/write from/to.
+         * @return the {@link PersistableBundleUtils.LockingReadWriteHelper} instance
+         */
+        public PersistableBundleUtils.LockingReadWriteHelper
+                newPersistableBundleLockingReadWriteHelper(@NonNull String path) {
+            return new PersistableBundleUtils.LockingReadWriteHelper(path);
+        }
     }
 
     /** Notifies the VcnManagementService that external dependencies can be set up. */
     public void systemReady() {
-        // TODO: Retrieve existing profiles from KeyStore
-
         mContext.getSystemService(ConnectivityManager.class)
                 .registerNetworkProvider(mNetworkProvider);
     }
@@ -217,9 +289,15 @@
 
         enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
 
-        // TODO: Clear Binder calling identity
+        synchronized (mLock) {
+            mConfigs.put(subscriptionGroup, config);
 
-        // TODO: Store VCN configuration, trigger startup as necessary
+            // Must be done synchronously to ensure that writes do not happen out-of-order.
+            writeConfigsToDiskLocked();
+        }
+
+        // TODO: Clear Binder calling identity
+        // TODO: Trigger startup as necessary
     }
 
     /**
@@ -233,9 +311,38 @@
 
         enforceCallingUserAndCarrierPrivilege(subscriptionGroup);
 
-        // TODO: Clear Binder calling identity
+        synchronized (mLock) {
+            mConfigs.remove(subscriptionGroup);
 
-        // TODO: Clear VCN configuration, trigger teardown as necessary
+            // Must be done synchronously to ensure that writes do not happen out-of-order.
+            writeConfigsToDiskLocked();
+        }
+
+        // TODO: Clear Binder calling identity
+        // TODO: Trigger teardown as necessary
+    }
+
+    @GuardedBy("mLock")
+    private void writeConfigsToDiskLocked() {
+        try {
+            PersistableBundle bundle =
+                    PersistableBundleUtils.fromMap(
+                            mConfigs,
+                            PersistableBundleUtils::fromParcelUuid,
+                            VcnConfig::toPersistableBundle);
+            mConfigDiskRwHelper.writeToDisk(bundle);
+        } catch (IOException e) {
+            Slog.e(TAG, "Failed to save configs to disk", e);
+            throw new ServiceSpecificException(0, "Failed to save configs");
+        }
+    }
+
+    /** Get current configuration list for testing purposes */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    Map<ParcelUuid, VcnConfig> getConfigs() {
+        synchronized (mLock) {
+            return Collections.unmodifiableMap(mConfigs);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index 62630300..fa03e59 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -60,12 +60,12 @@
 import android.net.ipsec.ike.TunnelModeChildSessionParams;
 import android.net.ipsec.ike.exceptions.IkeException;
 import android.net.ipsec.ike.exceptions.IkeProtocolException;
-import android.net.util.IpRange;
 import android.system.OsConstants;
 import android.util.Log;
 
 import com.android.internal.net.VpnProfile;
 import com.android.internal.util.HexDump;
+import com.android.net.module.util.IpRange;
 
 import java.net.Inet4Address;
 import java.net.Inet6Address;
diff --git a/services/core/java/com/android/server/vcn/Android.bp b/services/core/java/com/android/server/vcn/Android.bp
new file mode 100644
index 0000000..5ed204f
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/Android.bp
@@ -0,0 +1,4 @@
+filegroup {
+    name: "framework-vcn-util-sources",
+    srcs: ["util/**/*.java"],
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/MacAddressTest.java b/tests/net/java/android/net/MacAddressTest.java
index 91c9a2a..6de31f6 100644
--- a/tests/net/java/android/net/MacAddressTest.java
+++ b/tests/net/java/android/net/MacAddressTest.java
@@ -22,11 +22,11 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import android.net.util.MacAddressUtils;
-
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.net.module.util.MacAddressUtils;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 21dbbc6..a68044a 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -8109,7 +8109,16 @@
 
     @Test
     public void testDumpDoesNotCrash() {
-        StringWriter stringWriter = new StringWriter();
+        // Filing a couple requests prior to testing the dump.
+        final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+        final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
+        final NetworkRequest genericRequest = new NetworkRequest.Builder()
+                .clearCapabilities().build();
+        final NetworkRequest wifiRequest = new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_WIFI).build();
+        mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+        mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
+        final StringWriter stringWriter = new StringWriter();
 
         mService.dump(new FileDescriptor(), new PrintWriter(stringWriter), new String[0]);
 
@@ -8131,11 +8140,11 @@
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
         mCm.registerNetworkCallback(cellRequest, cellNetworkCallback);
 
-        ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
+        final ConnectivityService.NetworkRequestInfo[] nriOutput = mService.requestsSortedById();
 
         assertTrue(nriOutput.length > 1);
         for (int i = 0; i < nriOutput.length - 1; i++) {
-            boolean isRequestIdInOrder =
+            final boolean isRequestIdInOrder =
                     nriOutput[i].mRequests.get(0).requestId
                             < nriOutput[i + 1].mRequests.get(0).requestId;
             assertTrue(isRequestIdInOrder);
diff --git a/tests/vcn/java/android/net/vcn/VcnConfigTest.java b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
new file mode 100644
index 0000000..77944de
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnConfigTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.os.Parcel;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Collections;
+import java.util.Set;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnConfigTest {
+    private static final Set<VcnGatewayConnectionConfig> GATEWAY_CONNECTION_CONFIGS =
+            Collections.singleton(VcnGatewayConnectionConfigTest.buildTestConfig());
+
+    // Public visibility for VcnManagementServiceTest
+    public static VcnConfig buildTestConfig() {
+        VcnConfig.Builder builder = new VcnConfig.Builder();
+
+        for (VcnGatewayConnectionConfig gatewayConnectionConfig : GATEWAY_CONNECTION_CONFIGS) {
+            builder.addGatewayConnectionConfig(gatewayConnectionConfig);
+        }
+
+        return builder.build();
+    }
+
+    @Test
+    public void testBuilderRequiresGatewayConnectionConfig() {
+        try {
+            new VcnConfig.Builder().build();
+            fail("Expected exception due to no VcnGatewayConnectionConfigs provided");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderAndGetters() {
+        final VcnConfig config = buildTestConfig();
+
+        assertEquals(GATEWAY_CONNECTION_CONFIGS, config.getGatewayConnectionConfigs());
+    }
+
+    @Test
+    public void testPersistableBundle() {
+        final VcnConfig config = buildTestConfig();
+
+        assertEquals(config, new VcnConfig(config.toPersistableBundle()));
+    }
+
+    @Test
+    public void testParceling() {
+        final VcnConfig config = buildTestConfig();
+
+        Parcel parcel = Parcel.obtain();
+        config.writeToParcel(parcel, 0);
+        parcel.setDataPosition(0);
+
+        assertEquals(config, VcnConfig.CREATOR.createFromParcel(parcel));
+    }
+}
diff --git a/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
new file mode 100644
index 0000000..e98b6ef
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnGatewayConnectionConfigTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import android.net.NetworkCapabilities;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class VcnGatewayConnectionConfigTest {
+    private static final int[] EXPOSED_CAPS =
+            new int[] {
+                NetworkCapabilities.NET_CAPABILITY_INTERNET, NetworkCapabilities.NET_CAPABILITY_MMS
+            };
+    private static final int[] UNDERLYING_CAPS = new int[] {NetworkCapabilities.NET_CAPABILITY_DUN};
+    private static final long[] RETRY_INTERVALS_MS =
+            new long[] {
+                TimeUnit.SECONDS.toMillis(5),
+                TimeUnit.SECONDS.toMillis(30),
+                TimeUnit.MINUTES.toMillis(1),
+                TimeUnit.MINUTES.toMillis(5),
+                TimeUnit.MINUTES.toMillis(15),
+                TimeUnit.MINUTES.toMillis(30)
+            };
+    private static final int MAX_MTU = 1360;
+
+    // Package protected for use in VcnConfigTest
+    static VcnGatewayConnectionConfig buildTestConfig() {
+        final VcnGatewayConnectionConfig.Builder builder =
+                new VcnGatewayConnectionConfig.Builder()
+                        .setRetryInterval(RETRY_INTERVALS_MS)
+                        .setMaxMtu(MAX_MTU);
+
+        for (int caps : EXPOSED_CAPS) {
+            builder.addExposedCapability(caps);
+        }
+
+        for (int caps : UNDERLYING_CAPS) {
+            builder.addRequiredUnderlyingCapability(caps);
+        }
+
+        return builder.build();
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyExposedCaps() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .addRequiredUnderlyingCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .build();
+
+            fail("Expected exception due to invalid exposed capabilities");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyUnderlyingCaps() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .addExposedCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                    .build();
+
+            fail("Expected exception due to invalid required underlying capabilities");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonNullRetryInterval() {
+        try {
+            new VcnGatewayConnectionConfig.Builder().setRetryInterval(null);
+            fail("Expected exception due to invalid retryIntervalMs");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresNonEmptyRetryInterval() {
+        try {
+            new VcnGatewayConnectionConfig.Builder().setRetryInterval(new long[0]);
+            fail("Expected exception due to invalid retryIntervalMs");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderRequiresValidMtu() {
+        try {
+            new VcnGatewayConnectionConfig.Builder()
+                    .setMaxMtu(VcnGatewayConnectionConfig.MIN_MTU_V6 - 1);
+            fail("Expected exception due to invalid mtu");
+        } catch (IllegalArgumentException e) {
+        }
+    }
+
+    @Test
+    public void testBuilderAndGetters() {
+        final VcnGatewayConnectionConfig config = buildTestConfig();
+
+        for (int cap : EXPOSED_CAPS) {
+            config.hasExposedCapability(cap);
+        }
+        for (int cap : UNDERLYING_CAPS) {
+            config.requiresUnderlyingCapability(cap);
+        }
+
+        assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMs());
+        assertEquals(MAX_MTU, config.getMaxMtu());
+    }
+
+    @Test
+    public void testPersistableBundle() {
+        final VcnGatewayConnectionConfig config = buildTestConfig();
+
+        assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
+    }
+}
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index 633cf64..1cc9532 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -16,6 +16,9 @@
 
 package com.android.server;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.doReturn;
@@ -26,7 +29,9 @@
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnConfigTest;
 import android.os.ParcelUuid;
+import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.test.TestLooper;
@@ -37,10 +42,14 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.vcn.util.PersistableBundleUtils;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.io.FileNotFoundException;
 import java.util.Collections;
+import java.util.Map;
 import java.util.UUID;
 
 /** Tests for {@link VcnManagementService}. */
@@ -48,6 +57,11 @@
 @SmallTest
 public class VcnManagementServiceTest {
     private static final ParcelUuid TEST_UUID_1 = new ParcelUuid(new UUID(0, 0));
+    private static final ParcelUuid TEST_UUID_2 = new ParcelUuid(new UUID(1, 1));
+    private static final VcnConfig TEST_VCN_CONFIG = VcnConfigTest.buildTestConfig();
+    private static final Map<ParcelUuid, VcnConfig> TEST_VCN_CONFIG_MAP =
+            Collections.unmodifiableMap(Collections.singletonMap(TEST_UUID_1, TEST_VCN_CONFIG));
+
     private static final SubscriptionInfo TEST_SUBSCRIPTION_INFO =
             new SubscriptionInfo(
                     1 /* id */,
@@ -79,6 +93,8 @@
     private final TelephonyManager mTelMgr = mock(TelephonyManager.class);
     private final SubscriptionManager mSubMgr = mock(SubscriptionManager.class);
     private final VcnManagementService mVcnMgmtSvc;
+    private final PersistableBundleUtils.LockingReadWriteHelper mConfigReadWriteHelper =
+            mock(PersistableBundleUtils.LockingReadWriteHelper.class);
 
     public VcnManagementServiceTest() throws Exception {
         setupSystemService(mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
@@ -88,6 +104,16 @@
 
         doReturn(mTestLooper.getLooper()).when(mMockDeps).getLooper();
         doReturn(Process.FIRST_APPLICATION_UID).when(mMockDeps).getBinderCallingUid();
+        doReturn(mConfigReadWriteHelper)
+                .when(mMockDeps)
+                .newPersistableBundleLockingReadWriteHelper(any());
+
+        final PersistableBundle bundle =
+                PersistableBundleUtils.fromMap(
+                        TEST_VCN_CONFIG_MAP,
+                        PersistableBundleUtils::fromParcelUuid,
+                        VcnConfig::toPersistableBundle);
+        doReturn(bundle).when(mConfigReadWriteHelper).readFromDisk();
 
         setupMockedCarrierPrivilege(true);
         mVcnMgmtSvc = new VcnManagementService(mMockContext, mMockDeps);
@@ -116,11 +142,41 @@
     }
 
     @Test
+    public void testNonSystemServerRealConfigFileAccessPermission() throws Exception {
+        // Attempt to build a real instance of the dependencies, and verify we cannot write to the
+        // file.
+        VcnManagementService.Dependencies deps = new VcnManagementService.Dependencies();
+        PersistableBundleUtils.LockingReadWriteHelper configReadWriteHelper =
+                deps.newPersistableBundleLockingReadWriteHelper(
+                        VcnManagementService.VCN_CONFIG_FILE);
+
+        // Even tests should not be able to read/write configs from disk; SELinux policies restrict
+        // it to only the system server.
+        // Reading config should always return null since the file "does not exist", and writing
+        // should throw an IOException.
+        assertNull(configReadWriteHelper.readFromDisk());
+
+        try {
+            configReadWriteHelper.writeToDisk(new PersistableBundle());
+            fail("Expected IOException due to SELinux policy");
+        } catch (FileNotFoundException expected) {
+        }
+    }
+
+    @Test
+    public void testLoadVcnConfigsOnStartup() throws Exception {
+        mTestLooper.dispatchAll();
+
+        assertEquals(TEST_VCN_CONFIG_MAP, mVcnMgmtSvc.getConfigs());
+        verify(mConfigReadWriteHelper).readFromDisk();
+    }
+
+    @Test
     public void testSetVcnConfigRequiresNonSystemServer() throws Exception {
         doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
 
         try {
-            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, new VcnConfig.Builder().build());
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
             fail("Expected IllegalStateException exception for system server");
         } catch (IllegalStateException expected) {
         }
@@ -133,7 +189,7 @@
                 .getBinderCallingUid();
 
         try {
-            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, new VcnConfig.Builder().build());
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
             fail("Expected security exception for non system user");
         } catch (SecurityException expected) {
         }
@@ -144,13 +200,21 @@
         setupMockedCarrierPrivilege(false);
 
         try {
-            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, new VcnConfig.Builder().build());
+            mVcnMgmtSvc.setVcnConfig(TEST_UUID_1, VcnConfigTest.buildTestConfig());
             fail("Expected security exception for missing carrier privileges");
         } catch (SecurityException expected) {
         }
     }
 
     @Test
+    public void testSetVcnConfig() throws Exception {
+        // Use a different UUID to simulate a new VCN config.
+        mVcnMgmtSvc.setVcnConfig(TEST_UUID_2, TEST_VCN_CONFIG);
+        assertEquals(TEST_VCN_CONFIG, mVcnMgmtSvc.getConfigs().get(TEST_UUID_2));
+        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+    }
+
+    @Test
     public void testClearVcnConfigRequiresNonSystemServer() throws Exception {
         doReturn(Process.SYSTEM_UID).when(mMockDeps).getBinderCallingUid();
 
@@ -184,4 +248,11 @@
         } catch (SecurityException expected) {
         }
     }
+
+    @Test
+    public void testClearVcnConfig() throws Exception {
+        mVcnMgmtSvc.clearVcnConfig(TEST_UUID_1);
+        assertTrue(mVcnMgmtSvc.getConfigs().isEmpty());
+        verify(mConfigReadWriteHelper).writeToDisk(any(PersistableBundle.class));
+    }
 }
diff --git a/wifi/jarjar-rules.txt b/wifi/jarjar-rules.txt
index 4099c27..7b84d57 100644
--- a/wifi/jarjar-rules.txt
+++ b/wifi/jarjar-rules.txt
@@ -112,8 +112,6 @@
 ## used by both framework-wifi and service-wifi ##
 rule android.content.pm.BaseParceledListSlice* com.android.wifi.x.@0
 rule android.content.pm.ParceledListSlice* com.android.wifi.x.@0
-rule android.net.util.MacAddressUtils* com.android.wifi.x.@0
-rule android.net.util.nsd.DnsSdTxtRecord* com.android.wifi.x.@0
 rule android.os.HandlerExecutor* com.android.wifi.x.@0
 rule android.telephony.Annotation* com.android.wifi.x.@0
 rule com.android.internal.util.AsyncChannel* com.android.wifi.x.@0
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 8c32d18..93c6358 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -29,7 +29,6 @@
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
 import android.net.Uri;
-import android.net.util.MacAddressUtils;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -41,6 +40,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.net.module.util.MacAddressUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
diff --git a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
index dad431c1..e2f40cf 100644
--- a/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
+++ b/wifi/java/android/net/wifi/p2p/nsd/WifiP2pDnsSdServiceInfo.java
@@ -17,10 +17,11 @@
 package android.net.wifi.p2p.nsd;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.net.util.nsd.DnsSdTxtRecord;
 import android.os.Build;
 import android.text.TextUtils;
 
+import com.android.net.module.util.DnsSdTxtRecord;
+
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
diff --git a/wifi/tests/Android.bp b/wifi/tests/Android.bp
index b710a14..0e58740 100644
--- a/wifi/tests/Android.bp
+++ b/wifi/tests/Android.bp
@@ -36,6 +36,7 @@
         "mockito-target-minus-junit4",
         "modules-utils-build",
         "net-tests-utils",
+        "net-utils-framework-common",
         "truth-prebuilt",
     ],
 
diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
index a7b6765..890d3d3 100644
--- a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java
@@ -32,13 +32,14 @@
 import static org.junit.Assert.assertTrue;
 
 import android.net.MacAddress;
-import android.net.util.MacAddressUtils;
 import android.net.wifi.WifiConfiguration.KeyMgmt;
 import android.net.wifi.WifiConfiguration.NetworkSelectionStatus;
 import android.os.Parcel;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.net.module.util.MacAddressUtils;
+
 import org.junit.Before;
 import org.junit.Test;