Merge "Add ART optimization dimension to reportFullyDrawn"
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 5bcf307..2c7ee21 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -582,6 +582,7 @@
         result = movie();
     }
 
+    mCallbacks->shutdown();
     eglMakeCurrent(mDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglDestroyContext(mDisplay, mContext);
     eglDestroySurface(mDisplay, mSurface);
@@ -668,7 +669,6 @@
     int exitnow = atoi(value);
     if (exitnow) {
         requestExit();
-        mCallbacks->shutdown();
     }
 }
 
diff --git a/cmds/statsd/OWNERS b/cmds/statsd/OWNERS
index a61babf..4e4e119 100644
--- a/cmds/statsd/OWNERS
+++ b/cmds/statsd/OWNERS
@@ -1,9 +1 @@
-jeffreyhuang@google.com
-joeo@google.com
-jtnguyen@google.com
-muhammadq@google.com
-ruchirr@google.com
-singhtejinder@google.com
-tsaichristine@google.com
-yaochen@google.com
-yro@google.com
+baligh@google.com
diff --git a/core/api/current.txt b/core/api/current.txt
index a20b58e..b579d2c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9051,6 +9051,15 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothHidDeviceAppSdpSettings> CREATOR;
   }
 
+  public final class BluetoothLeAudio implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public void close();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) protected void finalize();
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
+    field public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED = "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
+  }
+
   public final class BluetoothManager {
     method public android.bluetooth.BluetoothAdapter getAdapter();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices(int);
@@ -45091,6 +45100,7 @@
   }
 
   public static final class CarrierConfigManager.Ims {
+    field public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL = "ims.enable_presence_publish_bool";
     field public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL = "ims.ims_single_registration_required_bool";
     field public static final String KEY_PREFIX = "ims.";
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT = "ims.wifi_off_deferring_time_millis_int";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 3d69cbd..44917df 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5986,6 +5986,7 @@
     field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
     field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
     field public static final int TYPE_NONE = -1; // 0xffffffff
+    field @Deprecated public static final int TYPE_PROXY = 16; // 0x10
     field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
   }
 
@@ -10153,6 +10154,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
     method @Nullable public android.os.Bundle getVisualVoicemailSettings();
diff --git a/core/java/android/bluetooth/BluetoothLeAudio.java b/core/java/android/bluetooth/BluetoothLeAudio.java
new file mode 100644
index 0000000..3f00fa6
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothLeAudio.java
@@ -0,0 +1,451 @@
+/*
+ * Copyright 2020 HIMSA II K/S - www.himsa.com.
+ * Represented by EHIMA - www.ehima.com
+ *
+ * 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.bluetooth;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.CloseGuard;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class provides the public APIs to control the LeAudio profile.
+ *
+ * <p>BluetoothLeAudio is a proxy object for controlling the Bluetooth LE Audio
+ * Service via IPC. Use {@link BluetoothAdapter#getProfileProxy} to get
+ * the BluetoothLeAudio proxy object.
+ *
+ * <p> Android only supports one set of connected Bluetooth LeAudio device at a time. Each
+ * method is protected with its appropriate permission.
+ */
+public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable {
+    private static final String TAG = "BluetoothLeAudio";
+    private static final boolean DBG = false;
+    private static final boolean VDBG = false;
+
+    private CloseGuard mCloseGuard;
+
+    /**
+     * Intent used to broadcast the change in connection state of the LeAudio
+     * profile. Please note that in the binaural case, there will be two different LE devices for
+     * the left and right side and each device will have their own connection state changes.
+     *
+     * <p>This intent will have 3 extras:
+     * <ul>
+     * <li> {@link #EXTRA_STATE} - The current state of the profile. </li>
+     * <li> {@link #EXTRA_PREVIOUS_STATE}- The previous state of the profile.</li>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. </li>
+     * </ul>
+     *
+     * <p>{@link #EXTRA_STATE} or {@link #EXTRA_PREVIOUS_STATE} can be any of
+     * {@link #STATE_DISCONNECTED}, {@link #STATE_CONNECTING},
+     * {@link #STATE_CONNECTED}, {@link #STATE_DISCONNECTING}.
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_CONNECTION_STATE_CHANGED";
+
+    /**
+     * Intent used to broadcast the selection of a connected device as active.
+     *
+     * <p>This intent will have one extra:
+     * <ul>
+     * <li> {@link BluetoothDevice#EXTRA_DEVICE} - The remote device. It can
+     * be null if no device is active. </li>
+     * </ul>
+     *
+     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission to
+     * receive.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_LE_AUDIO_ACTIVE_DEVICE_CHANGED =
+            "android.bluetooth.action.LE_AUDIO_ACTIVE_DEVICE_CHANGED";
+
+    /**
+     * This represents an invalid group ID.
+     *
+     * @hide
+     */
+    public static final int GROUP_ID_INVALID = IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID;
+
+    private BluetoothAdapter mAdapter;
+    private final BluetoothProfileConnector<IBluetoothLeAudio> mProfileConnector =
+            new BluetoothProfileConnector(this, BluetoothProfile.LE_AUDIO, "BluetoothLeAudio",
+                    IBluetoothLeAudio.class.getName()) {
+                @Override
+                public IBluetoothLeAudio getServiceInterface(IBinder service) {
+                    return IBluetoothLeAudio.Stub.asInterface(Binder.allowBlocking(service));
+                }
+    };
+
+    /**
+     * Create a BluetoothLeAudio proxy object for interacting with the local
+     * Bluetooth LeAudio service.
+     */
+    /*package*/ BluetoothLeAudio(Context context, ServiceListener listener) {
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        mProfileConnector.connect(context, listener);
+        mCloseGuard = new CloseGuard();
+        mCloseGuard.open("close");
+    }
+
+    /**
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public void close() {
+        mProfileConnector.disconnect();
+    }
+
+    private IBluetoothLeAudio getService() {
+        return mProfileConnector.getService();
+    }
+
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    protected void finalize() {
+        if (mCloseGuard != null) {
+            mCloseGuard.warnIfOpen();
+        }
+        close();
+    }
+
+    /**
+     * Initiate connection to a profile of the remote bluetooth device.
+     *
+     * <p> This API returns false in scenarios like the profile on the
+     * device is already connected or Bluetooth is not turned on.
+     * When this API returns true, it is guaranteed that
+     * connection state intent for the profile will be broadcasted with
+     * the state. Users can get the connection state of the profile
+     * from this intent.
+     *
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error, true otherwise
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean connect(@Nullable BluetoothDevice device) {
+        if (DBG) log("connect(" + device + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled() && isValidDevice(device)) {
+                return service.connect(device);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * Initiate disconnection from a profile
+     *
+     * <p> This API will return false in scenarios like the profile on the
+     * Bluetooth device is not in connected state etc. When this API returns,
+     * true, it is guaranteed that the connection state change
+     * intent will be broadcasted with the state. Users can get the
+     * disconnection state of the profile from this intent.
+     *
+     * <p> If the disconnection is initiated by a remote device, the state
+     * will transition from {@link #STATE_CONNECTED} to
+     * {@link #STATE_DISCONNECTED}. If the disconnect is initiated by the
+     * host (local) device the state will transition from
+     * {@link #STATE_CONNECTED} to state {@link #STATE_DISCONNECTING} to
+     * state {@link #STATE_DISCONNECTED}. The transition to
+     * {@link #STATE_DISCONNECTING} can be used to distinguish between the
+     * two scenarios.
+     *
+     *
+     * @param device Remote Bluetooth Device
+     * @return false on immediate error, true otherwise
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean disconnect(@Nullable BluetoothDevice device) {
+        if (DBG) log("disconnect(" + device + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled() && isValidDevice(device)) {
+                return service.disconnect(device);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public @NonNull List<BluetoothDevice> getConnectedDevices() {
+        if (VDBG) log("getConnectedDevices()");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()) {
+                return service.getConnectedDevices();
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return new ArrayList<BluetoothDevice>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<BluetoothDevice>();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+            @NonNull int[] states) {
+        if (VDBG) log("getDevicesMatchingStates()");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()) {
+                return service.getDevicesMatchingConnectionStates(states);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return new ArrayList<BluetoothDevice>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<BluetoothDevice>();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @BtProfileState int getConnectionState(@NonNull BluetoothDevice device) {
+        if (VDBG) log("getState(" + device + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()
+                    && isValidDevice(device)) {
+                return service.getConnectionState(device);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return BluetoothProfile.STATE_DISCONNECTED;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return BluetoothProfile.STATE_DISCONNECTED;
+        }
+    }
+
+    /**
+     * Select a connected device as active.
+     *
+     * The active device selection is per profile. An active device's
+     * purpose is profile-specific. For example, LeAudio audio
+     * streaming is to the active LeAudio device. If a remote device
+     * is not connected, it cannot be selected as active.
+     *
+     * <p> This API returns false in scenarios like the profile on the
+     * device is not connected or Bluetooth is not turned on.
+     * When this API returns true, it is guaranteed that the
+     * {@link #ACTION_LEAUDIO_ACTIVE_DEVICE_CHANGED} intent will be broadcasted
+     * with the active device.
+     *
+     *
+     * @param device the remote Bluetooth device. Could be null to clear
+     * the active device and stop streaming audio to a Bluetooth device.
+     * @return false on immediate error, true otherwise
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean setActiveDevice(@Nullable BluetoothDevice device) {
+        if (DBG) log("setActiveDevice(" + device + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()
+                    && ((device == null) || isValidDevice(device))) {
+                service.setActiveDevice(device);
+                return true;
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * Get the connected LeAudio devices that are active
+     *
+     * @return the list of active devices. Returns empty list on error.
+     * @hide
+     */
+    @NonNull
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public List<BluetoothDevice> getActiveDevices() {
+        if (VDBG) log("getActiveDevices()");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()) {
+                return service.getActiveDevices();
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return new ArrayList<>();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return new ArrayList<>();
+        }
+    }
+
+    /**
+     * Get device group id. Devices with same group id belong to same group (i.e left and right
+     * earbud)
+     * @param device LE Audio capable device
+     * @return group id that this device currently belongs to
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getGroupId(@NonNull BluetoothDevice device) {
+        if (VDBG) log("getGroupId()");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()) {
+                return service.getGroupId(device);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return GROUP_ID_INVALID;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return GROUP_ID_INVALID;
+        }
+    }
+
+    /**
+     * Set connection policy of the profile
+     *
+     * <p> The device should already be paired.
+     * Connection policy can be one of {@link #CONNECTION_POLICY_ALLOWED},
+     * {@link #CONNECTION_POLICY_FORBIDDEN}, {@link #CONNECTION_POLICY_UNKNOWN}
+     *
+     * @param device Paired bluetooth device
+     * @param connectionPolicy is the connection policy to set to for this profile
+     * @return true if connectionPolicy is set, false on error
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()
+                    && isValidDevice(device)) {
+                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                        && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
+                    return false;
+                }
+                return service.setConnectionPolicy(device, connectionPolicy);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return false;
+        }
+    }
+
+    /**
+     * Get the connection policy of the profile.
+     *
+     * <p> The connection policy can be any of:
+     * {@link #CONNECTION_POLICY_ALLOWED}, {@link #CONNECTION_POLICY_FORBIDDEN},
+     * {@link #CONNECTION_POLICY_UNKNOWN}
+     *
+     * @param device Bluetooth device
+     * @return connection policy of the device
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
+    public @ConnectionPolicy int getConnectionPolicy(@Nullable BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
+        try {
+            final IBluetoothLeAudio service = getService();
+            if (service != null && mAdapter.isEnabled()
+                    && isValidDevice(device)) {
+                return service.getConnectionPolicy(device);
+            }
+            if (service == null) Log.w(TAG, "Proxy not attached to service");
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        } catch (RemoteException e) {
+            Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+        }
+    }
+
+
+    /**
+     * Helper for converting a state to a string.
+     *
+     * For debug use only - strings are not internationalized.
+     *
+     * @hide
+     */
+    public static String stateToString(int state) {
+        switch (state) {
+            case STATE_DISCONNECTED:
+                return "disconnected";
+            case STATE_CONNECTING:
+                return "connecting";
+            case STATE_CONNECTED:
+                return "connected";
+            case STATE_DISCONNECTING:
+                return "disconnecting";
+            default:
+                return "<unknown state " + state + ">";
+        }
+    }
+
+    private boolean isValidDevice(@Nullable BluetoothDevice device) {
+        if (device == null) return false;
+
+        if (BluetoothAdapter.checkBluetoothAddress(device.getAddress())) return true;
+        return false;
+    }
+
+    private static void log(String msg) {
+        Log.d(TAG, msg);
+    }
+}
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index db851c4..c31b04e 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -207,12 +207,19 @@
     int HEARING_AID = 21;
 
     /**
+     * LE Audio Device
+     *
+     * @hide
+     */
+    int LE_AUDIO = 22;
+
+    /**
      * Max profile ID. This value should be updated whenever a new profile is added to match
      * the largest value assigned to a profile.
      *
      * @hide
      */
-    int MAX_PROFILE_ID = 21;
+    int MAX_PROFILE_ID = 22;
 
     /**
      * Default priority for devices that we try to auto-connect to and
diff --git a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
index 55b0726..6b2bab4 100644
--- a/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
+++ b/core/java/android/hardware/hdmi/HdmiDeviceInfo.java
@@ -513,4 +513,19 @@
                 && mDeviceId == other.mDeviceId
                 && mAdopterId == other.mAdopterId;
     }
+
+    @Override
+    public int hashCode() {
+        return java.util.Objects.hash(
+                mHdmiDeviceType,
+                mPhysicalAddress,
+                mPortId,
+                mLogicalAddress,
+                mDeviceType,
+                mVendorId,
+                mDevicePowerStatus,
+                mDisplayName,
+                mDeviceId,
+                mAdopterId);
+    }
 }
diff --git a/core/java/android/net/CaptivePortal.java b/core/java/android/net/CaptivePortal.java
index c2586fa..269bbf2 100644
--- a/core/java/android/net/CaptivePortal.java
+++ b/core/java/android/net/CaptivePortal.java
@@ -15,7 +15,6 @@
  */
 package android.net;
 
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
@@ -24,8 +23,6 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-
 /**
  * A class allowing apps handling the {@link ConnectivityManager#ACTION_CAPTIVE_PORTAL_SIGN_IN}
  * activity to indicate to the system different outcomes of captive portal sign in.  This class is
@@ -75,17 +72,6 @@
     private final IBinder mBinder;
 
     /** @hide */
-    @IntDef(value = {
-        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_ACTIVITY,
-        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_DISMISSED,
-        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_UNWANTED,
-        MetricsEvent.ACTION_CAPTIVE_PORTAL_LOGIN_RESULT_WANTED_AS_IS,
-        MetricsEvent.CAPTIVE_PORTAL_LOGIN_ACTIVITY_SSL_ERROR,
-    })
-    public @interface EventId {
-    }
-
-    /** @hide */
     public CaptivePortal(@NonNull IBinder binder) {
         mBinder = binder;
     }
@@ -176,7 +162,7 @@
      * @hide
      */
     @SystemApi
-    public void logEvent(@EventId int eventId, @NonNull String packageName) {
+    public void logEvent(int eventId, @NonNull String packageName) {
         try {
             ICaptivePortal.Stub.asInterface(mBinder).logEvent(eventId, packageName);
         } catch (RemoteException e) {
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c28a901..cf5d4e5 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -684,7 +684,7 @@
      * {@hide}
      */
     @Deprecated
-    @UnsupportedAppUsage
+    @SystemApi
     public static final int TYPE_PROXY = 16;
 
     /**
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 522add1..8b06ebe 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -19,7 +19,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import com.android.internal.util.BitUtils;
+import java.util.BitSet;
 
 /**
  * Represents a core networking event defined in package android.net.metrics.
@@ -86,9 +86,7 @@
         if (ifname != null) {
             buffer.append(", ").append(ifname);
         }
-        for (int t : BitUtils.unpackBits(transports)) {
-            buffer.append(", ").append(NetworkCapabilities.transportNameOf(t));
-        }
+        buffer.append(", transports=").append(BitSet.valueOf(new long[] { transports }));
         buffer.append("): ").append(data.toString());
         return buffer.toString();
     }
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 0948a4da..efbfbf9 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -17,7 +17,6 @@
 package android.net;
 
 import static android.net.ConnectivityManager.TYPE_WIFI;
-import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeMobile;
 
 import android.content.Context;
@@ -84,7 +83,7 @@
     @Override
     public String toString() {
         final StringBuilder builder = new StringBuilder("{");
-        builder.append("type=").append(getNetworkTypeName(mType));
+        builder.append("type=").append(mType);
         builder.append(", subType=");
         if (mSubType == SUBTYPE_COMBINED) {
             builder.append("COMBINED");
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a643d09..f05f033 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -144,6 +144,8 @@
     public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
     /** @hide */
     public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
+    /** @hide */
+    public static final String FIREWALL_CHAIN_NAME_RESTRICTED = "restricted";
 
     private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
 
diff --git a/core/java/android/net/NetworkProvider.java b/core/java/android/net/NetworkProvider.java
index a17a498..14cb51c 100644
--- a/core/java/android/net/NetworkProvider.java
+++ b/core/java/android/net/NetworkProvider.java
@@ -63,7 +63,7 @@
 
     private final Messenger mMessenger;
     private final String mName;
-    private final ConnectivityManager mCm;
+    private final Context mContext;
 
     private int mProviderId = ID_NONE;
 
@@ -78,8 +78,6 @@
      */
     @SystemApi
     public NetworkProvider(@NonNull Context context, @NonNull Looper looper, @NonNull String name) {
-        mCm = ConnectivityManager.from(context);
-
         Handler handler = new Handler(looper) {
             @Override
             public void handleMessage(Message m) {
@@ -95,6 +93,7 @@
                 }
             }
         };
+        mContext = context;
         mMessenger = new Messenger(handler);
         mName = name;
     }
@@ -158,6 +157,6 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY)
     public void declareNetworkRequestUnfulfillable(@NonNull NetworkRequest request) {
-        mCm.declareNetworkRequestUnfulfillable(request);
+        ConnectivityManager.from(mContext).declareNetworkRequestUnfulfillable(request);
     }
 }
diff --git a/core/java/android/net/metrics/ConnectStats.java b/core/java/android/net/metrics/ConnectStats.java
index b320b75..c67259d 100644
--- a/core/java/android/net/metrics/ConnectStats.java
+++ b/core/java/android/net/metrics/ConnectStats.java
@@ -16,14 +16,14 @@
 
 package android.net.metrics;
 
-import android.net.NetworkCapabilities;
 import android.system.OsConstants;
 import android.util.IntArray;
 import android.util.SparseIntArray;
 
-import com.android.internal.util.BitUtils;
 import com.android.internal.util.TokenBucket;
 
+import java.util.BitSet;
+
 /**
  * A class that aggregates connect() statistics.
  * {@hide}
@@ -120,10 +120,9 @@
     @Override
     public String toString() {
         StringBuilder builder =
-                new StringBuilder("ConnectStats(").append("netId=").append(netId).append(", ");
-        for (int t : BitUtils.unpackBits(transports)) {
-            builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
-        }
+                new StringBuilder("ConnectStats(").append("netId=").append(netId)
+                        .append(", transports=").append(BitSet.valueOf(new long[] { transports }))
+                        .append(", ");
         builder.append(String.format("%d events, ", eventCount));
         builder.append(String.format("%d success, ", connectCount));
         builder.append(String.format("%d blocking, ", connectBlockingCount));
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index 6f383b4..8988983 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -16,12 +16,7 @@
 
 package android.net.metrics;
 
-import static android.net.ConnectivityManager.NETID_UNSET;
-
-import android.net.NetworkCapabilities;
-
-import com.android.internal.util.BitUtils;
-
+import java.util.BitSet;
 import java.util.StringJoiner;
 
 /**
@@ -32,8 +27,8 @@
 
     // The creation time in milliseconds of this DefaultNetworkEvent.
     public final long creationTimeMs;
-    // The network ID of the network or NETID_UNSET if none.
-    public int netId = NETID_UNSET;
+    // The network ID of the network or 0 if none.
+    public int netId = 0;
     // The list of transport types, as defined in NetworkCapabilities.java.
     public int transports;
     // The list of transport types of the last previous default network.
@@ -63,9 +58,7 @@
     public String toString() {
         StringJoiner j = new StringJoiner(", ", "DefaultNetworkEvent(", ")");
         j.add("netId=" + netId);
-        for (int t : BitUtils.unpackBits(transports)) {
-            j.add(NetworkCapabilities.transportNameOf(t));
-        }
+        j.add("transports=" + BitSet.valueOf(new long[] { transports }));
         j.add("ip=" + ipSupport());
         if (initialScore > 0) {
             j.add("initial_score=" + initialScore);
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index 5aa705b..bf351ce 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -16,11 +16,8 @@
 
 package android.net.metrics;
 
-import android.net.NetworkCapabilities;
-
-import com.android.internal.util.BitUtils;
-
 import java.util.Arrays;
+import java.util.BitSet;
 
 /**
  * A batch of DNS events recorded by NetdEventListenerService for a specific network.
@@ -86,10 +83,10 @@
     @Override
     public String toString() {
         StringBuilder builder =
-                new StringBuilder("DnsEvent(").append("netId=").append(netId).append(", ");
-        for (int t : BitUtils.unpackBits(transports)) {
-            builder.append(NetworkCapabilities.transportNameOf(t)).append(", ");
-        }
+                new StringBuilder("DnsEvent(").append("netId=").append(netId)
+                        .append(", transports=")
+                        .append(BitSet.valueOf(new long[] { transports }))
+                        .append(", ");
         builder.append(String.format("%d events, ", eventCount));
         builder.append(String.format("%d success)", successCount));
         return builder.toString();
diff --git a/core/java/android/net/metrics/NetworkMetrics.java b/core/java/android/net/metrics/NetworkMetrics.java
index 66d92c4..8f2f612 100644
--- a/core/java/android/net/metrics/NetworkMetrics.java
+++ b/core/java/android/net/metrics/NetworkMetrics.java
@@ -16,11 +16,9 @@
 
 package android.net.metrics;
 
-import android.net.NetworkCapabilities;
-
-import com.android.internal.util.BitUtils;
 import com.android.internal.util.TokenBucket;
 
+import java.util.BitSet;
 import java.util.StringJoiner;
 
 /**
@@ -144,9 +142,7 @@
         public String toString() {
             StringJoiner j = new StringJoiner(", ", "{", "}");
             j.add("netId=" + netId);
-            for (int t : BitUtils.unpackBits(transports)) {
-                j.add(NetworkCapabilities.transportNameOf(t));
-            }
+            j.add("transports=" + BitSet.valueOf(new long[] { transports }));
             j.add(String.format("dns avg=%dms max=%dms err=%.1f%% tot=%d",
                     (int) dnsLatencies.average(), (int) dnsLatencies.max,
                     100 * dnsErrorRate.average(), dnsErrorRate.count));
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a0d2f0d..49b4e00 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -65,7 +65,7 @@
     /* NOTE: Wake lock levels were previously defined as a bit field, except that only a few
      * combinations were actually supported so the bit field was removed.  This explains
      * why the numbering scheme is so odd.  If adding a new wake lock level, any unused
-     * value (in frameworks/base/core/proto/android/os/enums.proto) can be used.
+     * value (in frameworks/proto_logging/stats/enums/os/enums.proto) can be used.
      */
 
     /**
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 8926b27..67d5f5f 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -3172,28 +3172,55 @@
     }
 
     /**
-     * Returns information for all users on this device, including ones marked for deletion.
-     * To retrieve only users that are alive, use {@link #getUsers(boolean)}.
+     * Returns information for all fully-created users on this device, including ones marked for
+     * deletion.
      *
-     * @return the list of users that exist on the device.
+     * <p>To retrieve only users that are not marked for deletion, use {@link #getAliveUsers()}.
+     *
+     * <p>To retrieve *all* users (including partial and pre-created users), use
+     * {@link #getUsers(boolean, boolean, boolean)) getUsers(false, false, false)}.
+     *
+     * <p>To retrieve a more specific list of users, use
+     * {@link #getUsers(boolean, boolean, boolean)}.
+     *
+     * @return the list of users that were created.
+     *
      * @hide
      */
     @UnsupportedAppUsage
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public List<UserInfo> getUsers() {
-        return getUsers(/* excludeDying= */ false);
+        return getUsers(/*excludePartial= */ true, /* excludeDying= */ false,
+                /* excludePreCreated= */ true);
     }
 
     /**
-     * Returns information for all users on this device. Requires
-     * {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Returns information for all "usable" users on this device (i.e, it excludes users that are
+     * marked for deletion, pre-created users, etc...).
      *
-     * @param excludeDying specify if the list should exclude users being
-     *            removed.
+     * <p>To retrieve all fully-created users, use {@link #getUsers()}.
+     *
+     * <p>To retrieve a more specific list of users, use
+     * {@link #getUsers(boolean, boolean, boolean)}.
+     *
      * @return the list of users that were created.
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    public @NonNull List<UserInfo> getAliveUsers() {
+        return getUsers(/*excludePartial= */ true, /* excludeDying= */ true,
+                /* excludePreCreated= */ true);
+    }
+
+    /**
+     * @deprecated use {@link #getAliveUsers()} for {@code getUsers(true)}, or
+     * {@link #getUsers()} for @code getUsers(false)}.
+     *
+     * @hide
+     */
+    @Deprecated
     @UnsupportedAppUsage
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
         return getUsers(/*excludePartial= */ true, excludeDying,
                 /* excludePreCreated= */ true);
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index e6bb088..3edc154 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -200,6 +200,21 @@
         internalPath = parcel.readString8();
     }
 
+    public VolumeInfo(VolumeInfo volumeInfo) {
+        this.id = volumeInfo.id;
+        this.type = volumeInfo.type;
+        this.disk = volumeInfo.disk;
+        this.partGuid = volumeInfo.partGuid;
+        this.mountFlags = volumeInfo.mountFlags;
+        this.mountUserId = volumeInfo.mountUserId;
+        this.state = volumeInfo.state;
+        this.fsType = volumeInfo.fsType;
+        this.fsUuid = volumeInfo.fsUuid;
+        this.fsLabel = volumeInfo.fsLabel;
+        this.path = volumeInfo.path;
+        this.internalPath = volumeInfo.internalPath;
+    }
+
     @UnsupportedAppUsage
     public static @NonNull String getEnvironmentForState(int state) {
         final String envState = sStateToEnvironment.get(state);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 1f62544..7493e39 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -336,7 +336,7 @@
             return (jint)AUDIO_JAVA_BAD_VALUE;
         }
         const char *address = env->GetStringUTFChars((jstring)addrJobj, NULL);
-        AudioDeviceTypeAddr dev = AudioDeviceTypeAddr(typesPtr[i], address);
+        AudioDeviceTypeAddr dev = AudioDeviceTypeAddr((audio_devices_t)typesPtr[i], address);
         audioDeviceTypeAddrVector.add(dev);
         env->ReleaseStringUTFChars((jstring)addrJobj, address);
     }
@@ -818,7 +818,8 @@
                                                bool useInMask)
 {
     nAudioGainConfig->index = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mIndex);
-    nAudioGainConfig->mode = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
+    nAudioGainConfig->mode =
+            (audio_gain_mode_t)env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mMode);
     ALOGV("convertAudioGainConfigToNative got gain index %d", nAudioGainConfig->index);
     jint jMask = env->GetIntField(jAudioGainConfig, gAudioGainConfigFields.mChannelMask);
     audio_channel_mask_t nMask;
@@ -938,8 +939,8 @@
 
     jobject jAudioDevicePort = env->GetObjectField(jAudioPortConfig,
             gAudioPortConfigFields.mPort);
-    nAudioPortConfig->ext.device.type = env->GetIntField(jAudioDevicePort,
-            gAudioPortFields.mType);
+    nAudioPortConfig->ext.device.type =
+            (audio_devices_t)env->GetIntField(jAudioDevicePort, gAudioPortFields.mType);
     jstring jDeviceAddress = (jstring)env->GetObjectField(jAudioDevicePort,
             gAudioPortFields.mAddress);
     const char *nDeviceAddress = env->GetStringUTFChars(jDeviceAddress, NULL);
@@ -2332,7 +2333,7 @@
 
 static jint
 android_media_AudioSystem_setAllowedCapturePolicy(JNIEnv *env, jobject thiz, jint uid, jint flags) {
-    return AudioSystem::setAllowedCapturePolicy(uid, flags);
+    return AudioSystem::setAllowedCapturePolicy(uid, static_cast<audio_flags_mask_t>(flags));
 }
 
 static jint
@@ -2367,8 +2368,10 @@
 
     const char *c_address = env->GetStringUTFChars(deviceAddress, NULL);
     int status = check_AudioSystem_Command(
-            AudioSystem::setPreferredDeviceForStrategy((product_strategy_t) strategy,
-                    AudioDeviceTypeAddr(deviceType, c_address)));
+            AudioSystem::setPreferredDeviceForStrategy((product_strategy_t)strategy,
+                                                       AudioDeviceTypeAddr((audio_devices_t)
+                                                                                   deviceType,
+                                                                           c_address)));
     env->ReleaseStringUTFChars(deviceAddress, c_address);
     return (jint) status;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a417f0c..e6619f5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3032,6 +3032,12 @@
     <permission android:name="android.permission.DUMP"
         android:protectionLevel="signature|privileged|development" />
 
+    <!-- Allows an application to start tracing for InputMethod and WindowManager.
+    <p>Not for use by third-party applications.
+    @hide -->
+    <permission android:name="android.permission.CONTROL_UI_TRACING"
+        android:protectionLevel="signature|privileged|development" />
+
     <!-- Allows an application to read the low-level system log files.
     <p>Not for use by third-party applications, because
     Log entries can contain the user's private information. -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2b2bf8d..7fdbad0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1532,6 +1532,14 @@
     <!-- Class name of WallpaperManagerService. -->
     <string name="config_wallpaperManagerServiceName" translatable="false">com.android.server.wallpaper.WallpaperManagerService</string>
 
+    <!-- Specifies priority of automatic time sources. Suggestions from higher entries in the list
+         take precedence over lower ones.
+         See com.android.server.timedetector.TimeDetectorStrategy for available sources. -->
+    <string-array name="config_autoTimeSourcesPriority">
+        <item>telephony</item>
+        <item>network</item>
+    </string-array>
+
     <!-- Enables the TimeZoneRuleManager service. This is the global switch for the updateable time
          zone update mechanism. -->
     <bool name="config_enableUpdateableTimeZoneRules">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index c51dca1..36e94e5 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2161,6 +2161,7 @@
   <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
   <java-symbol type="string" name="config_persistentDataPackageName" />
   <java-symbol type="string" name="config_deviceConfiguratorPackageName" />
+  <java-symbol type="array" name="config_autoTimeSourcesPriority" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 2194d4b..4755e0e 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -19,6 +19,7 @@
     static_libs: [
         "androidx.test.rules",
         "frameworks-base-testutils",
+        "guava-android-testlib",
         "truth-prebuilt",
     ],
     libs: ["android.test.runner"],
diff --git a/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
new file mode 100755
index 0000000..4c0de62
--- /dev/null
+++ b/core/tests/hdmitests/src/android/hardware/hdmi/HdmiDeviceInfoTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.hdmi;
+
+import androidx.test.filters.SmallTest;
+
+import com.google.common.testing.EqualsTester;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link HdmiDeviceInfo} */
+@RunWith(JUnit4.class)
+@SmallTest
+public class HdmiDeviceInfoTest {
+
+    @Test
+    public void testEquals() {
+        int logicalAddr = 0x00;
+        int phyAddr = 0x1000;
+        int portId = 1;
+        int deviceType = 0;
+        int vendorId = 0x123456;
+        String displayName = "test device";
+        int powerStatus = HdmiControlManager.POWER_STATUS_TRANSIENT_TO_STANDBY;
+        int deviceId = 3;
+        int adopterId = 2;
+
+        new EqualsTester()
+                .addEqualityGroup(new HdmiDeviceInfo())
+                .addEqualityGroup(
+                        new HdmiDeviceInfo(phyAddr, portId), new HdmiDeviceInfo(phyAddr, portId))
+                .addEqualityGroup(
+                        new HdmiDeviceInfo(phyAddr, portId, adopterId, deviceId),
+                        new HdmiDeviceInfo(phyAddr, portId, adopterId, deviceId))
+                .addEqualityGroup(
+                        new HdmiDeviceInfo(
+                                logicalAddr, phyAddr, portId, deviceType, vendorId, displayName),
+                        new HdmiDeviceInfo(
+                                logicalAddr, phyAddr, portId, deviceType, vendorId, displayName))
+                .addEqualityGroup(
+                        new HdmiDeviceInfo(
+                                logicalAddr,
+                                phyAddr,
+                                portId,
+                                deviceType,
+                                vendorId,
+                                displayName,
+                                powerStatus),
+                        new HdmiDeviceInfo(
+                                logicalAddr,
+                                phyAddr,
+                                portId,
+                                deviceType,
+                                vendorId,
+                                displayName,
+                                powerStatus))
+                .testEquals();
+    }
+}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 0806e71..ce6deeab 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -316,6 +316,7 @@
         <permission name="android.permission.DELETE_CACHE_FILES"/>
         <permission name="android.permission.DELETE_PACKAGES"/>
         <permission name="android.permission.DUMP"/>
+        <permission name="android.permission.CONTROL_UI_TRACING"/>
         <permission name="android.permission.ACTIVITY_EMBEDDING"/>
         <permission name="android.permission.FORCE_STOP_PACKAGES"/>
         <permission name="android.permission.GET_APP_OPS_STATS"/>
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 96961ac2..d55e9d0 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -331,7 +331,7 @@
     }
 
     if (deviceType != AUDIO_DEVICE_NONE) {
-        device.mType = deviceType;
+        device.mType = (audio_devices_t)deviceType;
         ScopedUtfChars address(env, deviceAddress);
         device.mAddress = address.c_str();
     }
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index ca3cc855..26725f8 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -200,7 +200,7 @@
     paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
     paa->content_type =
             (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
-    paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
+    paa->flags = (audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
 
     ALOGV("android_media_SoundPool_native_setup");
     auto *ap = new SoundPool(maxChannels, paa);
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a927997..fa4da28 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -70,6 +70,7 @@
     <uses-permission android:name="android.permission.SET_PROCESS_LIMIT" />
     <uses-permission android:name="android.permission.SET_ALWAYS_FINISH" />
     <uses-permission android:name="android.permission.DUMP" />
+    <uses-permission android:name="android.permission.CONTROL_UI_TRACING" />
     <uses-permission android:name="android.permission.SIGNAL_PERSISTENT_PROCESSES" />
     <uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
     <!-- Internal permissions granted to the shell. -->
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f056117..e0a484f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -41,6 +41,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
@@ -170,7 +171,6 @@
 import android.util.LocalLog;
 import android.util.Log;
 import android.util.Pair;
-import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.util.Xml;
@@ -1972,7 +1972,7 @@
     private void registerNetdEventCallback() {
         final IIpConnectivityMetrics ipConnectivityMetrics = mDeps.getIpConnectivityMetrics();
         if (ipConnectivityMetrics == null) {
-            Slog.wtf(TAG, "Missing IIpConnectivityMetrics");
+            Log.wtf(TAG, "Missing IIpConnectivityMetrics");
             return;
         }
 
@@ -2438,7 +2438,7 @@
             if (VDBG || DDBG) log("Setting MTU size: " + iface + ", " + mtu);
             mNetd.interfaceSetMtu(iface, mtu);
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "exception in interfaceSetMtu()" + e);
+            loge("exception in interfaceSetMtu()" + e);
         }
     }
 
@@ -2460,7 +2460,7 @@
         if (tcpBufferSizes.equals(mCurrentTcpBufferSizes)) return;
 
         try {
-            if (VDBG || DDBG) Slog.d(TAG, "Setting tx/rx TCP buffers to " + tcpBufferSizes);
+            if (VDBG || DDBG) log("Setting tx/rx TCP buffers to " + tcpBufferSizes);
 
             String rmemValues = String.join(" ", values[0], values[1], values[2]);
             String wmemValues = String.join(" ", values[3], values[4], values[5]);
@@ -2761,7 +2761,7 @@
                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
                     NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
                     if (networkCapabilities.hasConnectivityManagedCapability()) {
-                        Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
+                        Log.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
                     }
                     if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
                         // Make sure the original object is not mutated. NetworkAgent normally
@@ -3066,7 +3066,7 @@
             // Legacy version of notifyNetworkTestedWithExtras.
             // Would only be called if the system has a NetworkStack module older than the
             // framework, which does not happen in practice.
-            Slog.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken");
+            Log.wtf(TAG, "Deprecated notifyNetworkTested called: no action taken");
         }
 
         @Override
@@ -3543,7 +3543,7 @@
                 numRequests = nai.numForegroundNetworkRequests();
                 break;
             default:
-                Slog.wtf(TAG, "Invalid reason. Cannot happen.");
+                Log.wtf(TAG, "Invalid reason. Cannot happen.");
                 return true;
         }
 
@@ -3705,7 +3705,7 @@
         synchronized (mUidToNetworkRequestCount) {
             final int requests = mUidToNetworkRequestCount.get(nri.mUid, 0);
             if (requests < 1) {
-                Slog.wtf(TAG, "BUG: too small request count " + requests + " for UID " + nri.mUid);
+                Log.wtf(TAG, "BUG: too small request count " + requests + " for UID " + nri.mUid);
             } else if (requests == 1) {
                 mUidToNetworkRequestCount.removeAt(mUidToNetworkRequestCount.indexOfKey(nri.mUid));
             } else {
@@ -3750,7 +3750,7 @@
         }
 
         if (!nai.networkAgentConfig.explicitlySelected) {
-            Slog.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
+            Log.wtf(TAG, "BUG: setAcceptUnvalidated non non-explicitly selected network");
         }
 
         if (accept != nai.networkAgentConfig.acceptUnvalidated) {
@@ -4020,7 +4020,7 @@
                 highPriority = nai.networkAgentConfig.explicitlySelected;
                 break;
             default:
-                Slog.wtf(TAG, "Unknown notification type " + type);
+                Log.wtf(TAG, "Unknown notification type " + type);
                 return;
         }
 
@@ -4342,7 +4342,7 @@
         synchronized (this) {
             if (!mNetTransitionWakeLock.isHeld()) {
                 mWakelockLogs.log(String.format("RELEASE: already released (%s)", event));
-                Slog.w(TAG, "expected Net Transition WakeLock to be held");
+                Log.w(TAG, "expected Net Transition WakeLock to be held");
                 return;
             }
             mNetTransitionWakeLock.release();
@@ -4514,7 +4514,7 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            Slog.wtf(TAG, "Should never be reached.");
+            Log.wtf(TAG, "Should never be reached.");
         }
 
         @Override
@@ -4529,15 +4529,19 @@
     }
 
     private static void log(String s) {
-        Slog.d(TAG, s);
+        Log.d(TAG, s);
+    }
+
+    private static void logw(String s) {
+        Log.w(TAG, s);
     }
 
     private static void loge(String s) {
-        Slog.e(TAG, s);
+        Log.e(TAG, s);
     }
 
     private static void loge(String s, Throwable t) {
-        Slog.e(TAG, s, t);
+        Log.e(TAG, s, t);
     }
 
     /**
@@ -4824,7 +4828,7 @@
     @Override
     public boolean updateLockdownVpn() {
         if (Binder.getCallingUid() != Process.SYSTEM_UID) {
-            Slog.w(TAG, "Lockdown VPN only available to AID_SYSTEM");
+            logw("Lockdown VPN only available to AID_SYSTEM");
             return false;
         }
 
@@ -4834,21 +4838,21 @@
             if (mLockdownEnabled) {
                 byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
                 if (profileTag == null) {
-                    Slog.e(TAG, "Lockdown VPN configured but cannot be read from keystore");
+                    loge("Lockdown VPN configured but cannot be read from keystore");
                     return false;
                 }
                 String profileName = new String(profileTag);
                 final VpnProfile profile = VpnProfile.decode(
                         profileName, mKeyStore.get(Credentials.VPN + profileName));
                 if (profile == null) {
-                    Slog.e(TAG, "Lockdown VPN configured invalid profile " + profileName);
+                    loge("Lockdown VPN configured invalid profile " + profileName);
                     setLockdownTracker(null);
                     return true;
                 }
                 int user = UserHandle.getUserId(Binder.getCallingUid());
                 Vpn vpn = mVpns.get(user);
                 if (vpn == null) {
-                    Slog.w(TAG, "VPN for user " + user + " not ready yet. Skipping lockdown");
+                    logw("VPN for user " + user + " not ready yet. Skipping lockdown");
                     return false;
                 }
                 setLockdownTracker(new LockdownVpnTracker(mContext, this, mHandler, vpn, profile));
@@ -4908,7 +4912,7 @@
             if (vpn == null) {
                 // Shouldn't happen as all code paths that point here should have checked the Vpn
                 // exists already.
-                Slog.wtf(TAG, "User " + userId + " has no Vpn configuration");
+                Log.wtf(TAG, "User " + userId + " has no Vpn configuration");
                 return false;
             }
 
@@ -4924,7 +4928,7 @@
         synchronized (mVpns) {
             Vpn vpn = mVpns.get(userId);
             if (vpn == null) {
-                Slog.w(TAG, "User " + userId + " has no Vpn configuration");
+                logw("User " + userId + " has no Vpn configuration");
                 return false;
             }
             return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore);
@@ -4945,7 +4949,7 @@
 
             Vpn vpn = mVpns.get(userId);
             if (vpn == null) {
-                Slog.w(TAG, "User " + userId + " has no Vpn configuration");
+                logw("User " + userId + " has no Vpn configuration");
                 return false;
             }
             if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) {
@@ -4967,7 +4971,7 @@
         synchronized (mVpns) {
             Vpn vpn = mVpns.get(userId);
             if (vpn == null) {
-                Slog.w(TAG, "User " + userId + " has no Vpn configuration");
+                logw("User " + userId + " has no Vpn configuration");
                 return null;
             }
             return vpn.getAlwaysOnPackage();
@@ -4982,7 +4986,7 @@
         synchronized (mVpns) {
             Vpn vpn = mVpns.get(userId);
             if (vpn == null) {
-                Slog.w(TAG, "User " + userId + " has no Vpn configuration");
+                logw("User " + userId + " has no Vpn configuration");
                 return false;
             }
             return vpn.getLockdown();
@@ -4997,7 +5001,7 @@
         synchronized (mVpns) {
             Vpn vpn = mVpns.get(userId);
             if (vpn == null) {
-                Slog.w(TAG, "User " + userId + " has no Vpn configuration");
+                logw("User " + userId + " has no Vpn configuration");
                 return null;
             }
             return vpn.getLockdownAllowlist();
@@ -5182,7 +5186,7 @@
 
     private void onPackageReplaced(String packageName, int uid) {
         if (TextUtils.isEmpty(packageName) || uid < 0) {
-            Slog.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
+            Log.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
             return;
         }
         final int userId = UserHandle.getUserId(uid);
@@ -5193,7 +5197,7 @@
             }
             // Legacy always-on VPN won't be affected since the package name is not set.
             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
-                Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
+                log("Restarting always-on VPN package " + packageName + " for user "
                         + userId);
                 vpn.startAlwaysOnVpn(mKeyStore);
             }
@@ -5202,7 +5206,7 @@
 
     private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
         if (TextUtils.isEmpty(packageName) || uid < 0) {
-            Slog.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
+            Log.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
             return;
         }
 
@@ -5214,7 +5218,7 @@
             }
             // Legacy always-on VPN won't be affected since the package name is not set.
             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
-                Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
+                log("Removing always-on VPN package " + packageName + " for user "
                         + userId);
                 vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
             }
@@ -5830,7 +5834,7 @@
             // Avoid creating duplicates. even if an app makes a direct AIDL call.
             // This will never happen if an app calls ConnectivityManager#registerNetworkProvider,
             // as that will throw if a duplicate provider is registered.
-            Slog.e(TAG, "Attempt to register existing NetworkProviderInfo "
+            loge("Attempt to register existing NetworkProviderInfo "
                     + mNetworkProviderInfos.get(npi.messenger).name);
             return;
         }
@@ -6354,18 +6358,71 @@
         nai.declaredMetered = !nc.hasCapability(NET_CAPABILITY_NOT_METERED);
     }
 
-    /** Propagates to |nc| the capabilities declared by the underlying networks of |nai|. */
-    private void mixInUnderlyingCapabilities(NetworkAgentInfo nai, NetworkCapabilities nc) {
-        Network[] underlyingNetworks = nai.declaredUnderlyingNetworks;
-        Network defaultNetwork = getNetwork(getDefaultNetwork());
+    /** Modifies |caps| based on the capabilities of the specified underlying networks. */
+    @VisibleForTesting
+    void applyUnderlyingCapabilities(@Nullable Network[] underlyingNetworks,
+            @NonNull NetworkCapabilities caps,  boolean declaredMetered) {
+        final Network defaultNetwork = getNetwork(getDefaultNetwork());
         if (underlyingNetworks == null && defaultNetwork != null) {
             // null underlying networks means to track the default.
             underlyingNetworks = new Network[] { defaultNetwork };
         }
+        int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
+        int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+        int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+        boolean metered = declaredMetered; // metered if any underlying is metered, or agentMetered
+        boolean roaming = false; // roaming if any underlying is roaming
+        boolean congested = false; // congested if any underlying is congested
+        boolean suspended = true; // suspended if all underlying are suspended
 
-        // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
-        final ConnectivityManager cm = mContext.getSystemService(ConnectivityManager.class);
-        Vpn.applyUnderlyingCapabilities(cm, underlyingNetworks, nc, nai.declaredMetered);
+        boolean hadUnderlyingNetworks = false;
+        if (null != underlyingNetworks) {
+            for (Network underlyingNetwork : underlyingNetworks) {
+                final NetworkAgentInfo underlying =
+                        getNetworkAgentInfoForNetwork(underlyingNetwork);
+                if (underlying == null) continue;
+
+                final NetworkCapabilities underlyingCaps = underlying.networkCapabilities;
+                hadUnderlyingNetworks = true;
+                for (int underlyingType : underlyingCaps.getTransportTypes()) {
+                    transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
+                }
+
+                // Merge capabilities of this underlying network. For bandwidth, assume the
+                // worst case.
+                downKbps = NetworkCapabilities.minBandwidth(downKbps,
+                        underlyingCaps.getLinkDownstreamBandwidthKbps());
+                upKbps = NetworkCapabilities.minBandwidth(upKbps,
+                        underlyingCaps.getLinkUpstreamBandwidthKbps());
+                // If this underlying network is metered, the VPN is metered (it may cost money
+                // to send packets on this network).
+                metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
+                // If this underlying network is roaming, the VPN is roaming (the billing structure
+                // is different than the usual, local one).
+                roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+                // If this underlying network is congested, the VPN is congested (the current
+                // condition of the network affects the performance of this network).
+                congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
+                // If this network is not suspended, the VPN is not suspended (the VPN
+                // is able to transfer some data).
+                suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
+            }
+        }
+        if (!hadUnderlyingNetworks) {
+            // No idea what the underlying networks are; assume reasonable defaults
+            metered = true;
+            roaming = false;
+            congested = false;
+            suspended = false;
+        }
+
+        caps.setTransportTypes(transportTypes);
+        caps.setLinkDownstreamBandwidthKbps(downKbps);
+        caps.setLinkUpstreamBandwidthKbps(upKbps);
+        caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
+        caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
+        caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
+        caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
     }
 
     /**
@@ -6387,7 +6444,7 @@
             // stop being matched by the updated agent.
             String diff = nai.networkCapabilities.describeImmutableDifferences(nc);
             if (!TextUtils.isEmpty(diff)) {
-                Slog.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
+                Log.wtf(TAG, "BUG: " + nai + " lost immutable capabilities:" + diff);
             }
         }
 
@@ -6422,7 +6479,7 @@
         }
 
         if (nai.supportsUnderlyingNetworks()) {
-            mixInUnderlyingCapabilities(nai, newNc);
+            applyUnderlyingCapabilities(nai.declaredUnderlyingNetworks, newNc, nai.declaredMetered);
         }
 
         return newNc;
@@ -6947,7 +7004,7 @@
             }
             newSatisfier.unlingerRequest(nri.request);
             if (!newSatisfier.addRequest(nri.request)) {
-                Slog.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
+                Log.wtf(TAG, "BUG: " + newSatisfier.toShortString() + " already has "
                         + nri.request);
             }
         } else {
@@ -7295,7 +7352,7 @@
             networkAgent.everConnected = true;
 
             if (networkAgent.linkProperties == null) {
-                Slog.wtf(TAG, networkAgent.toShortString() + " connected with null LinkProperties");
+                Log.wtf(TAG, networkAgent.toShortString() + " connected with null LinkProperties");
             }
 
             // NetworkCapabilities need to be set before sending the private DNS config to
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 1c99465..821a967 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -24,12 +24,14 @@
 import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
 import static android.net.INetd.FIREWALL_CHAIN_NONE;
 import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
 import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_DENYLIST;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 import static android.net.NetworkStats.SET_DEFAULT;
@@ -88,7 +90,6 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FrameworkStatsLog;
@@ -122,7 +123,7 @@
      * Helper class that encapsulates NetworkManagementService dependencies and makes them
      * easier to mock in unit tests.
      */
-    static class SystemServices {
+    static class Dependencies {
         public IBinder getService(String name) {
             return ServiceManager.getService(name);
         }
@@ -132,6 +133,10 @@
         public INetd getNetd() {
             return NetdService.get();
         }
+
+        public int getCallingUid() {
+            return Binder.getCallingUid();
+        }
     }
 
     private static final String TAG = "NetworkManagement";
@@ -157,7 +162,7 @@
 
     private final Handler mDaemonHandler;
 
-    private final SystemServices mServices;
+    private final Dependencies mDeps;
 
     private INetd mNetdService;
 
@@ -215,6 +220,11 @@
      */
     @GuardedBy("mRulesLock")
     private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
+    /**
+     * Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled.
+     */
+    @GuardedBy("mRulesLock")
+    private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
     /** Set of states for the child firewall chains. True if the chain is active. */
     @GuardedBy("mRulesLock")
     final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -254,33 +264,32 @@
      * @param context  Binder context for this service
      */
     private NetworkManagementService(
-            Context context, SystemServices services) {
+            Context context, Dependencies deps) {
         mContext = context;
-        mServices = services;
+        mDeps = deps;
 
         mDaemonHandler = new Handler(FgThread.get().getLooper());
 
         mNetdUnsolicitedEventListener = new NetdUnsolicitedEventListener();
 
-        mServices.registerLocalService(new LocalService());
+        mDeps.registerLocalService(new LocalService());
 
         synchronized (mTetheringStatsProviders) {
             mTetheringStatsProviders.put(new NetdTetheringStatsProvider(), "netd");
         }
     }
 
-    @VisibleForTesting
-    NetworkManagementService() {
+    private NetworkManagementService() {
         mContext = null;
         mDaemonHandler = null;
-        mServices = null;
+        mDeps = null;
         mNetdUnsolicitedEventListener = null;
     }
 
-    static NetworkManagementService create(Context context, SystemServices services)
+    static NetworkManagementService create(Context context, Dependencies deps)
             throws InterruptedException {
         final NetworkManagementService service =
-                new NetworkManagementService(context, services);
+                new NetworkManagementService(context, deps);
         if (DBG) Slog.d(TAG, "Creating NetworkManagementService");
         if (DBG) Slog.d(TAG, "Connecting native netd service");
         service.connectNativeNetdService();
@@ -289,7 +298,7 @@
     }
 
     public static NetworkManagementService create(Context context) throws InterruptedException {
-        return create(context, new SystemServices());
+        return create(context, new Dependencies());
     }
 
     public void systemReady() {
@@ -310,7 +319,7 @@
                 return mBatteryStats;
             }
             mBatteryStats =
-                    IBatteryStats.Stub.asInterface(mServices.getService(BatteryStats.SERVICE_NAME));
+                    IBatteryStats.Stub.asInterface(mDeps.getService(BatteryStats.SERVICE_NAME));
             return mBatteryStats;
         }
     }
@@ -511,7 +520,7 @@
     }
 
     private void connectNativeNetdService() {
-        mNetdService = mServices.getNetd();
+        mNetdService = mDeps.getNetd();
         try {
             mNetdService.registerUnsolicitedEventListener(mNetdUnsolicitedEventListener);
             if (DBG) Slog.d(TAG, "Register unsolicited event listener");
@@ -602,9 +611,15 @@
             syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
             syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
             syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
+            syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
 
-            final int[] chains =
-                    {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
+            final int[] chains = {
+                    FIREWALL_CHAIN_STANDBY,
+                    FIREWALL_CHAIN_DOZABLE,
+                    FIREWALL_CHAIN_POWERSAVE,
+                    FIREWALL_CHAIN_RESTRICTED
+            };
+
             for (int chain : chains) {
                 if (getFirewallChainState(chain)) {
                     setFirewallChainEnabled(chain, true);
@@ -1437,7 +1452,7 @@
 
     @Override
     public void setUidCleartextNetworkPolicy(int uid, int policy) {
-        if (Binder.getCallingUid() != uid) {
+        if (mDeps.getCallingUid() != uid) {
             NetworkStack.checkNetworkStackPermission(mContext);
         }
 
@@ -1695,6 +1710,8 @@
                 return FIREWALL_CHAIN_NAME_DOZABLE;
             case FIREWALL_CHAIN_POWERSAVE:
                 return FIREWALL_CHAIN_NAME_POWERSAVE;
+            case FIREWALL_CHAIN_RESTRICTED:
+                return FIREWALL_CHAIN_NAME_RESTRICTED;
             default:
                 throw new IllegalArgumentException("Bad child chain: " + chain);
         }
@@ -1708,6 +1725,8 @@
                 return FIREWALL_ALLOWLIST;
             case FIREWALL_CHAIN_POWERSAVE:
                 return FIREWALL_ALLOWLIST;
+            case FIREWALL_CHAIN_RESTRICTED:
+                return FIREWALL_ALLOWLIST;
             default:
                 return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
         }
@@ -1752,6 +1771,9 @@
                     case FIREWALL_CHAIN_POWERSAVE:
                         mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
                         break;
+                    case FIREWALL_CHAIN_RESTRICTED:
+                        mNetdService.firewallReplaceUidChain("fw_restricted", true, uids);
+                        break;
                     case FIREWALL_CHAIN_NONE:
                     default:
                         Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
@@ -1836,6 +1858,8 @@
                 return mUidFirewallDozableRules;
             case FIREWALL_CHAIN_POWERSAVE:
                 return mUidFirewallPowerSaveRules;
+            case FIREWALL_CHAIN_RESTRICTED:
+                return mUidFirewallRestrictedRules;
             case FIREWALL_CHAIN_NONE:
                 return mUidFirewallRules;
             default:
@@ -1851,8 +1875,8 @@
         return rule;
     }
 
-    private static void enforceSystemUid() {
-        final int uid = Binder.getCallingUid();
+    private void enforceSystemUid() {
+        final int uid = mDeps.getCallingUid();
         if (uid != Process.SYSTEM_UID) {
             throw new SecurityException("Only available to AID_SYSTEM");
         }
@@ -1910,17 +1934,22 @@
         synchronized (mRulesLock) {
             dumpUidFirewallRule(pw, "", mUidFirewallRules);
 
-            pw.print("UID firewall standby chain enabled: "); pw.println(
-                    getFirewallChainState(FIREWALL_CHAIN_STANDBY));
+            pw.print("UID firewall standby chain enabled: ");
+            pw.println(getFirewallChainState(FIREWALL_CHAIN_STANDBY));
             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
 
-            pw.print("UID firewall dozable chain enabled: "); pw.println(
-                    getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
+            pw.print("UID firewall dozable chain enabled: ");
+            pw.println(getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
 
-            pw.println("UID firewall powersave chain enabled: " +
-                    getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
+            pw.print("UID firewall powersave chain enabled: ");
+            pw.println(getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
             dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
+
+            pw.print("UID firewall restricted mode chain enabled: ");
+            pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED));
+            dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED,
+                    mUidFirewallRestrictedRules);
         }
 
         synchronized (mIdleTimerLock) {
@@ -2071,6 +2100,11 @@
                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
                 return true;
             }
+            if (getFirewallChainState(FIREWALL_CHAIN_RESTRICTED)
+                    && mUidFirewallRestrictedRules.get(uid) != FIREWALL_RULE_ALLOW) {
+                if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode");
+                return true;
+            }
             if (mUidRejectOnMetered.get(uid)) {
                 if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
                         + " in the background");
@@ -2096,60 +2130,10 @@
         }
     }
 
-    @VisibleForTesting
-    class LocalService extends NetworkManagementInternal {
+    private class LocalService extends NetworkManagementInternal {
         @Override
         public boolean isNetworkRestrictedForUid(int uid) {
             return isNetworkRestrictedInternal(uid);
         }
     }
-
-    @VisibleForTesting
-    Injector getInjector() {
-        return new Injector();
-    }
-
-    @VisibleForTesting
-    class Injector {
-        void setDataSaverMode(boolean dataSaverMode) {
-            mDataSaverMode = dataSaverMode;
-        }
-
-        void setFirewallChainState(int chain, boolean state) {
-            NetworkManagementService.this.setFirewallChainState(chain, state);
-        }
-
-        void setFirewallRule(int chain, int uid, int rule) {
-            synchronized (mRulesLock) {
-                getUidFirewallRulesLR(chain).put(uid, rule);
-            }
-        }
-
-        void setUidOnMeteredNetworkList(boolean denylist, int uid, boolean enable) {
-            synchronized (mRulesLock) {
-                if (denylist) {
-                    mUidRejectOnMetered.put(uid, enable);
-                } else {
-                    mUidAllowOnMetered.put(uid, enable);
-                }
-            }
-        }
-
-        void reset() {
-            synchronized (mRulesLock) {
-                setDataSaverMode(false);
-                final int[] chains = {
-                        FIREWALL_CHAIN_DOZABLE,
-                        FIREWALL_CHAIN_STANDBY,
-                        FIREWALL_CHAIN_POWERSAVE
-                };
-                for (int chain : chains) {
-                    setFirewallChainState(chain, false);
-                    getUidFirewallRulesLR(chain).clear();
-                }
-                mUidAllowOnMetered.clear();
-                mUidRejectOnMetered.clear();
-            }
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 1147db5..70ef44c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1391,12 +1391,13 @@
                     final int oldState = vol.state;
                     final int newState = state;
                     vol.state = newState;
+                    final VolumeInfo vInfo = new VolumeInfo(vol);
                     final SomeArgs args = SomeArgs.obtain();
-                    args.arg1 = vol;
+                    args.arg1 = vInfo;
                     args.arg2 = oldState;
                     args.arg3 = newState;
                     mHandler.obtainMessage(H_VOLUME_STATE_CHANGED, args).sendToTarget();
-                    onVolumeStateChangedLocked(vol, oldState, newState);
+                    onVolumeStateChangedLocked(vInfo, oldState, newState);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
index d6bd5a1..a45466d 100644
--- a/services/core/java/com/android/server/TestNetworkService.java
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -29,9 +29,9 @@
 import android.net.LinkAddress;
 import android.net.LinkProperties;
 import android.net.NetworkAgent;
+import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkProvider;
 import android.net.RouteInfo;
 import android.net.StringNetworkSpecifier;
 import android.net.TestNetworkInterface;
@@ -62,7 +62,8 @@
 /** @hide */
 class TestNetworkService extends ITestNetworkManager.Stub {
     @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
-    @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
+    @NonNull private static final String TEST_NETWORK_LOGTAG = "TestNetworkAgent";
+    @NonNull private static final String TEST_NETWORK_PROVIDER_NAME = TAG;
     @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
 
     @NonNull private final Context mContext;
@@ -72,6 +73,9 @@
     @NonNull private final HandlerThread mHandlerThread;
     @NonNull private final Handler mHandler;
 
+    @NonNull private final ConnectivityManager mCm;
+    @NonNull private final NetworkProvider mNetworkProvider;
+
     // Native method stubs
     private static native int jniCreateTunTap(boolean isTun, @NonNull String iface);
 
@@ -85,6 +89,10 @@
         mContext = Objects.requireNonNull(context, "missing Context");
         mNMS = Objects.requireNonNull(netManager, "missing INetworkManagementService");
         mNetd = Objects.requireNonNull(NetdService.getInstance(), "could not get netd instance");
+        mCm = mContext.getSystemService(ConnectivityManager.class);
+        mNetworkProvider = new NetworkProvider(mContext, mHandler.getLooper(),
+                TEST_NETWORK_PROVIDER_NAME);
+        mCm.registerNetworkProvider(mNetworkProvider);
     }
 
     /**
@@ -150,9 +158,6 @@
         private static final int NETWORK_SCORE = 1; // Use a low, non-zero score.
 
         private final int mUid;
-        @NonNull private final NetworkInfo mNi;
-        @NonNull private final NetworkCapabilities mNc;
-        @NonNull private final LinkProperties mLp;
 
         @GuardedBy("mBinderLock")
         @NonNull
@@ -161,20 +166,18 @@
         @NonNull private final Object mBinderLock = new Object();
 
         private TestNetworkAgent(
-                @NonNull Looper looper,
                 @NonNull Context context,
-                @NonNull NetworkInfo ni,
+                @NonNull Looper looper,
+                @NonNull NetworkAgentConfig config,
                 @NonNull NetworkCapabilities nc,
                 @NonNull LinkProperties lp,
                 int uid,
-                @NonNull IBinder binder)
+                @NonNull IBinder binder,
+                @NonNull NetworkProvider np)
                 throws RemoteException {
-            super(looper, context, TEST_NETWORK_TYPE, ni, nc, lp, NETWORK_SCORE);
+            super(context, looper, TEST_NETWORK_LOGTAG, nc, lp, NETWORK_SCORE, config, np);
 
             mUid = uid;
-            mNi = ni;
-            mNc = nc;
-            mLp = lp;
 
             synchronized (mBinderLock) {
                 mBinder = binder; // Binder null-checks in create()
@@ -203,9 +206,7 @@
         }
 
         private void teardown() {
-            mNi.setDetailedState(DetailedState.DISCONNECTED, null, null);
-            mNi.setIsAvailable(false);
-            sendNetworkInfo(mNi);
+            unregister();
 
             // Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than
             // once (otherwise it could throw an exception)
@@ -238,11 +239,6 @@
         Objects.requireNonNull(context, "missing Context");
         // iface and binder validity checked by caller
 
-        // Build network info with special testing type
-        NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_TEST, 0, TEST_NETWORK_TYPE, "");
-        ni.setDetailedState(DetailedState.CONNECTED, null, null);
-        ni.setIsAvailable(true);
-
         // Build narrow set of NetworkCapabilities, useful only for testing
         NetworkCapabilities nc = new NetworkCapabilities();
         nc.clearAll(); // Remove default capabilities.
@@ -290,7 +286,12 @@
             lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
         }
 
-        return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder);
+        final TestNetworkAgent agent = new TestNetworkAgent(context, looper,
+                new NetworkAgentConfig.Builder().build(), nc, lp, callingUid, binder,
+                mNetworkProvider);
+        agent.register();
+        agent.markConnected();
+        return agent;
     }
 
     /**
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index 0ee30f9..9340be1 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -1662,6 +1662,10 @@
                                     // Vibrator is already ON, so just change its amplitude.
                                     doVibratorSetAmplitude(amplitude);
                                 }
+                            } else {
+                                // Previous vibration should have already finished, but we make sure
+                                // the vibrator will be off for the next step when amplitude is 0.
+                                doVibratorOff();
                             }
 
                             // We wait until the time this waveform step was supposed to end,
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index c789186..1f0fb5e 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -45,8 +45,8 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
+import android.util.Log;
 import android.util.Pair;
-import android.util.Slog;
 
 import java.net.InetAddress;
 import java.util.Arrays;
@@ -279,7 +279,7 @@
     }
 
     public PrivateDnsConfig updatePrivateDns(Network network, PrivateDnsConfig cfg) {
-        Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
+        Log.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
         return (cfg != null)
                 ? mPrivateDnsMap.put(network.netId, cfg)
                 : mPrivateDnsMap.remove(network.netId);
@@ -389,7 +389,7 @@
             mPrivateDnsValidationMap.remove(netId);
         }
 
-        Slog.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
+        Log.d(TAG, String.format("sendDnsConfigurationForNetwork(%d, %s, %s, %d, %d, %d, %d, "
                 + "%d, %d, %s, %s)", paramsParcel.netId, Arrays.toString(paramsParcel.servers),
                 Arrays.toString(paramsParcel.domains), paramsParcel.sampleValiditySeconds,
                 paramsParcel.successThreshold, paramsParcel.minSamples,
@@ -400,7 +400,7 @@
         try {
             mDnsResolver.setResolverConfiguration(paramsParcel);
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error setting DNS configuration: " + e);
+            Log.e(TAG, "Error setting DNS configuration: " + e);
             return;
         }
     }
@@ -431,8 +431,8 @@
                 DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS,
                 DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
         if (mSampleValidity < 0 || mSampleValidity > 65535) {
-            Slog.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default=" +
-                    DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
+            Log.w(TAG, "Invalid sampleValidity=" + mSampleValidity + ", using default="
+                    + DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS);
             mSampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS;
         }
 
@@ -440,17 +440,17 @@
                 DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT,
                 DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
         if (mSuccessThreshold < 0 || mSuccessThreshold > 100) {
-            Slog.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default=" +
-                    DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
+            Log.w(TAG, "Invalid successThreshold=" + mSuccessThreshold + ", using default="
+                    + DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT);
             mSuccessThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT;
         }
 
         mMinSamples = getIntSetting(DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES);
         mMaxSamples = getIntSetting(DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES);
         if (mMinSamples < 0 || mMinSamples > mMaxSamples || mMaxSamples > 64) {
-            Slog.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples +
-                    "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " +
-                    DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
+            Log.w(TAG, "Invalid sample count (min, max)=(" + mMinSamples + ", " + mMaxSamples
+                    + "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", "
+                    + DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")");
             mMinSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES;
             mMaxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES;
         }
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 17828a0..21ef356 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -60,8 +60,8 @@
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
 import android.util.DebugUtils;
+import android.util.Log;
 import android.util.Range;
-import android.util.Slog;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -230,7 +230,7 @@
             mUsageCallback = new UsageCallback() {
                 @Override
                 public void onThresholdReached(int networkType, String subscriberId) {
-                    if (DBG) Slog.d(TAG, "onThresholdReached for network " + network);
+                    if (DBG) Log.d(TAG, "onThresholdReached for network " + network);
                     mMultipathBudget = 0;
                     updateMultipathBudget();
                 }
@@ -252,7 +252,7 @@
             final long bytes = getNetworkTotalBytes(
                     start.toInstant().toEpochMilli(),
                     end.toInstant().toEpochMilli());
-            if (DBG) Slog.d(TAG, "Non-default data usage: " + bytes);
+            if (DBG) Log.d(TAG, "Non-default data usage: " + bytes);
             return bytes;
         }
 
@@ -261,7 +261,7 @@
                 return LocalServices.getService(NetworkStatsManagerInternal.class)
                         .getNetworkTotalBytes(mNetworkTemplate, start, end);
             } catch (RuntimeException e) {
-                Slog.w(TAG, "Failed to get data usage: " + e);
+                Log.w(TAG, "Failed to get data usage: " + e);
                 return -1;
             }
         }
@@ -326,17 +326,17 @@
         void updateMultipathBudget() {
             long quota = LocalServices.getService(NetworkPolicyManagerInternal.class)
                     .getSubscriptionOpportunisticQuota(this.network, QUOTA_TYPE_MULTIPATH);
-            if (DBG) Slog.d(TAG, "Opportunistic quota from data plan: " + quota + " bytes");
+            if (DBG) Log.d(TAG, "Opportunistic quota from data plan: " + quota + " bytes");
 
             // Fallback to user settings-based quota if not available from phone plan
             if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
                 quota = getUserPolicyOpportunisticQuotaBytes();
-                if (DBG) Slog.d(TAG, "Opportunistic quota from user policy: " + quota + " bytes");
+                if (DBG) Log.d(TAG, "Opportunistic quota from user policy: " + quota + " bytes");
             }
 
             if (quota == OPPORTUNISTIC_QUOTA_UNKNOWN) {
                 quota = getDefaultDailyMultipathQuotaBytes();
-                if (DBG) Slog.d(TAG, "Setting quota: " + quota + " bytes");
+                if (DBG) Log.d(TAG, "Setting quota: " + quota + " bytes");
             }
 
             // TODO: re-register if day changed: budget may have run out but should be refreshed.
@@ -344,7 +344,7 @@
                 // If there is already a usage callback pending , there's no need to re-register it
                 // if the quota hasn't changed. The callback will simply fire as expected when the
                 // budget is spent.
-                if (DBG) Slog.d(TAG, "Quota still " + quota + ", not updating.");
+                if (DBG) Log.d(TAG, "Quota still " + quota + ", not updating.");
                 return;
             }
             mQuota = quota;
@@ -364,8 +364,9 @@
             // since last time, so even if this is called very often the budget will not snap to 0
             // as soon as there are less than 2MB left for today.
             if (budget > NetworkStatsManager.MIN_THRESHOLD_BYTES) {
-                if (DBG) Slog.d(TAG, "Setting callback for " + budget +
-                        " bytes on network " + network);
+                if (DBG) {
+                    Log.d(TAG, "Setting callback for " + budget + " bytes on network " + network);
+                }
                 registerUsageCallback(budget);
             } else {
                 maybeUnregisterUsageCallback();
@@ -402,7 +403,7 @@
 
         private void maybeUnregisterUsageCallback() {
             if (haveMultipathBudget()) {
-                if (DBG) Slog.d(TAG, "Unregistering callback, budget was " + mMultipathBudget);
+                if (DBG) Log.d(TAG, "Unregistering callback, budget was " + mMultipathBudget);
                 mStatsManager.unregisterUsageCallback(mUsageCallback);
                 mMultipathBudget = 0;
             }
@@ -467,9 +468,9 @@
                 try {
                     mMultipathTrackers.put(network, new MultipathTracker(network, nc));
                 } catch (IllegalStateException e) {
-                    Slog.e(TAG, "Can't track mobile network " + network + ": " + e.getMessage());
+                    Log.e(TAG, "Can't track mobile network " + network + ": " + e.getMessage());
                 }
-                if (DBG) Slog.d(TAG, "Tracking mobile network " + network);
+                if (DBG) Log.d(TAG, "Tracking mobile network " + network);
             }
 
             @Override
@@ -479,7 +480,7 @@
                     existing.shutdown();
                     mMultipathTrackers.remove(network);
                 }
-                if (DBG) Slog.d(TAG, "No longer tracking mobile network " + network);
+                if (DBG) Log.d(TAG, "No longer tracking mobile network " + network);
             }
         };
 
@@ -524,16 +525,16 @@
 
         @Override
         public void onChange(boolean selfChange) {
-            Slog.wtf(TAG, "Should never be reached.");
+            Log.wtf(TAG, "Should never be reached.");
         }
 
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             if (!Settings.Global.getUriFor(NETWORK_DEFAULT_DAILY_MULTIPATH_QUOTA_BYTES)
                     .equals(uri)) {
-                Slog.wtf(TAG, "Unexpected settings observation: " + uri);
+                Log.wtf(TAG, "Unexpected settings observation: " + uri);
             }
-            if (DBG) Slog.d(TAG, "Settings change: updating budgets.");
+            if (DBG) Log.d(TAG, "Settings change: updating budgets.");
             updateAllMultipathBudgets();
         }
     }
@@ -541,7 +542,7 @@
     private final class ConfigChangeReceiver extends BroadcastReceiver {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (DBG) Slog.d(TAG, "Configuration change: updating budgets.");
+            if (DBG) Log.d(TAG, "Configuration change: updating budgets.");
             updateAllMultipathBudgets();
         }
     }
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 163788f..d9c2e80 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -30,7 +30,7 @@
 import android.os.INetworkManagementService;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
-import android.util.Slog;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
@@ -176,7 +176,7 @@
         try {
             mNMService.registerObserver(this);
         } catch (RemoteException e) {
-            Slog.e(TAG, "Can't register iface observer for clat on " + mNetwork.toShortString());
+            Log.e(TAG, "Can't register iface observer for clat on " + mNetwork.toShortString());
             return;
         }
 
@@ -185,7 +185,7 @@
         try {
             addrStr = mNetd.clatdStart(baseIface, mNat64PrefixInUse.toString());
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
+            Log.e(TAG, "Error starting clatd on " + baseIface + ": " + e);
         }
         mIface = CLAT_PREFIX + baseIface;
         mBaseIface = baseIface;
@@ -193,7 +193,7 @@
         try {
             mIPv6Address = (Inet6Address) InetAddresses.parseNumericAddress(addrStr);
         } catch (ClassCastException | IllegalArgumentException | NullPointerException e) {
-            Slog.e(TAG, "Invalid IPv6 address " + addrStr);
+            Log.e(TAG, "Invalid IPv6 address " + addrStr);
         }
         if (mPrefixDiscoveryRunning && !isPrefixDiscoveryNeeded()) {
             stopPrefixDiscovery();
@@ -218,7 +218,7 @@
         try {
             mNMService.unregisterObserver(this);
         } catch (RemoteException | IllegalStateException e) {
-            Slog.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e);
+            Log.e(TAG, "Error unregistering clatd observer on " + mBaseIface + ": " + e);
         }
         mNat64PrefixInUse = null;
         mIface = null;
@@ -242,37 +242,37 @@
     @VisibleForTesting
     protected void start() {
         if (isStarted()) {
-            Slog.e(TAG, "startClat: already started");
+            Log.e(TAG, "startClat: already started");
             return;
         }
 
         if (mNetwork.linkProperties == null) {
-            Slog.e(TAG, "startClat: Can't start clat with null LinkProperties");
+            Log.e(TAG, "startClat: Can't start clat with null LinkProperties");
             return;
         }
 
         String baseIface = mNetwork.linkProperties.getInterfaceName();
         if (baseIface == null) {
-            Slog.e(TAG, "startClat: Can't start clat on null interface");
+            Log.e(TAG, "startClat: Can't start clat on null interface");
             return;
         }
         // TODO: should we only do this if mNetd.clatdStart() succeeds?
-        Slog.i(TAG, "Starting clatd on " + baseIface);
+        Log.i(TAG, "Starting clatd on " + baseIface);
         enterStartingState(baseIface);
     }
 
     @VisibleForTesting
     protected void stop() {
         if (!isStarted()) {
-            Slog.e(TAG, "stopClat: already stopped");
+            Log.e(TAG, "stopClat: already stopped");
             return;
         }
 
-        Slog.i(TAG, "Stopping clatd on " + mBaseIface);
+        Log.i(TAG, "Stopping clatd on " + mBaseIface);
         try {
             mNetd.clatdStop(mBaseIface);
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error stopping clatd on " + mBaseIface + ": " + e);
+            Log.e(TAG, "Error stopping clatd on " + mBaseIface + ": " + e);
         }
 
         String iface = mIface;
@@ -294,7 +294,7 @@
         try {
             mDnsResolver.startPrefix64Discovery(getNetId());
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
+            Log.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
         }
         mPrefixDiscoveryRunning = true;
     }
@@ -303,7 +303,7 @@
         try {
             mDnsResolver.stopPrefix64Discovery(getNetId());
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
+            Log.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
         }
         mPrefixDiscoveryRunning = false;
     }
@@ -320,7 +320,7 @@
         try {
             mDnsResolver.setPrefix64(getNetId(), prefixString);
         } catch (RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error setting NAT64 prefix on netId " + getNetId() + " to "
+            Log.e(TAG, "Error setting NAT64 prefix on netId " + getNetId() + " to "
                     + prefix + ": " + e);
         }
     }
@@ -328,7 +328,7 @@
     private void maybeHandleNat64PrefixChange() {
         final IpPrefix newPrefix = selectNat64Prefix();
         if (!Objects.equals(mNat64PrefixInUse, newPrefix)) {
-            Slog.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to "
+            Log.d(TAG, "NAT64 prefix changed from " + mNat64PrefixInUse + " to "
                     + newPrefix);
             stop();
             // It's safe to call update here, even though this method is called from update, because
@@ -418,7 +418,7 @@
             return;
         }
 
-        Slog.d(TAG, "clatd running, updating NAI for " + mIface);
+        Log.d(TAG, "clatd running, updating NAI for " + mIface);
         for (LinkProperties stacked: oldLp.getStackedLinks()) {
             if (Objects.equals(mIface, stacked.getInterfaceName())) {
                 lp.addStackedLink(stacked);
@@ -451,7 +451,7 @@
             return new LinkAddress(
                     InetAddresses.parseNumericAddress(config.ipv4Addr), config.prefixLength);
         } catch (IllegalArgumentException | RemoteException | ServiceSpecificException e) {
-            Slog.e(TAG, "Error getting link properties: " + e);
+            Log.e(TAG, "Error getting link properties: " + e);
             return null;
         }
     }
@@ -480,11 +480,11 @@
 
         LinkAddress clatAddress = getLinkAddress(iface);
         if (clatAddress == null) {
-            Slog.e(TAG, "clatAddress was null for stacked iface " + iface);
+            Log.e(TAG, "clatAddress was null for stacked iface " + iface);
             return;
         }
 
-        Slog.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s",
+        Log.i(TAG, String.format("interface %s is up, adding stacked link %s on top of %s",
                 mIface, mIface, mBaseIface));
         enterRunningState();
         LinkProperties lp = new LinkProperties(mNetwork.linkProperties);
@@ -503,7 +503,7 @@
             return;
         }
 
-        Slog.i(TAG, "interface " + iface + " removed");
+        Log.i(TAG, "interface " + iface + " removed");
         // If we're running, and the interface was removed, then we didn't call stop(), and it's
         // likely that clatd crashed. Ensure we call stop() so we can start clatd again. Calling
         // stop() will also update LinkProperties, and if clatd crashed, the LinkProperties update
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 7f4fb40..7795ed3 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -35,7 +35,7 @@
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
-import android.util.Slog;
+import android.util.Log;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 import android.widget.Toast;
@@ -175,7 +175,7 @@
         final int previousEventId = mNotificationTypeMap.get(id);
         final NotificationType previousNotifyType = NotificationType.getFromId(previousEventId);
         if (priority(previousNotifyType) > priority(notifyType)) {
-            Slog.d(TAG, String.format(
+            Log.d(TAG, String.format(
                     "ignoring notification %s for network %s with existing notification %s",
                     notifyType, id, previousNotifyType));
             return;
@@ -183,7 +183,7 @@
         clearNotification(id);
 
         if (DBG) {
-            Slog.d(TAG, String.format(
+            Log.d(TAG, String.format(
                     "showNotification tag=%s event=%s transport=%s name=%s highPriority=%s",
                     tag, nameOf(eventId), getTransportName(transportType), name, highPriority));
         }
@@ -253,7 +253,7 @@
             // are sent, but they are not implemented yet.
             return;
         } else {
-            Slog.wtf(TAG, "Unknown notification type " + notifyType + " on network transport "
+            Log.wtf(TAG, "Unknown notification type " + notifyType + " on network transport "
                     + getTransportName(transportType));
             return;
         }
@@ -294,7 +294,7 @@
         try {
             mNotificationManager.notify(tag, eventId, notification);
         } catch (NullPointerException npe) {
-            Slog.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
+            Log.d(TAG, "setNotificationVisible: visible notificationManager error", npe);
         }
     }
 
@@ -317,13 +317,13 @@
         final String tag = tagFor(id);
         final int eventId = mNotificationTypeMap.get(id);
         if (DBG) {
-            Slog.d(TAG, String.format("clearing notification tag=%s event=%s", tag,
+            Log.d(TAG, String.format("clearing notification tag=%s event=%s", tag,
                    nameOf(eventId)));
         }
         try {
             mNotificationManager.cancel(tag, eventId);
         } catch (NullPointerException npe) {
-            Slog.d(TAG, String.format(
+            Log.d(TAG, String.format(
                     "failed to clear notification tag=%s event=%s", tag, nameOf(eventId)), npe);
         }
         mNotificationTypeMap.delete(id);
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index a75a80a..4c63eb4 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -174,7 +174,7 @@
             netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
         }
 
-        List<UserInfo> users = mUserManager.getUsers(true);  // exclude dying users
+        List<UserInfo> users = mUserManager.getAliveUsers();
         if (users != null) {
             for (UserInfo user : users) {
                 mUsers.add(user.id);
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index 26cc3ee..5cb3d94 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -35,7 +35,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.util.Slog;
+import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -168,7 +168,7 @@
                 proxyProperties = new ProxyInfo(host, port, exclList);
             }
             if (!proxyProperties.isValid()) {
-                if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyProperties);
+                if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyProperties);
                 return;
             }
 
@@ -223,7 +223,7 @@
         if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
             return;
         }
-        if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
+        if (DBG) Log.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
         Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
         intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
@@ -255,7 +255,7 @@
             if (proxyInfo != null && (!TextUtils.isEmpty(proxyInfo.getHost()) ||
                     !Uri.EMPTY.equals(proxyInfo.getPacFileUrl()))) {
                 if (!proxyInfo.isValid()) {
-                    if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
+                    if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
                     return;
                 }
                 mGlobalProxy = new ProxyInfo(proxyInfo);
@@ -296,7 +296,7 @@
         synchronized (mProxyLock) {
             if (Objects.equals(mDefaultProxy, proxyInfo)) return;
             if (proxyInfo != null &&  !proxyInfo.isValid()) {
-                if (DBG) Slog.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
+                if (DBG) Log.d(TAG, "Invalid proxy properties, ignoring: " + proxyInfo);
                 return;
             }
 
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 73125c1..3445275 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -18,10 +18,7 @@
 
 import static android.Manifest.permission.BIND_VPN_SERVICE;
 import static android.net.ConnectivityManager.NETID_UNSET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.RouteInfo.RTN_THROW;
 import static android.net.RouteInfo.RTN_UNREACHABLE;
 
@@ -111,7 +108,6 @@
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.net.VpnProfile;
-import com.android.internal.util.ArrayUtils;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.LocalServices;
 import com.android.server.net.BaseNetworkObserver;
@@ -463,99 +459,6 @@
     }
 
     /**
-     * Updates {@link #mNetworkCapabilities} based on current underlying networks and returns a
-     * defensive copy.
-     *
-     * <p>Does not propagate updated capabilities to apps.
-     *
-     * @param defaultNetwork underlying network for VPNs following platform's default
-     */
-    public synchronized NetworkCapabilities updateCapabilities(@Nullable Network defaultNetwork) {
-        if (mConfig == null) {
-            // VPN is not running.
-            return null;
-        }
-
-        Network[] underlyingNetworks = mConfig.underlyingNetworks;
-        if (underlyingNetworks == null && defaultNetwork != null) {
-            // null underlying networks means to track the default.
-            underlyingNetworks = new Network[] { defaultNetwork };
-        }
-        // Only apps targeting Q and above can explicitly declare themselves as metered.
-        final boolean isAlwaysMetered = mIsPackageTargetingAtLeastQ && mConfig.isMetered;
-
-        applyUnderlyingCapabilities(
-                mConnectivityManager,
-                underlyingNetworks,
-                mNetworkCapabilities,
-                isAlwaysMetered);
-
-        return new NetworkCapabilities(mNetworkCapabilities);
-    }
-
-    @VisibleForTesting
-    public static void applyUnderlyingCapabilities(
-            @NonNull final ConnectivityManager cm,
-            @Nullable final Network[] underlyingNetworks,
-            @NonNull final NetworkCapabilities caps,
-            final boolean isAlwaysMetered) {
-        int[] transportTypes = new int[] { NetworkCapabilities.TRANSPORT_VPN };
-        int downKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        int upKbps = NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-        boolean metered = isAlwaysMetered; // metered if any underlying is metered, or alwaysMetered
-        boolean roaming = false; // roaming if any underlying is roaming
-        boolean congested = false; // congested if any underlying is congested
-        boolean suspended = true; // suspended if all underlying are suspended
-
-        boolean hadUnderlyingNetworks = false;
-        if (null != underlyingNetworks) {
-            for (Network underlying : underlyingNetworks) {
-                // TODO(b/124469351): Get capabilities directly from ConnectivityService instead.
-                final NetworkCapabilities underlyingCaps = cm.getNetworkCapabilities(underlying);
-                if (underlyingCaps == null) continue;
-                hadUnderlyingNetworks = true;
-                for (int underlyingType : underlyingCaps.getTransportTypes()) {
-                    transportTypes = ArrayUtils.appendInt(transportTypes, underlyingType);
-                }
-
-                // Merge capabilities of this underlying network. For bandwidth, assume the
-                // worst case.
-                downKbps = NetworkCapabilities.minBandwidth(downKbps,
-                        underlyingCaps.getLinkDownstreamBandwidthKbps());
-                upKbps = NetworkCapabilities.minBandwidth(upKbps,
-                        underlyingCaps.getLinkUpstreamBandwidthKbps());
-                // If this underlying network is metered, the VPN is metered (it may cost money
-                // to send packets on this network).
-                metered |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_METERED);
-                // If this underlying network is roaming, the VPN is roaming (the billing structure
-                // is different than the usual, local one).
-                roaming |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_ROAMING);
-                // If this underlying network is congested, the VPN is congested (the current
-                // condition of the network affects the performance of this network).
-                congested |= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_CONGESTED);
-                // If this network is not suspended, the VPN is not suspended (the VPN
-                // is able to transfer some data).
-                suspended &= !underlyingCaps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED);
-            }
-        }
-        if (!hadUnderlyingNetworks) {
-            // No idea what the underlying networks are; assume the safer defaults
-            metered = true;
-            roaming = false;
-            congested = false;
-            suspended = false;
-        }
-
-        caps.setTransportTypes(transportTypes);
-        caps.setLinkDownstreamBandwidthKbps(downKbps);
-        caps.setLinkUpstreamBandwidthKbps(upKbps);
-        caps.setCapability(NET_CAPABILITY_NOT_METERED, !metered);
-        caps.setCapability(NET_CAPABILITY_NOT_ROAMING, !roaming);
-        caps.setCapability(NET_CAPABILITY_NOT_CONGESTED, !congested);
-        caps.setCapability(NET_CAPABILITY_NOT_SUSPENDED, !suspended);
-    }
-
-    /**
      * Chooses whether to force all connections to go though VPN.
      *
      * Used to enable/disable legacy VPN lockdown.
@@ -1500,7 +1403,7 @@
             final long token = Binder.clearCallingIdentity();
             List<UserInfo> users;
             try {
-                users = UserManager.get(mContext).getUsers(true);
+                users = UserManager.get(mContext).getAliveUsers();
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 804cc92..b2d694b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1569,10 +1569,11 @@
         // When the device is not unplugged but reawaken from standby, we check if the System
         // Audio Control Feature is enabled or not then decide if turning SAM on/off accordingly.
         if (getAvrDeviceInfo() != null && portId == getAvrDeviceInfo().getPortId()) {
+            HdmiLogger.debug("Port ID:%d, 5v=%b", portId, connected);
             if (!connected) {
                 setSystemAudioMode(false);
-            } else if (mSystemAudioControlFeatureEnabled != mService.isSystemAudioActivated()){
-                setSystemAudioMode(mSystemAudioControlFeatureEnabled);
+            } else {
+                onNewAvrAdded(getAvrDeviceInfo());
             }
         }
 
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index 6633789..db93ad0 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -102,12 +102,12 @@
     }
 
     private void setArcStatus(boolean enabled) {
-        boolean wasEnabled = tv().setArcStatus(enabled);
-        Slog.i(TAG, "Change arc status [old:" + wasEnabled + ", new:" + enabled + "]");
+        tv().setArcStatus(enabled);
+        Slog.i(TAG, "Change arc status to " + enabled);
 
         // If enabled before and set to "disabled" and send <Report Arc Terminated> to
         // av reciever.
-        if (!enabled && wasEnabled) {
+        if (!enabled) {
             sendCommand(HdmiCecMessageBuilder.buildReportArcTerminated(getSourceAddress(),
                     mAvrAddress));
         }
diff --git a/services/core/java/com/android/server/media/MediaKeyDispatcher.java b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
index 5933723..fc7c82a 100644
--- a/services/core/java/com/android/server/media/MediaKeyDispatcher.java
+++ b/services/core/java/com/android/server/media/MediaKeyDispatcher.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
+import android.content.Context;
 import android.media.session.ISessionManager;
 import android.media.session.MediaSession;
 import android.os.Binder;
@@ -60,7 +61,7 @@
 
     private Map<Integer, Integer> mOverriddenKeyEvents;
 
-    public MediaKeyDispatcher() {
+    public MediaKeyDispatcher(Context context) {
         // Constructor used for reflection
         mOverriddenKeyEvents = new HashMap<>();
         mOverriddenKeyEvents.put(KeyEvent.KEYCODE_MEDIA_PLAY, 0);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index b02b900..9dde4c8 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -96,7 +96,6 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 
 /**
  * System implementation of MediaSessionManager
@@ -152,7 +151,6 @@
 
     private SessionPolicyProvider mCustomSessionPolicyProvider;
     private MediaKeyDispatcher mCustomMediaKeyDispatcher;
-    private Map<Integer, Integer> mOverriddenKeyEventsMap;
 
     public MediaSessionService(Context context) {
         super(context);
@@ -771,7 +769,6 @@
     private void instantiateCustomDispatcher(String nameFromTesting) {
         synchronized (mLock) {
             mCustomMediaKeyDispatcher = null;
-            mOverriddenKeyEventsMap = null;
 
             String customDispatcherClassName = (nameFromTesting == null)
                     ? mContext.getResources().getString(R.string.config_customMediaKeyDispatcher)
@@ -779,9 +776,10 @@
             try {
                 if (!TextUtils.isEmpty(customDispatcherClassName)) {
                     Class customDispatcherClass = Class.forName(customDispatcherClassName);
-                    Constructor constructor = customDispatcherClass.getDeclaredConstructor();
-                    mCustomMediaKeyDispatcher = (MediaKeyDispatcher) constructor.newInstance();
-                    mOverriddenKeyEventsMap = mCustomMediaKeyDispatcher.getOverriddenKeyEvents();
+                    Constructor constructor =
+                            customDispatcherClass.getDeclaredConstructor(Context.class);
+                    mCustomMediaKeyDispatcher =
+                            (MediaKeyDispatcher) constructor.newInstance(mContext);
                 }
             } catch (ClassNotFoundException | InstantiationException | InvocationTargetException
                     | IllegalAccessException | NoSuchMethodException e) {
@@ -801,9 +799,10 @@
             try {
                 if (!TextUtils.isEmpty(customProviderClassName)) {
                     Class customProviderClass = Class.forName(customProviderClassName);
-                    Constructor constructor = customProviderClass.getDeclaredConstructor();
+                    Constructor constructor =
+                            customProviderClass.getDeclaredConstructor(Context.class);
                     mCustomSessionPolicyProvider =
-                            (SessionPolicyProvider) constructor.newInstance();
+                            (SessionPolicyProvider) constructor.newInstance(mContext);
                 }
             } catch (ClassNotFoundException | InstantiationException | InvocationTargetException
                     | IllegalAccessException | NoSuchMethodException e) {
@@ -2398,9 +2397,12 @@
                     return;
                 }
 
-                int overriddenKeyEvents = (mCustomMediaKeyDispatcher == null) ? 0
-                        : mCustomMediaKeyDispatcher.getOverriddenKeyEvents()
-                                .get(keyEvent.getKeyCode());
+                int overriddenKeyEvents = 0;
+                if (mCustomMediaKeyDispatcher != null
+                        && mCustomMediaKeyDispatcher.getOverriddenKeyEvents() != null) {
+                    overriddenKeyEvents = mCustomMediaKeyDispatcher.getOverriddenKeyEvents()
+                            .get(keyEvent.getKeyCode());
+                }
                 cancelTrackingIfNeeded(packageName, pid, uid, asSystemService, keyEvent,
                         needWakeLock, opPackageName, stream, musicOnly, overriddenKeyEvents);
                 if (!needTracking(keyEvent, overriddenKeyEvents)) {
diff --git a/services/core/java/com/android/server/media/SessionPolicyProvider.java b/services/core/java/com/android/server/media/SessionPolicyProvider.java
index 5f02a07..332c85a 100644
--- a/services/core/java/com/android/server/media/SessionPolicyProvider.java
+++ b/services/core/java/com/android/server/media/SessionPolicyProvider.java
@@ -18,6 +18,7 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.content.Context;
 import android.media.session.MediaSession;
 
 import java.lang.annotation.Retention;
@@ -54,7 +55,7 @@
      */
     static final int SESSION_POLICY_IGNORE_BUTTON_SESSION = 1 << 1;
 
-    public SessionPolicyProvider() {
+    public SessionPolicyProvider(Context context) {
         // Constructor used for reflection
     }
 
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index 64c3c28..ea1d8da 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -37,7 +37,7 @@
 import android.security.Credentials;
 import android.security.KeyStore;
 import android.text.TextUtils;
-import android.util.Slog;
+import android.util.Log;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
@@ -128,7 +128,7 @@
         final int egressType = (egressInfo == null) ? TYPE_NONE : egressInfo.getType();
         final String egressIface = (egressProp == null) ?
                 null : egressProp.getInterfaceName();
-        Slog.d(TAG, "handleStateChanged: egress=" + egressType
+        Log.d(TAG, "handleStateChanged: egress=" + egressType
                 + " " + mAcceptedEgressIface + "->" + egressIface);
 
         if (egressDisconnected || egressChanged) {
@@ -149,7 +149,7 @@
 
         } else if (egressInfo.isConnected() && !vpnInfo.isConnectedOrConnecting()) {
             if (mProfile.isValidLockdownProfile()) {
-                Slog.d(TAG, "Active network connected; starting VPN");
+                Log.d(TAG, "Active network connected; starting VPN");
                 EventLogTags.writeLockdownVpnConnecting(egressType);
                 showNotification(R.string.vpn_lockdown_connecting, R.drawable.vpn_disconnected);
 
@@ -160,11 +160,11 @@
                     mVpn.startLegacyVpnPrivileged(mProfile, KeyStore.getInstance(), egressProp);
                 } catch (IllegalStateException e) {
                     mAcceptedEgressIface = null;
-                    Slog.e(TAG, "Failed to start VPN", e);
+                    Log.e(TAG, "Failed to start VPN", e);
                     showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
                 }
             } else {
-                Slog.e(TAG, "Invalid VPN profile; requires IP-based server and DNS");
+                Log.e(TAG, "Invalid VPN profile; requires IP-based server and DNS");
                 showNotification(R.string.vpn_lockdown_error, R.drawable.vpn_disconnected);
             }
 
@@ -172,8 +172,8 @@
             final String iface = vpnConfig.interfaze;
             final List<LinkAddress> sourceAddrs = vpnConfig.addresses;
 
-            Slog.d(TAG, "VPN connected using iface=" + iface +
-                    ", sourceAddr=" + sourceAddrs.toString());
+            Log.d(TAG, "VPN connected using iface=" + iface
+                    + ", sourceAddr=" + sourceAddrs.toString());
             EventLogTags.writeLockdownVpnConnected(egressType);
             showNotification(R.string.vpn_lockdown_connected, R.drawable.vpn_connected);
 
@@ -190,7 +190,7 @@
     }
 
     private void initLocked() {
-        Slog.d(TAG, "initLocked()");
+        Log.d(TAG, "initLocked()");
 
         mVpn.setEnableTeardown(false);
         mVpn.setLockdown(true);
@@ -204,7 +204,7 @@
     }
 
     private void shutdownLocked() {
-        Slog.d(TAG, "shutdownLocked()");
+        Log.d(TAG, "shutdownLocked()");
 
         mAcceptedEgressIface = null;
         mErrorCount = 0;
@@ -222,7 +222,7 @@
      */
     @GuardedBy("mConnService.mVpns")
     public void reset() {
-        Slog.d(TAG, "reset()");
+        Log.d(TAG, "reset()");
         synchronized (mStateLock) {
             // cycle tracker, reset error count, and trigger retry
             shutdownLocked();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 006d78e..5bd352c 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -17,11 +17,13 @@
 
 import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
 import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
 import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
 import static android.net.INetd.FIREWALL_RULE_ALLOW;
 import static android.net.INetd.FIREWALL_RULE_DENY;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
 import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
 import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
 import static android.os.Process.INVALID_UID;
@@ -339,6 +341,8 @@
                 return FIREWALL_CHAIN_NAME_STANDBY;
             case FIREWALL_CHAIN_POWERSAVE:
                 return FIREWALL_CHAIN_NAME_POWERSAVE;
+            case FIREWALL_CHAIN_RESTRICTED:
+                return FIREWALL_CHAIN_NAME_RESTRICTED;
             default:
                 return String.valueOf(chain);
         }
diff --git a/services/core/java/com/android/server/pm/PreferredComponent.java b/services/core/java/com/android/server/pm/PreferredComponent.java
index c312fc0..a0b2e86 100644
--- a/services/core/java/com/android/server/pm/PreferredComponent.java
+++ b/services/core/java/com/android/server/pm/PreferredComponent.java
@@ -254,6 +254,37 @@
         return numMatch == NS;
     }
 
+    public boolean sameSet(PreferredComponent pc) {
+        if (mSetPackages == null || pc == null || pc.mSetPackages == null
+                || !sameComponent(pc.mComponent)) {
+            return false;
+        }
+        final int otherPackageCount = pc.mSetPackages.length;
+        final int packageCount = mSetPackages.length;
+        if (otherPackageCount != packageCount) {
+            return false;
+        }
+        for (int i = 0; i < packageCount; i++) {
+            if (!mSetPackages[i].equals(pc.mSetPackages[i])
+                    || !mSetClasses[i].equals(pc.mSetClasses[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /** Returns true if the preferred component represents the provided ComponentName. */
+    private boolean sameComponent(ComponentName comp) {
+        if (mComponent == null || comp == null) {
+            return false;
+        }
+        if (mComponent.getPackageName().equals(comp.getPackageName())
+                && mComponent.getClassName().equals(comp.getClassName())) {
+            return true;
+        }
+        return false;
+    }
+
     public boolean isSuperset(List<ResolveInfo> query, boolean excludeSetupWizardPackage) {
         if (mSetPackages == null) {
             return query == null;
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index a261e29..ff3df13 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -22,6 +22,7 @@
 import java.io.PrintWriter;
 
 import com.android.server.IntentResolver;
+import java.util.ArrayList;
 
 public class PreferredIntentResolver
         extends IntentResolver<PreferredActivity, PreferredActivity> {
@@ -45,4 +46,24 @@
     protected IntentFilter getIntentFilter(@NonNull PreferredActivity input) {
         return input;
     }
+
+    public boolean shouldAddPreferredActivity(PreferredActivity pa) {
+        ArrayList<PreferredActivity> pal = findFilters(pa);
+        if (pal == null || pal.isEmpty()) {
+            return true;
+        }
+        if (!pa.mPref.mAlways) {
+            return false;
+        }
+        final int activityCount = pal.size();
+        for (int i = 0; i < activityCount; i++) {
+            PreferredActivity cur = pal.get(i);
+            if (cur.mPref.mAlways
+                    && cur.mPref.mMatch == (pa.mPref.mMatch & IntentFilter.MATCH_CATEGORY_MASK)
+                    && cur.mPref.sameSet(pa.mPref)) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 0f5d978..79e5b27 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1410,8 +1410,7 @@
                 PreferredActivity pa = new PreferredActivity(parser);
                 if (pa.mPref.getParseError() == null) {
                     final PreferredIntentResolver resolver = editPreferredActivitiesLPw(userId);
-                    ArrayList<PreferredActivity> pal = resolver.findFilters(pa);
-                    if (pal == null || pal.size() == 0 || pa.mPref.mAlways) {
+                    if (resolver.shouldAddPreferredActivity(pa)) {
                         resolver.addFilter(pa);
                     }
                 } else {
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
index 5b6de05..4f3f9dc 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyCallbackImpl.java
@@ -16,6 +16,8 @@
 
 package com.android.server.timedetector;
 
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
+import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_TELEPHONY;
 import static com.android.server.timedetector.TimeDetectorStrategy.stringToOrigin;
 
 import android.annotation.NonNull;
@@ -30,6 +32,9 @@
 import android.provider.Settings;
 import android.util.Slog;
 
+import com.android.internal.R;
+import com.android.server.timedetector.TimeDetectorStrategy.Origin;
+
 import java.time.Instant;
 import java.util.Objects;
 
@@ -50,6 +55,13 @@
             Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
 
     /**
+     * By default telephony and network only suggestions are accepted and telephony takes
+     * precedence over network.
+     */
+    private static final @Origin int[] DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES =
+            { ORIGIN_TELEPHONY, ORIGIN_NETWORK };
+
+    /**
      * If a newly calculated system clock time and the current system clock time differs by this or
      * more the system clock will actually be updated. Used to prevent the system clock being set
      * for only minor differences.
@@ -76,14 +88,7 @@
                 SystemProperties.getInt("ro.sys.time_detector_update_diff",
                         SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT);
 
-        // TODO(b/172230856): Obtain these values from configuration.
-        String[] originStrings = { "telephony", "network" };
-        int[] origins = new int[originStrings.length];
-        for (int i = 0; i < originStrings.length; i++) {
-            int origin = stringToOrigin(originStrings[i]);
-            origins[i] = origin;
-        }
-        mOriginPriorities = origins;
+        mOriginPriorities = getOriginPriorities(context);
     }
 
     @Override
@@ -106,7 +111,7 @@
     }
 
     @Override
-    public int[] getAutoOriginPriorities() {
+    public int[] autoOriginPriorities() {
         return mOriginPriorities;
     }
 
@@ -145,4 +150,20 @@
             Slog.wtf(TAG, "WakeLock " + mWakeLock + " not held");
         }
     }
+
+    private static int[] getOriginPriorities(@NonNull Context context) {
+        String[] originStrings =
+                context.getResources().getStringArray(R.array.config_autoTimeSourcesPriority);
+        if (originStrings.length == 0) {
+            return DEFAULT_AUTOMATIC_TIME_ORIGIN_PRIORITIES;
+        } else {
+            int[] origins = new int[originStrings.length];
+            for (int i = 0; i < originStrings.length; i++) {
+                int origin = stringToOrigin(originStrings[i]);
+                origins[i] = origin;
+            }
+
+            return origins;
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 36a3ddd..b3c8c90 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -18,6 +18,8 @@
 
 import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
 
+import static java.util.stream.Collectors.joining;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AlarmManager;
@@ -141,7 +143,7 @@
          * Returns the order to look at time suggestions when automatically detecting time.
          * See {@code #ORIGIN_} constants
          */
-        @Origin int[] getAutoOriginPriorities();
+        @Origin int[] autoOriginPriorities();
 
         /** Acquire a suitable wake lock. Must be followed by {@link #releaseWakeLock()} */
         void acquireWakeLock();
@@ -254,6 +256,14 @@
         ipw.println("mCallback.systemClockMillis()=" + mCallback.systemClockMillis());
         ipw.println("mCallback.systemClockUpdateThresholdMillis()="
                 + mCallback.systemClockUpdateThresholdMillis());
+        ipw.printf("mCallback.autoTimeLowerBound()=%s(%s)\n",
+                mCallback.autoTimeLowerBound(),
+                mCallback.autoTimeLowerBound().toEpochMilli());
+        String priorities =
+                Arrays.stream(mCallback.autoOriginPriorities())
+                        .mapToObj(TimeDetectorStrategy::originToString)
+                        .collect(joining(",", "[", "]"));
+        ipw.println("mCallback.autoOriginPriorities()=" + priorities);
 
         ipw.println("Time change log:");
         ipw.increaseIndent(); // level 2
@@ -356,7 +366,7 @@
         }
 
         // Try the different origins one at a time.
-        int[] originPriorities = mCallback.getAutoOriginPriorities();
+        int[] originPriorities = mCallback.autoOriginPriorities();
         for (int origin : originPriorities) {
             TimestampedValue<Long> newUtcTime = null;
             String cause = null;
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 323ac7b..bedcf9c 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -714,6 +714,7 @@
         SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
 
         if (sessionState == null) {
+            Slog.e(TAG, "sessionState null, no more remove session action!");
             return;
         }
 
@@ -2278,8 +2279,16 @@
                 ClientState clientState = userState.clientStateMap.get(clientToken);
                 if (clientState != null) {
                     while (clientState.sessionTokens.size() > 0) {
+                        IBinder sessionToken = clientState.sessionTokens.get(0);
                         releaseSessionLocked(
-                                clientState.sessionTokens.get(0), Process.SYSTEM_UID, userId);
+                                sessionToken, Process.SYSTEM_UID, userId);
+                        // the releaseSessionLocked function may return before the sessionToken
+                        // is removed if the related sessionState is null. So need to check again
+                        // to avoid death curculation.
+                        if (clientState.sessionTokens.contains(sessionToken)) {
+                            Slog.d(TAG, "remove sessionToken " + sessionToken + " for " + clientToken);
+                            clientState.sessionTokens.remove(sessionToken);
+                        }
                     }
                 }
                 clientToken = null;
diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
deleted file mode 100644
index 33ea1d6..0000000
--- a/services/tests/servicestests/src/com/android/server/NetworkManagementInternalTest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2017 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 com.android.server;
-
-import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
-import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
-import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
-import static android.net.INetd.FIREWALL_RULE_ALLOW;
-import static android.net.INetd.FIREWALL_RULE_DENY;
-import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
-import static android.util.DebugUtils.valueToString;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import android.net.NetworkPolicyManager;
-import android.util.ArrayMap;
-
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.function.BiFunction;
-
-/**
- * Test class for {@link NetworkManagementInternal}.
- *
- * To run the tests, use
- *
- * runtest -c com.android.server.NetworkManagementInternalTest frameworks-services
- *
- * or the following steps:
- *
- * Build: m FrameworksServicesTests
- * Install: adb install -r \
- *     ${ANDROID_PRODUCT_OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk
- * Run: adb shell am instrument -e class com.android.server.NetworkManagementInternalTest -w \
- *     com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
- */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class NetworkManagementInternalTest {
-    private static final int TEST_UID = 111;
-
-    private NetworkManagementService.Injector mInjector;
-    private NetworkManagementInternal mNmi;
-
-    @Before
-    public void setUp() {
-        final NetworkManagementService service = new NetworkManagementService();
-        mInjector = service.getInjector();
-        mNmi = service.new LocalService();
-    }
-
-    @Test
-    public void testIsNetworkRestrictedForUid() {
-        // No firewall chains enabled
-        assertFalse(mNmi.isNetworkRestrictedForUid(TEST_UID));
-
-        // Restrict usage of mobile data in background
-        mInjector.setUidOnMeteredNetworkList(true, TEST_UID, true);
-        assertTrue("Should be true since mobile data usage is restricted",
-                mNmi.isNetworkRestrictedForUid(TEST_UID));
-        mInjector.reset();
-
-        // Data saver is on and uid is not allowlisted
-        mInjector.setDataSaverMode(true);
-        mInjector.setUidOnMeteredNetworkList(false, TEST_UID, false);
-        assertTrue("Should be true since data saver is on and the uid is not whitelisted",
-                mNmi.isNetworkRestrictedForUid(TEST_UID));
-        mInjector.reset();
-
-        // Data saver is on and uid is allowlisted
-        mInjector.setDataSaverMode(true);
-        mInjector.setUidOnMeteredNetworkList(false, TEST_UID, true);
-        assertFalse("Should be false since data saver is on and the uid is whitelisted",
-                mNmi.isNetworkRestrictedForUid(TEST_UID));
-        mInjector.reset();
-
-        final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>();
-        // Dozable chain
-        final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>();
-        isRestrictedForDozable.put(FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForDozable.put(FIREWALL_RULE_ALLOW, false);
-        isRestrictedForDozable.put(FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
-        // Powersaver chain
-        final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
-        isRestrictedForPowerSave.put(FIREWALL_RULE_DEFAULT, true);
-        isRestrictedForPowerSave.put(FIREWALL_RULE_ALLOW, false);
-        isRestrictedForPowerSave.put(FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
-        // Standby chain
-        final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
-        isRestrictedForStandby.put(FIREWALL_RULE_DEFAULT, false);
-        isRestrictedForStandby.put(FIREWALL_RULE_ALLOW, false);
-        isRestrictedForStandby.put(FIREWALL_RULE_DENY, true);
-        expected.put(FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
-
-        final int[] chains = {
-                FIREWALL_CHAIN_STANDBY,
-                FIREWALL_CHAIN_POWERSAVE,
-                FIREWALL_CHAIN_DOZABLE
-        };
-        final int[] states = {
-                FIREWALL_RULE_ALLOW,
-                FIREWALL_RULE_DENY,
-                FIREWALL_RULE_DEFAULT
-        };
-        BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> {
-            return String.format("Unexpected value for chain: %s and state: %s",
-                    valueToString(NetworkPolicyManager.class, "FIREWALL_CHAIN_", chain),
-                    valueToString(NetworkPolicyManager.class, "FIREWALL_RULE_", state));
-        };
-        for (int chain : chains) {
-            final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain);
-            mInjector.setFirewallChainState(chain, true);
-            for (int state : states) {
-                mInjector.setFirewallRule(chain, TEST_UID, state);
-                assertEquals(errorMsg.apply(chain, state),
-                        expectedValues.get(state), mNmi.isNetworkRestrictedForUid(TEST_UID));
-            }
-            mInjector.reset();
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index c23fb80..21396fd 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -525,6 +525,7 @@
     @Test
     public void testSuggestNetworkTime_autoTimeEnabled() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_NETWORK)
                 .pokeAutoTimeDetectionEnabled(true);
 
         NetworkTimeSuggestion timeSuggestion =
@@ -541,6 +542,7 @@
     @Test
     public void testSuggestNetworkTime_autoTimeDisabled() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_NETWORK)
                 .pokeAutoTimeDetectionEnabled(false);
 
         NetworkTimeSuggestion timeSuggestion =
@@ -552,10 +554,26 @@
     }
 
     @Test
-    public void testSuggestNetworkTime_telephonySuggestionsBeatNetworkSuggestions() {
+    public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoOriginPriorities(ORIGIN_NETWORK)
                 .pokeAutoTimeDetectionEnabled(true);
 
+        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
+        NetworkTimeSuggestion timeSuggestion = mScript
+                .generateNetworkTimeSuggestion(suggestedTime);
+
+        mScript.simulateNetworkTimeSuggestion(timeSuggestion)
+                .verifySystemClockWasNotSetAndResetCallTracking()
+                .assertLatestNetworkSuggestion(null);
+    }
+
+    @Test
+    public void highPrioritySuggestionsShouldBeatLowerPrioritySuggestions() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
+
         // Three obviously different times that could not be mistaken for each other.
         Instant networkTime1 = ARBITRARY_TEST_TIME;
         Instant networkTime2 = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
@@ -576,7 +594,7 @@
         mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, null)
                 .assertLatestNetworkSuggestion(networkTimeSuggestion1);
         assertEquals(networkTimeSuggestion1, mScript.peekLatestValidNetworkSuggestion());
-        assertNull(mScript.peekBestTelephonySuggestion());
+        assertNull("No telephony suggestions were made:", mScript.peekBestTelephonySuggestion());
 
         // Simulate a little time passing.
         mScript.simulateTimePassing(smallTimeIncrementMillis)
@@ -631,7 +649,9 @@
         mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
                 .assertLatestNetworkSuggestion(networkTimeSuggestion2);
         assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
-        assertNull(mScript.peekBestTelephonySuggestion());
+        assertNull(
+                "Telephony suggestion should be expired:",
+                mScript.peekBestTelephonySuggestion());
 
         // Toggle auto-time off and on to force the detection logic to run.
         mScript.simulateAutoTimeDetectionToggle()
@@ -646,27 +666,16 @@
         mScript.assertLatestTelephonySuggestion(ARBITRARY_SLOT_INDEX, telephonyTimeSuggestion)
                 .assertLatestNetworkSuggestion(networkTimeSuggestion2);
         assertEquals(networkTimeSuggestion2, mScript.peekLatestValidNetworkSuggestion());
-        assertNull(mScript.peekBestTelephonySuggestion());
-    }
-
-    @Test
-    public void networkTimeSuggestion_ignoredWhenReferencedTimeIsInThePast() {
-        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
-                .pokeAutoTimeDetectionEnabled(true);
-
-        Instant suggestedTime = TIME_LOWER_BOUND.minus(Duration.ofDays(1));
-        NetworkTimeSuggestion timeSuggestion = mScript
-                .generateNetworkTimeSuggestion(suggestedTime);
-
-        mScript.simulateNetworkTimeSuggestion(timeSuggestion)
-                .verifySystemClockWasNotSetAndResetCallTracking()
-                .assertLatestNetworkSuggestion(null);
+        assertNull(
+                "Telephony suggestion should still be expired:",
+                mScript.peekBestTelephonySuggestion());
     }
 
     @Test
     public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_lowerPriorityComesFirst() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
-                .pokeAutoTimeDetectionEnabled(true);
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
 
         Instant networkTime = ARBITRARY_TEST_TIME;
         Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
@@ -686,7 +695,8 @@
     @Test
     public void whenAllTimeSuggestionsAreAvailable_higherPriorityWins_higherPriorityComesFirst() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
-                .pokeAutoTimeDetectionEnabled(true);
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
 
         Instant networkTime = ARBITRARY_TEST_TIME;
         Instant telephonyTime = ARBITRARY_TEST_TIME.plus(Duration.ofDays(30));
@@ -706,7 +716,8 @@
     @Test
     public void whenHighestPrioritySuggestionIsNotAvailable_fallbacksToNext() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
-                .pokeAutoTimeDetectionEnabled(true);
+                .pokeAutoTimeDetectionEnabled(true)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY, ORIGIN_NETWORK);
 
         NetworkTimeSuggestion timeSuggestion =
                 mScript.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -720,7 +731,7 @@
     public void suggestionsFromSourceNotListedInPrioritiesList_areIgnored() {
         mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
                 .pokeAutoTimeDetectionEnabled(true)
-                .pokeAutoOriginPriorities(new int[]{ORIGIN_TELEPHONY});
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
 
         NetworkTimeSuggestion timeSuggestion = mScript.generateNetworkTimeSuggestion(
                 ARBITRARY_TEST_TIME);
@@ -730,6 +741,19 @@
                 .verifySystemClockWasNotSetAndResetCallTracking();
     }
 
+    @Test
+    public void autoOriginPrioritiesList_doesNotAffectManualSuggestion() {
+        mScript.pokeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO)
+                .pokeAutoTimeDetectionEnabled(false)
+                .pokeAutoOriginPriorities(ORIGIN_TELEPHONY);
+
+        ManualTimeSuggestion timeSuggestion =
+                mScript.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
+
+        mScript.simulateManualTimeSuggestion(timeSuggestion, true /* expectedResult */)
+                .verifySystemClockWasSetAndResetCallTracking(ARBITRARY_TEST_TIME.toEpochMilli());
+    }
+
     /**
      * A fake implementation of TimeDetectorStrategy.Callback. Besides tracking changes and behaving
      * like the real thing should, it also asserts preconditions.
@@ -761,7 +785,7 @@
         }
 
         @Override
-        public int[] getAutoOriginPriorities() {
+        public int[] autoOriginPriorities() {
             return mAutoOriginPriorities;
         }
 
@@ -886,8 +910,8 @@
             return this;
         }
 
-        Script pokeAutoOriginPriorities(@Origin int[] autoOriginPriorites) {
-            mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorites);
+        Script pokeAutoOriginPriorities(@Origin int... autoOriginPriorities) {
+            mFakeCallback.pokeAutoOriginPriorities(autoOriginPriorities);
             return this;
         }
 
diff --git a/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl b/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl
deleted file mode 100644
index 45e4c69..0000000
--- a/services/wifi/java/android/net/wifi/WifiApiServiceInfo.aidl
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 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.wifi;
-
-/** @hide */
-parcelable WifiApiServiceInfo {
-    String name;
-    IBinder binder;
-}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 92febd9..27ea690 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2030,8 +2030,16 @@
             "allow_hold_call_during_emergency_bool";
 
     /**
-     * Flag indicating whether the carrier supports RCS presence indication for
-     * User Capability Exchange (UCE).  When presence is supported, the device should use the
+     * Flag indicating whether or not the carrier supports the periodic exchange of phone numbers
+     * in the user's address book with the carrier's presence server in order to retrieve the RCS
+     * capabilities for each contact used in the RCS User Capability Exchange (UCE) procedure. See
+     * RCC.71, section 3 for more information.
+     * <p>
+     * The flag {@link Ims#KEY_ENABLE_PRESENCE_PUBLISH_BOOL} must also be enabled if this flag is
+     * enabled, as sending a periodic SIP PUBLISH with this device's RCS capabilities is a
+     * requirement for capability exchange to begin.
+     * <p>
+     * When presence is supported, the device should use the
      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE} bit mask and set the
      * {@link android.provider.ContactsContract.Data#CARRIER_PRESENCE_VT_CAPABLE} bit to indicate
      * whether each contact supports video calling.  The UI is made aware that presence is enabled
@@ -3847,12 +3855,27 @@
         public static final String KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL =
                 KEY_PREFIX + "ims_single_registration_required_bool";
 
+        /**
+         * A boolean flag specifying whether or not this carrier supports the device notifying the
+         * network of its RCS capabilities using the SIP PUBLISH procedure defined for User
+         * Capability Exchange (UCE). See RCC.71, section 3 for more information.
+         * <p>
+         * If this key's value is set to false, the procedure for RCS contact capability exchange
+         * via SIP SUBSCRIBE/NOTIFY will also be disabled internally, and
+         * {@link #KEY_USE_RCS_PRESENCE_BOOL} must also be set to false to ensure apps do not
+         * improperly think that capability exchange via SIP PUBLISH is enabled.
+         * <p> The default value for this key is {@code false}.
+         */
+        public static final String KEY_ENABLE_PRESENCE_PUBLISH_BOOL =
+                KEY_PREFIX + "enable_presence_publish_bool";
+
         private Ims() {}
 
         private static PersistableBundle getDefaults() {
             PersistableBundle defaults = new PersistableBundle();
             defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000);
             defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false);
+            defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false);
             return defaults;
         }
     }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 44aa6bc..d156907 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -13030,6 +13030,37 @@
     }
 
     /**
+     * Get which bands the modem's background scan is acting on, specified by
+     * {@link #setSystemSelectionChannels}.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @return a list of {@link RadioAccessSpecifier}, or an empty list if no bands are specified.
+     * @throws IllegalStateException if the Telephony process is not currently available.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @NonNull List<RadioAccessSpecifier> getSystemSelectionChannels() {
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                return service.getSystemSelectionChannels(getSubId());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException ex) {
+            if (!isSystemProcess()) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        return new ArrayList<>();
+    }
+
+    /**
      * Verifies whether the input MCC/MNC and MVNO correspond to the current carrier.
      *
      * @param mccmnc the carrier's mccmnc that you want to match
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index d12a6ae..5848be8 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -105,10 +105,17 @@
     public @interface RequestResult {}
 
     /**
+     * The base class of {@link OptionsBuilder} and {@link PresenceBuilder}
+     */
+    public static abstract class RcsUcsCapabilityBuilder {
+        public abstract @NonNull RcsContactUceCapability build();
+    }
+
+    /**
      * Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
      * queried through SIP OPTIONS.
      */
-    public static class OptionsBuilder {
+    public static class OptionsBuilder extends RcsUcsCapabilityBuilder {
 
         private final RcsContactUceCapability mCapabilities;
 
@@ -155,6 +162,7 @@
         /**
          * @return the constructed instance.
          */
+        @Override
         public @NonNull RcsContactUceCapability build() {
             return mCapabilities;
         }
@@ -164,7 +172,7 @@
      * Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
      * queried through a presence server.
      */
-    public static class PresenceBuilder {
+    public static class PresenceBuilder extends RcsUcsCapabilityBuilder {
 
         private final RcsContactUceCapability mCapabilities;
 
@@ -205,6 +213,7 @@
         /**
          * @return the RcsContactUceCapability instance.
          */
+        @Override
         public @NonNull RcsContactUceCapability build() {
             return mCapabilities;
         }
diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
index 4deaba1..a141993 100644
--- a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
@@ -32,5 +32,5 @@
     void onNetworkResponse(int code, in String reason);
     void onNotifyCapabilitiesUpdate(in List<String> pidfXmls);
     void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason);
-    void onTerminated(in String reason, in String retryAfter);
+    void onTerminated(in String reason, long retryAfterMilliseconds);
 }
diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
index 37588ed..1fb339c 100644
--- a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
@@ -86,9 +86,9 @@
     }
 
     @Override
-    public void onTerminated(String reason, String retryAfter) throws ImsException {
+    public void onTerminated(String reason, long retryAfterMilliseconds) throws ImsException {
         try {
-            mResponseBinder.onTerminated(reason, retryAfter);
+            mResponseBinder.onTerminated(reason, retryAfterMilliseconds);
         } catch (RemoteException e) {
         }
     }
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index b5704bf..3a0fb6e 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -250,7 +250,7 @@
          * This allows the framework to know that there will no longer be any
          * capability updates for the requested operationToken.
          */
-        void onTerminated(String reason, String retryAfter) throws ImsException;
+        void onTerminated(String reason, long retryAfterMilliseconds) throws ImsException;
     }
 
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 9f675f6..69525a8 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2159,6 +2159,8 @@
     oneway void setSystemSelectionChannels(in List<RadioAccessSpecifier> specifiers,
             int subId, IBooleanConsumer resultCallback);
 
+    List<RadioAccessSpecifier> getSystemSelectionChannels(int subId);
+
     boolean isMvnoMatched(int subId, int mvnoType, String mvnoMatchData);
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 9d4072f..a2361a7 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -519,6 +519,7 @@
     int RIL_REQUEST_RELEASE_PDU_SESSION_ID = 216;
     int RIL_REQUEST_START_HANDOVER = 217;
     int RIL_REQUEST_CANCEL_HANDOVER = 218;
+    int RIL_REQUEST_GET_SYSTEM_SELECTION_CHANNELS = 219;
 
     /* Responses begin */
     int RIL_RESPONSE_ACKNOWLEDGEMENT = 800;
diff --git a/tests/BootImageProfileTest/TEST_MAPPING b/tests/BootImageProfileTest/TEST_MAPPING
new file mode 100644
index 0000000..1b569f9
--- /dev/null
+++ b/tests/BootImageProfileTest/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "BootImageProfileTest"
+    }
+  ]
+}
diff --git a/tests/net/common/java/android/net/NetworkProviderTest.kt b/tests/net/common/java/android/net/NetworkProviderTest.kt
index dd3f5be..77e9f12 100644
--- a/tests/net/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/net/common/java/android/net/NetworkProviderTest.kt
@@ -33,6 +33,9 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.Mockito.doReturn
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verifyNoMoreInteractions
 import java.util.UUID
 import kotlin.test.assertEquals
 import kotlin.test.assertNotEquals
@@ -87,8 +90,8 @@
         ) = seenEvents.poll(DEFAULT_TIMEOUT_MS) { it is T && predicate(it) }
     }
 
-    private fun createNetworkProvider(): TestNetworkProvider {
-        return TestNetworkProvider(context, mHandlerThread.looper)
+    private fun createNetworkProvider(ctx: Context = context): TestNetworkProvider {
+        return TestNetworkProvider(ctx, mHandlerThread.looper)
     }
 
     @Test
@@ -169,7 +172,12 @@
 
     @Test
     fun testDeclareNetworkRequestUnfulfillable() {
-        val provider = createNetworkProvider()
+        val mockContext = mock(Context::class.java)
+        val provider = createNetworkProvider(mockContext)
+        // ConnectivityManager not required at creation time
+        verifyNoMoreInteractions(mockContext)
+        doReturn(mCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
+
         mCm.registerNetworkProvider(provider)
 
         val specifier = StringNetworkSpecifier(UUID.randomUUID().toString())
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c917e66..7a1cb25 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -56,8 +56,10 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_IMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
@@ -1233,7 +1235,7 @@
         MockitoAnnotations.initMocks(this);
         when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
 
-        when(mUserManager.getUsers(eq(true))).thenReturn(
+        when(mUserManager.getAliveUsers()).thenReturn(
                 Arrays.asList(new UserInfo[] {
                         new UserInfo(VPN_USER, "", 0),
                 }));
@@ -5398,6 +5400,106 @@
     }
 
     @Test
+    public void testApplyUnderlyingCapabilities() throws Exception {
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
+        mCellNetworkAgent.connect(false /* validated */);
+        mWiFiNetworkAgent.connect(false /* validated */);
+
+        final NetworkCapabilities cellNc = new NetworkCapabilities()
+                .addTransportType(TRANSPORT_CELLULAR)
+                .addCapability(NET_CAPABILITY_INTERNET)
+                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                .setLinkDownstreamBandwidthKbps(10);
+        final NetworkCapabilities wifiNc = new NetworkCapabilities()
+                .addTransportType(TRANSPORT_WIFI)
+                .addCapability(NET_CAPABILITY_INTERNET)
+                .addCapability(NET_CAPABILITY_NOT_METERED)
+                .addCapability(NET_CAPABILITY_NOT_ROAMING)
+                .addCapability(NET_CAPABILITY_NOT_CONGESTED)
+                .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
+                .setLinkUpstreamBandwidthKbps(20);
+        mCellNetworkAgent.setNetworkCapabilities(cellNc, true /* sendToConnectivityService */);
+        mWiFiNetworkAgent.setNetworkCapabilities(wifiNc, true /* sendToConnectivityService */);
+        waitForIdle();
+
+        final Network mobile = mCellNetworkAgent.getNetwork();
+        final Network wifi = mWiFiNetworkAgent.getNetwork();
+
+        final NetworkCapabilities initialCaps = new NetworkCapabilities();
+        initialCaps.addCapability(NET_CAPABILITY_INTERNET);
+        initialCaps.removeCapability(NET_CAPABILITY_NOT_VPN);
+
+        final NetworkCapabilities withNoUnderlying = new NetworkCapabilities();
+        withNoUnderlying.addCapability(NET_CAPABILITY_INTERNET);
+        withNoUnderlying.addCapability(NET_CAPABILITY_NOT_CONGESTED);
+        withNoUnderlying.addCapability(NET_CAPABILITY_NOT_ROAMING);
+        withNoUnderlying.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        withNoUnderlying.addTransportType(TRANSPORT_VPN);
+        withNoUnderlying.removeCapability(NET_CAPABILITY_NOT_VPN);
+
+        final NetworkCapabilities withMobileUnderlying = new NetworkCapabilities(withNoUnderlying);
+        withMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
+        withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+        withMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_SUSPENDED);
+        withMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
+
+        final NetworkCapabilities withWifiUnderlying = new NetworkCapabilities(withNoUnderlying);
+        withWifiUnderlying.addTransportType(TRANSPORT_WIFI);
+        withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
+        withWifiUnderlying.setLinkUpstreamBandwidthKbps(20);
+
+        final NetworkCapabilities withWifiAndMobileUnderlying =
+                new NetworkCapabilities(withNoUnderlying);
+        withWifiAndMobileUnderlying.addTransportType(TRANSPORT_CELLULAR);
+        withWifiAndMobileUnderlying.addTransportType(TRANSPORT_WIFI);
+        withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
+        withWifiAndMobileUnderlying.removeCapability(NET_CAPABILITY_NOT_ROAMING);
+        withWifiAndMobileUnderlying.setLinkDownstreamBandwidthKbps(10);
+        withWifiAndMobileUnderlying.setLinkUpstreamBandwidthKbps(20);
+
+        NetworkCapabilities caps = new NetworkCapabilities(initialCaps);
+        final boolean notDeclaredMetered = false;
+        mService.applyUnderlyingCapabilities(new Network[]{}, caps, notDeclaredMetered);
+        assertEquals(withNoUnderlying, caps);
+
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{null}, caps, notDeclaredMetered);
+        assertEquals(withNoUnderlying, caps);
+
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{mobile}, caps, notDeclaredMetered);
+        assertEquals(withMobileUnderlying, caps);
+
+        mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, notDeclaredMetered);
+        assertEquals(withWifiUnderlying, caps);
+
+        final boolean isDeclaredMetered = true;
+        withWifiUnderlying.removeCapability(NET_CAPABILITY_NOT_METERED);
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{wifi}, caps, isDeclaredMetered);
+        assertEquals(withWifiUnderlying, caps);
+
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{mobile, wifi}, caps, isDeclaredMetered);
+        assertEquals(withWifiAndMobileUnderlying, caps);
+
+        withWifiUnderlying.addCapability(NET_CAPABILITY_NOT_METERED);
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
+                caps, notDeclaredMetered);
+        assertEquals(withWifiAndMobileUnderlying, caps);
+
+        caps = new NetworkCapabilities(initialCaps);
+        mService.applyUnderlyingCapabilities(new Network[]{null, mobile, null, wifi},
+                caps, notDeclaredMetered);
+        assertEquals(withWifiAndMobileUnderlying, caps);
+
+        mService.applyUnderlyingCapabilities(null, caps, notDeclaredMetered);
+        assertEquals(withWifiUnderlying, caps);
+    }
+
+    @Test
     public void testVpnConnectDisconnectUnderlyingNetwork() throws Exception {
         final TestNetworkCallback callback = new TestNetworkCallback();
         final NetworkRequest request = new NetworkRequest.Builder()
@@ -5947,17 +6049,28 @@
                 && caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_WIFI));
 
+        // Change the VPN's capabilities somehow (specifically, disconnect wifi).
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        callback.expectCapabilitiesThat(mMockVpn, (caps)
+                -> caps.getUids().size() == 2
+                && caps.getUids().contains(new UidRange(uid, uid))
+                && caps.getUids().contains(UidRange.createForUser(restrictedUserId))
+                && caps.hasTransport(TRANSPORT_VPN)
+                && !caps.hasTransport(TRANSPORT_WIFI));
+
         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
         removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
         handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
 
-        // Expect that the VPN gains the UID range for the restricted user.
+        // Expect that the VPN gains the UID range for the restricted user, and that the capability
+        // change made just before that (i.e., loss of TRANSPORT_WIFI) is preserved.
         callback.expectCapabilitiesThat(mMockVpn, (caps)
                 -> caps.getUids().size() == 1
                 && caps.getUids().contains(new UidRange(uid, uid))
                 && caps.hasTransport(TRANSPORT_VPN)
-                && caps.hasTransport(TRANSPORT_WIFI));
+                && !caps.hasTransport(TRANSPORT_WIFI));
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/NetworkManagementServiceTest.java b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
index 968b307..ea763d2 100644
--- a/tests/net/java/com/android/server/NetworkManagementServiceTest.java
+++ b/tests/net/java/com/android/server/NetworkManagementServiceTest.java
@@ -16,6 +16,12 @@
 
 package com.android.server;
 
+import static android.util.DebugUtils.valueToString;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
@@ -29,15 +35,19 @@
 import android.net.INetd;
 import android.net.INetdUnsolicitedEventListener;
 import android.net.LinkAddress;
+import android.net.NetworkPolicyManager;
 import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
 import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArrayMap;
 
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.app.IBatteryStats;
-import com.android.server.NetworkManagementService.SystemServices;
+import com.android.server.NetworkManagementService.Dependencies;
 import com.android.server.net.BaseNetworkObserver;
 
 import org.junit.After;
@@ -49,13 +59,14 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.function.BiFunction;
+
 /**
  * Tests for {@link NetworkManagementService}.
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class NetworkManagementServiceTest {
-
     private NetworkManagementService mNMService;
 
     @Mock private Context mContext;
@@ -66,7 +77,9 @@
     @Captor
     private ArgumentCaptor<INetdUnsolicitedEventListener> mUnsolListenerCaptor;
 
-    private final SystemServices mServices = new SystemServices() {
+    private final MockDependencies mDeps = new MockDependencies();
+
+    private final class MockDependencies extends Dependencies {
         @Override
         public IBinder getService(String name) {
             switch (name) {
@@ -76,14 +89,21 @@
                     throw new UnsupportedOperationException("Unknown service " + name);
             }
         }
+
         @Override
         public void registerLocalService(NetworkManagementInternal nmi) {
         }
+
         @Override
         public INetd getNetd() {
             return mNetdService;
         }
-    };
+
+        @Override
+        public int getCallingUid() {
+            return Process.SYSTEM_UID;
+        }
+    }
 
     @Before
     public void setUp() throws Exception {
@@ -91,7 +111,7 @@
         doNothing().when(mNetdService)
                 .registerUnsolicitedEventListener(mUnsolListenerCaptor.capture());
         // Start the service and wait until it connects to our socket.
-        mNMService = NetworkManagementService.create(mContext, mServices);
+        mNMService = NetworkManagementService.create(mContext, mDeps);
     }
 
     @After
@@ -192,4 +212,105 @@
         // Make sure nothing else was called.
         verifyNoMoreInteractions(observer);
     }
+
+    @Test
+    public void testFirewallEnabled() {
+        mNMService.setFirewallEnabled(true);
+        assertTrue(mNMService.isFirewallEnabled());
+
+        mNMService.setFirewallEnabled(false);
+        assertFalse(mNMService.isFirewallEnabled());
+    }
+
+    private static final int TEST_UID = 111;
+
+    @Test
+    public void testNetworkRestrictedDefault() {
+        assertFalse(mNMService.isNetworkRestricted(TEST_UID));
+    }
+
+    @Test
+    public void testMeteredNetworkRestrictions() throws RemoteException {
+        // Make sure the mocked netd method returns true.
+        doReturn(true).when(mNetdService).bandwidthEnableDataSaver(anyBoolean());
+
+        // Restrict usage of mobile data in background
+        mNMService.setUidMeteredNetworkDenylist(TEST_UID, true);
+        assertTrue("Should be true since mobile data usage is restricted",
+                mNMService.isNetworkRestricted(TEST_UID));
+
+        mNMService.setDataSaverModeEnabled(true);
+        verify(mNetdService).bandwidthEnableDataSaver(true);
+
+        mNMService.setUidMeteredNetworkDenylist(TEST_UID, false);
+        assertTrue("Should be true since data saver is on and the uid is not allowlisted",
+                mNMService.isNetworkRestricted(TEST_UID));
+
+        mNMService.setUidMeteredNetworkAllowlist(TEST_UID, true);
+        assertFalse("Should be false since data saver is on and the uid is allowlisted",
+                mNMService.isNetworkRestricted(TEST_UID));
+
+        // remove uid from allowlist and turn datasaver off again
+        mNMService.setUidMeteredNetworkAllowlist(TEST_UID, false);
+        mNMService.setDataSaverModeEnabled(false);
+        verify(mNetdService).bandwidthEnableDataSaver(false);
+        assertFalse("Network should not be restricted when data saver is off",
+                mNMService.isNetworkRestricted(TEST_UID));
+    }
+
+    @Test
+    public void testFirewallChains() {
+        final ArrayMap<Integer, ArrayMap<Integer, Boolean>> expected = new ArrayMap<>();
+        // Dozable chain
+        final ArrayMap<Integer, Boolean> isRestrictedForDozable = new ArrayMap<>();
+        isRestrictedForDozable.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+        isRestrictedForDozable.put(INetd.FIREWALL_RULE_ALLOW, false);
+        isRestrictedForDozable.put(INetd.FIREWALL_RULE_DENY, true);
+        expected.put(INetd.FIREWALL_CHAIN_DOZABLE, isRestrictedForDozable);
+        // Powersaver chain
+        final ArrayMap<Integer, Boolean> isRestrictedForPowerSave = new ArrayMap<>();
+        isRestrictedForPowerSave.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+        isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_ALLOW, false);
+        isRestrictedForPowerSave.put(INetd.FIREWALL_RULE_DENY, true);
+        expected.put(INetd.FIREWALL_CHAIN_POWERSAVE, isRestrictedForPowerSave);
+        // Standby chain
+        final ArrayMap<Integer, Boolean> isRestrictedForStandby = new ArrayMap<>();
+        isRestrictedForStandby.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, false);
+        isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
+        isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true);
+        expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
+        // Restricted mode chain
+        final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>();
+        isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
+        isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false);
+        isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true);
+        expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
+
+        final int[] chains = {
+                INetd.FIREWALL_CHAIN_STANDBY,
+                INetd.FIREWALL_CHAIN_POWERSAVE,
+                INetd.FIREWALL_CHAIN_DOZABLE,
+                INetd.FIREWALL_CHAIN_RESTRICTED
+        };
+        final int[] states = {
+                INetd.FIREWALL_RULE_ALLOW,
+                INetd.FIREWALL_RULE_DENY,
+                NetworkPolicyManager.FIREWALL_RULE_DEFAULT
+        };
+        BiFunction<Integer, Integer, String> errorMsg = (chain, state) -> {
+            return String.format("Unexpected value for chain: %s and state: %s",
+                    valueToString(INetd.class, "FIREWALL_CHAIN_", chain),
+                    valueToString(INetd.class, "FIREWALL_RULE_", state));
+        };
+        for (int chain : chains) {
+            final ArrayMap<Integer, Boolean> expectedValues = expected.get(chain);
+            mNMService.setFirewallChainEnabled(chain, true);
+            for (int state : states) {
+                mNMService.setFirewallUidRule(chain, TEST_UID, state);
+                assertEquals(errorMsg.apply(chain, state),
+                        expectedValues.get(state), mNMService.isNetworkRestricted(TEST_UID));
+            }
+            mNMService.setFirewallChainEnabled(chain, false);
+        }
+    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
index 5a29c2c..de35f91 100644
--- a/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -123,7 +123,7 @@
         MockitoAnnotations.initMocks(this);
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
-        when(mUserManager.getUsers(eq(true))).thenReturn(
+        when(mUserManager.getAliveUsers()).thenReturn(
                 Arrays.asList(new UserInfo[] {
                         new UserInfo(MOCK_USER1, "", 0),
                         new UserInfo(MOCK_USER2, "", 0),
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index e1e0efa..337507a 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -21,15 +21,6 @@
 import static android.content.pm.UserInfo.FLAG_PRIMARY;
 import static android.content.pm.UserInfo.FLAG_RESTRICTED;
 import static android.net.ConnectivityManager.NetworkCallback;
-import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_VPN;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
@@ -621,102 +612,6 @@
         order.verify(mNotificationManager).cancel(anyString(), anyInt());
     }
 
-    @Test
-    public void testCapabilities() {
-        setMockedUsers(primaryUser);
-
-        final Network mobile = new Network(1);
-        final Network wifi = new Network(2);
-
-        final Map<Network, NetworkCapabilities> networks = new HashMap<>();
-        networks.put(
-                mobile,
-                new NetworkCapabilities()
-                        .addTransportType(TRANSPORT_CELLULAR)
-                        .addCapability(NET_CAPABILITY_INTERNET)
-                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                        .setLinkDownstreamBandwidthKbps(10));
-        networks.put(
-                wifi,
-                new NetworkCapabilities()
-                        .addTransportType(TRANSPORT_WIFI)
-                        .addCapability(NET_CAPABILITY_INTERNET)
-                        .addCapability(NET_CAPABILITY_NOT_METERED)
-                        .addCapability(NET_CAPABILITY_NOT_ROAMING)
-                        .addCapability(NET_CAPABILITY_NOT_CONGESTED)
-                        .addCapability(NET_CAPABILITY_NOT_SUSPENDED)
-                        .setLinkUpstreamBandwidthKbps(20));
-        setMockedNetworks(networks);
-
-        final NetworkCapabilities caps = new NetworkCapabilities();
-
-        Vpn.applyUnderlyingCapabilities(
-                mConnectivityManager, new Network[] {}, caps, false /* isAlwaysMetered */);
-        assertTrue(caps.hasTransport(TRANSPORT_VPN));
-        assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
-        assertFalse(caps.hasTransport(TRANSPORT_WIFI));
-        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
-        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
-        Vpn.applyUnderlyingCapabilities(
-                mConnectivityManager,
-                new Network[] {mobile},
-                caps,
-                false /* isAlwaysMetered */);
-        assertTrue(caps.hasTransport(TRANSPORT_VPN));
-        assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
-        assertFalse(caps.hasTransport(TRANSPORT_WIFI));
-        assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
-        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkUpstreamBandwidthKbps());
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
-        Vpn.applyUnderlyingCapabilities(
-                mConnectivityManager, new Network[] {wifi}, caps, false /* isAlwaysMetered */);
-        assertTrue(caps.hasTransport(TRANSPORT_VPN));
-        assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
-        assertTrue(caps.hasTransport(TRANSPORT_WIFI));
-        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
-        assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
-        Vpn.applyUnderlyingCapabilities(
-                mConnectivityManager, new Network[] {wifi}, caps, true /* isAlwaysMetered */);
-        assertTrue(caps.hasTransport(TRANSPORT_VPN));
-        assertFalse(caps.hasTransport(TRANSPORT_CELLULAR));
-        assertTrue(caps.hasTransport(TRANSPORT_WIFI));
-        assertEquals(LINK_BANDWIDTH_UNSPECIFIED, caps.getLinkDownstreamBandwidthKbps());
-        assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-
-        Vpn.applyUnderlyingCapabilities(
-                mConnectivityManager,
-                new Network[] {mobile, wifi},
-                caps,
-                false /* isAlwaysMetered */);
-        assertTrue(caps.hasTransport(TRANSPORT_VPN));
-        assertTrue(caps.hasTransport(TRANSPORT_CELLULAR));
-        assertTrue(caps.hasTransport(TRANSPORT_WIFI));
-        assertEquals(10, caps.getLinkDownstreamBandwidthKbps());
-        assertEquals(20, caps.getLinkUpstreamBandwidthKbps());
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_METERED));
-        assertFalse(caps.hasCapability(NET_CAPABILITY_NOT_ROAMING));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_CONGESTED));
-        assertTrue(caps.hasCapability(NET_CAPABILITY_NOT_SUSPENDED));
-    }
-
     /**
      * The profile name should NOT change between releases for backwards compatibility
      *
@@ -1325,15 +1220,14 @@
          * @see UserManagerService#getUsers(boolean)
          */
         doAnswer(invocation -> {
-            final boolean excludeDying = (boolean) invocation.getArguments()[0];
             final ArrayList<UserInfo> result = new ArrayList<>(users.length);
             for (UserInfo ui : users) {
-                if (!excludeDying || (ui.isEnabled() && !ui.partial)) {
+                if (ui.isEnabled() && !ui.partial) {
                     result.add(ui);
                 }
             }
             return result;
-        }).when(mUserManager).getUsers(anyBoolean());
+        }).when(mUserManager).getAliveUsers();
 
         doAnswer(invocation -> {
             final int id = (int) invocation.getArguments()[0];