Merge "Adds client info in ContextHubService dump"
diff --git a/api/current.txt b/api/current.txt
index b8e4531..297835c 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6726,7 +6726,8 @@
     method @Nullable public String getAlwaysOnVpnPackage(@NonNull android.content.ComponentName);
     method @NonNull @WorkerThread public android.os.Bundle getApplicationRestrictions(@Nullable android.content.ComponentName, String);
     method @Deprecated @Nullable public String getApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName);
-    method public boolean getAutoTimeRequired();
+    method public boolean getAutoTime(@NonNull android.content.ComponentName);
+    method @Deprecated public boolean getAutoTimeRequired();
     method @NonNull public java.util.List<android.os.UserHandle> getBindDeviceAdminTargetUsers(@NonNull android.content.ComponentName);
     method public boolean getBluetoothContactSharingDisabled(@NonNull android.content.ComponentName);
     method public boolean getCameraDisabled(@Nullable android.content.ComponentName);
@@ -6842,7 +6843,8 @@
     method public boolean setApplicationHidden(@NonNull android.content.ComponentName, String, boolean);
     method @WorkerThread public void setApplicationRestrictions(@Nullable android.content.ComponentName, String, android.os.Bundle);
     method @Deprecated public void setApplicationRestrictionsManagingPackage(@NonNull android.content.ComponentName, @Nullable String) throws android.content.pm.PackageManager.NameNotFoundException;
-    method public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
+    method public void setAutoTime(@NonNull android.content.ComponentName, boolean);
+    method @Deprecated public void setAutoTimeRequired(@NonNull android.content.ComponentName, boolean);
     method public void setBackupServiceEnabled(@NonNull android.content.ComponentName, boolean);
     method public void setBluetoothContactSharingDisabled(@NonNull android.content.ComponentName, boolean);
     method public void setCameraDisabled(@NonNull android.content.ComponentName, boolean);
@@ -44373,6 +44375,8 @@
   public static final class AccessNetworkConstants.NgranBands {
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_12 = 12; // 0xc
+    field public static final int BAND_14 = 14; // 0xe
+    field public static final int BAND_18 = 18; // 0x12
     field public static final int BAND_2 = 2; // 0x2
     field public static final int BAND_20 = 20; // 0x14
     field public static final int BAND_25 = 25; // 0x19
@@ -44381,15 +44385,19 @@
     field public static final int BAND_260 = 260; // 0x104
     field public static final int BAND_261 = 261; // 0x105
     field public static final int BAND_28 = 28; // 0x1c
+    field public static final int BAND_29 = 29; // 0x1d
     field public static final int BAND_3 = 3; // 0x3
+    field public static final int BAND_30 = 30; // 0x1e
     field public static final int BAND_34 = 34; // 0x22
     field public static final int BAND_38 = 38; // 0x26
     field public static final int BAND_39 = 39; // 0x27
     field public static final int BAND_40 = 40; // 0x28
     field public static final int BAND_41 = 41; // 0x29
+    field public static final int BAND_48 = 48; // 0x30
     field public static final int BAND_5 = 5; // 0x5
     field public static final int BAND_50 = 50; // 0x32
     field public static final int BAND_51 = 51; // 0x33
+    field public static final int BAND_65 = 65; // 0x41
     field public static final int BAND_66 = 66; // 0x42
     field public static final int BAND_7 = 7; // 0x7
     field public static final int BAND_70 = 70; // 0x46
@@ -44407,6 +44415,7 @@
     field public static final int BAND_83 = 83; // 0x53
     field public static final int BAND_84 = 84; // 0x54
     field public static final int BAND_86 = 86; // 0x56
+    field public static final int BAND_90 = 90; // 0x5a
   }
 
   public static final class AccessNetworkConstants.UtranBand {
@@ -44993,6 +45002,12 @@
     field public static final int SCAN_TYPE_PERIODIC = 1; // 0x1
   }
 
+  public final class PhoneCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
+  }
+
   public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
     ctor public PhoneNumberFormattingTextWatcher();
     ctor public PhoneNumberFormattingTextWatcher(String);
@@ -46729,30 +46744,30 @@
   public static class Layout.Directions {
   }
 
-  public abstract class LoginFilter implements android.text.InputFilter {
-    method public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
-    method public abstract boolean isAllowed(char);
-    method public void onInvalidCharacter(char);
-    method public void onStart();
-    method public void onStop();
+  @Deprecated public abstract class LoginFilter implements android.text.InputFilter {
+    method @Deprecated public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
+    method @Deprecated public abstract boolean isAllowed(char);
+    method @Deprecated public void onInvalidCharacter(char);
+    method @Deprecated public void onStart();
+    method @Deprecated public void onStop();
   }
 
-  public static class LoginFilter.PasswordFilterGMail extends android.text.LoginFilter {
-    ctor public LoginFilter.PasswordFilterGMail();
-    ctor public LoginFilter.PasswordFilterGMail(boolean);
-    method public boolean isAllowed(char);
+  @Deprecated public static class LoginFilter.PasswordFilterGMail extends android.text.LoginFilter {
+    ctor @Deprecated public LoginFilter.PasswordFilterGMail();
+    ctor @Deprecated public LoginFilter.PasswordFilterGMail(boolean);
+    method @Deprecated public boolean isAllowed(char);
   }
 
-  public static class LoginFilter.UsernameFilterGMail extends android.text.LoginFilter {
-    ctor public LoginFilter.UsernameFilterGMail();
-    ctor public LoginFilter.UsernameFilterGMail(boolean);
-    method public boolean isAllowed(char);
+  @Deprecated public static class LoginFilter.UsernameFilterGMail extends android.text.LoginFilter {
+    ctor @Deprecated public LoginFilter.UsernameFilterGMail();
+    ctor @Deprecated public LoginFilter.UsernameFilterGMail(boolean);
+    method @Deprecated public boolean isAllowed(char);
   }
 
-  public static class LoginFilter.UsernameFilterGeneric extends android.text.LoginFilter {
-    ctor public LoginFilter.UsernameFilterGeneric();
-    ctor public LoginFilter.UsernameFilterGeneric(boolean);
-    method public boolean isAllowed(char);
+  @Deprecated public static class LoginFilter.UsernameFilterGeneric extends android.text.LoginFilter {
+    ctor @Deprecated public LoginFilter.UsernameFilterGeneric();
+    ctor @Deprecated public LoginFilter.UsernameFilterGeneric(boolean);
+    method @Deprecated public boolean isAllowed(char);
   }
 
   public interface NoCopySpan {
diff --git a/api/system-current.txt b/api/system-current.txt
index 9c8bce6..8bb1983 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1329,6 +1329,11 @@
 
 package android.bluetooth {
 
+  public final class BluetoothA2dp implements android.bluetooth.BluetoothProfile {
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+  }
+
   public final class BluetoothAdapter {
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean addOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull java.util.concurrent.Executor, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connectAllEnabledProfiles(@NonNull android.bluetooth.BluetoothDevice);
@@ -1393,7 +1398,14 @@
   public final class BluetoothHeadset implements android.bluetooth.BluetoothProfile {
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean connect(android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean disconnect(android.bluetooth.BluetoothDevice);
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setPriority(android.bluetooth.BluetoothDevice, int);
+  }
+
+  public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public int getConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setConnectionPolicy(@NonNull android.bluetooth.BluetoothDevice, int);
   }
 
   public final class BluetoothPan implements android.bluetooth.BluetoothProfile {
@@ -1412,9 +1424,12 @@
   }
 
   public interface BluetoothProfile {
+    field public static final int CONNECTION_POLICY_ALLOWED = 100; // 0x64
+    field public static final int CONNECTION_POLICY_FORBIDDEN = 0; // 0x0
+    field public static final int CONNECTION_POLICY_UNKNOWN = -1; // 0xffffffff
     field public static final int PAN = 5; // 0x5
-    field public static final int PRIORITY_OFF = 0; // 0x0
-    field public static final int PRIORITY_ON = 100; // 0x64
+    field @Deprecated public static final int PRIORITY_OFF = 0; // 0x0
+    field @Deprecated public static final int PRIORITY_ON = 100; // 0x64
   }
 
 }
@@ -8036,7 +8051,7 @@
   }
 
   public static class CallScreeningService.CallResponse.Builder {
-    method public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallFurther(boolean);
+    method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
   }
 
   public abstract class Conference extends android.telecom.Conferenceable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 89fdb3f..2d35736 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2944,7 +2944,7 @@
   }
 
   public static class CallScreeningService.CallResponse.Builder {
-    method public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallFurther(boolean);
+    method @NonNull public android.telecom.CallScreeningService.CallResponse.Builder setShouldScreenCallViaAudioProcessing(boolean);
   }
 
   public abstract class Conference extends android.telecom.Conferenceable {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 47fd87d..39dc51e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5001,14 +5001,15 @@
      * <p>Device owner, profile owner and their delegated certificate installer can use
      * {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device information
      * including manufacturer, model, brand, device and product in the attestation record.
-     * Only device owner and their delegated certificate installer can use
-     * {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID} to request
-     * unique device identifiers to be attested (the serial number, IMEI and MEID correspondingly),
-     * if supported by the device (see {@link #isDeviceIdAttestationSupported()}).
-     * Additionally, device owner and their delegated certificate installer can also request the
-     * attestation record to be signed using an individual attestation certificate by specifying
-     * the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION} flag (if supported by the device, see
-     * {@link #isUniqueDeviceAttestationSupported()}).
+     * Only device owner, profile owner on an organization-owned device and their delegated
+     * certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and
+     * {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial number,
+     * IMEI and MEID correspondingly), if supported by the device
+     * (see {@link #isDeviceIdAttestationSupported()}).
+     * Additionally, device owner, profile owner on an organization-owned device and their delegated
+     * certificate installers can also request the attestation record to be signed using an
+     * individual attestation certificate by specifying the {@link #ID_TYPE_INDIVIDUAL_ATTESTATION}
+     * flag (if supported by the device, see {@link #isUniqueDeviceAttestationSupported()}).
      * <p>
      * If any of {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and {@link #ID_TYPE_MEID}
      * is set, it is implicitly assumed that {@link #ID_TYPE_BASE_INFO} is also set.
@@ -5696,11 +5697,21 @@
      * <p>
      * The calling device admin must be a device owner, or alternatively a profile owner from
      * Android 8.0 (API level 26) or higher. If it is not, a security exception will be thrown.
+     * <p>
+     * Staring from Android 11, this API switches to use
+     * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} to enforce the auto time settings. Calling
+     * this API to enforce auto time will result in
+     * {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being set, while calling this API to lift
+     * the requirement will result in {@link UserManager#DISALLOW_CONFIG_DATE_TIME} being cleared.
      *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param required Whether auto time is set required or not.
      * @throws SecurityException if {@code admin} is not a device owner.
+     * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #setAutoTime}
+     * to turn auto time on or off and use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
+     * to prevent the user from changing this setting.
      */
+    @Deprecated
     public void setAutoTimeRequired(@NonNull ComponentName admin, boolean required) {
         throwIfParentInstance("setAutoTimeRequired");
         if (mService != null) {
@@ -5714,7 +5725,9 @@
 
     /**
      * @return true if auto time is required.
+     * @deprecated From {@link android.os.Build.VERSION_CODES#R}. Use {@link #getAutoTime}
      */
+    @Deprecated
     public boolean getAutoTimeRequired() {
         throwIfParentInstance("getAutoTimeRequired");
         if (mService != null) {
@@ -5728,6 +5741,47 @@
     }
 
     /**
+     * Called by a device owner, a profile owner for the primary user or a profile
+     * owner of an organization-owned managed profile to turn auto time on and off.
+     * Callers are recommended to use {@link UserManager#DISALLOW_CONFIG_DATE_TIME}
+     * to prevent the user from changing this setting.
+     * <p>
+     * If user restriction {@link UserManager#DISALLOW_CONFIG_DATE_TIME} is used,
+     * no user will be able set the date and time. Instead, the network date
+     * and time will be used.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param enabled Whether time should be obtained automatically from the network or not.
+     * @throws SecurityException if caller is not a device owner, a profile owner for the
+     * primary user, or a profile owner of an organization-owned managed profile.
+     */
+    public void setAutoTime(@NonNull ComponentName admin, boolean enabled) {
+        if (mService != null) {
+            try {
+                mService.setAutoTime(admin, enabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * @return true if auto time is enabled on the device.
+     * @throws SecurityException if caller is not a device owner, a profile owner for the
+     * primary user, or a profile owner of an organization-owned managed profile.
+     */
+    public boolean getAutoTime(@NonNull ComponentName admin) {
+        if (mService != null) {
+            try {
+                return mService.getAutoTime(admin);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by a device owner to set whether all users created on the device should be ephemeral.
      * <p>
      * The system user is exempt from this policy - it is never ephemeral.
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index df4b554..f55026c 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -295,6 +295,9 @@
     void setAutoTimeRequired(in ComponentName who, boolean required);
     boolean getAutoTimeRequired();
 
+    void setAutoTime(in ComponentName who, boolean enabled);
+    boolean getAutoTime(in ComponentName who);
+
     void setForceEphemeralUsers(in ComponentName who, boolean forceEpehemeralUsers);
     boolean getForceEphemeralUsers(in ComponentName who);
 
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 1fe1b10..accdd8d 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -17,10 +17,12 @@
 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.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -439,28 +441,45 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
-     * {@link #PRIORITY_OFF},
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled()
                     && isValidDevice(device)) {
-                if (priority != BluetoothProfile.PRIORITY_OFF
-                        && priority != BluetoothProfile.PRIORITY_ON) {
+                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                        && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                     return false;
                 }
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             }
             if (service == null) Log.w(TAG, "Proxy not attached to service");
             return false;
@@ -474,8 +493,7 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
@@ -485,17 +503,35 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         try {
             final IBluetoothA2dp service = getService();
             if (service != null && isEnabled()
                     && isValidDevice(device)) {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             }
             if (service == null) Log.w(TAG, "Proxy not attached to service");
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothA2dpSink.java b/core/java/android/bluetooth/BluetoothA2dpSink.java
index 5a8055a..c17834a 100755
--- a/core/java/android/bluetooth/BluetoothA2dpSink.java
+++ b/core/java/android/bluetooth/BluetoothA2dpSink.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -317,27 +320,43 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
-     * {@link #PRIORITY_OFF},
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -351,28 +370,44 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothA2dpSink service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return BluetoothProfile.PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return BluetoothProfile.PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 89f9cbc..9b5280d 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -27,6 +27,7 @@
 import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityThread;
+import android.bluetooth.BluetoothProfile.ConnectionPolicy;
 import android.bluetooth.le.BluetoothLeAdvertiser;
 import android.bluetooth.le.BluetoothLeScanner;
 import android.bluetooth.le.PeriodicAdvertisingManager;
@@ -3447,4 +3448,48 @@
         void onMetadataChanged(@NonNull BluetoothDevice device, int key,
                 @Nullable byte[] value);
     }
+
+    /**
+     * Converts old constant of priority to the new for connection policy
+     *
+     * @param priority is the priority to convert to connection policy
+     * @return the equivalent connection policy constant to the priority
+     *
+     * @hide
+     */
+    public static @ConnectionPolicy int priorityToConnectionPolicy(int priority) {
+        switch(priority) {
+            case BluetoothProfile.PRIORITY_AUTO_CONNECT:
+                return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+            case BluetoothProfile.PRIORITY_ON:
+                return BluetoothProfile.CONNECTION_POLICY_ALLOWED;
+            case BluetoothProfile.PRIORITY_OFF:
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
+            case BluetoothProfile.PRIORITY_UNDEFINED:
+                return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+            default:
+                Log.e(TAG, "setPriority: Invalid priority: " + priority);
+                return BluetoothProfile.CONNECTION_POLICY_UNKNOWN;
+        }
+    }
+
+    /**
+     * Converts new constant of connection policy to the old for priority
+     *
+     * @param connectionPolicy is the connection policy to convert to priority
+     * @return the equivalent priority constant to the connectionPolicy
+     *
+     * @hide
+     */
+    public static int connectionPolicyToPriority(@ConnectionPolicy int connectionPolicy) {
+        switch(connectionPolicy) {
+            case BluetoothProfile.CONNECTION_POLICY_ALLOWED:
+                return BluetoothProfile.PRIORITY_ON;
+            case BluetoothProfile.CONNECTION_POLICY_FORBIDDEN:
+                return BluetoothProfile.PRIORITY_OFF;
+            case BluetoothProfile.CONNECTION_POLICY_UNKNOWN:
+                return BluetoothProfile.PRIORITY_UNDEFINED;
+        }
+        return BluetoothProfile.PRIORITY_UNDEFINED;
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index 672174f..ea3831a 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -560,26 +561,45 @@
      * Priority can be one of {@link BluetoothProfile#PRIORITY_ON} or
      * {@link BluetoothProfile#PRIORITY_OFF},
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
-     *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
+     * @deprecated Replaced with {@link #setConnectionPolicy(BluetoothDevice, int)}
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHeadset service = mService;
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -596,26 +616,43 @@
      * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
      * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
-     *
      * @param device Bluetooth device
      * @return priority of the device
      * @hide
      */
     @UnsupportedAppUsage
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHeadset service = mService;
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothHeadsetClient.java b/core/java/android/bluetooth/BluetoothHeadsetClient.java
index 5d00f09..a8e1fd2 100644
--- a/core/java/android/bluetooth/BluetoothHeadsetClient.java
+++ b/core/java/android/bluetooth/BluetoothHeadsetClient.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -553,19 +556,45 @@
     /**
      * Set priority of the profile
      *
-     * The device should already be paired.
+     * <p> The device should already be paired.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
+     *
+     * @param device Paired bluetooth device
+     * @param priority
+     * @return true if priority is set, false on error
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHeadsetClient service =
                 getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -577,21 +606,47 @@
 
     /**
      * Get the priority of the profile.
+     *
+     * <p> The priority can be any of:
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     *
+     * @param device Bluetooth device
+     * @return priority of the device
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHeadsetClient service =
                 getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index a812c32..ead8429 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -355,28 +356,45 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} orgetBluetoothManager
-     * {@link #PRIORITY_OFF},
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(@NonNull BluetoothDevice device,
+            @ConnectionPolicy int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHearingAid service = getService();
         try {
             if (service != null && isEnabled()
                     && isValidDevice(device)) {
-                if (priority != BluetoothProfile.PRIORITY_OFF
-                        && priority != BluetoothProfile.PRIORITY_ON) {
+                if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                        && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                     return false;
                 }
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             }
             if (service == null) Log.w(TAG, "Proxy not attached to service");
             return false;
@@ -390,8 +408,7 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
@@ -400,17 +417,35 @@
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public @ConnectionPolicy int getConnectionPolicy(@NonNull BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHearingAid service = getService();
         try {
             if (service != null && isEnabled()
                     && isValidDevice(device)) {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             }
             if (service == null) Log.w(TAG, "Proxy not attached to service");
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         } catch (RemoteException e) {
             Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-            return BluetoothProfile.PRIORITY_OFF;
+            return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
         }
     }
 
diff --git a/core/java/android/bluetooth/BluetoothHidHost.java b/core/java/android/bluetooth/BluetoothHidHost.java
index 4afb382..8f5cdf0 100644
--- a/core/java/android/bluetooth/BluetoothHidHost.java
+++ b/core/java/android/bluetooth/BluetoothHidHost.java
@@ -16,8 +16,11 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -379,27 +382,43 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or
-     * {@link #PRIORITY_OFF},
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
-     * permission.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothHidHost service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
                 return false;
@@ -413,28 +432,44 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
-     *
-     * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothHidHost service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, "Stack:" + Log.getStackTraceString(new Throwable()));
-                return BluetoothProfile.PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return BluetoothProfile.PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     private boolean isEnabled() {
diff --git a/core/java/android/bluetooth/BluetoothMap.java b/core/java/android/bluetooth/BluetoothMap.java
index dd2f150..979dfd4 100644
--- a/core/java/android/bluetooth/BluetoothMap.java
+++ b/core/java/android/bluetooth/BluetoothMap.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -271,23 +274,43 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or
-     * {@link #PRIORITY_OFF},
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothMap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -301,25 +324,44 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothMap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/bluetooth/BluetoothMapClient.java b/core/java/android/bluetooth/BluetoothMapClient.java
index 69682c6..0ec473c 100644
--- a/core/java/android/bluetooth/BluetoothMapClient.java
+++ b/core/java/android/bluetooth/BluetoothMapClient.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -240,22 +243,44 @@
     /**
      * Set priority of the profile
      *
-     * <p> The device should already be paired.  Priority can be one of {@link #PRIORITY_ON} or
-     * {@link #PRIORITY_OFF},
+     * <p> The device should already be paired.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
+     * @param priority
      * @return true if priority is set, false on error
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) Log.d(TAG, "setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) Log.d(TAG, "setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothMapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -269,25 +294,44 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) Log.d(TAG, "getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) Log.d(TAG, "getConnectionPolicy(" + device + ")");
         final IBluetoothMapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothPbapClient.java b/core/java/android/bluetooth/BluetoothPbapClient.java
index d70e1e7..9618ba0 100644
--- a/core/java/android/bluetooth/BluetoothPbapClient.java
+++ b/core/java/android/bluetooth/BluetoothPbapClient.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -241,25 +244,45 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
-     * Priority can be one of {@link #PRIORITY_ON} or
-     * {@link #PRIORITY_OFF},
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
-     * @param priority Priority of this profile
+     * @param priority
      * @return true if priority is set, false on error
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
+        if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
         if (DBG) {
-            log("setPriority(" + device + ", " + priority + ")");
+            log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         }
         final IBluetoothPbapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -275,28 +298,47 @@
      * Get the priority of the profile.
      *
      * <p> The priority can be any of:
-     * {@link #PRIORITY_AUTO_CONNECT}, {@link #PRIORITY_OFF},
-     * {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
      *
      * @param device Bluetooth device
      * @return priority of the device
+     * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
+        if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
         if (VDBG) {
-            log("getPriority(" + device + ")");
+            log("getConnectionPolicy(" + device + ")");
         }
         final IBluetoothPbapClient service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) {
             Log.w(TAG, "Proxy not attached to service");
         }
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 }
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index f1ac765..097a367 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -225,7 +225,9 @@
      * and outgoing connections for the profile
      *
      * @hide
+     * @deprecated Replaced with {@link #CONNECTION_POLICY_ALLOWED}
      **/
+    @Deprecated
     @SystemApi
     int PRIORITY_ON = 100;
 
@@ -234,7 +236,9 @@
      * connections and outgoing connections for the profile.
      *
      * @hide
+     * @deprecated Replaced with {@link #CONNECTION_POLICY_FORBIDDEN}
      **/
+    @Deprecated
     @SystemApi
     int PRIORITY_OFF = 0;
 
@@ -246,6 +250,38 @@
     @UnsupportedAppUsage
     int PRIORITY_UNDEFINED = -1;
 
+    /** @hide */
+    @IntDef(prefix = "CONNECTION_POLICY_", value = {CONNECTION_POLICY_ALLOWED,
+            CONNECTION_POLICY_FORBIDDEN, CONNECTION_POLICY_UNKNOWN})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ConnectionPolicy{}
+
+    /**
+     * Default connection policy for devices that allow incoming and outgoing connections
+     * for the profile
+     *
+     * @hide
+     **/
+    @SystemApi
+    int CONNECTION_POLICY_ALLOWED = 100;
+
+    /**
+     * Default connection policy for devices that do not allow incoming or outgoing connections
+     * for the profile.
+     *
+     * @hide
+     **/
+    @SystemApi
+    int CONNECTION_POLICY_FORBIDDEN = 0;
+
+    /**
+     * Default connection policy when not set or when the device is unpaired
+     *
+     * @hide
+     */
+    @SystemApi
+    int CONNECTION_POLICY_UNKNOWN = -1;
+
     /**
      * Get connected devices for this specific profile.
      *
diff --git a/core/java/android/bluetooth/BluetoothSap.java b/core/java/android/bluetooth/BluetoothSap.java
index e0610c8..9b4dabc 100644
--- a/core/java/android/bluetooth/BluetoothSap.java
+++ b/core/java/android/bluetooth/BluetoothSap.java
@@ -16,6 +16,9 @@
 
 package android.bluetooth;
 
+import android.Manifest;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
@@ -300,22 +303,43 @@
      * Set priority of the profile
      *
      * <p> The device should already be paired.
+     * Priority can be one of {@link #PRIORITY_ON} or {@link #PRIORITY_OFF},
      *
      * @param device Paired bluetooth device
      * @param priority
      * @return true if priority is set, false on error
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
     public boolean setPriority(BluetoothDevice device, int priority) {
         if (DBG) log("setPriority(" + device + ", " + priority + ")");
+        return setConnectionPolicy(device, BluetoothAdapter.priorityToConnectionPolicy(priority));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+    public boolean setConnectionPolicy(BluetoothDevice device, int connectionPolicy) {
+        if (DBG) log("setConnectionPolicy(" + device + ", " + connectionPolicy + ")");
         final IBluetoothSap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
-            if (priority != BluetoothProfile.PRIORITY_OFF
-                    && priority != BluetoothProfile.PRIORITY_ON) {
+            if (connectionPolicy != BluetoothProfile.CONNECTION_POLICY_FORBIDDEN
+                    && connectionPolicy != BluetoothProfile.CONNECTION_POLICY_ALLOWED) {
                 return false;
             }
             try {
-                return service.setPriority(device, priority);
+                return service.setConnectionPolicy(device, connectionPolicy);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
                 return false;
@@ -328,23 +352,45 @@
     /**
      * Get the priority of the profile.
      *
+     * <p> The priority can be any of:
+     * {@link #PRIORITY_OFF}, {@link #PRIORITY_ON}, {@link #PRIORITY_UNDEFINED}
+     *
      * @param device Bluetooth device
      * @return priority of the device
      * @hide
      */
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
     public int getPriority(BluetoothDevice device) {
         if (VDBG) log("getPriority(" + device + ")");
+        return BluetoothAdapter.connectionPolicyToPriority(getConnectionPolicy(device));
+    }
+
+    /**
+     * 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
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.BLUETOOTH)
+    public int getConnectionPolicy(BluetoothDevice device) {
+        if (VDBG) log("getConnectionPolicy(" + device + ")");
         final IBluetoothSap service = getService();
         if (service != null && isEnabled() && isValidDevice(device)) {
             try {
-                return service.getPriority(device);
+                return service.getConnectionPolicy(device);
             } catch (RemoteException e) {
                 Log.e(TAG, Log.getStackTraceString(new Throwable()));
-                return PRIORITY_OFF;
+                return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
             }
         }
         if (service == null) Log.w(TAG, "Proxy not attached to service");
-        return PRIORITY_OFF;
+        return BluetoothProfile.CONNECTION_POLICY_FORBIDDEN;
     }
 
     private static void log(String msg) {
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index a65c8fd..716a522 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -286,14 +286,6 @@
     public static final int LISTEN_USER_MOBILE_DATA_STATE                  = 0x00080000;
 
     /**
-     *  Listen for changes to the physical channel configuration.
-     *
-     *  @see #onPhysicalChannelConfigurationChanged
-     *  @hide
-     */
-    public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION          = 0x00100000;
-
-    /**
      *  Listen for changes to the phone capability.
      *
      *  @see #onPhoneCapabilityChanged
@@ -831,24 +823,6 @@
     }
 
     /**
-     * Callback invoked when the current physical channel configuration has changed on the
-     * registered subscription.
-     * Note, the registration subId comes from {@link TelephonyManager} object which registers
-     * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
-     * If this TelephonyManager object was created with
-     * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
-     * subId. Otherwise, this callback applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}.
-     *
-     * @param configs List of the current {@link PhysicalChannelConfig}s
-     * @hide
-     */
-    public void onPhysicalChannelConfigurationChanged(
-            @NonNull List<PhysicalChannelConfig> configs) {
-        // default implementation empty
-    }
-
-    /**
      * Callback invoked when the current emergency number list has changed on the registered
      * subscription.
      * Note, the registration subId comes from {@link TelephonyManager} object which registers
@@ -1194,15 +1168,6 @@
                     () -> mExecutor.execute(() -> psl.onCarrierNetworkChange(active)));
         }
 
-        public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) {
-            PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
-            if (psl == null) return;
-
-            Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(
-                            () -> psl.onPhysicalChannelConfigurationChanged(configs)));
-        }
-
         public void onEmergencyNumberListChanged(Map emergencyNumberList) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
diff --git a/core/java/android/text/LoginFilter.java b/core/java/android/text/LoginFilter.java
index e2d1596..0e4eec44 100644
--- a/core/java/android/text/LoginFilter.java
+++ b/core/java/android/text/LoginFilter.java
@@ -19,7 +19,10 @@
 /**
  * Abstract class for filtering login-related text (user names and passwords)
  * 
+ * @deprecated Password requirements should not be hardcoded in clients. This class also does not
+ * handle non-BMP characters.
  */
+@Deprecated
 public abstract class LoginFilter implements InputFilter {
     private boolean mAppendInvalid;  // whether to append or ignore invalid characters
     /**
@@ -130,7 +133,9 @@
      * account creation. It prevents the user from entering user names with characters other than 
      * [a-zA-Z0-9.]. 
      * 
+     * @deprecated Do not encode assumptions about Google account names into client applications.
      */
+    @Deprecated
     public static class UsernameFilterGMail extends LoginFilter {
         
         public UsernameFilterGMail() {
@@ -190,8 +195,12 @@
     /**
      * This filter is compatible with GMail passwords which restricts characters to 
      * the Latin-1 (ISO8859-1) char set.
-     * 
+     *
+     * @deprecated Do not handle a user's Google password. Refer to
+     *   <a href="https://support.google.com/accounts/answer/32040">Google Help</a> for
+     *   password restriction information.
      */
+    @Deprecated
     public static class PasswordFilterGMail extends LoginFilter {
         
         public PasswordFilterGMail() {
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 084a3cc..01f5743 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -21,7 +21,6 @@
 import android.telephony.CellInfo;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
@@ -44,7 +43,6 @@
     void onDataConnectionStateChanged(int state, int networkType);
     void onDataActivity(int direction);
     void onSignalStrengthsChanged(in SignalStrength signalStrength);
-    void onPhysicalChannelConfigurationChanged(in List<PhysicalChannelConfig> configs);
     void onOtaspChanged(in int otaspMode);
     void onCellInfoChanged(in List<CellInfo> cellInfo);
     void onPreciseCallStateChanged(in PreciseCallState callState);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 9ae0ba5..2f34aa0 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -24,7 +24,6 @@
 import android.telephony.CellInfo;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.PhoneCapability;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.emergency.EmergencyNumber;
@@ -78,8 +77,6 @@
     void notifyOtaspChanged(in int subId, in int otaspMode);
     @UnsupportedAppUsage
     void notifyCellInfo(in List<CellInfo> cellInfo);
-    void notifyPhysicalChannelConfigurationForSubscriber(in int phoneId, in int subId,
-            in List<PhysicalChannelConfig> configs);
     void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
             int foregroundCallState, int backgroundCallState);
     void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 15813a1..f8c304c 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -151,4 +151,5 @@
   PROVISIONING_FLOW_TYPE = 124;
   CROSS_PROFILE_APPS_GET_TARGET_USER_PROFILES = 125;
   CROSS_PROFILE_APPS_START_ACTIVITY_AS_USER = 126;
+  SET_AUTO_TIME = 127;
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
index 9672fea..9f16d03 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java
@@ -408,23 +408,6 @@
     }
 
     /**
-     * Checks if {@link android.app.admin.DevicePolicyManager#setAutoTimeRequired} is enforced
-     * on the device.
-     *
-     * @return EnforcedAdmin Object containing the device owner component and
-     * userId the device owner is running as, or {@code null} setAutoTimeRequired is not enforced.
-     */
-    public static EnforcedAdmin checkIfAutoTimeRequired(Context context) {
-        DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-        if (dpm == null || !dpm.getAutoTimeRequired()) {
-            return null;
-        }
-        ComponentName adminComponent = dpm.getDeviceOwnerComponentOnCallingUser();
-        return new EnforcedAdmin(adminComponent, getUserHandleOf(UserHandle.myUserId()));
-    }
-
-    /**
      * Checks if an admin has enforced minimum password quality requirements on the given user.
      *
      * @return EnforcedAdmin Object containing the enforced admin component and admin user details,
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index c1a23c8..493186b 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -37,7 +37,7 @@
  */
 @Singleton
 public class ForegroundServiceController {
-    private static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
+    public static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
             AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
             AppOpsManager.OP_RECORD_AUDIO,
             AppOpsManager.OP_COARSE_LOCATION,
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index b983966..c4e2762 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -27,6 +27,8 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import javax.inject.Inject;
@@ -46,7 +48,8 @@
     @Inject
     public ForegroundServiceNotificationListener(Context context,
             ForegroundServiceController foregroundServiceController,
-            NotificationEntryManager notificationEntryManager) {
+            NotificationEntryManager notificationEntryManager,
+            NotifCollection notifCollection) {
         mContext = context;
         mForegroundServiceController = foregroundServiceController;
         mEntryManager = notificationEntryManager;
@@ -69,8 +72,24 @@
                 removeNotification(entry.getSbn());
             }
         });
-
         mEntryManager.addNotificationLifetimeExtender(new ForegroundServiceLifetimeExtender());
+
+        notifCollection.addCollectionListener(new NotifCollectionListener() {
+            @Override
+            public void onEntryAdded(NotificationEntry entry) {
+                addNotification(entry, entry.getImportance());
+            }
+
+            @Override
+            public void onEntryUpdated(NotificationEntry entry) {
+                updateNotification(entry, entry.getImportance());
+            }
+
+            @Override
+            public void onEntryRemoved(NotificationEntry entry, int reason, boolean removedByUser) {
+                removeNotification(entry.getSbn());
+            }
+        });
     }
 
     /**
@@ -152,6 +171,8 @@
                 true /* create if not found */);
     }
 
+    // TODO: remove this when fully migrated to the NewNotifPipeline (work done in
+    //  ForegroundCoordinator)
     private void tagForeground(NotificationEntry entry) {
         final StatusBarNotification sbn = entry.getSbn();
         ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
index a8ae654..2ef46dc 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServicesUserState.java
@@ -24,7 +24,7 @@
 /**
  * Struct to track relevant packages and notifications for a userid's foreground services.
  */
-class ForegroundServicesUserState {
+public class ForegroundServicesUserState {
     // shelf life of foreground services before they go bad
     private static final long FG_SERVICE_GRACE_MILLIS = 5000;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
index 4cc5b21..ff4ce94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManager.java
@@ -65,8 +65,18 @@
 
     boolean needsRedaction(NotificationEntry entry);
 
+    /**
+     * Has the given user chosen to allow their private (full) notifications to be shown even
+     * when the lockscreen is in "public" (secure & locked) mode?
+     */
     boolean userAllowsPrivateNotificationsInPublic(int currentUserId);
 
+    /**
+     * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
+     * "public" (secure & locked) mode?
+     */
+    boolean userAllowsNotificationsInPublic(int userId);
+
     /** Notified when the current user changes. */
     interface UserChangedListener {
         void onUserChanged(int userId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index f5710a8..0f3f6b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -435,7 +435,7 @@
      * Has the given user chosen to allow notifications to be shown even when the lockscreen is in
      * "public" (secure & locked) mode?
      */
-    private boolean userAllowsNotificationsInPublic(int userHandle) {
+    public boolean userAllowsNotificationsInPublic(int userHandle) {
         if (isCurrentProfile(userHandle) && userHandle != mCurrentUserId) {
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index e5f44bd..b61c1ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -36,7 +36,10 @@
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-/** Component which manages the various reasons a notification might be filtered out. */
+/** Component which manages the various reasons a notification might be filtered out.*/
+// TODO: delete NotificationFilter.java after migrating to new NotifPipeline b/145659174.
+//  Notification filtering is taken care of across the different Coordinators (mostly
+//  KeyguardCoordinator.java)
 @Singleton
 public class NotificationFilter {
 
@@ -109,7 +112,7 @@
             return true;
         }
 
-        if (entry.isSuspended()) {
+        if (entry.getRanking().isSuspended()) {
             return true;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index f9f3266..9ae3882 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -18,6 +18,8 @@
 
 import android.annotation.Nullable;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -34,7 +36,8 @@
     private final List<NotificationEntry> mUnmodifiableChildren =
             Collections.unmodifiableList(mChildren);
 
-    GroupEntry(String key) {
+    @VisibleForTesting
+    public GroupEntry(String key) {
         super(key);
     }
 
@@ -52,7 +55,8 @@
         return mUnmodifiableChildren;
     }
 
-    void setSummary(@Nullable NotificationEntry summary) {
+    @VisibleForTesting
+    public void setSummary(@Nullable NotificationEntry summary) {
         mSummary = summary;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index dc68c4b..6ce7fd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -18,6 +18,8 @@
 
 import android.annotation.Nullable;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Abstract superclass for top-level entries, i.e. things that can appear in the final notification
  * list shown to users. In practice, this means either GroupEntries or NotificationEntries.
@@ -49,7 +51,8 @@
         return mParent;
     }
 
-    void setParent(@Nullable GroupEntry parent) {
+    @VisibleForTesting
+    public void setParent(@Nullable GroupEntry parent) {
         mParent = parent;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 3eb55ef..232fb6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -275,10 +275,6 @@
         return mRanking.getSuppressedVisualEffects();
     }
 
-    public boolean isSuspended() {
-        return mRanking.isSuspended();
-    }
-
     /** @see Ranking#canBubble() */
     public boolean canBubble() {
         return mRanking.canBubble();
@@ -951,6 +947,15 @@
     }
 
     /**
+     * Whether or not this row represents a system notification. Note that if this is
+     * {@code null}, that means we were either unable to retrieve the info or have yet to
+     * retrieve the info.
+     */
+    public Boolean isSystemNotification() {
+        return mIsSystemNotification;
+    }
+
+    /**
      * Set this notification to be sensitive.
      *
      * @param sensitive true if the content of this notification is sensitive right now
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
new file mode 100644
index 0000000..898918e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/Coordinator.java
@@ -0,0 +1,42 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.init.NewNotifPipeline;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+
+/**
+ * Interface for registering callbacks to the {@link NewNotifPipeline}.
+ *
+ * This includes registering:
+ *  {@link Pluggable}s to the {@link NotifListBuilder}
+ *  {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s to {@link NotifCollection}
+ */
+public interface Coordinator {
+
+    /**
+     * Called after the NewNotifPipeline is initialized.
+     * Coordinators should register their {@link Pluggable}s to the notifListBuilder
+     * and their {@link NotifCollectionListener}s and {@link NotifLifetimeExtender}s
+     * to the notifCollection in this method.
+     */
+    void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
new file mode 100644
index 0000000..511aafc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/DeviceProvisionedCoordinator.java
@@ -0,0 +1,96 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import android.Manifest;
+import android.app.AppGlobals;
+import android.app.Notification;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.RemoteException;
+import android.service.notification.StatusBarNotification;
+
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters out most notifications when the device is unprovisioned.
+ * Special notifications with extra permissions and tags won't be filtered out even when the
+ * device is unprovisioned.
+ */
+@Singleton
+public class DeviceProvisionedCoordinator implements Coordinator {
+    private static final String TAG = "DeviceProvisionedCoordinator";
+
+    private final DeviceProvisionedController mDeviceProvisionedController;
+
+    @Inject
+    public DeviceProvisionedCoordinator(DeviceProvisionedController deviceProvisionedController) {
+        mDeviceProvisionedController = deviceProvisionedController;
+    }
+
+    @Override
+    public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+        mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+
+        notifListBuilder.addFilter(mNotifFilter);
+    }
+
+    protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+        @Override
+        public boolean shouldFilterOut(NotificationEntry entry, long now) {
+            return !mDeviceProvisionedController.isDeviceProvisioned()
+                    && !showNotificationEvenIfUnprovisioned(entry.getSbn());
+        }
+    };
+
+    /**
+     * Only notifications coming from packages with permission
+     * android.permission.NOTIFICATION_DURING_SETUP that also have special tags
+     * marking them as relevant for setup are allowed to show when device is unprovisioned
+     */
+    private boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
+        final boolean hasPermission = checkUidPermission(AppGlobals.getPackageManager(),
+                Manifest.permission.NOTIFICATION_DURING_SETUP,
+                sbn.getUid()) == PackageManager.PERMISSION_GRANTED;
+        return hasPermission
+                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
+    }
+
+    private static int checkUidPermission(IPackageManager packageManager, String permission,
+            int uid) {
+        try {
+            return packageManager.checkUidPermission(permission, uid);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private final DeviceProvisionedController.DeviceProvisionedListener mDeviceProvisionedListener =
+            new DeviceProvisionedController.DeviceProvisionedListener() {
+                @Override
+                public void onDeviceProvisionedChanged() {
+                    mNotifFilter.invalidateList();
+                }
+            };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
new file mode 100644
index 0000000..4803cf4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinator.java
@@ -0,0 +1,243 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import android.app.Notification;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+
+import com.android.systemui.ForegroundServiceController;
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.dagger.qualifiers.BgHandler;
+import com.android.systemui.dagger.qualifiers.MainHandler;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles ForegroundService interactions with notifications.
+ *  Tags notifications with appOps.
+ *  Lifetime extends notifications associated with an ongoing ForegroundService.
+ *  Filters out notifications that represent foreground services that are no longer running
+ *
+ * Previously this logic lived in
+ *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceController
+ *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener
+ *  frameworks/base/packages/SystemUI/src/com/android/systemui/ForegroundServiceLifetimeExtender
+ */
+@Singleton
+public class ForegroundCoordinator implements Coordinator {
+    private static final String TAG = "ForegroundNotificationCoordinator";
+
+    private final ForegroundServiceController mForegroundServiceController;
+    private final AppOpsController mAppOpsController;
+    private final Handler mMainHandler;
+    private final Handler mBgHandler;
+
+    private NotifCollection mNotifCollection;
+
+    @Inject
+    public ForegroundCoordinator(
+            ForegroundServiceController foregroundServiceController,
+            AppOpsController appOpsController,
+            @MainHandler Handler mainHandler,
+            @BgHandler Handler bgHandler) {
+        mForegroundServiceController = foregroundServiceController;
+        mAppOpsController = appOpsController;
+        mMainHandler = mainHandler;
+        mBgHandler = bgHandler;
+    }
+
+    @Override
+    public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+        mNotifCollection = notifCollection;
+
+        // extend the lifetime of foreground notification services to show for at least 5 seconds
+        mNotifCollection.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
+
+        // listen for new notifications to add appOps
+        mNotifCollection.addCollectionListener(mNotifCollectionListener);
+
+        // when appOps change, update any relevant notifications to update appOps for
+        mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
+
+        // filter out foreground service notifications that aren't necessary anymore
+        notifListBuilder.addFilter(mNotifFilter);
+    }
+
+    /**
+     * Filters out notifications that represent foreground services that are no longer running.
+     */
+    protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+        @Override
+        public boolean shouldFilterOut(NotificationEntry entry, long now) {
+            StatusBarNotification sbn = entry.getSbn();
+            if (mForegroundServiceController.isDisclosureNotification(sbn)
+                    && !mForegroundServiceController.isDisclosureNeededForUser(sbn.getUserId())) {
+                return true;
+            }
+
+            if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
+                final String[] apps = sbn.getNotification().extras.getStringArray(
+                        Notification.EXTRA_FOREGROUND_APPS);
+                if (apps != null && apps.length >= 1) {
+                    if (!mForegroundServiceController.isSystemAlertWarningNeeded(
+                            sbn.getUserId(), apps[0])) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    };
+
+    /**
+     * Extends the lifetime of foreground notification services such that they show for at least
+     * five seconds
+     */
+    private final NotifLifetimeExtender mForegroundLifetimeExtender = new NotifLifetimeExtender() {
+        private static final int MIN_FGS_TIME_MS = 5000;
+        private OnEndLifetimeExtensionCallback mEndCallback;
+        private Map<String, Runnable> mEndRunnables = new HashMap<>();
+
+        @Override
+        public String getName() {
+            return TAG;
+        }
+
+        @Override
+        public void setCallback(OnEndLifetimeExtensionCallback callback) {
+            mEndCallback = callback;
+        }
+
+        @Override
+        public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
+            if ((entry.getSbn().getNotification().flags
+                    & Notification.FLAG_FOREGROUND_SERVICE) == 0) {
+                return false;
+            }
+
+            final long currTime = System.currentTimeMillis();
+            final boolean extendLife = currTime - entry.getSbn().getPostTime() < MIN_FGS_TIME_MS;
+
+            if (extendLife) {
+                if (!mEndRunnables.containsKey(entry.getKey())) {
+                    final Runnable runnable = new Runnable() {
+                        @Override
+                        public void run() {
+                            mEndCallback.onEndLifetimeExtension(mForegroundLifetimeExtender, entry);
+                        }
+                    };
+                    mEndRunnables.put(entry.getKey(), runnable);
+                    mBgHandler.postDelayed(runnable, MIN_FGS_TIME_MS
+                            - (currTime - entry.getSbn().getPostTime()));
+                }
+            }
+
+            return extendLife;
+        }
+
+        @Override
+        public void cancelLifetimeExtension(NotificationEntry entry) {
+            if (mEndRunnables.containsKey(entry.getKey())) {
+                Runnable endRunnable = mEndRunnables.remove(entry.getKey());
+                mBgHandler.removeCallbacks(endRunnable);
+            }
+        }
+    };
+
+    /**
+     * Adds appOps to incoming and updating notifications
+     */
+    private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
+        @Override
+        public void onEntryAdded(NotificationEntry entry) {
+            tagForeground(entry);
+        }
+
+        @Override
+        public void onEntryUpdated(NotificationEntry entry) {
+            tagForeground(entry);
+        }
+
+        private void tagForeground(NotificationEntry entry) {
+            final StatusBarNotification sbn = entry.getSbn();
+            // note: requires that the ForegroundServiceController is updating their appOps first
+            ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(sbn.getUserId(),
+                    sbn.getPackageName());
+            if (activeOps != null) {
+                synchronized (entry.mActiveAppOps) {
+                    entry.mActiveAppOps.clear();
+                    entry.mActiveAppOps.addAll(activeOps);
+                }
+            }
+        }
+    };
+
+    /**
+     * Update the appOp for the posted notification associated with the current foreground service
+     * @param code code for appOp to add/remove
+     * @param uid of user the notification is sent to
+     * @param packageName package that created the notification
+     * @param active whether the appOpCode is active or not
+     */
+    private void onAppOpsChanged(int code, int uid, String packageName, boolean active) {
+        int userId = UserHandle.getUserId(uid);
+
+        // Update appOp if there's an associated posted notification:
+        final String foregroundKey = mForegroundServiceController.getStandardLayoutKey(userId,
+                packageName);
+        if (foregroundKey != null) {
+            final NotificationEntry entry = findNotificationEntryWithKey(foregroundKey);
+            if (entry != null
+                    && uid == entry.getSbn().getUid()
+                    && packageName.equals(entry.getSbn().getPackageName())) {
+                boolean changed;
+                synchronized (entry.mActiveAppOps) {
+                    if (active) {
+                        changed = entry.mActiveAppOps.add(code);
+                    } else {
+                        changed = entry.mActiveAppOps.remove(code);
+                    }
+                }
+                if (changed) {
+                    mMainHandler.post(mNotifFilter::invalidateList);
+                }
+            }
+        }
+    }
+
+    private NotificationEntry findNotificationEntryWithKey(String key) {
+        for (NotificationEntry entry : mNotifCollection.getNotifs()) {
+            if (entry.getKey().equals(key)) {
+                return entry;
+            }
+        }
+        return null;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
new file mode 100644
index 0000000..f5ed089
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java
@@ -0,0 +1,233 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import static android.app.Notification.VISIBILITY_SECRET;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.notification.StatusBarNotification;
+
+import androidx.annotation.MainThread;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters low priority and privacy-sensitive notifications from the lockscreen.
+ */
+@Singleton
+public class KeyguardCoordinator implements Coordinator {
+    private static final String TAG = "KeyguardNotificationCoordinator";
+
+    private final Context mContext;
+    private final Handler mMainHandler;
+    private final KeyguardStateController mKeyguardStateController;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final StatusBarStateController mStatusBarStateController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+    @Inject
+    public KeyguardCoordinator(
+            Context context,
+            @MainThread Handler mainThreadHandler,
+            KeyguardStateController keyguardStateController,
+            NotificationLockscreenUserManager lockscreenUserManager,
+            BroadcastDispatcher broadcastDispatcher,
+            StatusBarStateController statusBarStateController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor) {
+        mContext = context;
+        mMainHandler = mainThreadHandler;
+        mKeyguardStateController = keyguardStateController;
+        mLockscreenUserManager = lockscreenUserManager;
+
+        mBroadcastDispatcher = broadcastDispatcher;
+        mStatusBarStateController = statusBarStateController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+    }
+
+    @Override
+    public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+        setupInvalidateNotifListCallbacks();
+        notifListBuilder.addFilter(mNotifFilter);
+    }
+
+    protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+        @Override
+        public boolean shouldFilterOut(NotificationEntry entry, long now) {
+            final StatusBarNotification sbn = entry.getSbn();
+
+            // FILTER OUT the notification when the notification isn't for the current profile
+            if (!mLockscreenUserManager.isCurrentProfile(sbn.getUserId())) {
+                return true;
+            }
+
+            // FILTER OUT the notification when the keyguard is showing and...
+            if (mKeyguardStateController.isShowing()) {
+                // ... user settings or the device policy manager doesn't allow lockscreen
+                // notifications;
+                if (!mLockscreenUserManager.shouldShowLockscreenNotifications()) {
+                    return true;
+                }
+
+                final int currUserId = mLockscreenUserManager.getCurrentUserId();
+                final int notifUserId = (sbn.getUser().getIdentifier() == UserHandle.USER_ALL)
+                        ? currUserId : sbn.getUser().getIdentifier();
+
+                // ... user is in lockdown
+                if (mKeyguardUpdateMonitor.isUserInLockdown(currUserId)
+                        || mKeyguardUpdateMonitor.isUserInLockdown(notifUserId)) {
+                    return true;
+                }
+
+                // ... device is in public mode and the user's settings doesn't allow
+                // notifications to show in public mode
+                if (mLockscreenUserManager.isLockscreenPublicMode(currUserId)
+                        || mLockscreenUserManager.isLockscreenPublicMode(notifUserId)) {
+                    if (entry.getRanking().getVisibilityOverride() == VISIBILITY_SECRET) {
+                        return true;
+                    }
+
+                    if (!mLockscreenUserManager.userAllowsNotificationsInPublic(currUserId)
+                            || !mLockscreenUserManager.userAllowsNotificationsInPublic(
+                            notifUserId)) {
+                        return true;
+                    }
+                }
+
+                // ... neither this notification nor its summary have high enough priority
+                // to be shown on the lockscreen
+                // TODO: grouping hasn't happened yet (b/145134683)
+                if (entry.getParent() != null) {
+                    final NotificationEntry summary = entry.getParent().getRepresentativeEntry();
+                    if (priorityExceedsLockscreenShowingThreshold(summary)) {
+                        return false;
+                    }
+                }
+                return !priorityExceedsLockscreenShowingThreshold(entry);
+            }
+            return false;
+        }
+    };
+
+    private boolean priorityExceedsLockscreenShowingThreshold(NotificationEntry entry) {
+        if (entry == null) {
+            return false;
+        }
+        if (NotificationUtils.useNewInterruptionModel(mContext)
+                && hideSilentNotificationsOnLockscreen()) {
+            // TODO: make sure in the NewNotifPipeline that entry.isHighPriority() has been
+            //  correctly updated before reaching this point (b/145134683)
+            return entry.isHighPriority();
+        } else {
+            return !entry.getRanking().isAmbient();
+        }
+    }
+
+    private boolean hideSilentNotificationsOnLockscreen() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) == 0;
+    }
+
+    private void setupInvalidateNotifListCallbacks() {
+        // register onKeyguardShowing callback
+        mKeyguardStateController.addCallback(mKeyguardCallback);
+
+        // register lockscreen settings changed callbacks:
+        final ContentObserver settingsObserver = new ContentObserver(mMainHandler) {
+            @Override
+            public void onChange(boolean selfChange, Uri uri) {
+                if (mKeyguardStateController.isShowing()) {
+                    invalidateListFromFilter("Settings " + uri + " changed");
+                }
+            }
+        };
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS),
+                false,
+                settingsObserver,
+                UserHandle.USER_ALL);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS),
+                true,
+                settingsObserver,
+                UserHandle.USER_ALL);
+
+        mContext.getContentResolver().registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.ZEN_MODE),
+                false,
+                settingsObserver);
+
+        // register (maybe) public mode changed callbacks:
+        mStatusBarStateController.addCallback(mStatusBarStateListener);
+        mBroadcastDispatcher.registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (mKeyguardStateController.isShowing()) {
+                    // maybe public mode changed
+                    invalidateListFromFilter(intent.getAction());
+                }
+            }}, new IntentFilter(Intent.ACTION_USER_SWITCHED));
+    }
+
+    private void invalidateListFromFilter(String reason) {
+        mNotifFilter.invalidateList();
+    }
+
+    private final KeyguardStateController.Callback mKeyguardCallback =
+            new KeyguardStateController.Callback() {
+        @Override
+        public void onUnlockedChanged() {
+            invalidateListFromFilter("onUnlockedChanged");
+        }
+
+        @Override
+        public void onKeyguardShowingChanged() {
+            invalidateListFromFilter("onKeyguardShowingChanged");
+        }
+    };
+
+    private final StatusBarStateController.StateListener mStatusBarStateListener =
+            new StatusBarStateController.StateListener() {
+                @Override
+                public void onStateChanged(int newState) {
+                    // maybe public mode changed
+                    invalidateListFromFilter("onStatusBarStateChanged");
+                }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
new file mode 100644
index 0000000..13247193
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -0,0 +1,78 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotifCollectionListener;
+import com.android.systemui.statusbar.notification.collection.NotifLifetimeExtender;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Handles the attachment of the {@link NotifListBuilder} and {@link NotifCollection} to the
+ * {@link Coordinator}s, so that the Coordinators can register their respective callbacks.
+ */
+@Singleton
+public class NotifCoordinators implements Dumpable {
+    private static final String TAG = "NotifCoordinators";
+    private final List<Coordinator> mCoordinators = new ArrayList<>();
+
+    /**
+     * Creates all the coordinators.
+     */
+    @Inject
+    public NotifCoordinators(
+            KeyguardCoordinator keyguardCoordinator,
+            RankingCoordinator rankingCoordinator,
+            ForegroundCoordinator foregroundCoordinator,
+            DeviceProvisionedCoordinator deviceProvisionedCoordinator) {
+        mCoordinators.add(keyguardCoordinator);
+        mCoordinators.add(rankingCoordinator);
+        mCoordinators.add(foregroundCoordinator);
+        mCoordinators.add(deviceProvisionedCoordinator);
+        // TODO: add new Coordinators here! (b/145134683, b/112656837)
+    }
+
+    /**
+     * Sends the initialized notifListBuilder and notifCollection to each
+     * coordinator to indicate the notifListBuilder is ready to accept {@link Pluggable}s
+     * and the notifCollection is ready to accept {@link NotifCollectionListener}s and
+     * {@link NotifLifetimeExtender}s.
+     */
+    public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+        for (Coordinator c : mCoordinators) {
+            c.attach(notifCollection, notifListBuilder);
+        }
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println(TAG + ":");
+        for (Coordinator c : mCoordinators) {
+            pw.println("\t" + c.getClass());
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
new file mode 100644
index 0000000..c390f96
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -0,0 +1,83 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifListBuilder;
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Filters out NotificationEntries based on its Ranking.
+ */
+@Singleton
+public class RankingCoordinator implements Coordinator {
+    private static final String TAG = "RankingNotificationCoordinator";
+
+    private final StatusBarStateController mStatusBarStateController;
+
+    @Inject
+    public RankingCoordinator(StatusBarStateController statusBarStateController) {
+        mStatusBarStateController = statusBarStateController;
+    }
+
+    @Override
+    public void attach(NotifCollection notifCollection, NotifListBuilder notifListBuilder) {
+        mStatusBarStateController.addCallback(mStatusBarStateCallback);
+
+        notifListBuilder.addFilter(mNotifFilter);
+    }
+
+    /**
+     * Checks whether to filter out the given notification based the notification's Ranking object.
+     * NotifListBuilder invalidates the notification list each time the ranking is updated,
+     * so we don't need to explicitly invalidate this filter on ranking update.
+     */
+    protected final NotifFilter mNotifFilter = new NotifFilter(TAG) {
+        @Override
+        public boolean shouldFilterOut(NotificationEntry entry, long now) {
+            // App suspended from Ranking
+            if (entry.getRanking().isSuspended()) {
+                return true;
+            }
+
+            // Dozing + DND Settings from Ranking object
+            if (mStatusBarStateController.isDozing() && entry.shouldSuppressAmbient()) {
+                return true;
+            }
+
+            if (!mStatusBarStateController.isDozing() && entry.shouldSuppressNotificationList()) {
+                return true;
+            }
+
+            return false;
+        }
+    };
+
+
+    private final StatusBarStateController.StateListener mStatusBarStateCallback =
+            new StatusBarStateController.StateListener() {
+                @Override
+                public void onDozingChanged(boolean isDozing) {
+                    mNotifFilter.invalidateList();
+                }
+            };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
index 3b3e7e2..5fc55da 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/init/NewNotifPipeline.java
@@ -23,6 +23,7 @@
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
+import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -37,6 +38,7 @@
 public class NewNotifPipeline implements Dumpable {
     private final NotifCollection mNotifCollection;
     private final NotifListBuilderImpl mNotifPipeline;
+    private final NotifCoordinators mNotifPluggableCoordinators;
     private final DumpController mDumpController;
 
     private final FakePipelineConsumer mFakePipelineConsumer = new FakePipelineConsumer();
@@ -45,9 +47,11 @@
     public NewNotifPipeline(
             NotifCollection notifCollection,
             NotifListBuilderImpl notifPipeline,
+            NotifCoordinators notifCoordinators,
             DumpController dumpController) {
         mNotifCollection = notifCollection;
         mNotifPipeline = notifPipeline;
+        mNotifPluggableCoordinators = notifCoordinators;
         mDumpController = dumpController;
     }
 
@@ -57,6 +61,7 @@
         mFakePipelineConsumer.attach(mNotifPipeline);
         mNotifPipeline.attach(mNotifCollection);
         mNotifCollection.attach(notificationService);
+        mNotifPluggableCoordinators.attach(mNotifCollection, mNotifPipeline);
 
         Log.d(TAG, "Notif pipeline initialized");
 
@@ -66,6 +71,7 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mFakePipelineConsumer.dump(fd, pw, args);
+        mNotifPluggableCoordinators.dump(fd, pw, args);
     }
 
     private static final String TAG = "NewNotifPipeline";
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 0990e22..4cb5472 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -49,6 +49,7 @@
 import com.android.systemui.statusbar.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 
 import junit.framework.Assert;
@@ -70,6 +71,7 @@
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private AppOpsController mAppOpsController;
     @Mock private Handler mMainHandler;
+    @Mock private NotifCollection mNotifCollection;
 
     @Before
     public void setUp() throws Exception {
@@ -79,7 +81,7 @@
         MockitoAnnotations.initMocks(this);
         mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler);
         mListener = new ForegroundServiceNotificationListener(
-                mContext, mFsc, mEntryManager);
+                mContext, mFsc, mEntryManager, mNotifCollection);
         ArgumentCaptor<NotificationEntryListener> entryListenerCaptor =
                 ArgumentCaptor.forClass(NotificationEntryListener.class);
         verify(mEntryManager).addNotificationEntryListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
new file mode 100644
index 0000000..87b3783d
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java
@@ -0,0 +1,243 @@
+/*
+ * 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 com.android.systemui.statusbar.notification.collection.coordinator;
+
+import static android.app.Notification.VISIBILITY_PUBLIC;
+import static android.app.Notification.VISIBILITY_SECRET;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_MIN;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.os.UserHandle;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.NotificationEntryBuilder;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class KeyguardCoordinatorTest extends SysuiTestCase {
+    private static final int NOTIF_USER_ID = 0;
+    private static final int CURR_USER_ID = 1;
+
+    @Mock private Handler mMainHandler;
+    @Mock private KeyguardStateController mKeyguardStateController;
+    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+    @Mock private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock private StatusBarStateController mStatusBarStateController;
+    @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+
+    private NotificationEntry mEntry;
+    private KeyguardCoordinator mKeyguardNotificationCoordinator;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        mKeyguardNotificationCoordinator = new KeyguardCoordinator(
+                mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager,
+                mBroadcastDispatcher, mStatusBarStateController,
+                mKeyguardUpdateMonitor);
+
+        mEntry = new NotificationEntryBuilder()
+                .setUser(new UserHandle(NOTIF_USER_ID))
+                .build();
+    }
+
+    @Test
+    public void unfilteredState() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // THEN don't filter out the entry
+        assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void notificationNotForCurrentProfile() {
+        // GIVEN the notification isn't for the given user
+        setupUnfilteredState();
+        when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(false);
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void keyguardNotShowing() {
+        // GIVEN the lockscreen isn't showing
+        setupUnfilteredState();
+        when(mKeyguardStateController.isShowing()).thenReturn(false);
+
+        // THEN don't filter out the entry
+        assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void doNotShowLockscreenNotifications() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN we shouldn't show any lockscreen notifications
+        when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false);
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void lockdown() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN the notification's user is in lockdown:
+        when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true);
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void publicMode_settingsDisallow() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN the notification's user is in public mode and settings are configured to disallow
+        // notifications in public mode
+        when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true);
+        when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
+                .thenReturn(false);
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void publicMode_notifDisallowed() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN the notification's user is in public mode and settings are configured to disallow
+        // notifications in public mode
+        when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true);
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setVisibilityOverride(VISIBILITY_SECRET).build());
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void doesNotExceedThresholdToShow() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN the notification doesn't exceed the threshold to show on the lockscreen
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setImportance(IMPORTANCE_MIN)
+                .build());
+
+        // THEN filter out the entry
+        assertTrue(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    @Test
+    public void summaryExceedsThresholdToShow() {
+        // GIVEN an 'unfiltered-keyguard-showing' state
+        setupUnfilteredState();
+
+        // WHEN the notification doesn't exceed the threshold to show on the lockscreen
+        // but its summary does
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setImportance(IMPORTANCE_MIN)
+                .build());
+
+        final NotificationEntry summary = new NotificationEntryBuilder().build();
+        summary.setRanking(new RankingBuilder()
+                .setKey(summary.getKey())
+                .setImportance(IMPORTANCE_HIGH)
+                .build());
+        final GroupEntry group = new GroupEntry(mEntry.getSbn().getGroupKey());
+        group.setSummary(summary);
+        mEntry.setParent(group);
+
+        // THEN don't filter out the entry
+        assertFalse(mKeyguardNotificationCoordinator.mNotifFilter.shouldFilterOut(mEntry, 0));
+    }
+
+    /**
+     * setup a state where the notification will not be filtered by the
+     * KeyguardNotificationCoordinator when the keyguard is showing.
+     */
+    private void setupUnfilteredState() {
+        // notification is for current profile
+        when(mLockscreenUserManager.isCurrentProfile(NOTIF_USER_ID)).thenReturn(true);
+
+        // keyguard is showing
+        when(mKeyguardStateController.isShowing()).thenReturn(true);
+
+        // show notifications on the lockscreen
+        when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true);
+
+        // neither the current user nor the notification's user is in lockdown
+        when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID);
+        when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false);
+        when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false);
+
+        // not in public mode
+        when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false);
+        when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false);
+
+        // entry's ranking - should show on all lockscreens
+        // + priority of the notification exceeds the threshold to be shown on the lockscreen
+        mEntry.setRanking(new RankingBuilder()
+                .setKey(mEntry.getKey())
+                .setVisibilityOverride(VISIBILITY_PUBLIC)
+                .setImportance(IMPORTANCE_HIGH)
+                .build());
+
+        // settings allows notifications in public mode
+        when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true);
+        when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID))
+                .thenReturn(true);
+
+        // notification doesn't have a summary
+    }
+}
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index d4889ea..822fc90 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1556,8 +1556,6 @@
     public StorageManagerService(Context context) {
         sSelf = this;
 
-        updateFusePropFromSettings();
-
         // Snapshot feature flag used for this boot
         SystemProperties.set(StorageManager.PROP_ISOLATED_STORAGE_SNAPSHOT, Boolean.toString(
                 SystemProperties.getBoolean(StorageManager.PROP_ISOLATED_STORAGE, true)));
@@ -1757,6 +1755,7 @@
     private void bootCompleted() {
         mBootCompleted = true;
         mHandler.obtainMessage(H_BOOT_COMPLETED).sendToTarget();
+        updateFusePropFromSettings();
     }
 
     private void handleBootCompleted() {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 24cd21e..9875f6d 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -51,7 +51,6 @@
 import android.telephony.LocationAccessPolicy;
 import android.telephony.PhoneCapability;
 import android.telephony.PhoneStateListener;
-import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.PreciseDisconnectCause;
@@ -214,8 +213,6 @@
 
     private ArrayList<List<CellInfo>> mCellInfo = null;
 
-    private ArrayList<List<PhysicalChannelConfig>> mPhysicalChannelConfigs;
-
     private Map<Integer, List<EmergencyNumber>> mEmergencyNumberList;
 
     private EmergencyNumber[] mOutgoingSmsEmergencyNumber;
@@ -425,7 +422,6 @@
         if (mNumPhones < oldNumPhones) {
             cutListToSize(mCellInfo, mNumPhones);
             cutListToSize(mImsReasonInfo, mNumPhones);
-            cutListToSize(mPhysicalChannelConfigs, mNumPhones);
             return;
         }
 
@@ -446,7 +442,6 @@
             mCellInfo.add(i, null);
             mImsReasonInfo.add(i, null);
             mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
-            mPhysicalChannelConfigs.add(i, new ArrayList<>());
             mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
             mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
             mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
@@ -523,7 +518,6 @@
         mPreciseDataConnectionState = new PreciseDataConnectionState[numPhones];
         mCellInfo = new ArrayList<>();
         mImsReasonInfo = new ArrayList<>();
-        mPhysicalChannelConfigs = new ArrayList<>();
         mEmergencyNumberList = new HashMap<>();
         mOutgoingCallEmergencyNumber = new EmergencyNumber[numPhones];
         mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
@@ -543,7 +537,6 @@
             mCellInfo.add(i, null);
             mImsReasonInfo.add(i, null);
             mSrvccState[i] = TelephonyManager.SRVCC_STATE_HANDOVER_NONE;
-            mPhysicalChannelConfigs.add(i, new ArrayList<>());
             mOtaspMode[i] = TelephonyManager.OTASP_UNKNOWN;
             mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
             mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
@@ -962,14 +955,6 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION) != 0) {
-                        try {
-                            r.callback.onPhysicalChannelConfigurationChanged(
-                                    mPhysicalChannelConfigs.get(phoneId));
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
                     if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
                         try {
                             r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
@@ -1394,43 +1379,6 @@
         }
     }
 
-    /**
-     * Notify physical channel configuration according to subscripton ID and phone ID
-     */
-    public void notifyPhysicalChannelConfigurationForSubscriber(int phoneId, int subId,
-            List<PhysicalChannelConfig> configs) {
-        if (!checkNotifyPermission("notifyPhysicalChannelConfiguration()")) {
-            return;
-        }
-
-        if (VDBG) {
-            log("notifyPhysicalChannelConfiguration: subId=" + subId + " phoneId=" + phoneId
-                    + " configs=" + configs);
-        }
-
-        synchronized (mRecords) {
-            if (validatePhoneId(phoneId)) {
-                mPhysicalChannelConfigs.set(phoneId, configs);
-                for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_PHYSICAL_CHANNEL_CONFIGURATION)
-                            && idMatch(r.subId, subId, phoneId)) {
-                        try {
-                            if (DBG_LOC) {
-                                log("notifyPhysicalChannelConfiguration: mPhysicalChannelConfigs="
-                                        + configs + " r=" + r);
-                            }
-                            r.callback.onPhysicalChannelConfigurationChanged(configs);
-                        } catch (RemoteException ex) {
-                            mRemoveList.add(r.binder);
-                        }
-                    }
-                }
-            }
-            handleRemoveListLocked();
-        }
-    }
-
     @Override
     public void notifyMessageWaitingChangedForPhoneId(int phoneId, int subId, boolean mwi) {
         if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
index 7ecd624..d4f41eb 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleBinarySerializer.java
@@ -32,7 +32,7 @@
     }
 
     @Override
-    public String serialize(List<Rule> rules, Optional<Integer> formatVersion) {
+    public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion) {
         // TODO: Implement text serializer.
         return null;
     }
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
index 1125f78..4fcff65 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleSerializer.java
@@ -29,7 +29,7 @@
     void serialize(List<Rule> rules, Optional<Integer> formatVersion, OutputStream outputStream)
             throws RuleSerializeException;
 
-    /** Serialize rules to a string. */
-    String serialize(List<Rule> rule, Optional<Integer> formatVersion)
+    /** Serialize rules to a ByteArray. */
+    byte[] serialize(List<Rule> rule, Optional<Integer> formatVersion)
             throws RuleSerializeException;
 }
diff --git a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
index 254baba..3ec9cf2 100644
--- a/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
+++ b/services/core/java/com/android/server/integrity/serializer/RuleXmlSerializer.java
@@ -62,14 +62,14 @@
     }
 
     @Override
-    public String serialize(List<Rule> rules, Optional<Integer> formatVersion)
+    public byte[] serialize(List<Rule> rules, Optional<Integer> formatVersion)
             throws RuleSerializeException {
         try {
             XmlSerializer xmlSerializer = Xml.newSerializer();
             StringWriter writer = new StringWriter();
             xmlSerializer.setOutput(writer);
             serializeRules(rules, xmlSerializer);
-            return writer.toString();
+            return writer.toString().getBytes(StandardCharsets.UTF_8);
         } catch (Exception e) {
             throw new RuleSerializeException(e.getMessage(), e);
         }
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 9b50307..0beff7a 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
-import android.app.admin.DevicePolicyManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -777,16 +776,6 @@
                 break;
 
             case android.provider.Settings.Global.AUTO_TIME:
-                DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
-                if (dpm != null && dpm.getAutoTimeRequired()
-                        && "0".equals(value)) {
-                    return true;
-                } else if (callingUid == Process.SYSTEM_UID) {
-                    return false;
-                }
-                restriction = UserManager.DISALLOW_CONFIG_DATE_TIME;
-                break;
-
             case android.provider.Settings.Global.AUTO_TIME_ZONE:
                 if (callingUid == Process.SYSTEM_UID) {
                     return false;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b264684..2499ad8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7366,6 +7366,7 @@
             }
         }
 
+        // TODO: (b/145604635) Add upgrade case
         // Turn AUTO_TIME on in settings if it is required
         if (required) {
             long ident = mInjector.binderClearCallingIdentity();
@@ -7409,6 +7410,42 @@
         }
     }
 
+    /**
+     * Set whether auto time is enabled on the device.
+     */
+    @Override
+    public void setAutoTime(ComponentName who, boolean enabled) {
+        if (!mHasFeature) {
+            return;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        // TODO (b/145286957) Refactor security checks
+        enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+        mInjector.binderWithCleanCallingIdentity(() ->
+                mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, enabled ? 1 : 0));
+
+        DevicePolicyEventLogger
+                .createEvent(DevicePolicyEnums.SET_AUTO_TIME)
+                .setAdmin(who)
+                .setBoolean(enabled)
+                .write();
+    }
+
+    /**
+     * Returns whether or auto time is used on the device or not.
+     */
+    @Override
+    public boolean getAutoTime(ComponentName who) {
+        if (!mHasFeature) {
+            return false;
+        }
+        Preconditions.checkNotNull(who, "ComponentName is null");
+        enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned();
+
+        return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
+    }
+
     @Override
     public void setForceEphemeralUsers(ComponentName who, boolean forceEphemeralUsers) {
         if (!mHasFeature) {
@@ -8599,20 +8636,42 @@
 
     @Override
     public boolean checkDeviceIdentifierAccess(String packageName, int pid, int uid) {
-        // If the caller is not a system app then it should only be able to check its own device
-        // identifier access.
-        int callingUid = mInjector.binderGetCallingUid();
-        int callingPid = mInjector.binderGetCallingPid();
-        if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID
-                && (callingUid != uid || callingPid != pid)) {
-            String message = String.format(
-                    "Calling uid %d, pid %d cannot check device identifier access for package %s "
-                            + "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid);
-            Log.w(LOG_TAG, message);
-            throw new SecurityException(message);
-        }
+        ensureCallerIdentityMatchesIfNotSystem(packageName, pid, uid);
+
         // Verify that the specified packages matches the provided uid.
-        int userId = UserHandle.getUserId(uid);
+        if (!doesPackageMatchUid(packageName, uid)) {
+            return false;
+        }
+        // A device or profile owner must also have the READ_PHONE_STATE permission to access device
+        // identifiers. If the package being checked does not have this permission then deny access.
+        if (mContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid, uid)
+                != PackageManager.PERMISSION_GRANTED) {
+            return false;
+        }
+
+        // Allow access to the device owner or delegate cert installer.
+        ComponentName deviceOwner = getDeviceOwnerComponent(true);
+        if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
+                    || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+            return true;
+        }
+        final int userId = UserHandle.getUserId(uid);
+        // Allow access to the profile owner for the specified user, or delegate cert installer
+        // But only if this is an organization-owned device.
+        ComponentName profileOwner = getProfileOwnerAsUser(userId);
+        if (profileOwner != null && canProfileOwnerAccessDeviceIds(userId)
+                && (profileOwner.getPackageName().equals(packageName)
+                || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
+            return true;
+        }
+
+        Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
+                    packageName, uid, pid));
+        return false;
+    }
+
+    private boolean doesPackageMatchUid(String packageName, int uid) {
+        final int userId = UserHandle.getUserId(uid);
         try {
             ApplicationInfo appInfo = mIPackageManager.getApplicationInfo(packageName, 0, userId);
             // Since this call goes directly to PackageManagerService a NameNotFoundException is not
@@ -8634,29 +8693,22 @@
             Log.e(LOG_TAG, "Exception caught obtaining appInfo for package " + packageName, e);
             return false;
         }
-        // A device or profile owner must also have the READ_PHONE_STATE permission to access device
-        // identifiers. If the package being checked does not have this permission then deny access.
-        if (mContext.checkPermission(android.Manifest.permission.READ_PHONE_STATE, pid, uid)
-                != PackageManager.PERMISSION_GRANTED) {
-            return false;
-        }
+        return true;
+    }
 
-        // Allow access to the device owner or delegate cert installer.
-        ComponentName deviceOwner = getDeviceOwnerComponent(true);
-        if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName)
-                    || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
-            return true;
+    private void ensureCallerIdentityMatchesIfNotSystem(String packageName, int pid, int uid) {
+        // If the caller is not a system app then it should only be able to check its own device
+        // identifier access.
+        int callingUid = mInjector.binderGetCallingUid();
+        int callingPid = mInjector.binderGetCallingPid();
+        if (UserHandle.getAppId(callingUid) >= Process.FIRST_APPLICATION_UID
+                && (callingUid != uid || callingPid != pid)) {
+            String message = String.format(
+                    "Calling uid %d, pid %d cannot check device identifier access for package %s "
+                            + "(uid=%d, pid=%d)", callingUid, callingPid, packageName, uid, pid);
+            Log.w(LOG_TAG, message);
+            throw new SecurityException(message);
         }
-        // Allow access to the profile owner for the specified user, or delegate cert installer
-        ComponentName profileOwner = getProfileOwnerAsUser(userId);
-        if (profileOwner != null && (profileOwner.getPackageName().equals(packageName)
-                    || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) {
-            return true;
-        }
-
-        Log.w(LOG_TAG, String.format("Package %s (uid=%d, pid=%d) cannot access Device IDs",
-                    packageName, uid, pid));
-        return false;
     }
 
     /**
@@ -8883,6 +8935,28 @@
                 "Only profile owner, device owner and system may call this method.");
     }
 
+    private ActiveAdmin enforceDeviceOwnerOrProfileOwnerOnUser0OrProfileOwnerOrganizationOwned() {
+        synchronized (getLockObject()) {
+            // Check if there is a device owner
+            ActiveAdmin deviceOwner = getActiveAdminWithPolicyForUidLocked(null,
+                    DeviceAdminInfo.USES_POLICY_DEVICE_OWNER, mInjector.binderGetCallingUid());
+            if (deviceOwner != null) return deviceOwner;
+
+            ActiveAdmin profileOwner = getActiveAdminWithPolicyForUidLocked(null,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, mInjector.binderGetCallingUid());
+
+            // Check if there is a profile owner of an organization owned device
+            if (isProfileOwnerOfOrganizationOwnedDevice(profileOwner)) return profileOwner;
+
+            // Check if there is a profile owner called on user 0
+            if (profileOwner != null) {
+                enforceCallerSystemUserHandle();
+                return profileOwner;
+            }
+        }
+        throw new SecurityException("No active admin found");
+    }
+
     private void enforceProfileOwnerOrFullCrossUsersPermission(int userId) {
         if (userId == mInjector.userHandleGetCallingUserId()) {
             synchronized (getLockObject()) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 162e766..0590020 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -2635,6 +2635,16 @@
         mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
     }
 
+    private void setupProfileOwnerOnUser0() throws Exception {
+        mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
+
+        setUpPackageManagerForAdmin(admin1, DpmMockContext.CALLER_SYSTEM_USER_UID);
+        dpm.setActiveAdmin(admin1, false);
+        assertTrue(dpm.setProfileOwner(admin1, null, UserHandle.USER_SYSTEM));
+
+        mContext.callerPermissions.removeAll(OWNER_SETUP_PERMISSIONS);
+    }
+
     private void setupDeviceOwner() throws Exception {
         mContext.callerPermissions.addAll(OWNER_SETUP_PERMISSIONS);
 
@@ -3611,6 +3621,43 @@
             Settings.System.SCREEN_BRIGHTNESS, "0", DpmMockContext.CALLER_USER_HANDLE);
     }
 
+    public void testSetAutoTimeModifiesSetting() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupDeviceOwner();
+        dpm.setAutoTime(admin1, true);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+        dpm.setAutoTime(admin1, false);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+    }
+
+    public void testSetAutoTimeWithPOOnUser0() throws Exception {
+        mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
+        setupProfileOwnerOnUser0();
+        dpm.setAutoTime(admin1, true);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+        dpm.setAutoTime(admin1, false);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+    }
+
+    public void testSetAutoTimeFailWithPONotOnUser0() throws Exception {
+        setupProfileOwner();
+        assertExpectException(SecurityException.class, null, () -> dpm.setAutoTime(admin1, false));
+        verify(getServices().settings, never()).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+    }
+
+    public void testSetAutoTimeWithPOOfOrganizationOwnedDevice() throws Exception {
+        setupProfileOwner();
+        configureProfileOwnerOfOrgOwnedDevice(admin1, DpmMockContext.CALLER_USER_HANDLE);
+
+        dpm.setAutoTime(admin1, true);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 1);
+
+        dpm.setAutoTime(admin1, false);
+        verify(getServices().settings).settingsGlobalPutInt(Settings.Global.AUTO_TIME, 0);
+    }
+
     public void testSetTime() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
diff --git a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
index 180de2f..5903b5a 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/serializer/RuleXmlSerializerTest.java
@@ -34,6 +34,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashMap;
@@ -49,11 +50,11 @@
         RuleSerializer xmlSerializer = new RuleXmlSerializer();
         String expectedRules = "<RL />";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -82,11 +83,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Arrays.asList(rule1, rule2), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -128,8 +129,8 @@
                 /* formatVersion= */ Optional.empty(),
                 outputStream);
 
-        String actualRules = outputStream.toString();
-        assertEquals(expectedRules, actualRules);
+        byte[] actualRules = outputStream.toString().getBytes(StandardCharsets.UTF_8);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -165,11 +166,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -215,11 +216,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -265,11 +266,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -297,11 +298,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -327,11 +328,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
@@ -355,11 +356,11 @@
                         + "</R>"
                         + "</RL>";
 
-        String actualRules =
+        byte[] actualRules =
                 xmlSerializer.serialize(
                         Collections.singletonList(rule), /* formatVersion= */ Optional.empty());
 
-        assertEquals(expectedRules, actualRules);
+        assertEquals(expectedRules, new String(actualRules, StandardCharsets.UTF_8));
     }
 
     @Test
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index 3ecf8d7..a0739c4 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -1512,7 +1512,6 @@
      */
     @SystemApi
     @TestApi
-    //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
     public void enterBackgroundAudioProcessing() {
         if (mState != STATE_ACTIVE && mState != STATE_RINGING) {
             throw new IllegalStateException("Call must be active or ringing");
@@ -1534,7 +1533,6 @@
      */
     @SystemApi
     @TestApi
-    //@RequiresPermission(android.Manifest.permission.BACKGROUND_CALL_AUDIO)
     public void exitBackgroundAudioProcessing(boolean shouldRing) {
         if (mState != STATE_AUDIO_PROCESSING) {
             throw new IllegalStateException("Call must in the audio processing state");
diff --git a/telecomm/java/android/telecom/CallScreeningService.java b/telecomm/java/android/telecom/CallScreeningService.java
index b91787c..f8722f4 100644
--- a/telecomm/java/android/telecom/CallScreeningService.java
+++ b/telecomm/java/android/telecom/CallScreeningService.java
@@ -144,7 +144,7 @@
         private final boolean mShouldSilenceCall;
         private final boolean mShouldSkipCallLog;
         private final boolean mShouldSkipNotification;
-        private final boolean mShouldScreenCallFurther;
+        private final boolean mShouldScreenCallViaAudioProcessing;
 
         private CallResponse(
                 boolean shouldDisallowCall,
@@ -152,13 +152,13 @@
                 boolean shouldSilenceCall,
                 boolean shouldSkipCallLog,
                 boolean shouldSkipNotification,
-                boolean shouldScreenCallFurther) {
+                boolean shouldScreenCallViaAudioProcessing) {
             if (!shouldDisallowCall
                     && (shouldRejectCall || shouldSkipCallLog || shouldSkipNotification)) {
                 throw new IllegalStateException("Invalid response state for allowed call.");
             }
 
-            if (shouldDisallowCall && shouldScreenCallFurther) {
+            if (shouldDisallowCall && shouldScreenCallViaAudioProcessing) {
                 throw new IllegalStateException("Invalid response state for allowed call.");
             }
 
@@ -167,7 +167,7 @@
             mShouldSkipCallLog = shouldSkipCallLog;
             mShouldSkipNotification = shouldSkipNotification;
             mShouldSilenceCall = shouldSilenceCall;
-            mShouldScreenCallFurther = shouldScreenCallFurther;
+            mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
         }
 
         /*
@@ -211,8 +211,8 @@
          * for further screening of the call.
          * @hide
          */
-        public boolean getShouldScreenCallFurther() {
-            return mShouldScreenCallFurther;
+        public boolean getShouldScreenCallViaAudioProcessing() {
+            return mShouldScreenCallViaAudioProcessing;
         }
 
         public static class Builder {
@@ -221,7 +221,7 @@
             private boolean mShouldSilenceCall;
             private boolean mShouldSkipCallLog;
             private boolean mShouldSkipNotification;
-            private boolean mShouldScreenCallFurther;
+            private boolean mShouldScreenCallViaAudioProcessing;
 
             /**
              * Sets whether the incoming call should be blocked.
@@ -285,13 +285,14 @@
              * This request will only be honored if the {@link CallScreeningService} shares the same
              * uid as the default dialer app. Otherwise, the call will go through as usual.
              *
-             * @param shouldScreenCallFurther Whether to request further call screening.
+             * @param shouldScreenCallViaAudioProcessing Whether to request further call screening.
              * @hide
              */
             @SystemApi
             @TestApi
-            public Builder setShouldScreenCallFurther(boolean shouldScreenCallFurther) {
-                mShouldScreenCallFurther = shouldScreenCallFurther;
+            public @NonNull Builder setShouldScreenCallViaAudioProcessing(
+                    boolean shouldScreenCallViaAudioProcessing) {
+                mShouldScreenCallViaAudioProcessing = shouldScreenCallViaAudioProcessing;
                 return this;
             }
 
@@ -302,7 +303,7 @@
                         mShouldSilenceCall,
                         mShouldSkipCallLog,
                         mShouldSkipNotification,
-                        mShouldScreenCallFurther);
+                        mShouldScreenCallViaAudioProcessing);
             }
        }
     }
@@ -380,7 +381,7 @@
                         new ComponentName(getPackageName(), getClass().getName()));
             } else if (response.getSilenceCall()) {
                 mCallScreeningAdapter.silenceCall(callDetails.getTelecomCallId());
-            } else if (response.getShouldScreenCallFurther()) {
+            } else if (response.getShouldScreenCallViaAudioProcessing()) {
                 mCallScreeningAdapter.screenCallFurther(callDetails.getTelecomCallId());
             } else {
                 mCallScreeningAdapter.allowCall(callDetails.getTelecomCallId());
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 0320f75..bb28df2 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -261,16 +261,22 @@
         public static final int BAND_7 = 7;
         public static final int BAND_8 = 8;
         public static final int BAND_12 = 12;
+        public static final int BAND_14 = 14;
+        public static final int BAND_18 = 18;
         public static final int BAND_20 = 20;
         public static final int BAND_25 = 25;
         public static final int BAND_28 = 28;
+        public static final int BAND_29 = 29;
+        public static final int BAND_30 = 30;
         public static final int BAND_34 = 34;
         public static final int BAND_38 = 38;
         public static final int BAND_39 = 39;
         public static final int BAND_40 = 40;
         public static final int BAND_41 = 41;
+        public static final int BAND_48 = 48;
         public static final int BAND_50 = 50;
         public static final int BAND_51 = 51;
+        public static final int BAND_65 = 65;
         public static final int BAND_66 = 66;
         public static final int BAND_70 = 70;
         public static final int BAND_71 = 71;
@@ -286,6 +292,7 @@
         public static final int BAND_83 = 83;
         public static final int BAND_84 = 84;
         public static final int BAND_86 = 86;
+        public static final int BAND_90 = 90;
 
         /** FR2 bands */
         public static final int BAND_257 = 257;
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index 17b7963f..8a75831 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,6 +16,8 @@
 
 package android.telephony;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -27,12 +29,13 @@
 /**
  * Define capability of a modem group. That is, the capabilities
  * are shared between those modems defined by list of modem IDs.
- * @hide
  */
-public class PhoneCapability implements Parcelable {
+public final class PhoneCapability implements Parcelable {
     // Hardcoded default DSDS capability.
+    /** @hide */
     public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
     // Hardcoded default Single SIM single standby capability.
+    /** @hide */
     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
 
     static {
@@ -48,13 +51,18 @@
         logicalModemList.add(modemInfo1);
         DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
     }
-
+    /** @hide */
     public final int maxActiveVoiceCalls;
+    /** @hide */
     public final int maxActiveData;
+    /** @hide */
     public final int max5G;
+    /** @hide */
     public final boolean validationBeforeSwitchSupported;
+    /** @hide */
     public final List<ModemInfo> logicalModemList;
 
+    /** @hide */
     public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
             List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
         this.maxActiveVoiceCalls = maxActiveVoiceCalls;
@@ -116,7 +124,7 @@
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) {
+    public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
         dest.writeInt(maxActiveVoiceCalls);
         dest.writeInt(maxActiveData);
         dest.writeInt(max5G);