Merge "create owners"
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 061d4cc..230863d 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -11,6 +11,7 @@
 package android.net {
 
   public class ConnectivityManager {
+    method @RequiresPermission(anyOf={android.Manifest.permission.NETWORK_SETTINGS, android.Manifest.permission.NETWORK_STACK, android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK}) public void requestBackgroundNetwork(@NonNull android.net.NetworkRequest, @Nullable android.os.Handler, @NonNull android.net.ConnectivityManager.NetworkCallback);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_TEST_NETWORKS, android.Manifest.permission.NETWORK_STACK}) public void simulateDataStall(int, long, @NonNull android.net.Network, @NonNull android.os.PersistableBundle);
   }
 
@@ -18,6 +19,14 @@
     method public int getResourceId();
   }
 
+  public final class NetworkAgentConfig implements android.os.Parcelable {
+    method @Nullable public String getSubscriberId();
+  }
+
+  public static final class NetworkAgentConfig.Builder {
+    method @NonNull public android.net.NetworkAgentConfig.Builder setSubscriberId(@Nullable String);
+  }
+
   public final class NetworkCapabilities implements android.os.Parcelable {
     field public static final int TRANSPORT_TEST = 7; // 0x7
   }
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index a7c5b74..6026211 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -1415,8 +1415,10 @@
 package android.apphibernation {
 
   public final class AppHibernationManager {
-    method public boolean isHibernating(@NonNull String);
-    method public void setHibernating(@NonNull String, boolean);
+    method public boolean isHibernatingForUser(@NonNull String);
+    method public boolean isHibernatingGlobally(@NonNull String);
+    method public void setHibernatingForUser(@NonNull String, boolean);
+    method public void setHibernatingGlobally(@NonNull String, boolean);
   }
 
 }
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index afa1560..e6aa7a7 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -47,8 +47,19 @@
 per-file *Zen* = file:/packages/SystemUI/OWNERS
 per-file *StatusBar* = file:/packages/SystemUI/OWNERS
 
+# PackageManager
+per-file ApplicationPackageManager.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file InstantAppResolverService.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file LoadedApk.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file PackageDeleteObserver.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file PackageInstallObserver.java = file:/services/core/java/com/android/server/pm/OWNERS
+per-file EphemeralResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file IEphemeralResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file IInstantAppResolver.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+per-file InstantAppResolveInfo.aidl = file:/services/core/java/com/android/server/pm/OWNERS
+
 # ResourcesManager
-per-file ResourcesManager = rtmitchell@google.com, toddke@google.com
+per-file ResourcesManager.java = rtmitchell@google.com, toddke@google.com
 
 # VoiceInteraction
 per-file *VoiceInteract* = file:/core/java/android/service/voice/OWNERS
diff --git a/core/java/android/apphibernation/AppHibernationManager.java b/core/java/android/apphibernation/AppHibernationManager.java
index 8f1934c..7281d50 100644
--- a/core/java/android/apphibernation/AppHibernationManager.java
+++ b/core/java/android/apphibernation/AppHibernationManager.java
@@ -49,31 +49,61 @@
     }
 
     /**
-     * Returns true if the package is hibernating, false otherwise.
+     * Returns true if the package is hibernating for this context's user, false otherwise.
      *
      * @hide
      */
     @SystemApi
-    public boolean isHibernating(@NonNull String packageName) {
+    public boolean isHibernatingForUser(@NonNull String packageName) {
         try {
-            return mIAppHibernationService.isHibernating(packageName, mContext.getUserId());
+            return mIAppHibernationService.isHibernatingForUser(packageName, mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Set whether the package is hibernating.
+     * Set whether the package is hibernating for this context's user.
      *
      * @hide
      */
     @SystemApi
-    public void setHibernating(@NonNull String packageName, boolean isHibernating) {
+    public void setHibernatingForUser(@NonNull String packageName, boolean isHibernating) {
         try {
-            mIAppHibernationService.setHibernating(packageName, mContext.getUserId(),
+            mIAppHibernationService.setHibernatingForUser(packageName, mContext.getUserId(),
                     isHibernating);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Returns true if app is hibernating globally / at the package level.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean isHibernatingGlobally(@NonNull String packageName) {
+        try {
+            return mIAppHibernationService.isHibernatingGlobally(packageName);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Set whether a package should be globally hibernating. This hibernates the package at a
+     * package level. User-level hibernation (e.g.. {@link #isHibernatingForUser} is independent
+     * from global hibernation.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void setHibernatingGlobally(@NonNull String packageName, boolean isHibernating) {
+        try {
+            mIAppHibernationService.setHibernatingGlobally(packageName, isHibernating);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/apphibernation/IAppHibernationService.aidl b/core/java/android/apphibernation/IAppHibernationService.aidl
index db57ecb..6a068ee 100644
--- a/core/java/android/apphibernation/IAppHibernationService.aidl
+++ b/core/java/android/apphibernation/IAppHibernationService.aidl
@@ -21,6 +21,8 @@
  * @hide
  */
 interface IAppHibernationService {
-    boolean isHibernating(String packageName, int userId);
-    void setHibernating(String packageName, int userId, boolean isHibernating);
+    boolean isHibernatingForUser(String packageName, int userId);
+    void setHibernatingForUser(String packageName, int userId, boolean isHibernating);
+    boolean isHibernatingGlobally(String packageName);
+    void setHibernatingGlobally(String packageName, boolean isHibernating);
 }
\ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 36076da..4fb5577 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -80,7 +80,7 @@
 
     /**
      * Intent used to broadcast the change in the Audio Connection state of the
-     * A2DP profile.
+     * HFP profile.
      *
      * <p>This intent will have 3 extras:
      * <ul>
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 0ef55f4..3730790 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -954,7 +954,10 @@
 
     /**
      * Returns whether the given functions are valid inputs to UsbManager.
-     * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted.
+     * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM are accepted.
+     *
+     * Only one function may be set at a time, except for RNDIS and NCM, which can be set together
+     * because from a user perspective they are the same function (tethering).
      *
      * @return Whether the mask is settable.
      *
@@ -962,7 +965,9 @@
      */
     public static boolean areSettableFunctions(long functions) {
         return functions == FUNCTION_NONE
-                || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1);
+                || ((~SETTABLE_FUNCTIONS & functions) == 0
+                        && ((Long.bitCount(functions) == 1)
+                                || (functions == (FUNCTION_RNDIS | FUNCTION_NCM))));
     }
 
     /**
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index d107261..7f07bba 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -15,7 +15,9 @@
  */
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 import static android.net.IpSecManager.INVALID_RESOURCE_ID;
+import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
 import static android.net.NetworkRequest.Type.LISTEN;
 import static android.net.NetworkRequest.Type.REQUEST;
 import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
@@ -28,6 +30,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.app.PendingIntent;
@@ -4964,4 +4967,92 @@
         }
         return null;
     }
+
+    /**
+     * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, but
+     * does not cause any networks to retain the NET_CAPABILITY_FOREGROUND capability. This can
+     * be used to request that the system provide a network without causing the network to be
+     * in the foreground.
+     *
+     * <p>This method will attempt to find the best network that matches the passed
+     * {@link NetworkRequest}, and to bring up one that does if none currently satisfies the
+     * criteria. The platform will evaluate which network is the best at its own discretion.
+     * Throughput, latency, cost per byte, policy, user preference and other considerations
+     * may be factored in the decision of what is considered the best network.
+     *
+     * <p>As long as this request is outstanding, the platform will try to maintain the best network
+     * matching this request, while always attempting to match the request to a better network if
+     * possible. If a better match is found, the platform will switch this request to the now-best
+     * network and inform the app of the newly best network by invoking
+     * {@link NetworkCallback#onAvailable(Network)} on the provided callback. Note that the platform
+     * will not try to maintain any other network than the best one currently matching the request:
+     * a network not matching any network request may be disconnected at any time.
+     *
+     * <p>For example, an application could use this method to obtain a connected cellular network
+     * even if the device currently has a data connection over Ethernet. This may cause the cellular
+     * radio to consume additional power. Or, an application could inform the system that it wants
+     * a network supporting sending MMSes and have the system let it know about the currently best
+     * MMS-supporting network through the provided {@link NetworkCallback}.
+     *
+     * <p>The status of the request can be followed by listening to the various callbacks described
+     * in {@link NetworkCallback}. The {@link Network} object passed to the callback methods can be
+     * used to direct traffic to the network (although accessing some networks may be subject to
+     * holding specific permissions). Callers will learn about the specific characteristics of the
+     * network through
+     * {@link NetworkCallback#onCapabilitiesChanged(Network, NetworkCapabilities)} and
+     * {@link NetworkCallback#onLinkPropertiesChanged(Network, LinkProperties)}. The methods of the
+     * provided {@link NetworkCallback} will only be invoked due to changes in the best network
+     * matching the request at any given time; therefore when a better network matching the request
+     * becomes available, the {@link NetworkCallback#onAvailable(Network)} method is called
+     * with the new network after which no further updates are given about the previously-best
+     * network, unless it becomes the best again at some later time. All callbacks are invoked
+     * in order on the same thread, which by default is a thread created by the framework running
+     * in the app.
+     *
+     * <p>This{@link NetworkRequest} will live until released via
+     * {@link #unregisterNetworkCallback(NetworkCallback)} or the calling application exits, at
+     * which point the system may let go of the network at any time.
+     *
+     * <p>It is presently unsupported to request a network with mutable
+     * {@link NetworkCapabilities} such as
+     * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED} or
+     * {@link NetworkCapabilities#NET_CAPABILITY_CAPTIVE_PORTAL}
+     * as these {@code NetworkCapabilities} represent states that a particular
+     * network may never attain, and whether a network will attain these states
+     * is unknown prior to bringing up the network so the framework does not
+     * know how to go about satisfying a request with these capabilities.
+     *
+     * <p>To avoid performance issues due to apps leaking callbacks, the system will limit the
+     * number of outstanding requests to 100 per app (identified by their UID), shared with
+     * all variants of this method, of {@link #registerNetworkCallback} as well as
+     * {@link ConnectivityDiagnosticsManager#registerConnectivityDiagnosticsCallback}.
+     * Requesting a network with this method will count toward this limit. If this limit is
+     * exceeded, an exception will be thrown. To avoid hitting this issue and to conserve resources,
+     * make sure to unregister the callbacks with
+     * {@link #unregisterNetworkCallback(NetworkCallback)}.
+     *
+     * @param request {@link NetworkRequest} describing this request.
+     * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     *                If null, the callback is invoked on the default internal Handler.
+     * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
+     *                        the callback must not be shared - it uniquely specifies this request.
+     * @throws IllegalArgumentException if {@code request} contains invalid network capabilities.
+     * @throws SecurityException if missing the appropriate permissions.
+     * @throws RuntimeException if the app already has too many callbacks registered.
+     *
+     * @hide
+     */
+    @SystemApi(client = MODULE_LIBRARIES)
+    @SuppressLint("ExecutorRegistration")
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.NETWORK_SETTINGS,
+            android.Manifest.permission.NETWORK_STACK,
+            NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
+    })
+    public void requestBackgroundNetwork(@NonNull NetworkRequest request,
+            @Nullable Handler handler, @NonNull NetworkCallback networkCallback) {
+        final NetworkCapabilities nc = request.networkCapabilities;
+        sendRequestForNetwork(nc, networkCallback, 0, BACKGROUND_REQUEST,
+                TYPE_NONE, handler == null ? getDefaultHandler() : new CallbackHandler(handler));
+    }
 }
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 7197831..1b4d2e4 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -31,7 +31,6 @@
 import android.net.NetworkState;
 import android.net.ProxyInfo;
 import android.net.UidRange;
-import android.net.VpnInfo;
 import android.net.QosSocketInfo;
 import android.os.Bundle;
 import android.os.IBinder;
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index d5aede7..0baf11e 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -23,7 +23,7 @@
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
 import android.net.netstats.provider.INetworkStatsProvider;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.os.IBinder;
@@ -70,7 +70,7 @@
          in Network[] defaultNetworks,
          in NetworkState[] networkStates,
          in String activeIface,
-         in VpnInfo[] vpnInfos);
+         in UnderlyingNetworkInfo[] underlyingNetworkInfos);
     /** Force update of statistics. */
     @UnsupportedAppUsage
     void forceUpdate();
diff --git a/core/java/android/net/NetworkAgentConfig.java b/core/java/android/net/NetworkAgentConfig.java
index fe1268d..664c265 100644
--- a/core/java/android/net/NetworkAgentConfig.java
+++ b/core/java/android/net/NetworkAgentConfig.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -125,6 +127,7 @@
      * @return the subscriber ID, or null if none.
      * @hide
      */
+    @SystemApi(client = MODULE_LIBRARIES)
     @Nullable
     public String getSubscriberId() {
         return subscriberId;
@@ -275,6 +278,7 @@
          * @hide
          */
         @NonNull
+        @SystemApi(client = MODULE_LIBRARIES)
         public Builder setSubscriberId(@Nullable String subscriberId) {
             mConfig.subscriberId = subscriberId;
             return this;
diff --git a/core/java/android/net/VpnInfo.aidl b/core/java/android/net/UnderlyingNetworkInfo.aidl
similarity index 94%
rename from core/java/android/net/VpnInfo.aidl
rename to core/java/android/net/UnderlyingNetworkInfo.aidl
index 8bcaa81..a56f2f4 100644
--- a/core/java/android/net/VpnInfo.aidl
+++ b/core/java/android/net/UnderlyingNetworkInfo.aidl
@@ -16,4 +16,4 @@
 
 package android.net;
 
-parcelable VpnInfo;
+parcelable UnderlyingNetworkInfo;
diff --git a/core/java/android/net/UnderlyingNetworkInfo.java b/core/java/android/net/UnderlyingNetworkInfo.java
new file mode 100644
index 0000000..8fb4832
--- /dev/null
+++ b/core/java/android/net/UnderlyingNetworkInfo.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2015 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;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * A lightweight container used to carry information on the networks that underly a given
+ * virtual network.
+ *
+ * @hide
+ */
+public final class UnderlyingNetworkInfo implements Parcelable {
+    /** The owner of this network. */
+    public final int ownerUid;
+    /** The interface name of this network. */
+    @NonNull
+    public final String iface;
+    /** The names of the interfaces underlying this network. */
+    @NonNull
+    public final List<String> underlyingIfaces;
+
+    public UnderlyingNetworkInfo(int ownerUid, @NonNull String iface,
+            @NonNull List<String> underlyingIfaces) {
+        Objects.requireNonNull(iface);
+        Objects.requireNonNull(underlyingIfaces);
+        this.ownerUid = ownerUid;
+        this.iface = iface;
+        this.underlyingIfaces = underlyingIfaces;
+    }
+
+    private UnderlyingNetworkInfo(@NonNull Parcel in) {
+        this.ownerUid = in.readInt();
+        this.iface = in.readString();
+        this.underlyingIfaces = new ArrayList<>();
+        in.readList(this.underlyingIfaces, null /*classLoader*/);
+    }
+
+    @Override
+    public String toString() {
+        return "UnderlyingNetworkInfo{"
+                + "ownerUid=" + ownerUid
+                + ", iface='" + iface + '\''
+                + ", underlyingIfaces='" + underlyingIfaces.toString() + '\''
+                + '}';
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(ownerUid);
+        dest.writeString(iface);
+        dest.writeList(underlyingIfaces);
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<UnderlyingNetworkInfo> CREATOR =
+            new Parcelable.Creator<UnderlyingNetworkInfo>() {
+        @NonNull
+        @Override
+        public UnderlyingNetworkInfo createFromParcel(@NonNull Parcel in) {
+            return new UnderlyingNetworkInfo(in);
+        }
+
+        @NonNull
+        @Override
+        public UnderlyingNetworkInfo[] newArray(int size) {
+            return new UnderlyingNetworkInfo[size];
+        }
+    };
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof UnderlyingNetworkInfo)) return false;
+        final UnderlyingNetworkInfo that = (UnderlyingNetworkInfo) o;
+        return ownerUid == that.ownerUid
+                && Objects.equals(iface, that.iface)
+                && Objects.equals(underlyingIfaces, that.underlyingIfaces);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ownerUid, iface, underlyingIfaces);
+    }
+}
diff --git a/core/java/android/net/VpnInfo.java b/core/java/android/net/VpnInfo.java
deleted file mode 100644
index cf58c57..0000000
--- a/core/java/android/net/VpnInfo.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2015 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;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Arrays;
-
-/**
- * A lightweight container used to carry information of the ongoing VPN.
- * Internal use only.
- *
- * @hide
- */
-public class VpnInfo implements Parcelable {
-    public final int ownerUid;
-    @Nullable
-    public final String vpnIface;
-    @Nullable
-    public final String[] underlyingIfaces;
-
-    public VpnInfo(int ownerUid, @Nullable String vpnIface, @Nullable String[] underlyingIfaces) {
-        this.ownerUid = ownerUid;
-        this.vpnIface = vpnIface;
-        this.underlyingIfaces = underlyingIfaces;
-    }
-
-    private VpnInfo(@NonNull Parcel in) {
-        this.ownerUid = in.readInt();
-        this.vpnIface = in.readString();
-        this.underlyingIfaces = in.createStringArray();
-    }
-
-    @Override
-    public String toString() {
-        return "VpnInfo{"
-                + "ownerUid=" + ownerUid
-                + ", vpnIface='" + vpnIface + '\''
-                + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\''
-                + '}';
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(ownerUid);
-        dest.writeString(vpnIface);
-        dest.writeStringArray(underlyingIfaces);
-    }
-
-    @NonNull
-    public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
-        @NonNull
-        @Override
-        public VpnInfo createFromParcel(@NonNull Parcel in) {
-            return new VpnInfo(in);
-        }
-
-        @NonNull
-        @Override
-        public VpnInfo[] newArray(int size) {
-            return new VpnInfo[size];
-        }
-    };
-}
diff --git a/core/java/android/net/vcn/IVcnManagementService.aidl b/core/java/android/net/vcn/IVcnManagementService.aidl
index 80ac64b..4f293ee 100644
--- a/core/java/android/net/vcn/IVcnManagementService.aidl
+++ b/core/java/android/net/vcn/IVcnManagementService.aidl
@@ -16,8 +16,11 @@
 
 package android.net.vcn;
 
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
 import android.os.ParcelUuid;
 
 /**
@@ -29,4 +32,5 @@
 
     void addVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
     void removeVcnUnderlyingNetworkPolicyListener(in IVcnUnderlyingNetworkPolicyListener listener);
+    VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(in NetworkCapabilities nc, in LinkProperties lp);
 }
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 2d0a6d7..33beb6a 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -21,6 +21,8 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
@@ -62,7 +64,7 @@
  * @hide
  */
 @SystemService(Context.VCN_MANAGEMENT_SERVICE)
-public final class VcnManager {
+public class VcnManager {
     @NonNull private static final String TAG = VcnManager.class.getSimpleName();
 
     /** @hide */
@@ -223,6 +225,37 @@
     }
 
     /**
+     * Queries the underlying network policy for a network with the given parameters.
+     *
+     * <p>Prior to a new NetworkAgent being registered, or upon notification that Carrier VCN policy
+     * may have changed via {@link VcnUnderlyingNetworkPolicyListener#onPolicyChanged()}, a Network
+     * Provider MUST poll for the updated Network policy based on that Network's capabilities and
+     * properties.
+     *
+     * @param networkCapabilities the NetworkCapabilities to be used in determining the Network
+     *     policy for this Network.
+     * @param linkProperties the LinkProperties to be used in determining the Network policy for
+     *     this Network.
+     * @throws SecurityException if the caller does not have permission NETWORK_FACTORY
+     * @return the VcnUnderlyingNetworkPolicy to be used for this Network.
+     * @hide
+     */
+    @NonNull
+    @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
+    public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
+            @NonNull NetworkCapabilities networkCapabilities,
+            @NonNull LinkProperties linkProperties) {
+        requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+        requireNonNull(linkProperties, "linkProperties must not be null");
+
+        try {
+            return mService.getUnderlyingNetworkPolicy(networkCapabilities, linkProperties);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Binder wrapper for added VcnUnderlyingNetworkPolicyListeners to receive signals from System
      * Server.
      *
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 71344f9..f853e67 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -288,6 +288,20 @@
     }
 
     /**
+     * Get service debug info.
+     * @return an array of information for each service (like listServices, but with PIDs)
+     * @hide
+     */
+    public static ServiceDebugInfo[] getServiceDebugInfo() {
+        try {
+            return getIServiceManager().getServiceDebugInfo();
+        } catch (RemoteException e) {
+            Log.e(TAG, "error in getServiceDebugInfo", e);
+            return null;
+        }
+    }
+
+    /**
      * This is only intended to be called when the process is first being brought
      * up and bound by the activity manager. There is only one thread in the process
      * at that time, so no locking is done.
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index b70b6b5..60acc57 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -103,6 +103,10 @@
         throw new RemoteException();
     }
 
+    public ServiceDebugInfo[] getServiceDebugInfo() throws RemoteException {
+        return mServiceManager.getServiceDebugInfo();
+    }
+
     /**
      * Same as mServiceManager but used by apps.
      *
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 24dabfc..a668e8e 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4507,7 +4507,7 @@
     <!-- Allows access to keyguard secure storage.  Only allowed for system processes.
         @hide -->
     <permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
-        android:protectionLevel="signature" />
+        android:protectionLevel="signature|setup" />
 
     <!-- Allows applications to set the initial lockscreen state.
          <p>Not for use by third-party applications. @hide -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index d30efa9..20cb270 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4411,4 +4411,7 @@
 
     <!-- Component names of the services which will keep critical code path warm -->
     <string-array name="config_keep_warming_services" translatable="false" />
+
+    <!-- Whether to select voice/data/sms preference without user confirmation -->
+    <bool name="config_voice_data_sms_auto_fallback">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 937716d..4509b4e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4057,4 +4057,6 @@
   <java-symbol type="array" name="config_notificationMsgPkgsAllowedAsConvos" />
 
   <java-symbol type="array" name="config_keep_warming_services" />
+
+  <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
 </resources>
diff --git a/core/tests/mockingcoretests/src/android/view/OWNERS b/core/tests/mockingcoretests/src/android/view/OWNERS
new file mode 100644
index 0000000..9c9f824
--- /dev/null
+++ b/core/tests/mockingcoretests/src/android/view/OWNERS
@@ -0,0 +1,2 @@
+# Display
+per-file Display*.java = file:/services/core/java/com/android/server/display/OWNERS
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 30501fb..a664ee3 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -345,7 +345,6 @@
         <permission name="android.permission.MOVE_PACKAGE"/>
         <!-- Needed for test only -->
         <permission name="android.permission.RESTART_WIFI_SUBSYSTEM"/>
-        <permission name="android.permission.NETWORK_AIRPLANE_MODE"/>
         <permission name="android.permission.OBSERVE_APP_USAGE"/>
         <permission name="android.permission.NETWORK_SCAN"/>
         <permission name="android.permission.PACKAGE_USAGE_STATS" />
@@ -444,6 +443,9 @@
         <!-- Permission needed for CTS test - WifiManagerTest -->
         <permission name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
         <permission name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
+        <!-- Permission required for GTS test - GtsAssistIntentTestCases -->
+        <permission name="android.permission.MANAGE_SOUND_TRIGGER" />
+        <permission name="android.permission.CAPTURE_AUDIO_HOTWORD" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.statementservice">
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index d67cf8c..621f286 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -301,7 +301,8 @@
     }
     sk_sp<SkImage> image = bitmap.makeImage();
 
-    applyLooper(get_looper(paint), *filterBitmap(paint), [&](SkScalar x, SkScalar y, const SkPaint& p) {
+    applyLooper(get_looper(paint), *filterBitmap(std::move(filteredPaint)),
+                [&](SkScalar x, SkScalar y, const SkPaint& p) {
         mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), &p, bitmap.palette());
     });
 
diff --git a/media/native/midi/include/amidi/AMidi.h b/media/native/midi/include/amidi/AMidi.h
index 0f930b5..742db34 100644
--- a/media/native/midi/include/amidi/AMidi.h
+++ b/media/native/midi/include/amidi/AMidi.h
@@ -61,8 +61,6 @@
     AMIDI_DEVICE_TYPE_BLUETOOTH = 3 /* A MIDI device connected via BlueTooth */
 };
 
-#if __ANDROID_API__ >= 29
-
 /*
  * Device API
  */
@@ -249,8 +247,6 @@
  */
 void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) __INTRODUCED_IN(29);
 
-#endif /* __ANDROID_API__ >= 29 */
-
 #ifdef __cplusplus
 }
 #endif
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 266bfe0..6568bff 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -846,8 +846,8 @@
             try {
                 stmt = db.compileStatement("INSERT INTO system(name,value)"
                         + " VALUES(?,?);");
-                loadBooleanSetting(stmt, Settings.System.USER_ROTATION,
-                        R.integer.def_user_rotation); // should be zero degrees
+                loadIntegerSetting(stmt, Settings.System.USER_ROTATION,
+                        R.integer.def_user_rotation);
                 db.setTransactionSuccessful();
             } finally {
                 db.endTransaction();
@@ -2265,6 +2265,8 @@
             loadBooleanSetting(stmt, Settings.System.ACCELEROMETER_ROTATION,
                     R.bool.def_accelerometer_rotation);
 
+            loadIntegerSetting(stmt, Settings.System.USER_ROTATION, R.integer.def_user_rotation);
+
             loadDefaultHapticSettings(stmt);
 
             loadBooleanSetting(stmt, Settings.System.NOTIFICATION_LIGHT_PULSE,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index dcbad30..135356c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -296,9 +296,6 @@
     <uses-permission android:name="android.permission.RESTART_WIFI_SUBSYSTEM" />
 
     <!-- Permission needed to read wifi network credentials for CtsNetTestCases -->
-    <uses-permission android:name="android.permission.NETWORK_AIRPLANE_MODE" />
-
-    <!-- Permission needed to read wifi network credentials for CtsNetTestCases -->
     <uses-permission android:name="android.permission.READ_WIFI_CREDENTIAL" />
 
     <!-- Permission needed to use wifi usability API's for CtsNetTestCases -->
@@ -352,6 +349,13 @@
     <!-- Permission required for CTS test - CtsSensorPrivacyTestCases -->
     <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
 
+    <!-- Permission required for GTS test - GtsAssistIntentTestCases -->
+    <uses-permission android:name="android.permission.MANAGE_SOUND_TRIGGER" />
+    <uses-permission android:name="android.permission.CAPTURE_AUDIO_HOTWORD" />
+    <uses-permission android:name="android.permission.BIND_VOICE_INTERACTION" />
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d129b9c..554edc6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -132,8 +132,8 @@
 import android.net.TetheringManager;
 import android.net.UidRange;
 import android.net.UidRangeParcel;
+import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
-import android.net.VpnInfo;
 import android.net.VpnManager;
 import android.net.VpnService;
 import android.net.metrics.INetdEventListener;
@@ -4854,28 +4854,28 @@
      *
      * <p>Must be called on the handler thread.
      */
-    private VpnInfo[] getAllVpnInfo() {
+    private UnderlyingNetworkInfo[] getAllVpnInfo() {
         ensureRunningOnConnectivityServiceThread();
         synchronized (mVpns) {
             if (mLockdownEnabled) {
-                return new VpnInfo[0];
+                return new UnderlyingNetworkInfo[0];
             }
         }
-        List<VpnInfo> infoList = new ArrayList<>();
+        List<UnderlyingNetworkInfo> infoList = new ArrayList<>();
         for (NetworkAgentInfo nai : mNetworkAgentInfos) {
-            VpnInfo info = createVpnInfo(nai);
+            UnderlyingNetworkInfo info = createVpnInfo(nai);
             if (info != null) {
                 infoList.add(info);
             }
         }
-        return infoList.toArray(new VpnInfo[infoList.size()]);
+        return infoList.toArray(new UnderlyingNetworkInfo[infoList.size()]);
     }
 
     /**
      * @return VPN information for accounting, or null if we can't retrieve all required
      *         information, e.g underlying ifaces.
      */
-    private VpnInfo createVpnInfo(NetworkAgentInfo nai) {
+    private UnderlyingNetworkInfo createVpnInfo(NetworkAgentInfo nai) {
         if (!nai.isVPN()) return null;
 
         Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
@@ -4907,11 +4907,11 @@
         // Must be non-null or NetworkStatsService will crash.
         // Cannot happen in production code because Vpn only registers the NetworkAgent after the
         // tun or ipsec interface is created.
+        // TODO: Remove this check.
         if (nai.linkProperties.getInterfaceName() == null) return null;
 
-        return new VpnInfo(nai.networkCapabilities.getOwnerUid(),
-                nai.linkProperties.getInterfaceName(),
-                interfaces.toArray(new String[0]));
+        return new UnderlyingNetworkInfo(nai.networkCapabilities.getOwnerUid(),
+                nai.linkProperties.getInterfaceName(), interfaces);
     }
 
     /**
@@ -5707,6 +5707,9 @@
                 networkCapabilities = createDefaultNetworkCapabilitiesForUid(callingUid);
                 enforceAccessPermission();
                 break;
+            case BACKGROUND_REQUEST:
+                enforceNetworkStackOrSettingsPermission();
+                // Fall-through since other checks are the same with normal requests.
             case REQUEST:
                 networkCapabilities = new NetworkCapabilities(networkCapabilities);
                 enforceNetworkRequestPermissions(networkCapabilities, callingPackageName,
@@ -7998,10 +8001,10 @@
             activeIface = activeLinkProperties.getInterfaceName();
         }
 
-        final VpnInfo[] vpnInfos = getAllVpnInfo();
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos = getAllVpnInfo();
         try {
-            mStatsService.forceUpdateIfaces(
-                    getDefaultNetworks(), getAllNetworkState(), activeIface, vpnInfos);
+            mStatsService.forceUpdateIfaces(getDefaultNetworks(), getAllNetworkState(), activeIface,
+                    underlyingNetworkInfos);
         } catch (Exception ignored) {
         }
     }
@@ -8261,6 +8264,7 @@
         return getVpnIfOwner(mDeps.getCallingUid());
     }
 
+    // TODO: stop calling into Vpn.java and get this information from data in this class.
     @GuardedBy("mVpns")
     private Vpn getVpnIfOwner(int uid) {
         final int user = UserHandle.getUserId(uid);
@@ -8269,7 +8273,7 @@
         if (vpn == null) {
             return null;
         } else {
-            final VpnInfo info = vpn.getVpnInfo();
+            final UnderlyingNetworkInfo info = vpn.getUnderlyingNetworkInfo();
             return (info == null || info.ownerUid != uid) ? null : vpn;
         }
     }
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index 76db019..8562b0d 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -25,9 +25,12 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.net.vcn.IVcnManagementService;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.HandlerThread;
@@ -527,7 +530,7 @@
             @NonNull IVcnUnderlyingNetworkPolicyListener listener) {
         requireNonNull(listener, "listener was null");
 
-        mContext.enforceCallingPermission(
+        mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.NETWORK_FACTORY,
                 "Must have permission NETWORK_FACTORY to register a policy listener");
 
@@ -561,4 +564,27 @@
             }
         }
     }
+
+    /**
+     * Gets the UnderlyingNetworkPolicy as determined by the provided NetworkCapabilities and
+     * LinkProperties.
+     */
+    @NonNull
+    @Override
+    public VcnUnderlyingNetworkPolicy getUnderlyingNetworkPolicy(
+            @NonNull NetworkCapabilities networkCapabilities,
+            @NonNull LinkProperties linkProperties) {
+        requireNonNull(networkCapabilities, "networkCapabilities was null");
+        requireNonNull(linkProperties, "linkProperties was null");
+
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.NETWORK_FACTORY,
+                "Must have permission NETWORK_FACTORY or be the SystemServer to get underlying"
+                        + " Network policies");
+
+        // TODO(b/175914059): implement policy generation once VcnManagementService is able to
+        // determine policies
+
+        return new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, networkCapabilities);
+    }
 }
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index ab24015..c3f4294 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -31,6 +31,7 @@
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceDebugInfo;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -135,6 +136,11 @@
             "android.system.suspend@1.0::ISystemSuspend"
     );
 
+    public static final String[] AIDL_INTERFACE_PREFIXES_OF_INTEREST = new String[] {
+            "android.hardware.light.ILights/",
+            "android.hardware.power.stats.IPowerStats/",
+    };
+
     private static Watchdog sWatchdog;
 
     /* This handler will be used to post message back onto the main thread */
@@ -515,12 +521,11 @@
         return builder.toString();
     }
 
-    private static ArrayList<Integer> getInterestingHalPids() {
+    private static void addInterestingHidlPids(HashSet<Integer> pids) {
         try {
             IServiceManager serviceManager = IServiceManager.getService();
             ArrayList<IServiceManager.InstanceDebugInfo> dump =
                     serviceManager.debugDump();
-            HashSet<Integer> pids = new HashSet<>();
             for (IServiceManager.InstanceDebugInfo info : dump) {
                 if (info.pid == IServiceManager.PidConstant.NO_PID) {
                     continue;
@@ -532,24 +537,37 @@
 
                 pids.add(info.pid);
             }
-            return new ArrayList<Integer>(pids);
         } catch (RemoteException e) {
-            return new ArrayList<Integer>();
+            Log.w(TAG, e);
+        }
+    }
+
+    private static void addInterestingAidlPids(HashSet<Integer> pids) {
+        ServiceDebugInfo[] infos = ServiceManager.getServiceDebugInfo();
+        if (infos == null) return;
+
+        for (ServiceDebugInfo info : infos) {
+            for (String prefix : AIDL_INTERFACE_PREFIXES_OF_INTEREST) {
+                if (info.name.startsWith(prefix)) {
+                    pids.add(info.debugPid);
+                }
+            }
         }
     }
 
     static ArrayList<Integer> getInterestingNativePids() {
-        ArrayList<Integer> pids = getInterestingHalPids();
+        HashSet<Integer> pids = new HashSet<>();
+        addInterestingAidlPids(pids);
+        addInterestingHidlPids(pids);
 
         int[] nativePids = Process.getPidsForCommands(NATIVE_STACKS_OF_INTEREST);
         if (nativePids != null) {
-            pids.ensureCapacity(pids.size() + nativePids.length);
             for (int i : nativePids) {
                 pids.add(i);
             }
         }
 
-        return pids;
+        return new ArrayList<Integer>(pids);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationService.java b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
index 508bb01..fded85c 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationService.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationService.java
@@ -20,6 +20,7 @@
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.EXTRA_REMOVED_FOR_ALL_USERS;
 import static android.content.Intent.EXTRA_REPLACING;
 import static android.content.pm.PackageManager.MATCH_ALL;
 import static android.provider.DeviceConfig.NAMESPACE_APP_HIBERNATION;
@@ -46,6 +47,7 @@
 import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.GuardedBy;
@@ -55,6 +57,7 @@
 import java.io.FileDescriptor;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 /**
  * System service that manages app hibernation state, a state apps can enter that means they are
@@ -74,6 +77,8 @@
     private final UserManager mUserManager;
     @GuardedBy("mLock")
     private final SparseArray<Map<String, UserPackageState>> mUserStates = new SparseArray<>();
+    @GuardedBy("mLock")
+    private final Set<String> mGloballyHibernatedPackages = new ArraySet<>();
 
     /**
      * Initializes the system service.
@@ -138,7 +143,7 @@
      * @param userId the user to check
      * @return true if package is hibernating for the user
      */
-    public boolean isHibernating(String packageName, int userId) {
+    boolean isHibernatingForUser(String packageName, int userId) {
         userId = handleIncomingUser(userId, "isHibernating");
         synchronized (mLock) {
             final Map<String, UserPackageState> packageStates = mUserStates.get(userId);
@@ -151,7 +156,19 @@
                         String.format("Package %s is not installed for user %s",
                                 packageName, userId));
             }
-            return pkgState != null ? pkgState.hibernated : null;
+            return pkgState.hibernated;
+        }
+    }
+
+    /**
+     * Whether a package is hibernated globally. This only occurs when a package is hibernating for
+     * all users and allows us to make optimizations at the package or APK level.
+     *
+     * @param packageName package to check
+     */
+    boolean isHibernatingGlobally(String packageName) {
+        synchronized (mLock) {
+            return mGloballyHibernatedPackages.contains(packageName);
         }
     }
 
@@ -162,7 +179,7 @@
      * @param userId user
      * @param isHibernating new hibernation state
      */
-    public void setHibernating(String packageName, int userId, boolean isHibernating) {
+    void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
         userId = handleIncomingUser(userId, "setHibernating");
         synchronized (mLock) {
             if (!mUserStates.contains(userId)) {
@@ -180,32 +197,99 @@
                 return;
             }
 
-
-            final long caller = Binder.clearCallingIdentity();
-            try {
-                if (isHibernating) {
-                    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
-                    mIActivityManager.forceStopPackage(packageName, userId);
-                    mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
-                            null /* observer */);
-                } else {
-                    Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
-                    mIPackageManager.setPackageStoppedState(packageName, false, userId);
-                }
-                pkgState.hibernated = isHibernating;
-            } catch (RemoteException e) {
-                throw new IllegalStateException(
-                        "Failed to hibernate due to manager not being available", e);
-            } finally {
-                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
-                Binder.restoreCallingIdentity(caller);
+            if (isHibernating) {
+                hibernatePackageForUserL(packageName, userId, pkgState);
+            } else {
+                unhibernatePackageForUserL(packageName, userId, pkgState);
             }
-
-            // TODO: Support package level hibernation when package is hibernating for all users
         }
     }
 
     /**
+     * Set whether the package should be hibernated globally at a package level, allowing the
+     * the system to make optimizations at the package or APK level.
+     *
+     * @param packageName package to hibernate globally
+     * @param isHibernating new hibernation state
+     */
+    void setHibernatingGlobally(String packageName, boolean isHibernating) {
+        if (isHibernating != mGloballyHibernatedPackages.contains(packageName)) {
+            synchronized (mLock) {
+                if (isHibernating) {
+                    hibernatePackageGloballyL(packageName);
+                } else {
+                    unhibernatePackageGloballyL(packageName);
+                }
+            }
+        }
+    }
+
+    /**
+     * Put an app into hibernation for a given user, allowing user-level optimizations to occur.
+     * The caller should hold {@link #mLock}
+     *
+     * @param pkgState package hibernation state
+     */
+    private void hibernatePackageForUserL(@NonNull String packageName, int userId,
+            @NonNull UserPackageState pkgState) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackage");
+        final long caller = Binder.clearCallingIdentity();
+        try {
+            mIActivityManager.forceStopPackage(packageName, userId);
+            mIPackageManager.deleteApplicationCacheFilesAsUser(packageName, userId,
+                    null /* observer */);
+            pkgState.hibernated = true;
+        } catch (RemoteException e) {
+            throw new IllegalStateException(
+                    "Failed to hibernate due to manager not being available", e);
+        } finally {
+            Binder.restoreCallingIdentity(caller);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+    }
+
+    /**
+     * Remove a package from hibernation for a given user. The caller should hold {@link #mLock}.
+     *
+     * @param pkgState package hibernation state
+     */
+    private void unhibernatePackageForUserL(@NonNull String packageName, int userId,
+            UserPackageState pkgState) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackage");
+        final long caller = Binder.clearCallingIdentity();
+        try {
+            mIPackageManager.setPackageStoppedState(packageName, false, userId);
+            pkgState.hibernated = false;
+        } catch (RemoteException e) {
+            throw new IllegalStateException(
+                    "Failed to unhibernate due to manager not being available", e);
+        } finally {
+            Binder.restoreCallingIdentity(caller);
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+    }
+
+    /**
+     * Put a package into global hibernation, optimizing its storage at a package / APK level.
+     * The caller should hold {@link #mLock}.
+     */
+    private void hibernatePackageGloballyL(@NonNull String packageName) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "hibernatePackageGlobally");
+        // TODO(175830194): Delete vdex/odex when DexManager API is built out
+        mGloballyHibernatedPackages.add(packageName);
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    /**
+     * Unhibernate a package from global hibernation. The caller should hold {@link #mLock}.
+     */
+    private void unhibernatePackageGloballyL(@NonNull String packageName) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "unhibernatePackageGlobally");
+        mGloballyHibernatedPackages.remove(packageName);
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    /**
      * Populates {@link #mUserStates} with the users installed packages. The caller should hold
      * {@link #mLock}.
      *
@@ -220,8 +304,8 @@
             throw new IllegalStateException("Package manager not available.", e);
         }
 
-        for (PackageInfo pkg : packageList) {
-            packages.put(pkg.packageName, new UserPackageState());
+        for (int i = 0, size = packageList.size(); i < size; i++) {
+            packages.put(packageList.get(i).packageName, new UserPackageState());
         }
         mUserStates.put(userId, packages);
     }
@@ -250,6 +334,12 @@
         }
     }
 
+    private void onPackageRemovedForAllUsers(@NonNull String packageName) {
+        synchronized (mLock) {
+            mGloballyHibernatedPackages.remove(packageName);
+        }
+    }
+
     /**
      * Private helper method to get the real user id and enforce permission checks.
      *
@@ -277,13 +367,23 @@
         }
 
         @Override
-        public boolean isHibernating(String packageName, int userId) {
-            return mService.isHibernating(packageName, userId);
+        public boolean isHibernatingForUser(String packageName, int userId) {
+            return mService.isHibernatingForUser(packageName, userId);
         }
 
         @Override
-        public void setHibernating(String packageName, int userId, boolean isHibernating) {
-            mService.setHibernating(packageName, userId, isHibernating);
+        public void setHibernatingForUser(String packageName, int userId, boolean isHibernating) {
+            mService.setHibernatingForUser(packageName, userId, isHibernating);
+        }
+
+        @Override
+        public void setHibernatingGlobally(String packageName, boolean isHibernating) {
+            mService.setHibernatingGlobally(packageName, isHibernating);
+        }
+
+        @Override
+        public boolean isHibernatingGlobally(String packageName) {
+            return mService.isHibernatingGlobally(packageName);
         }
 
         @Override
@@ -322,6 +422,9 @@
                     onPackageAdded(packageName, userId);
                 } else if (ACTION_PACKAGE_REMOVED.equals(action)) {
                     onPackageRemoved(packageName, userId);
+                    if (intent.getBooleanExtra(EXTRA_REMOVED_FOR_ALL_USERS, false)) {
+                        onPackageRemovedForAllUsers(packageName);
+                    }
                 }
             }
         }
diff --git a/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java b/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
index 869885e..7d6eea2 100644
--- a/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
+++ b/services/core/java/com/android/server/apphibernation/AppHibernationShellCommand.java
@@ -18,7 +18,6 @@
 
 import android.os.ShellCommand;
 import android.os.UserHandle;
-import android.text.TextUtils;
 
 import java.io.PrintWriter;
 
@@ -27,6 +26,7 @@
  */
 final class AppHibernationShellCommand extends ShellCommand {
     private static final String USER_OPT = "--user";
+    private static final String GLOBAL_OPT = "--global";
     private static final int SUCCESS = 0;
     private static final int ERROR = -1;
     private final AppHibernationService mService;
@@ -51,7 +51,21 @@
     }
 
     private int runSetState() {
-        int userId = parseUserOption();
+        String opt;
+        boolean setsGlobal = false;
+        int userId = UserHandle.USER_CURRENT;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case USER_OPT:
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                case GLOBAL_OPT:
+                    setsGlobal = true;
+                    break;
+                default:
+                    getErrPrintWriter().println("Error: Unknown option: " + opt);
+            }
+        }
 
         String pkg = getNextArgRequired();
         if (pkg == null) {
@@ -66,32 +80,43 @@
         }
         boolean newState = Boolean.parseBoolean(newStateRaw);
 
-        mService.setHibernating(pkg, userId, newState);
+        if (setsGlobal) {
+            mService.setHibernatingGlobally(pkg, newState);
+        } else {
+            mService.setHibernatingForUser(pkg, userId, newState);
+        }
         return SUCCESS;
     }
 
     private int runGetState() {
-        int userId = parseUserOption();
+        String opt;
+        boolean requestsGlobal = false;
+        int userId = UserHandle.USER_CURRENT;
+        while ((opt = getNextOption()) != null) {
+            switch (opt) {
+                case USER_OPT:
+                    userId = UserHandle.parseUserArg(getNextArgRequired());
+                    break;
+                case GLOBAL_OPT:
+                    requestsGlobal = true;
+                    break;
+                default:
+                    getErrPrintWriter().println("Error: Unknown option: " + opt);
+            }
+        }
 
         String pkg = getNextArgRequired();
         if (pkg == null) {
             getErrPrintWriter().println("Error: No package specified");
             return ERROR;
         }
-        boolean isHibernating = mService.isHibernating(pkg, userId);
+        boolean isHibernating = requestsGlobal
+                ? mService.isHibernatingGlobally(pkg) : mService.isHibernatingForUser(pkg, userId);
         final PrintWriter pw = getOutPrintWriter();
         pw.println(isHibernating);
         return SUCCESS;
     }
 
-    private int parseUserOption() {
-        String option = getNextOption();
-        if (TextUtils.equals(option, USER_OPT)) {
-            return UserHandle.parseUserArg(getNextArgRequired());
-        }
-        return UserHandle.USER_CURRENT;
-    }
-
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -99,11 +124,13 @@
         pw.println("  help");
         pw.println("    Print this help text.");
         pw.println("");
-        pw.println("  set-state [--user USER_ID] PACKAGE true|false");
-        pw.println("    Sets the hibernation state of the package to value specified");
+        pw.println("  set-state [--user USER_ID] [--global] PACKAGE true|false");
+        pw.println("    Sets the hibernation state of the package to value specified. Optionally");
+        pw.println("    may specify a user id or set global hibernation state.");
         pw.println("");
-        pw.println("  get-state [--user USER_ID] PACKAGE");
-        pw.println("    Gets the hibernation state of the package");
+        pw.println("  get-state [--user USER_ID] [--global] PACKAGE");
+        pw.println("    Gets the hibernation state of the package. Optionally may specify a user");
+        pw.println("    id or request global hibernation state.");
         pw.println("");
     }
 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 8ce6746..b455a3f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -70,7 +70,7 @@
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.UidRangeParcel;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
 import android.net.VpnManager;
 import android.net.VpnService;
 import android.net.ipsec.ike.ChildSessionCallback;
@@ -426,6 +426,7 @@
         mNetworkCapabilities = new NetworkCapabilities();
         mNetworkCapabilities.addTransportType(NetworkCapabilities.TRANSPORT_VPN);
         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
+        mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED);
 
         loadAlwaysOnPackage(keyStore);
     }
@@ -1819,12 +1820,12 @@
      * This method should not be called if underlying interfaces field is needed, because it doesn't
      * have enough data to fill VpnInfo.underlyingIfaces field.
      */
-    public synchronized VpnInfo getVpnInfo() {
+    public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
         if (!isRunningLocked()) {
             return null;
         }
 
-        return new VpnInfo(mOwnerUID, mInterface, null);
+        return new UnderlyingNetworkInfo(mOwnerUID, mInterface, new ArrayList<>());
     }
 
     public synchronized boolean appliesToUid(int uid) {
diff --git a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
index 8399f54..a1e18bd 100644
--- a/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
+++ b/services/core/java/com/android/server/locksettings/ResumeOnRebootServiceProvider.java
@@ -106,6 +106,8 @@
         private final Context mContext;
         private final ComponentName mComponentName;
         private IResumeOnRebootService mBinder;
+        @Nullable
+        ServiceConnection mServiceConnection;
 
         private ResumeOnRebootServiceConnection(Context context,
                 @NonNull ComponentName componentName) {
@@ -115,17 +117,9 @@
 
         /** Unbind from the service */
         public void unbindService() {
-            mContext.unbindService(new ServiceConnection() {
-                @Override
-                public void onServiceConnected(ComponentName name, IBinder service) {
-                }
-
-                @Override
-                public void onServiceDisconnected(ComponentName name) {
-                    mBinder = null;
-
-                }
-            });
+            if (mServiceConnection != null) {
+                mContext.unbindService(mServiceConnection);
+            }
         }
 
         /** Bind to the service */
@@ -134,17 +128,19 @@
                 CountDownLatch connectionLatch = new CountDownLatch(1);
                 Intent intent = new Intent();
                 intent.setComponent(mComponentName);
-                final boolean success = mContext.bindServiceAsUser(intent, new ServiceConnection() {
-                            @Override
-                            public void onServiceConnected(ComponentName name, IBinder service) {
-                                mBinder = IResumeOnRebootService.Stub.asInterface(service);
-                                connectionLatch.countDown();
-                            }
+                mServiceConnection = new ServiceConnection() {
+                    @Override
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        mBinder = IResumeOnRebootService.Stub.asInterface(service);
+                        connectionLatch.countDown();
+                    }
 
-                            @Override
-                            public void onServiceDisconnected(ComponentName name) {
-                            }
-                        },
+                    @Override
+                    public void onServiceDisconnected(ComponentName name) {
+                        mBinder = null;
+                    }
+                };
+                final boolean success = mContext.bindServiceAsUser(intent, mServiceConnection,
                         Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
                         BackgroundThread.getHandler(), UserHandle.SYSTEM);
 
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 4faa790..d042b88 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -27,7 +27,7 @@
 import android.annotation.Nullable;
 import android.net.INetd;
 import android.net.NetworkStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
 import android.net.util.NetdService;
 import android.os.RemoteException;
 import android.os.StrictMode;
@@ -81,7 +81,7 @@
     private final Object mPersistentDataLock = new Object();
 
     /** Set containing info about active VPNs and their underlying networks. */
-    private volatile VpnInfo[] mVpnInfos = new VpnInfo[0];
+    private volatile UnderlyingNetworkInfo[] mUnderlyingNetworkInfos = new UnderlyingNetworkInfo[0];
 
     // A persistent snapshot of cumulative stats since device start
     @GuardedBy("mPersistentDataLock")
@@ -116,8 +116,8 @@
      *
      * @param vpnArray The snapshot of the currently-running VPNs.
      */
-    public void updateVpnInfos(VpnInfo[] vpnArray) {
-        mVpnInfos = vpnArray.clone();
+    public void updateUnderlyingNetworkInfos(UnderlyingNetworkInfo[] vpnArray) {
+        mUnderlyingNetworkInfos = vpnArray.clone();
     }
 
     /**
@@ -319,7 +319,7 @@
         // code that will acquire other locks within the system server. See b/134244752.
         synchronized (mPersistentDataLock) {
             // Take a reference. If this gets swapped out, we still have the old reference.
-            final VpnInfo[] vpnArray = mVpnInfos;
+            final UnderlyingNetworkInfo[] vpnArray = mUnderlyingNetworkInfos;
             // Take a defensive copy. mPersistSnapshot is mutated in some cases below
             final NetworkStats prev = mPersistSnapshot.clone();
 
@@ -369,8 +369,8 @@
     }
 
     @GuardedBy("mPersistentDataLock")
-    private NetworkStats adjustForTunAnd464Xlat(
-            NetworkStats uidDetailStats, NetworkStats previousStats, VpnInfo[] vpnArray) {
+    private NetworkStats adjustForTunAnd464Xlat(NetworkStats uidDetailStats,
+            NetworkStats previousStats, UnderlyingNetworkInfo[] vpnArray) {
         // Calculate delta from last snapshot
         final NetworkStats delta = uidDetailStats.subtract(previousStats);
 
@@ -381,8 +381,9 @@
         delta.apply464xlatAdjustments(mStackedIfaces);
 
         // Migrate data usage over a VPN to the TUN network.
-        for (VpnInfo info : vpnArray) {
-            delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+        for (UnderlyingNetworkInfo info : vpnArray) {
+            delta.migrateTun(info.ownerUid, info.iface,
+                    info.underlyingIfaces.toArray(new String[0]));
             // Filter out debug entries as that may lead to over counting.
             delta.filterDebugEntries();
         }
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4be7b48..0ab35a9 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -104,8 +104,8 @@
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
+import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
-import android.net.VpnInfo;
 import android.net.netstats.provider.INetworkStatsProvider;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.net.netstats.provider.NetworkStatsProvider;
@@ -973,7 +973,7 @@
             Network[] defaultNetworks,
             NetworkState[] networkStates,
             String activeIface,
-            VpnInfo[] vpnInfos) {
+            UnderlyingNetworkInfo[] underlyingNetworkInfos) {
         checkNetworkStackPermission(mContext);
 
         final long token = Binder.clearCallingIdentity();
@@ -986,7 +986,7 @@
         // Update the VPN underlying interfaces only after the poll is made and tun data has been
         // migrated. Otherwise the migration would use the new interfaces instead of the ones that
         // were current when the polled data was transferred.
-        mStatsFactory.updateVpnInfos(vpnInfos);
+        mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
index d0370b6..45bca68 100644
--- a/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/apphibernation/AppHibernationServiceTest.java
@@ -64,6 +64,8 @@
     private static final int USER_ID_1 = 1;
     private static final int USER_ID_2 = 2;
 
+    private final List<UserInfo> mUserInfos = new ArrayList<>();
+
     private AppHibernationService mAppHibernationService;
     private BroadcastReceiver mBroadcastReceiver;
     @Mock
@@ -88,47 +90,42 @@
         verify(mContext, times(2)).registerReceiver(mReceiverCaptor.capture(), any());
         mBroadcastReceiver = mReceiverCaptor.getValue();
 
-        List<UserInfo> userList = new ArrayList<>();
-        userList.add(new UserInfo(USER_ID_1, "user 1", 0 /* flags */));
-        doReturn(userList).when(mUserManager).getUsers();
-
-        List<PackageInfo> userPackages = new ArrayList<>();
-        userPackages.add(makePackageInfo(PACKAGE_NAME_1));
-
-        doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
-                .getInstalledPackages(anyInt(), eq(USER_ID_1));
+        doReturn(mUserInfos).when(mUserManager).getUsers();
 
         doAnswer(returnsArgAt(2)).when(mIActivityManager).handleIncomingUser(anyInt(), anyInt(),
                 anyInt(), anyBoolean(), anyBoolean(), any(), any());
 
+        addUser(USER_ID_1);
         mAppHibernationService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
     }
 
     @Test
-    public void testSetHibernating_packageIsHibernating() {
+    public void testSetHibernatingForUser_packageIsHibernating() throws RemoteException {
         // WHEN we hibernate a package for a user
-        mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
+        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
 
         // THEN the package is marked hibernating for the user
-        assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
+        assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
     }
 
     @Test
-    public void testSetHibernating_newPackageAdded_packageIsHibernating() {
+    public void testSetHibernatingForUser_newPackageAdded_packageIsHibernating()
+            throws RemoteException {
         // WHEN a new package is added and it is hibernated
         Intent intent = new Intent(Intent.ACTION_PACKAGE_ADDED,
                 Uri.fromParts(PACKAGE_SCHEME, PACKAGE_NAME_2, null /* fragment */));
         intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_1);
         mBroadcastReceiver.onReceive(mContext, intent);
 
-        mAppHibernationService.setHibernating(PACKAGE_NAME_2, USER_ID_1, true);
+        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_2, USER_ID_1, true);
 
         // THEN the new package is hibernated
-        assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_2, USER_ID_1));
+        assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_2, USER_ID_1));
     }
 
     @Test
-    public void testSetHibernating_newUserAdded_packageIsHibernating() throws RemoteException {
+    public void testSetHibernatingForUser_newUserAdded_packageIsHibernating()
+            throws RemoteException {
         // WHEN a new user is added and a package from the user is hibernated
         List<PackageInfo> userPackages = new ArrayList<>();
         userPackages.add(makePackageInfo(PACKAGE_NAME_1));
@@ -138,16 +135,17 @@
         intent.putExtra(Intent.EXTRA_USER_HANDLE, USER_ID_2);
         mBroadcastReceiver.onReceive(mContext, intent);
 
-        mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_2, true);
+        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_2, true);
 
         // THEN the new user's package is hibernated
-        assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_2));
+        assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_2));
     }
 
     @Test
-    public void testIsHibernating_packageReplaced_stillReturnsHibernating() {
+    public void testIsHibernatingForUser_packageReplaced_stillReturnsHibernating()
+            throws RemoteException {
         // GIVEN a package is currently hibernated
-        mAppHibernationService.setHibernating(PACKAGE_NAME_1, USER_ID_1, true);
+        mAppHibernationService.setHibernatingForUser(PACKAGE_NAME_1, USER_ID_1, true);
 
         // WHEN the package is removed but marked as replacing
         Intent intent = new Intent(Intent.ACTION_PACKAGE_REMOVED,
@@ -157,7 +155,38 @@
         mBroadcastReceiver.onReceive(mContext, intent);
 
         // THEN the package is still hibernating
-        assertTrue(mAppHibernationService.isHibernating(PACKAGE_NAME_1, USER_ID_1));
+        assertTrue(mAppHibernationService.isHibernatingForUser(PACKAGE_NAME_1, USER_ID_1));
+    }
+
+    @Test
+    public void testSetHibernatingGlobally_packageIsHibernatingGlobally() throws RemoteException {
+        // WHEN we hibernate a package
+        mAppHibernationService.setHibernatingGlobally(PACKAGE_NAME_1, true);
+
+        // THEN the package is marked hibernating for the user
+        assertTrue(mAppHibernationService.isHibernatingGlobally(PACKAGE_NAME_1));
+    }
+
+    /**
+     * Add a mock user with one package. Must be called before
+     * {@link AppHibernationService#onBootPhase(int)} to work properly.
+     */
+    private void addUser(int userId) throws RemoteException {
+        addUser(userId, new String[]{PACKAGE_NAME_1});
+    }
+
+    /**
+     * Add a mock user with the packages specified. Must be called before
+     * {@link AppHibernationService#onBootPhase(int)} to work properly
+     */
+    private void addUser(int userId, String[] packageNames) throws RemoteException {
+        mUserInfos.add(new UserInfo(userId, "user_" + userId, 0 /* flags */));
+        List<PackageInfo> userPackages = new ArrayList<>();
+        for (String pkgName : packageNames) {
+            userPackages.add(makePackageInfo(pkgName));
+        }
+        doReturn(new ParceledListSlice<>(userPackages)).when(mIPackageManager)
+                .getInstalledPackages(anyInt(), eq(userId));
     }
 
     private static PackageInfo makePackageInfo(String packageName) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index 9d48955..e567208 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -1025,6 +1025,8 @@
             writeLocked(fos, stats, version, packagesTokenData);
             file.finishWrite(fos);
             fos = null;
+        } catch (Exception e) {
+            // Do nothing. Exception has already been handled.
         } finally {
             // When fos is null (successful write), this will no-op
             file.failWrite(fos);
@@ -1032,7 +1034,7 @@
     }
 
     private static void writeLocked(OutputStream out, IntervalStats stats, int version,
-            PackagesTokenData packagesTokenData) throws RuntimeException {
+            PackagesTokenData packagesTokenData) throws Exception {
         switch (version) {
             case 1:
             case 2:
@@ -1044,6 +1046,7 @@
                     UsageStatsProto.write(out, stats);
                 } catch (Exception e) {
                     Slog.e(TAG, "Unable to write interval stats to proto.", e);
+                    throw e;
                 }
                 break;
             case 5:
@@ -1052,6 +1055,7 @@
                     UsageStatsProtoV2.write(out, stats);
                 } catch (Exception e) {
                     Slog.e(TAG, "Unable to write interval stats to proto.", e);
+                    throw e;
                 }
                 break;
             default:
diff --git a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
index a0fd9d4..b8bd98e 100644
--- a/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
+++ b/tests/UsbTests/src/com/android/server/usb/UsbManagerNoPermTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.usb;
 
+import static org.junit.Assert.assertEquals;
+
 import android.content.Context;
 import android.hardware.usb.UsbManager;
 
@@ -23,12 +25,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.usblib.UsbManagerTestLib;
+
 import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
-import com.android.server.usblib.UsbManagerTestLib;
-
 /**
  * Unit tests for {@link android.hardware.usb.UsbManager}.
  * Note: NOT claimed MANAGE_USB permission in Manifest
@@ -78,4 +80,35 @@
     public void testUsbApi_SetCurrentFunctions_OnSecurityException() throws Exception {
         mUsbManagerTestLib.testSetCurrentFunctionsEx(UsbManager.FUNCTION_NONE);
     }
+
+    public void assertSettableFunctions(boolean settable, long functions) {
+        assertEquals(
+                "areSettableFunctions(" + UsbManager.usbFunctionsToString(functions) + "):",
+                settable, UsbManager.areSettableFunctions(functions));
+    }
+
+    /**
+     * Tests the behaviour of the static areSettableFunctions method. This method performs no IPCs
+     * and requires no permissions.
+     */
+    @Test
+    public void testUsbManager_AreSettableFunctions() {
+        // NONE is settable.
+        assertSettableFunctions(true, UsbManager.FUNCTION_NONE);
+
+        // MTP, PTP, RNDIS, MIDI, NCM are all settable by themselves.
+        assertSettableFunctions(true, UsbManager.FUNCTION_MTP);
+        assertSettableFunctions(true, UsbManager.FUNCTION_PTP);
+        assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS);
+        assertSettableFunctions(true, UsbManager.FUNCTION_MIDI);
+        assertSettableFunctions(true, UsbManager.FUNCTION_NCM);
+
+        // Setting two functions at the same time is not allowed...
+        assertSettableFunctions(false, UsbManager.FUNCTION_MTP | UsbManager.FUNCTION_PTP);
+        assertSettableFunctions(false, UsbManager.FUNCTION_PTP | UsbManager.FUNCTION_RNDIS);
+        assertSettableFunctions(false, UsbManager.FUNCTION_MIDI | UsbManager.FUNCTION_NCM);
+
+        // ... except in the special case of RNDIS and NCM.
+        assertSettableFunctions(true, UsbManager.FUNCTION_RNDIS | UsbManager.FUNCTION_NCM);
+    }
 }
diff --git a/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt b/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
new file mode 100644
index 0000000..87cfb34
--- /dev/null
+++ b/tests/net/common/java/android/net/UnderlyingNetworkInfoTest.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2021 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
+
+import android.os.Build
+import androidx.test.filters.SmallTest
+import com.android.testutils.DevSdkIgnoreRule
+import com.android.testutils.DevSdkIgnoreRunner
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+
+private const val TEST_OWNER_UID = 123
+private const val TEST_IFACE = "test_tun0"
+private val TEST_IFACE_LIST = listOf("wlan0", "rmnet_data0", "eth0")
+
+@SmallTest
+@RunWith(DevSdkIgnoreRunner::class)
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+class UnderlyingNetworkInfoTest {
+    @Test
+    fun testParcelUnparcel() {
+        val testInfo = UnderlyingNetworkInfo(TEST_OWNER_UID, TEST_IFACE, TEST_IFACE_LIST)
+        assertEquals(TEST_OWNER_UID, testInfo.ownerUid)
+        assertEquals(TEST_IFACE, testInfo.iface)
+        assertEquals(TEST_IFACE_LIST, testInfo.underlyingIfaces)
+        assertParcelSane(testInfo, 3)
+
+        val emptyInfo = UnderlyingNetworkInfo(0, String(), listOf())
+        assertEquals(0, emptyInfo.ownerUid)
+        assertEquals(String(), emptyInfo.iface)
+        assertEquals(listOf(), emptyInfo.underlyingIfaces)
+        assertParcelSane(emptyInfo, 3)
+    }
+}
\ No newline at end of file
diff --git a/tests/net/java/android/net/ConnectivityManagerTest.java b/tests/net/java/android/net/ConnectivityManagerTest.java
index f2dd27e..c2fddf3 100644
--- a/tests/net/java/android/net/ConnectivityManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityManagerTest.java
@@ -32,6 +32,7 @@
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_ETHERNET;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkRequest.Type.BACKGROUND_REQUEST;
 import static android.net.NetworkRequest.Type.REQUEST;
 import static android.net.NetworkRequest.Type.TRACK_DEFAULT;
 
@@ -368,6 +369,12 @@
                 eq(TRACK_DEFAULT.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
                 eq(testPkgName), eq(null));
         reset(mService);
+
+        manager.requestBackgroundNetwork(request, null, callback);
+        verify(mService).requestNetwork(eq(request.networkCapabilities),
+                eq(BACKGROUND_REQUEST.ordinal()), any(), anyInt(), any(), eq(TYPE_NONE),
+                eq(testPkgName), eq(null));
+        reset(mService);
     }
 
     static Message makeMessage(NetworkRequest req, int messageType) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 81c1688..6523acc 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -201,8 +201,8 @@
 import android.net.SocketKeepalive;
 import android.net.UidRange;
 import android.net.UidRangeParcel;
+import android.net.UnderlyingNetworkInfo;
 import android.net.Uri;
-import android.net.VpnInfo;
 import android.net.VpnManager;
 import android.net.metrics.IpConnectivityLog;
 import android.net.shared.NetworkMonitorUtils;
@@ -1076,7 +1076,7 @@
         private boolean mAgentRegistered = false;
 
         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
-        private VpnInfo mVpnInfo;
+        private UnderlyingNetworkInfo mUnderlyingNetworkInfo;
 
         // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
         // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
@@ -1250,14 +1250,15 @@
         }
 
         @Override
-        public synchronized VpnInfo getVpnInfo() {
-            if (mVpnInfo != null) return mVpnInfo;
+        public synchronized UnderlyingNetworkInfo getUnderlyingNetworkInfo() {
+            if (mUnderlyingNetworkInfo != null) return mUnderlyingNetworkInfo;
 
-            return super.getVpnInfo();
+            return super.getUnderlyingNetworkInfo();
         }
 
-        private synchronized void setVpnInfo(VpnInfo vpnInfo) {
-            mVpnInfo = vpnInfo;
+        private synchronized void setUnderlyingNetworkInfo(
+                UnderlyingNetworkInfo underlyingNetworkInfo) {
+            mUnderlyingNetworkInfo = underlyingNetworkInfo;
         }
     }
 
@@ -3693,10 +3694,13 @@
 
     @Test
     public void testBackgroundNetworks() throws Exception {
-        // Create a background request. We can't do this ourselves because ConnectivityService
-        // doesn't have an API for it. So just turn on mobile data always on.
-        setAlwaysOnNetworks(true);
+        // Create a cellular background request.
         grantUsingBackgroundNetworksPermissionForUid(Binder.getCallingUid());
+        final TestNetworkCallback cellBgCallback = new TestNetworkCallback();
+        mCm.requestBackgroundNetwork(new NetworkRequest.Builder()
+                .addTransportType(TRANSPORT_CELLULAR).build(), null, cellBgCallback);
+
+        // Make callbacks for monitoring.
         final NetworkRequest request = new NetworkRequest.Builder().build();
         final NetworkRequest fgRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_FOREGROUND).build();
@@ -3765,6 +3769,7 @@
 
         mCm.unregisterNetworkCallback(callback);
         mCm.unregisterNetworkCallback(fgCallback);
+        mCm.unregisterNetworkCallback(cellBgCallback);
     }
 
     @Ignore // This test has instrinsic chances of spurious failures: ignore for continuous testing.
@@ -5195,20 +5200,22 @@
     private void expectForceUpdateIfaces(Network[] networks, String defaultIface,
             Integer vpnUid, String vpnIfname, String[] underlyingIfaces) throws Exception {
         ArgumentCaptor<Network[]> networksCaptor = ArgumentCaptor.forClass(Network[].class);
-        ArgumentCaptor<VpnInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(VpnInfo[].class);
+        ArgumentCaptor<UnderlyingNetworkInfo[]> vpnInfosCaptor = ArgumentCaptor.forClass(
+                UnderlyingNetworkInfo[].class);
 
         verify(mStatsService, atLeastOnce()).forceUpdateIfaces(networksCaptor.capture(),
                 any(NetworkState[].class), eq(defaultIface), vpnInfosCaptor.capture());
 
         assertSameElementsNoDuplicates(networksCaptor.getValue(), networks);
 
-        VpnInfo[] infos = vpnInfosCaptor.getValue();
+        UnderlyingNetworkInfo[] infos = vpnInfosCaptor.getValue();
         if (vpnUid != null) {
             assertEquals("Should have exactly one VPN:", 1, infos.length);
-            VpnInfo info = infos[0];
+            UnderlyingNetworkInfo info = infos[0];
             assertEquals("Unexpected VPN owner:", (int) vpnUid, info.ownerUid);
-            assertEquals("Unexpected VPN interface:", vpnIfname, info.vpnIface);
-            assertSameElementsNoDuplicates(underlyingIfaces, info.underlyingIfaces);
+            assertEquals("Unexpected VPN interface:", vpnIfname, info.iface);
+            assertSameElementsNoDuplicates(underlyingIfaces,
+                    info.underlyingIfaces.toArray(new String[0]));
         } else {
             assertEquals(0, infos.length);
             return;
@@ -5269,7 +5276,7 @@
         waitForIdle();
         verify(mStatsService, never())
                 .forceUpdateIfaces(eq(onlyCell), any(NetworkState[].class), eq(MOBILE_IFNAME),
-                        eq(new VpnInfo[0]));
+                        eq(new UnderlyingNetworkInfo[0]));
         reset(mStatsService);
 
         // Roaming change should update ifaces
@@ -5352,8 +5359,8 @@
         // network for the VPN...
         verify(mStatsService, never()).forceUpdateIfaces(any(Network[].class),
                 any(NetworkState[].class), any() /* anyString() doesn't match null */,
-                argThat(infos -> infos[0].underlyingIfaces.length == 1
-                        && WIFI_IFNAME.equals(infos[0].underlyingIfaces[0])));
+                argThat(infos -> infos[0].underlyingIfaces.size() == 1
+                        && WIFI_IFNAME.equals(infos[0].underlyingIfaces.get(0))));
         verifyNoMoreInteractions(mStatsService);
         reset(mStatsService);
 
@@ -5366,8 +5373,8 @@
         waitForIdle();
         verify(mStatsService).forceUpdateIfaces(any(Network[].class),
                 any(NetworkState[].class), any() /* anyString() doesn't match null */,
-                argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.length == 1
-                        && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces[0])));
+                argThat(vpnInfos -> vpnInfos[0].underlyingIfaces.size() == 1
+                        && WIFI_IFNAME.equals(vpnInfos[0].underlyingIfaces.get(0))));
         mEthernetNetworkAgent.disconnect();
         waitForIdle();
         reset(mStatsService);
@@ -8347,8 +8354,9 @@
         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
         mMockVpn.setVpnType(vpnType);
 
-        final VpnInfo vpnInfo = new VpnInfo(vpnOwnerUid, null, null);
-        mMockVpn.setVpnInfo(vpnInfo);
+        final UnderlyingNetworkInfo underlyingNetworkInfo =
+                new UnderlyingNetworkInfo(vpnOwnerUid, VPN_IFNAME, new ArrayList<String>());
+        mMockVpn.setUnderlyingNetworkInfo(underlyingNetworkInfo);
     }
 
     private void setupConnectionOwnerUidAsVpnApp(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
diff --git a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
index 1b33930e..a058a46 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsBaseTest.java
@@ -33,7 +33,9 @@
 import static org.junit.Assert.assertEquals;
 
 import android.net.NetworkStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
+
+import java.util.Arrays;
 
 /** Superclass with utilities for NetworkStats(Service|Factory)Test */
 abstract class NetworkStatsBaseTest {
@@ -107,11 +109,11 @@
         assertEquals("unexpected operations", operations, entry.operations);
     }
 
-    static VpnInfo createVpnInfo(String[] underlyingIfaces) {
+    static UnderlyingNetworkInfo createVpnInfo(String[] underlyingIfaces) {
         return createVpnInfo(TUN_IFACE, underlyingIfaces);
     }
 
-    static VpnInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) {
-        return new VpnInfo(UID_VPN, vpnIface, underlyingIfaces);
+    static UnderlyingNetworkInfo createVpnInfo(String vpnIface, String[] underlyingIfaces) {
+        return new UnderlyingNetworkInfo(UID_VPN, vpnIface, Arrays.asList(underlyingIfaces));
     }
 }
diff --git a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
index 76647a6..f3ae9b0 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -36,7 +36,7 @@
 import android.content.res.Resources;
 import android.net.NetworkStats;
 import android.net.TrafficStats;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -79,7 +79,7 @@
         // related to networkStatsFactory is compiled to a minimal native library and loaded here.
         System.loadLibrary("networkstatsfactorytestjni");
         mFactory = new NetworkStatsFactory(mTestProc, false);
-        mFactory.updateVpnInfos(new VpnInfo[0]);
+        mFactory.updateUnderlyingNetworkInfos(new UnderlyingNetworkInfo[0]);
     }
 
     @After
@@ -105,8 +105,9 @@
 
     @Test
     public void testVpnRewriteTrafficThroughItself() throws Exception {
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -134,8 +135,9 @@
 
     @Test
     public void testVpnWithClat() throws Exception {
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] {
+                createVpnInfo(new String[] {CLAT_PREFIX + TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
         mFactory.noteStackedIface(CLAT_PREFIX + TEST_IFACE, TEST_IFACE);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
@@ -167,8 +169,9 @@
 
     @Test
     public void testVpnWithOneUnderlyingIface() throws Exception {
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -191,8 +194,9 @@
     @Test
     public void testVpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception {
         // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -219,8 +223,9 @@
     @Test
     public void testVpnWithOneUnderlyingIface_withCompression() throws Exception {
         // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -242,8 +247,9 @@
         // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
         // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
         // Additionally, VPN is duplicating traffic across both WiFi and Cell.
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -267,10 +273,10 @@
     public void testConcurrentVpns() throws Exception {
         // Assume two VPNs are connected on two different network interfaces. VPN1 is using
         // TEST_IFACE and VPN2 is using TEST_IFACE2.
-        final VpnInfo[] vpnInfos = new VpnInfo[] {
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos = new UnderlyingNetworkInfo[] {
                 createVpnInfo(TUN_IFACE, new String[] {TEST_IFACE}),
                 createVpnInfo(TUN_IFACE2, new String[] {TEST_IFACE2})};
-        mFactory.updateVpnInfos(vpnInfos);
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -308,8 +314,9 @@
         // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
         // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
         // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell.
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
@@ -335,8 +342,9 @@
         // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
         // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
         // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell.
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface:
         // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
@@ -357,8 +365,9 @@
     public void testVpnWithIncorrectUnderlyingIface() throws Exception {
         // WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
         // but has declared only WiFi (TEST_IFACE) in its underlying network set.
-        VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
-        mFactory.updateVpnInfos(vpnInfos);
+        final UnderlyingNetworkInfo[] underlyingNetworkInfos =
+                new UnderlyingNetworkInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+        mFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
 
         // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
         // overhead per packet):
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index b4e37de..dde78aa 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -86,7 +86,7 @@
 import android.net.NetworkStats;
 import android.net.NetworkStatsHistory;
 import android.net.NetworkTemplate;
-import android.net.VpnInfo;
+import android.net.UnderlyingNetworkInfo;
 import android.net.netstats.provider.INetworkStatsProviderCallback;
 import android.os.ConditionVariable;
 import android.os.Handler;
@@ -286,7 +286,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -328,7 +329,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -401,7 +403,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // modify some number on wifi, and trigger poll event
         incrementCurrentTime(2 * HOUR_IN_MILLIS);
@@ -441,7 +444,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some traffic on first network
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -475,7 +479,8 @@
                 .insertEntry(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)
                 .insertEntry(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L));
 
-        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
         forcePollAndWaitForIdle();
 
 
@@ -514,7 +519,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -581,7 +587,7 @@
 
         setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
         mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
-                new VpnInfo[0]);
+                new UnderlyingNetworkInfo[0]);
 
         // Create some traffic.
         incrementCurrentTime(MINUTE_IN_MILLIS);
@@ -655,7 +661,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some traffic for two apps
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -713,7 +720,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         NetworkStats.Entry entry1 = new NetworkStats.Entry(
                 TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L);
@@ -756,7 +764,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         NetworkStats.Entry uidStats = new NetworkStats.Entry(
                 TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xF00D, 1024L, 8L, 512L, 4L, 0L);
@@ -810,7 +819,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some initial traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -867,7 +877,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some initial traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -906,7 +917,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // Create some traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -943,7 +955,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // create some tethering traffic
         incrementCurrentTime(HOUR_IN_MILLIS);
@@ -999,7 +1012,8 @@
         expectNetworkStatsSummary(buildEmptyStats());
         expectNetworkStatsUidDetail(buildEmptyStats());
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // verify service has empty history for wifi
         assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
@@ -1104,7 +1118,8 @@
                 mService.registerNetworkStatsProvider("TEST", provider);
         assertNotNull(cb);
 
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // Verifies that one requestStatsUpdate will be called during iface update.
         provider.expectOnRequestStatsUpdate(0 /* unused */);
@@ -1155,7 +1170,8 @@
         expectDefaultSettings();
         NetworkState[] states =
                 new NetworkState[]{buildWifiState(true /* isMetered */, TEST_IFACE)};
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // Register custom provider and retrieve callback.
         final TestableNetworkStatsProviderBinder provider =
@@ -1204,7 +1220,7 @@
         // 3G network comes online.
         setMobileRatTypeAndWaitForIdle(TelephonyManager.NETWORK_TYPE_UMTS);
         mService.forceUpdateIfaces(NETWORKS_MOBILE, states, getActiveIface(states),
-                new VpnInfo[0]);
+                new UnderlyingNetworkInfo[0]);
 
         // Create some traffic.
         incrementCurrentTime(MINUTE_IN_MILLIS);
@@ -1274,7 +1290,8 @@
         NetworkState[] states = new NetworkState[]{
                 buildWifiState(true /*isMetered*/, TEST_IFACE2), buildMobile3gState(IMSI_1)};
         expectNetworkStatsUidDetail(buildEmptyStats());
-        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states), new VpnInfo[0]);
+        mService.forceUpdateIfaces(NETWORKS_WIFI, states, getActiveIface(states),
+                new UnderlyingNetworkInfo[0]);
 
         // Create some traffic on mobile network.
         incrementCurrentTime(HOUR_IN_MILLIS);
diff --git a/tests/vcn/java/android/net/vcn/VcnManagerTest.java b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
index 9c6b719..f9db408 100644
--- a/tests/vcn/java/android/net/vcn/VcnManagerTest.java
+++ b/tests/vcn/java/android/net/vcn/VcnManagerTest.java
@@ -18,14 +18,19 @@
 
 import static androidx.test.InstrumentationRegistry.getContext;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.net.vcn.VcnManager.VcnUnderlyingNetworkPolicyListener;
 
 import org.junit.Before;
@@ -103,4 +108,28 @@
     public void testRemoveVcnUnderlyingNetworkPolicyListenerNullListener() {
         mVcnManager.removeVcnUnderlyingNetworkPolicyListener(null);
     }
+
+    @Test
+    public void testGetUnderlyingNetworkPolicy() throws Exception {
+        NetworkCapabilities nc = new NetworkCapabilities();
+        LinkProperties lp = new LinkProperties();
+        when(mMockVcnManagementService.getUnderlyingNetworkPolicy(eq(nc), eq(lp)))
+                .thenReturn(new VcnUnderlyingNetworkPolicy(false /* isTearDownRequested */, nc));
+
+        VcnUnderlyingNetworkPolicy policy = mVcnManager.getUnderlyingNetworkPolicy(nc, lp);
+
+        assertFalse(policy.isTeardownRequested());
+        assertEquals(nc, policy.getMergedNetworkCapabilities());
+        verify(mMockVcnManagementService).getUnderlyingNetworkPolicy(eq(nc), eq(lp));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testGetUnderlyingNetworkPolicyNullNetworkCapabilities() throws Exception {
+        mVcnManager.getUnderlyingNetworkPolicy(null, new LinkProperties());
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testGetUnderlyingNetworkPolicyNullLinkProperties() throws Exception {
+        mVcnManager.getUnderlyingNetworkPolicy(new NetworkCapabilities(), null);
+    }
 }
diff --git a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
index f0cdde3..e26bf19 100644
--- a/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
+++ b/tests/vcn/java/com/android/server/VcnManagementServiceTest.java
@@ -21,6 +21,8 @@
 import static com.android.server.vcn.VcnTestUtils.setupSystemService;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
@@ -41,9 +43,12 @@
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.net.ConnectivityManager;
+import android.net.LinkProperties;
+import android.net.NetworkCapabilities;
 import android.net.vcn.IVcnUnderlyingNetworkPolicyListener;
 import android.net.vcn.VcnConfig;
 import android.net.vcn.VcnConfigTest;
+import android.net.vcn.VcnUnderlyingNetworkPolicy;
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
@@ -63,6 +68,7 @@
 import com.android.server.vcn.VcnNetworkProvider;
 import com.android.server.vcn.util.PersistableBundleUtils;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
@@ -192,6 +198,14 @@
         mTestLooper.dispatchAll();
     }
 
+    @Before
+    public void setUp() {
+        doNothing()
+                .when(mMockContext)
+                .enforceCallingOrSelfPermission(
+                        eq(android.Manifest.permission.NETWORK_FACTORY), any());
+    }
+
     private void setupMockedCarrierPrivilege(boolean isPrivileged) {
         doReturn(Collections.singletonList(TEST_SUBSCRIPTION_INFO))
                 .when(mSubMgr)
@@ -455,10 +469,6 @@
 
     @Test
     public void testAddVcnUnderlyingNetworkPolicyListener() throws Exception {
-        doNothing()
-                .when(mMockContext)
-                .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
-
         mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
 
         verify(mMockIBinder).linkToDeath(any(), anyInt());
@@ -468,17 +478,14 @@
     public void testAddVcnUnderlyingNetworkPolicyListenerInvalidPermission() {
         doThrow(new SecurityException())
                 .when(mMockContext)
-                .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
+                .enforceCallingOrSelfPermission(
+                        eq(android.Manifest.permission.NETWORK_FACTORY), any());
 
         mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
     }
 
     @Test
     public void testRemoveVcnUnderlyingNetworkPolicyListener() {
-        // verify listener added
-        doNothing()
-                .when(mMockContext)
-                .enforceCallingPermission(eq(android.Manifest.permission.NETWORK_FACTORY), any());
         mVcnMgmtSvc.addVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
 
         mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
@@ -488,4 +495,24 @@
     public void testRemoveVcnUnderlyingNetworkPolicyListenerNeverRegistered() {
         mVcnMgmtSvc.removeVcnUnderlyingNetworkPolicyListener(mMockPolicyListener);
     }
+
+    @Test
+    public void testGetUnderlyingNetworkPolicy() throws Exception {
+        VcnUnderlyingNetworkPolicy policy =
+                mVcnMgmtSvc.getUnderlyingNetworkPolicy(
+                        new NetworkCapabilities(), new LinkProperties());
+
+        assertFalse(policy.isTeardownRequested());
+        assertNotNull(policy.getMergedNetworkCapabilities());
+    }
+
+    @Test(expected = SecurityException.class)
+    public void testGetUnderlyingNetworkPolicyInvalidPermission() {
+        doThrow(new SecurityException())
+                .when(mMockContext)
+                .enforceCallingOrSelfPermission(
+                        eq(android.Manifest.permission.NETWORK_FACTORY), any());
+
+        mVcnMgmtSvc.getUnderlyingNetworkPolicy(new NetworkCapabilities(), new LinkProperties());
+    }
 }