Merge "New sm command to unmount app data and obb app visibility mount"
diff --git a/core/api/current.txt b/core/api/current.txt
index 9f4af37..d1906c6 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -385,6 +385,7 @@
     field public static final int calendarViewShown = 16843596; // 0x101034c
     field public static final int calendarViewStyle = 16843613; // 0x101035d
     field public static final int canControlMagnification = 16844039; // 0x1010507
+    field public static final int canPauseRecording = 16844311; // 0x1010617
     field public static final int canPerformGestures = 16844045; // 0x101050d
     field public static final int canRecord = 16844060; // 0x101051c
     field @Deprecated public static final int canRequestEnhancedWebAccessibility = 16843736; // 0x10103d8
@@ -24265,6 +24266,7 @@
   }
 
   public final class TvInputInfo implements android.os.Parcelable {
+    method public boolean canPauseRecording();
     method public boolean canRecord();
     method @Deprecated public android.content.Intent createSettingsIntent();
     method public android.content.Intent createSetupIntent();
@@ -24298,6 +24300,7 @@
   public static final class TvInputInfo.Builder {
     ctor public TvInputInfo.Builder(android.content.Context, android.content.ComponentName);
     method public android.media.tv.TvInputInfo build();
+    method @NonNull public android.media.tv.TvInputInfo.Builder setCanPauseRecording(boolean);
     method public android.media.tv.TvInputInfo.Builder setCanRecord(boolean);
     method public android.media.tv.TvInputInfo.Builder setExtras(android.os.Bundle);
     method public android.media.tv.TvInputInfo.Builder setTunerCount(int);
@@ -24389,7 +24392,9 @@
     method public void notifyRecordingStopped(android.net.Uri);
     method public void notifyTuned(android.net.Uri);
     method public void onAppPrivateCommand(@NonNull String, android.os.Bundle);
+    method public void onPauseRecording(@NonNull android.os.Bundle);
     method public abstract void onRelease();
+    method public void onResumeRecording(@NonNull android.os.Bundle);
     method public abstract void onStartRecording(@Nullable android.net.Uri);
     method public void onStartRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
     method public abstract void onStopRecording();
@@ -24439,7 +24444,11 @@
 
   public class TvRecordingClient {
     ctor public TvRecordingClient(android.content.Context, String, @NonNull android.media.tv.TvRecordingClient.RecordingCallback, android.os.Handler);
+    method public void pauseRecording();
+    method public void pauseRecording(@NonNull android.os.Bundle);
     method public void release();
+    method public void resumeRecording();
+    method public void resumeRecording(@NonNull android.os.Bundle);
     method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle);
     method public void startRecording(@Nullable android.net.Uri);
     method public void startRecording(@Nullable android.net.Uri, @NonNull android.os.Bundle);
@@ -40486,6 +40495,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);
@@ -40555,10 +40570,10 @@
 
   public class PhoneStateListener {
     ctor public PhoneStateListener();
-    ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
+    ctor @Deprecated public PhoneStateListener(@NonNull java.util.concurrent.Executor);
     method public void onActiveDataSubscriptionIdChanged(int);
     method public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -40566,36 +40581,140 @@
     method public void onDataActivity(int);
     method public void onDataConnectionStateChanged(int);
     method public void onDataConnectionStateChanged(int, int);
-    method @RequiresPermission("android.permission.READ_PHONE_STATE") public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
     method public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
     method public void onMessageWaitingIndicatorChanged(boolean);
-    method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
     method public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
     method public void onServiceStateChanged(android.telephony.ServiceState);
     method @Deprecated public void onSignalStrengthChanged(int);
     method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
     method public void onUserMobileDataStateChanged(boolean);
-    field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
-    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
-    field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
-    field public static final int LISTEN_CALL_STATE = 32; // 0x20
-    field public static final int LISTEN_CELL_INFO = 1024; // 0x400
-    field public static final int LISTEN_CELL_LOCATION = 16; // 0x10
-    field public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
-    field public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
-    field public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000
-    field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
-    field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
+    field @Deprecated public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_BARRING_INFO = -2147483648; // 0x80000000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
+    field @Deprecated public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
+    field @Deprecated public static final int LISTEN_CALL_STATE = 32; // 0x20
+    field @Deprecated public static final int LISTEN_CELL_INFO = 1024; // 0x400
+    field @Deprecated public static final int LISTEN_CELL_LOCATION = 16; // 0x10
+    field @Deprecated public static final int LISTEN_DATA_ACTIVITY = 128; // 0x80
+    field @Deprecated public static final int LISTEN_DATA_CONNECTION_STATE = 64; // 0x40
+    field @Deprecated public static final int LISTEN_DISPLAY_INFO_CHANGED = 1048576; // 0x100000
+    field @Deprecated public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
+    field @Deprecated public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4
     field public static final int LISTEN_NONE = 0; // 0x0
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
-    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
-    field public static final int LISTEN_SERVICE_STATE = 1; // 0x1
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_REGISTRATION_FAILURE = 1073741824; // 0x40000000
+    field @Deprecated public static final int LISTEN_SERVICE_STATE = 1; // 0x1
     field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2
-    field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
-    field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
+    field @Deprecated public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100
+    field @Deprecated public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000
+  }
+
+  public static interface PhoneStateListener.ActiveDataSubscriptionIdChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onActiveDataSubscriptionIdChanged(int);
+  }
+
+  public static interface PhoneStateListener.AlwaysReportedSignalStrengthChangedListener {
+    method @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength);
+  }
+
+  public static interface PhoneStateListener.BarringInfoChangedListener {
+    method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onBarringInfoChanged(@NonNull android.telephony.BarringInfo);
+  }
+
+  public static interface PhoneStateListener.CallDisconnectCauseChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallDisconnectCauseChanged(int, int);
+  }
+
+  public static interface PhoneStateListener.CallForwardingIndicatorChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onCallForwardingIndicatorChanged(boolean);
+  }
+
+  public static interface PhoneStateListener.CallStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public void onCallStateChanged(int, @Nullable String);
+  }
+
+  public static interface PhoneStateListener.CarrierNetworkChangeListener {
+    method public void onCarrierNetworkChange(boolean);
+  }
+
+  public static interface PhoneStateListener.CellInfoChangedListener {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellInfoChanged(@NonNull java.util.List<android.telephony.CellInfo>);
+  }
+
+  public static interface PhoneStateListener.CellLocationChangedListener {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void onCellLocationChanged(@NonNull android.telephony.CellLocation);
+  }
+
+  public static interface PhoneStateListener.DataActivationStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivationStateChanged(int);
+  }
+
+  public static interface PhoneStateListener.DataActivityListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataActivity(int);
+  }
+
+  public static interface PhoneStateListener.DataConnectionStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onDataConnectionStateChanged(int, int);
+  }
+
+  public static interface PhoneStateListener.DisplayInfoChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onDisplayInfoChanged(@NonNull android.telephony.TelephonyDisplayInfo);
+  }
+
+  public static interface PhoneStateListener.EmergencyNumberListChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onEmergencyNumberListChanged(@NonNull java.util.Map<java.lang.Integer,java.util.List<android.telephony.emergency.EmergencyNumber>>);
+  }
+
+  public static interface PhoneStateListener.ImsCallDisconnectCauseChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
+  }
+
+  public static interface PhoneStateListener.MessageWaitingIndicatorChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public void onMessageWaitingIndicatorChanged(boolean);
+  }
+
+  public static interface PhoneStateListener.PhoneCapabilityChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onPhoneCapabilityChanged(@NonNull android.telephony.PhoneCapability);
+  }
+
+  public static interface PhoneStateListener.PreciseDataConnectionStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState);
+  }
+
+  public static interface PhoneStateListener.RegistrationFailedListener {
+    method @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void onRegistrationFailed(@NonNull android.telephony.CellIdentity, @NonNull String, int, int, int);
+  }
+
+  public static interface PhoneStateListener.ServiceStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onServiceStateChanged(@NonNull android.telephony.ServiceState);
+  }
+
+  public static interface PhoneStateListener.SignalStrengthsChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onSignalStrengthsChanged(@NonNull android.telephony.SignalStrength);
+  }
+
+  public static interface PhoneStateListener.UserMobileDataStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void onUserMobileDataStateChanged(boolean);
+  }
+
+  public final class PhysicalChannelConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getCellBandwidthDownlink();
+    method public int getChannelNumber();
+    method public int getConnectionStatus();
+    method public int getNetworkType();
+    method @IntRange(from=0, to=1007) public int getPhysicalCellId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CHANNEL_NUMBER_UNKNOWN = -1; // 0xffffffff
+    field public static final int CONNECTION_PRIMARY_SERVING = 1; // 0x1
+    field public static final int CONNECTION_SECONDARY_SERVING = 2; // 0x2
+    field public static final int CONNECTION_UNKNOWN = -1; // 0xffffffff
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhysicalChannelConfig> CREATOR;
+    field public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; // 0xffffffff
   }
 
   public final class PreciseDataConnectionState implements android.os.Parcelable {
@@ -40677,6 +40796,32 @@
     field public static final int INVALID = 2147483647; // 0x7fffffff
   }
 
+  public final class SignalThresholdInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getRadioAccessNetworkType();
+    method public int getSignalMeasurementType();
+    method @NonNull public int[] getThresholds();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SignalThresholdInfo> CREATOR;
+    field public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2; // 0x2
+    field public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3; // 0x3
+    field public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4; // 0x4
+    field public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1; // 0x1
+    field public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5; // 0x5
+    field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6; // 0x6
+    field public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7; // 0x7
+    field public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8; // 0x8
+    field public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0; // 0x0
+  }
+
+  public static final class SignalThresholdInfo.Builder {
+    ctor public SignalThresholdInfo.Builder();
+    method @NonNull public android.telephony.SignalThresholdInfo build();
+    method @NonNull public android.telephony.SignalThresholdInfo.Builder setRadioAccessNetworkType(int);
+    method @NonNull public android.telephony.SignalThresholdInfo.Builder setSignalMeasurementType(int);
+    method @NonNull public android.telephony.SignalThresholdInfo.Builder setThresholds(@NonNull int[]);
+  }
+
   public final class SmsManager {
     method public String createAppSpecificSmsToken(android.app.PendingIntent);
     method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
@@ -41106,7 +41251,8 @@
     method public boolean isVoiceCapable();
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
-    method public void listen(android.telephony.PhoneStateListener, int);
+    method @Deprecated public void listen(android.telephony.PhoneStateListener, int);
+    method public void registerPhoneStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.PhoneStateListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void requestCellInfoUpdate(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.TelephonyManager.CellInfoCallback);
     method @RequiresPermission(allOf={android.Manifest.permission.MODIFY_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
     method public void sendDialerSpecialCode(String);
@@ -41129,6 +41275,7 @@
     method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
+    method public void unregisterPhoneStateListener(@NonNull android.telephony.PhoneStateListener);
     method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     field public static final String ACTION_CARRIER_MESSAGING_CLIENT_SERVICE = "android.telephony.action.CARRIER_MESSAGING_CLIENT_SERVICE";
     field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 03e80fc..e768ea6 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -9813,17 +9813,87 @@
     method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
     method @Deprecated public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber);
     method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
-    method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
     method public void onRadioPowerStateChanged(int);
     method public void onSrvccStateChanged(int);
     method public void onVoiceActivationStateChanged(int);
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
-    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
-    field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
+    field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23; // 0x17
+    field @RequiresPermission("android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH") public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10; // 0xa
+    field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_BARRING_INFO_CHANGED = 32; // 0x20
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27; // 0x1b
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26; // 0x1a
+    field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4; // 0x4
+    field @RequiresPermission(android.Manifest.permission.READ_CALL_LOG) public static final int EVENT_CALL_STATE_CHANGED = 6; // 0x6
+    field public static final int EVENT_CARRIER_NETWORK_CHANGED = 17; // 0x11
+    field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_INFO_CHANGED = 11; // 0xb
+    field @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public static final int EVENT_CELL_LOCATION_CHANGED = 5; // 0x5
+    field public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19; // 0x13
+    field public static final int EVENT_DATA_ACTIVITY_CHANGED = 8; // 0x8
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14; // 0xe
+    field public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7; // 0x7
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_DATA_ENABLED_CHANGED = 34; // 0x22
+    field public static final int EVENT_DISPLAY_INFO_CHANGED = 21; // 0x15
+    field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25; // 0x19
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28; // 0x1c
+    field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3; // 0x3
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_OEM_HOOK_RAW = 15; // 0xf
+    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29; // 0x1d
+    field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30; // 0x1e
+    field public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22; // 0x16
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33; // 0x21
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12; // 0xc
+    field @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13; // 0xd
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24; // 0x18
+    field @RequiresPermission(allOf={android.Manifest.permission.READ_PRECISE_PHONE_STATE, android.Manifest.permission.ACCESS_FINE_LOCATION}) public static final int EVENT_REGISTRATION_FAILURE = 31; // 0x1f
+    field public static final int EVENT_SERVICE_STATE_CHANGED = 1; // 0x1
+    field public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9; // 0x9
+    field public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2; // 0x2
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_SRVCC_STATE_CHANGED = 16; // 0x10
+    field public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20; // 0x14
+    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18; // 0x12
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
+    field @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
+  }
+
+  public static interface PhoneStateListener.CallAttributesChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
+  }
+
+  public static interface PhoneStateListener.DataEnabledChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onDataEnabledChanged(boolean, int);
+  }
+
+  public static interface PhoneStateListener.OutgoingEmergencyCallListener {
+    method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber, int);
+  }
+
+  public static interface PhoneStateListener.OutgoingEmergencySmsListener {
+    method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber, int);
+  }
+
+  public static interface PhoneStateListener.PhysicalChannelConfigChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPhysicalChannelConfigChanged(@NonNull java.util.List<android.telephony.PhysicalChannelConfig>);
+  }
+
+  public static interface PhoneStateListener.PreciseCallStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
+  }
+
+  public static interface PhoneStateListener.RadioPowerStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onRadioPowerStateChanged(int);
+  }
+
+  public static interface PhoneStateListener.SrvccStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onSrvccStateChanged(int);
+  }
+
+  public static interface PhoneStateListener.VoiceActivationStateChangedListener {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void onVoiceActivationStateChanged(int);
   }
 
   public final class PinResult implements android.os.Parcelable {
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index be1681b..66a8325 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -223,7 +223,7 @@
      */
     IBinder requestStartActivityPermissionToken(in IBinder delegatorToken);
 
-    void releaseSomeActivities(in IApplicationThread app);
+    oneway void releaseSomeActivities(in IApplicationThread app);
     Bitmap getTaskDescriptionIcon(in String filename, int userId);
     void registerTaskStackListener(in ITaskStackListener listener);
     void unregisterTaskStackListener(in ITaskStackListener listener);
diff --git a/core/java/android/app/search/OWNERS b/core/java/android/app/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/app/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8742ecb..ce0ed5b 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -72,7 +72,6 @@
 
 import libcore.net.event.NetworkEventDispatcher;
 
-import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.lang.annotation.Retention;
@@ -1958,6 +1957,12 @@
         return k;
     }
 
+    // Construct an invalid fd.
+    private ParcelFileDescriptor createInvalidFd() {
+        final int invalidFd = -1;
+        return ParcelFileDescriptor.adoptFd(invalidFd);
+    }
+
     /**
      * Request that keepalives be started on a IPsec NAT-T socket.
      *
@@ -1988,7 +1993,7 @@
         } catch (IOException ignored) {
             // Construct an invalid fd, so that if the user later calls start(), it will fail with
             // ERROR_INVALID_SOCKET.
-            dup = new ParcelFileDescriptor(new FileDescriptor());
+            dup = createInvalidFd();
         }
         return new NattSocketKeepalive(mService, network, dup, socket.getResourceId(), source,
                 destination, executor, callback);
@@ -2030,7 +2035,7 @@
         } catch (IOException ignored) {
             // Construct an invalid fd, so that if the user later calls start(), it will fail with
             // ERROR_INVALID_SOCKET.
-            dup = new ParcelFileDescriptor(new FileDescriptor());
+            dup = createInvalidFd();
         }
         return new NattSocketKeepalive(mService, network, dup,
                 INVALID_RESOURCE_ID /* Unused */, source, destination, executor, callback);
@@ -2067,7 +2072,7 @@
         } catch (UncheckedIOException ignored) {
             // Construct an invalid fd, so that if the user later calls start(), it will fail with
             // ERROR_INVALID_SOCKET.
-            dup = new ParcelFileDescriptor(new FileDescriptor());
+            dup = createInvalidFd();
         }
         return new TcpSocketKeepalive(mService, network, dup, executor, callback);
     }
diff --git a/core/java/android/net/metrics/IpConnectivityLog.java b/core/java/android/net/metrics/IpConnectivityLog.java
index 58ea915..bb91f89 100644
--- a/core/java/android/net/metrics/IpConnectivityLog.java
+++ b/core/java/android/net/metrics/IpConnectivityLog.java
@@ -137,7 +137,7 @@
      * @return true if the event was successfully logged.
      */
     public boolean log(@NonNull Network network, @NonNull int[] transports, @NonNull Event data) {
-        return log(network.netId, transports, data);
+        return log(network.getNetId(), transports, data);
     }
 
     /**
diff --git a/core/java/android/net/vcn/VcnTransportInfo.java b/core/java/android/net/vcn/VcnTransportInfo.java
new file mode 100644
index 0000000..4d8cf91
--- /dev/null
+++ b/core/java/android/net/vcn/VcnTransportInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.TransportInfo;
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.SubscriptionManager;
+
+import java.util.Objects;
+
+/**
+ * VcnTransportInfo contains information about the VCN's underlying transports for SysUi.
+ *
+ * <p>Presence of this class in the NetworkCapabilities.TransportInfo implies that the network is a
+ * VCN.
+ *
+ * <p>VcnTransportInfo must exist on top of either an underlying Wifi or Cellular Network. If the
+ * underlying Network is WiFi, the subId will be {@link
+ * SubscriptionManager#INVALID_SUBSCRIPTION_ID}. If the underlying Network is Cellular, the WifiInfo
+ * will be {@code null}.
+ *
+ * @hide
+ */
+public class VcnTransportInfo implements TransportInfo, Parcelable {
+    @Nullable private final WifiInfo mWifiInfo;
+    private final int mSubId;
+
+    public VcnTransportInfo(@NonNull WifiInfo wifiInfo) {
+        this(wifiInfo, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
+    }
+
+    public VcnTransportInfo(int subId) {
+        this(null /* wifiInfo */, subId);
+    }
+
+    private VcnTransportInfo(@Nullable WifiInfo wifiInfo, int subId) {
+        if (wifiInfo == null && subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+            throw new IllegalArgumentException(
+                    "VcnTransportInfo requires either non-null WifiInfo or valid subId");
+        }
+
+        mWifiInfo = wifiInfo;
+        mSubId = subId;
+    }
+
+    /**
+     * Get the {@link WifiInfo} for this VcnTransportInfo.
+     *
+     * <p>If the underlying Network for the associated VCN is Cellular, returns null.
+     *
+     * @return the WifiInfo if there is an underlying WiFi connection, else null.
+     */
+    @Nullable
+    public WifiInfo getWifiInfo() {
+        return mWifiInfo;
+    }
+
+    /**
+     * Get the subId for the VCN Network associated with this VcnTransportInfo.
+     *
+     * <p>If the underlying Network for the associated VCN is WiFi, returns {@link
+     * SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+     *
+     * @return the Subscription ID if a cellular underlying Network is present, else {@link
+     *     android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID}.
+     */
+    public int getSubId() {
+        return mSubId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mWifiInfo, mSubId);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof VcnTransportInfo)) return false;
+        final VcnTransportInfo that = (VcnTransportInfo) o;
+
+        return Objects.equals(mWifiInfo, that.mWifiInfo) && mSubId == that.mSubId;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {}
+
+    /** Implement the Parcelable interface */
+    public static final @NonNull Creator<VcnTransportInfo> CREATOR =
+            new Creator<VcnTransportInfo>() {
+                public VcnTransportInfo createFromParcel(Parcel in) {
+                    // return null instead of a default VcnTransportInfo to avoid leaking
+                    // information about this being a VCN Network (instead of macro cellular, etc)
+                    return null;
+                }
+
+                public VcnTransportInfo[] newArray(int size) {
+                    return new VcnTransportInfo[size];
+                }
+            };
+}
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 46ad7b8..33736d3 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -26,7 +26,6 @@
 import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
-import android.os.Handler;
 import android.util.Log;
 import android.widget.Toast;
 
@@ -189,13 +188,18 @@
         }
     }
 
-    /*
-     * Cancels a currently running bugreport.
+    /**
+     * Cancels the currently running bugreport.
+     *
+     * <p>Apps are only able to cancel their own bugreports. App A cannot cancel a bugreport started
+     * by app B.
+     *
+     * @throws SecurityException if trying to cancel another app's bugreport in progress
      */
     @RequiresPermission(android.Manifest.permission.DUMP)
     public void cancelBugreport() {
         try {
-            mBinder.cancelBugreport();
+            mBinder.cancelBugreport(-1 /* callingUid */, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index df3c4d5..51856d8 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -50,6 +50,8 @@
     public static final int FLAG_DEFAULT_PRIMARY = 1 << 1;
     public static final int FLAG_SD = 1 << 2;
     public static final int FLAG_USB = 1 << 3;
+    /** The FLAG_STUB_VISIBLE is set from vold, which gets the flag from outside (e.g., ChromeOS) */
+    public static final int FLAG_STUB_VISIBLE = 1 << 6;
 
     public final String id;
     @UnsupportedAppUsage
@@ -152,6 +154,10 @@
         return (flags & FLAG_USB) != 0;
     }
 
+    public boolean isStubVisible() {
+        return (flags & FLAG_STUB_VISIBLE) != 0;
+    }
+
     @Override
     public String toString() {
         final CharArrayWriter writer = new CharArrayWriter();
diff --git a/core/java/android/service/search/OWNERS b/core/java/android/service/search/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/core/java/android/service/search/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index d6ae434..03d3755 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -17,7 +17,10 @@
 package android.telephony;
 
 import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
@@ -29,9 +32,16 @@
 import android.os.HandlerExecutor;
 import android.os.Looper;
 import android.telephony.Annotation.CallState;
+import android.telephony.Annotation.DataActivityType;
+import android.telephony.Annotation.DisconnectCauses;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.PreciseDisconnectCauses;
 import android.telephony.Annotation.RadioPowerState;
 import android.telephony.Annotation.SimActivationState;
 import android.telephony.Annotation.SrvccState;
+import android.telephony.NetworkRegistrationInfo.Domain;
+import android.telephony.TelephonyManager.DataEnabledReason;
+import android.telephony.TelephonyManager.DataState;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 
@@ -40,6 +50,8 @@
 
 import dalvik.system.VMRuntime;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.lang.ref.WeakReference;
 import java.util.List;
 import java.util.Map;
@@ -114,7 +126,9 @@
      *
      *  @see #onServiceStateChanged
      *  @see ServiceState
+     *  @deprecated Use {@link ServiceStateChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_SERVICE_STATE                            = 0x00000001;
 
     /**
@@ -122,8 +136,7 @@
      * {@more}
      *
      * @see #onSignalStrengthChanged
-     *
-     * @deprecated by {@link #LISTEN_SIGNAL_STRENGTHS}
+     * @deprecated Use {@link SignalStrengthsChangedListener} instead.
      */
     @Deprecated
     public static final int LISTEN_SIGNAL_STRENGTH                          = 0x00000002;
@@ -139,7 +152,9 @@
      * voicemail icon.
      *
      * @see #onMessageWaitingIndicatorChanged
+     * @deprecated Use {@link MessageWaitingIndicatorChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_MESSAGE_WAITING_INDICATOR                = 0x00000004;
 
     /**
@@ -150,7 +165,9 @@
      * {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @see #onCallForwardingIndicatorChanged
+     * @deprecated Use {@link CallForwardingIndicatorChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_CALL_FORWARDING_INDICATOR                = 0x00000008;
 
     /**
@@ -166,7 +183,9 @@
      * instead.
      *
      * @see #onCellLocationChanged
+     * @deprecated Use {@link CellLocationChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_CELL_LOCATION                            = 0x00000010;
 
     /**
@@ -174,14 +193,18 @@
      * {@more}
      *
      * @see #onCallStateChanged
+     * @deprecated Use {@link CallStateChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_CALL_STATE                               = 0x00000020;
 
     /**
      * Listen for changes to the data connection state (cellular).
      *
      * @see #onDataConnectionStateChanged
+     * @deprecated Use {@link DataConnectionStateChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_DATA_CONNECTION_STATE                    = 0x00000040;
 
     /**
@@ -192,7 +215,9 @@
      * data-traffic icon.
      *
      * @see #onDataActivity
+     * @deprecated Use {@link DataActivityListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_DATA_ACTIVITY                            = 0x00000080;
 
     /**
@@ -202,7 +227,9 @@
      * icon.
      *
      * @see #onSignalStrengthsChanged
+     * @deprecated Use {@link SignalStrengthsChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
     /**
@@ -212,7 +239,9 @@
      * @see #onSignalStrengthsChanged
      *
      * @hide
+     * @deprecated Use {@link AlwaysReportedSignalStrengthChangedListener} instead.
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
     public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH          = 0x00000200;
 
@@ -223,7 +252,9 @@
      * permission.
      *
      * @see #onCellInfoChanged
+     * @deprecated Use {@link CellInfoChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_CELL_INFO = 0x00000400;
 
     /**
@@ -235,8 +266,10 @@
      * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @hide
+     * @deprecated Use {@link PreciseCallStateChangedListener} instead.
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     @SystemApi
     public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;
 
@@ -248,8 +281,10 @@
      * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @see #onPreciseDataConnectionStateChanged
+     * @deprecated Use {@link PreciseDataConnectionStateChangedListener} instead.
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;
 
     /**
@@ -259,7 +294,7 @@
      * READ_PRECISE_PHONE_STATE}
      * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo)
      *
-     * @deprecated Use {@link TelephonyManager#getModemActivityInfo()}
+     * @deprecated Use {@link TelephonyManager#requestModemActivityInfo} instead.
      * @hide
      */
     @Deprecated
@@ -272,7 +307,9 @@
      *
      * @see #onServiceStateChanged(ServiceState)
      * @hide
+     * @deprecated Use {@link SrvccStateChangedListener} instead.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public static final int LISTEN_SRVCC_STATE_CHANGED                     = 0x00004000;
@@ -290,10 +327,11 @@
     /**
      * Listen for carrier network changes indicated by a carrier app.
      *
-     * @see #onCarrierNetworkRequest
-     * @see TelephonyManager#notifyCarrierNetworkChange(boolean)
+     * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)
      * @hide
+     * @deprecated Use {@link CarrierNetworkChangeListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_CARRIER_NETWORK_CHANGE                   = 0x00010000;
 
     /**
@@ -312,7 +350,9 @@
      *
      * @see #onVoiceActivationStateChanged
      * @hide
+     * @deprecated Use {@link VoiceActivationStateChangedListener} instead.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public static final int LISTEN_VOICE_ACTIVATION_STATE                   = 0x00020000;
@@ -324,20 +364,24 @@
      * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
      * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
      * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
-     * {@more}
+     *
      * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
      * fully activated
      *
      * @see #onDataActivationStateChanged
      * @hide
+     * @deprecated Use {@link DataActivationStateChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_DATA_ACTIVATION_STATE                   = 0x00040000;
 
     /**
      *  Listen for changes to the user mobile data state
      *
      *  @see #onUserMobileDataStateChanged
+     *  @deprecated Use {@link UserMobileDataStateChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_USER_MOBILE_DATA_STATE                  = 0x00080000;
 
     /**
@@ -348,7 +392,9 @@
      *  {@link TelephonyManager#hasCarrierPrivileges}).
      *
      *  @see #onDisplayInfoChanged
+     * @deprecated Use {@link DisplayInfoChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_DISPLAY_INFO_CHANGED = 0x00100000;
 
     /**
@@ -356,7 +402,9 @@
      *
      *  @see #onPhoneCapabilityChanged
      *  @hide
+     *  @deprecated Use {@link PhoneCapabilityChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
 
     /**
@@ -366,17 +414,19 @@
      *  subscription user selected as default data subscription in DSDS mode.
      *
      *  @see #onActiveDataSubscriptionIdChanged
+     *  @deprecated Use {@link ActiveDataSubscriptionIdChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000;
 
     /**
      *  Listen for changes to the radio power state.
      *
-     * <p>Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
-     *
      *  @see #onRadioPowerStateChanged
      *  @hide
+     *  @deprecated Use {@link RadioPowerStateChangedListener} instead.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public static final int LISTEN_RADIO_POWER_STATE_CHANGED               = 0x00800000;
@@ -386,7 +436,10 @@
      *
      * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
      * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @deprecated Use {@link EmergencyNumberListChangedListener} instead.
      */
+    @Deprecated
     public static final int LISTEN_EMERGENCY_NUMBER_LIST                   = 0x01000000;
 
     /**
@@ -397,8 +450,10 @@
      * or the calling app has carrier privileges
      * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
+     * @deprecated Use {@link CallDisconnectCauseChangedListener} instead.
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_CALL_DISCONNECT_CAUSES                  = 0x02000000;
 
     /**
@@ -410,9 +465,11 @@
      *
      * @see #onCallAttributesChanged
      * @hide
+     * @deprecated Use {@link CallAttributesChangedListener} instead.
      */
+    @Deprecated
     @SystemApi
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_CALL_ATTRIBUTES_CHANGED                 = 0x04000000;
 
     /**
@@ -424,18 +481,20 @@
      * (see {@link TelephonyManager#hasCarrierPrivileges}).
      *
      * @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
+     * @deprecated Use {@link ImsCallDisconnectCauseChangedListener} instead.
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES              = 0x08000000;
 
     /**
      * Listen for the emergency number placed from an outgoing call.
      *
-     * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
-     *
      * @see #onOutgoingEmergencyCall
      * @hide
+     * @deprecated Use {@link OutgoingEmergencyCallListener} instead.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     public static final int LISTEN_OUTGOING_EMERGENCY_CALL                  = 0x10000000;
@@ -443,11 +502,11 @@
     /**
      * Listen for the emergency number placed from an outgoing SMS.
      *
-     * <p>Requires permission {@link android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION}
-     *
      * @see #onOutgoingEmergencySms
      * @hide
+     * @deprecated Use {@link OutgoingEmergencySmsListener} instead.
      */
+    @Deprecated
     @SystemApi
     @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
     public static final int LISTEN_OUTGOING_EMERGENCY_SMS                   = 0x20000000;
@@ -466,7 +525,9 @@
      * of whether the calling app has carrier privileges.
      *
      * @see #onRegistrationFailed
+     * @deprecated Use {@link RegistrationFailedListener} instead.
      */
+    @Deprecated
     @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_REGISTRATION_FAILURE = 0x40000000;
 
@@ -480,10 +541,525 @@
      * of whether the calling app has carrier privileges.
      *
      * @see #onBarringInfoChanged
+     * @deprecated Use {@link BarringInfoChangedListener} instead.
      */
+    @Deprecated
     @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
     public static final int LISTEN_BARRING_INFO = 0x80000000;
 
+    /**
+     *  Event for changes to the network service state (cellular).
+     *
+     *  @see ServiceStateChangedListener#onServiceStateChanged
+     *  @see ServiceState
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_SERVICE_STATE_CHANGED = 1;
+
+    /**
+     * Event for changes to the network signal strength (cellular).
+     *
+     * @see SignalStrengthsChangedListener#onSignalStrengthsChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_SIGNAL_STRENGTH_CHANGED = 2;
+
+    /**
+     * Event for changes to the message-waiting indicator.
+     *
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that
+     * the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     * <p>
+     * Example: The status bar uses this to determine when to display the
+     * voicemail icon.
+     *
+     * @see MessageWaitingIndicatorChangedListener#onMessageWaitingIndicatorChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public static final int EVENT_MESSAGE_WAITING_INDICATOR_CHANGED = 3;
+
+    /**
+     * Event for changes to the call-forwarding indicator.
+     *
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE} or that
+     * the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see CallForwardingIndicatorChangedListener#onCallForwardingIndicatorChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public static final int EVENT_CALL_FORWARDING_INDICATOR_CHANGED = 4;
+
+    /**
+     * Event for changes to the device's cell location. Note that
+     * this will result in frequent callbacks to the listener.
+     *
+     * If you need regular location updates but want more control over
+     * the update interval or location precision, you can set up a listener
+     * through the {@link android.location.LocationManager location manager}
+     * instead.
+     *
+     * @see CellLocationChangedListener#onCellLocationChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+    public static final int EVENT_CELL_LOCATION_CHANGED = 5;
+
+    /**
+     * Event for changes to the device call state.
+     *
+     * @see CallStateChangedListener#onCallStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_CALL_LOG)
+    public static final int EVENT_CALL_STATE_CHANGED = 6;
+
+    /**
+     * Event for changes to the data connection state (cellular).
+     *
+     * @see DataConnectionStateChangedListener#onDataConnectionStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_DATA_CONNECTION_STATE_CHANGED = 7;
+
+    /**
+     * Event for changes to the direction of data traffic on the data
+     * connection (cellular).
+     *
+     * Example: The status bar uses this to display the appropriate
+     * data-traffic icon.
+     *
+     * @see DataActivityListener#onDataActivity
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_DATA_ACTIVITY_CHANGED = 8;
+
+    /**
+     * Event for changes to the network signal strengths (cellular).
+     * <p>
+     * Example: The status bar uses this to control the signal-strength
+     * icon.
+     *
+     * @see SignalStrengthsChangedListener#onSignalStrengthsChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_SIGNAL_STRENGTHS_CHANGED = 9;
+
+    /**
+     * Event for changes of the network signal strengths (cellular) always reported from modem,
+     * even in some situations such as the screen of the device is off.
+     *
+     * @see AlwaysReportedSignalStrengthChangedListener#onSignalStrengthsChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
+    public static final int EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED = 10;
+
+    /**
+     * Event for changes to observed cell info.
+     *
+     * @see CellInfoChangedListener#onCellInfoChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+    public static final int EVENT_CELL_INFO_CHANGED = 11;
+
+    /**
+     * Event for {@link android.telephony.Annotation.PreciseCallStates} of ringing,
+     * background and foreground calls.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see PreciseCallStateChangedListener#onPreciseCallStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_PRECISE_CALL_STATE_CHANGED = 12;
+
+    /**
+     * Event for {@link PreciseDataConnectionState} on the data connection (cellular).
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see PreciseDataConnectionStateChangedListener#onPreciseDataConnectionStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED = 13;
+
+    /**
+     * Event for real time info for all data connections (cellular)).
+     *
+     * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo)
+     *
+     * @deprecated Use {@link TelephonyManager#requestModemActivityInfo}
+     * @hide
+     */
+    @Deprecated
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED = 14;
+
+    /**
+     * Event for OEM hook raw event
+     *
+     * @see #onOemHookRawEvent
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int EVENT_OEM_HOOK_RAW = 15;
+
+    /**
+     * Event for changes to the SRVCC state of the active call.
+     *
+     * @see SrvccStateChangedListener#onSrvccStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int EVENT_SRVCC_STATE_CHANGED = 16;
+
+    /**
+     * Event for carrier network changes indicated by a carrier app.
+     *
+     * @see android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)
+     * @see CarrierNetworkChangeListener#onCarrierNetworkChange
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_CARRIER_NETWORK_CHANGED = 17;
+
+    /**
+     * Event for changes to the sim voice activation state
+     *
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+     *
+     * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates voice service has been
+     * fully activated
+     *
+     * @see VoiceActivationStateChangedListener#onVoiceActivationStateChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int EVENT_VOICE_ACTIVATION_STATE_CHANGED = 18;
+
+    /**
+     * Event for changes to the sim data activation state
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATING
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_RESTRICTED
+     * @see TelephonyManager#SIM_ACTIVATION_STATE_UNKNOWN
+     *
+     * Example: TelephonyManager#SIM_ACTIVATION_STATE_ACTIVATED indicates data service has been
+     * fully activated
+     *
+     * @see DataActivationStateChangedListener#onDataActivationStateChanged
+     * @hide
+     */
+    @SystemApi
+    public static final int EVENT_DATA_ACTIVATION_STATE_CHANGED = 19;
+
+    /**
+     *  Event for changes to the user mobile data state
+     *
+     *  @see UserMobileDataStateChangedListener#onUserMobileDataStateChanged
+     *
+     *  @hide
+     */
+    @SystemApi
+    public static final int EVENT_USER_MOBILE_DATA_STATE_CHANGED = 20;
+
+    /**
+     *  Event for display info changed event.
+     *
+     *  @see DisplayInfoChangedListener#onDisplayInfoChanged
+     *
+     *  @hide
+     */
+    @SystemApi
+    public static final int EVENT_DISPLAY_INFO_CHANGED = 21;
+
+    /**
+     *  Event for changes to the phone capability.
+     *
+     *  @see PhoneCapabilityChangedListener#onPhoneCapabilityChanged
+     *
+     *  @hide
+     */
+    @SystemApi
+    public static final int EVENT_PHONE_CAPABILITY_CHANGED = 22;
+
+    /**
+     *  Event for changes to active data subscription ID. Active data subscription is
+     *  the current subscription used to setup Cellular Internet data. For example,
+     *  it could be the current active opportunistic subscription in use, or the
+     *  subscription user selected as default data subscription in DSDS mode.
+     *
+     *  <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
+     *  app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     *  @see ActiveDataSubscriptionIdChangedListener#onActiveDataSubscriptionIdChanged
+     *
+     *  @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public static final int EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED = 23;
+
+    /**
+     *  Event for changes to the radio power state.
+     *
+     *  @see RadioPowerStateChangedListener#onRadioPowerStateChanged
+     *
+     *  @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public static final int EVENT_RADIO_POWER_STATE_CHANGED = 24;
+
+    /**
+     * Event for changes to emergency number list based on all active subscriptions.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PHONE_STATE} or the calling
+     * app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     *  @see EmergencyNumberListChangedListener#onEmergencyNumberListChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    public static final int EVENT_EMERGENCY_NUMBER_LIST_CHANGED = 25;
+
+    /**
+     * Event for call disconnect causes which contains {@link DisconnectCause} and
+     * {@link PreciseDisconnectCause}.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     *  @see CallDisconnectCauseChangedListener#onCallDisconnectCauseChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_CALL_DISCONNECT_CAUSE_CHANGED = 26;
+
+    /**
+     * Event for changes to the call attributes of a currently active call.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see CallAttributesChangedListener#onCallAttributesChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_CALL_ATTRIBUTES_CHANGED = 27;
+
+    /**
+     * Event for IMS call disconnect causes which contains
+     * {@link android.telephony.ims.ImsReasonInfo}
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see ImsCallDisconnectCauseChangedListener#onImsCallDisconnectCauseChanged(ImsReasonInfo)
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = 28;
+
+    /**
+     * Event for the emergency number placed from an outgoing call.
+     *
+     * @see OutgoingEmergencyCallListener#onOutgoingEmergencyCall
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+    public static final int EVENT_OUTGOING_EMERGENCY_CALL = 29;
+
+    /**
+     * Event for the emergency number placed from an outgoing SMS.
+     *
+     * @see OutgoingEmergencySmsListener#onOutgoingEmergencySms
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+    public static final int EVENT_OUTGOING_EMERGENCY_SMS = 30;
+
+    /**
+     * Event for registration failures.
+     *
+     * Event for indications that a registration procedure has failed in either the CS or PS
+     * domain. This indication does not necessarily indicate a change of service state, which should
+     * be tracked via {@link #EVENT_SERVICE_STATE_CHANGED}.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
+     * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless
+     * of whether the calling app has carrier privileges.
+     *
+     * @see RegistrationFailedListener#onRegistrationFailed
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {
+            Manifest.permission.READ_PRECISE_PHONE_STATE,
+            Manifest.permission.ACCESS_FINE_LOCATION
+    })
+    public static final int EVENT_REGISTRATION_FAILURE = 31;
+
+    /**
+     * Event for Barring Information for the current registered / camped cell.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE} or
+     * the calling app has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * <p>Also requires the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission, regardless
+     * of whether the calling app has carrier privileges.
+     *
+     * @see BarringInfoChangedListener#onBarringInfoChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(allOf = {
+            Manifest.permission.READ_PRECISE_PHONE_STATE,
+            Manifest.permission.ACCESS_FINE_LOCATION
+    })
+    public static final int EVENT_BARRING_INFO_CHANGED = 32;
+
+    /**
+     * Event for changes to the physical channel configuration.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see PhysicalChannelConfigChangedListener#onPhysicalChannelConfigChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED = 33;
+
+    /**
+     * Event for changes to the data enabled.
+     *
+     * Event for indications that the enabled status of current data has changed.
+     *
+     * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+     * or the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @see DataEnabledChangedListener#onDataEnabledChanged
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public static final int EVENT_DATA_ENABLED_CHANGED = 34;
+
+    /** @hide */
+    @IntDef(prefix = { "EVENT_" }, value = {
+            EVENT_SERVICE_STATE_CHANGED,
+            EVENT_SIGNAL_STRENGTH_CHANGED,
+            EVENT_MESSAGE_WAITING_INDICATOR_CHANGED,
+            EVENT_CALL_FORWARDING_INDICATOR_CHANGED,
+            EVENT_CELL_LOCATION_CHANGED,
+            EVENT_CALL_STATE_CHANGED,
+            EVENT_DATA_CONNECTION_STATE_CHANGED,
+            EVENT_DATA_ACTIVITY_CHANGED,
+            EVENT_SIGNAL_STRENGTHS_CHANGED,
+            EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED,
+            EVENT_CELL_INFO_CHANGED,
+            EVENT_PRECISE_CALL_STATE_CHANGED,
+            EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED,
+            EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED,
+            EVENT_OEM_HOOK_RAW,
+            EVENT_SRVCC_STATE_CHANGED,
+            EVENT_CARRIER_NETWORK_CHANGED,
+            EVENT_VOICE_ACTIVATION_STATE_CHANGED,
+            EVENT_DATA_ACTIVATION_STATE_CHANGED,
+            EVENT_USER_MOBILE_DATA_STATE_CHANGED,
+            EVENT_DISPLAY_INFO_CHANGED,
+            EVENT_PHONE_CAPABILITY_CHANGED,
+            EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED,
+            EVENT_RADIO_POWER_STATE_CHANGED,
+            EVENT_EMERGENCY_NUMBER_LIST_CHANGED,
+            EVENT_CALL_DISCONNECT_CAUSE_CHANGED,
+            EVENT_CALL_ATTRIBUTES_CHANGED,
+            EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED,
+            EVENT_OUTGOING_EMERGENCY_CALL,
+            EVENT_OUTGOING_EMERGENCY_SMS,
+            EVENT_REGISTRATION_FAILURE,
+            EVENT_BARRING_INFO_CHANGED,
+            EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED,
+            EVENT_DATA_ENABLED_CHANGED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface TelephonyEvent {}
+
     /*
      * Subscription used to listen to the phone state changes
      * @hide
@@ -495,13 +1071,19 @@
     /**
      * @hide
      */
+    //TODO: The maxTargetSdk should be S if the build time tool updates it.
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-    @UnsupportedAppUsage
-    public final IPhoneStateListener callback;
+    @UnsupportedAppUsage(
+            maxTargetSdk = Build.VERSION_CODES.R,
+            publicAlternatives = "Use {@code TelephonyManager#registerPhoneStateListener(" +
+                    "Executor, PhoneStateListener)} instead")
+    public IPhoneStateListener callback;
 
     /**
      * Create a PhoneStateListener for the Phone with the default subscription.
-     * This class requires Looper.myLooper() not return null.
+     * If this is created for use with deprecated API
+     * {@link TelephonyManager#listen(PhoneStateListener, int)}, then this class requires
+     * Looper.myLooper() not return null.
      */
     public PhoneStateListener() {
         this(null, Looper.myLooper());
@@ -539,7 +1121,10 @@
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     public PhoneStateListener(Integer subId, Looper looper) {
-        this(subId, new HandlerExecutor(new Handler(looper)));
+        if (looper != null) {
+            setExecutor(new HandlerExecutor(new Handler(looper)));
+        }
+        mSubId = subId;
         if (subId != null && VMRuntime.getRuntime().getTargetSdkVersion()
                 >= Build.VERSION_CODES.Q) {
             throw new IllegalArgumentException("PhoneStateListener with subId: "
@@ -554,17 +1139,744 @@
      * The Executor must not be null.
      *
      * @param executor a non-null Executor that will execute callbacks for the PhoneStateListener.
+     * @deprecated Use
+     * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)} instead.
      */
+    @Deprecated
     public PhoneStateListener(@NonNull Executor executor) {
-        this(null, executor);
+        setExecutor(executor);
+        mSubId = null;
     }
 
-    private PhoneStateListener(Integer subId, Executor e) {
-        if (e == null) {
+    private @NonNull Executor mExecutor;
+
+    /**
+     * @hide
+     */
+    public void setExecutor(@NonNull @CallbackExecutor Executor executor) {
+        if (executor == null) {
             throw new IllegalArgumentException("PhoneStateListener Executor must be non-null");
         }
-        mSubId = subId;
-        callback = new IPhoneStateListenerStub(this, e);
+        mExecutor = executor;
+        callback = new IPhoneStateListenerStub(this, mExecutor);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean isExecutorSet() {
+        return mExecutor != null;
+    }
+
+    /**
+     * Interface for service state listener.
+     */
+    public interface ServiceStateChangedListener {
+        /**
+         * Callback invoked when device service state changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * The instance of {@link ServiceState} passed as an argument here will have various
+         * levels of location information stripped from it depending on the location permissions
+         * that your app holds.
+         * Only apps holding the {@link Manifest.permission#ACCESS_FINE_LOCATION} permission will
+         * receive all the information in {@link ServiceState}.
+         *
+         * @see ServiceState#STATE_EMERGENCY_ONLY
+         * @see ServiceState#STATE_IN_SERVICE
+         * @see ServiceState#STATE_OUT_OF_SERVICE
+         * @see ServiceState#STATE_POWER_OFF
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onServiceStateChanged(@NonNull ServiceState serviceState);
+    }
+
+    /**
+     * Interface for message waiting indicator listener.
+     */
+    public interface MessageWaitingIndicatorChangedListener {
+        /**
+         * Callback invoked when the message-waiting indicator changes on the registered
+         * subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+        public void onMessageWaitingIndicatorChanged(boolean mwi);
+    }
+
+    /**
+     * Interface for call-forwarding indicator listener.
+     */
+    public interface CallForwardingIndicatorChangedListener {
+        /**
+         * Callback invoked when the call-forwarding indicator changes on the registered
+         * subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+        public void onCallForwardingIndicatorChanged(boolean cfi);
+    }
+
+    /**
+     * Interface for device cell location listener.
+     */
+    public interface CellLocationChangedListener {
+        /**
+         * Callback invoked when device cell location changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+        public void onCellLocationChanged(@NonNull CellLocation location);
+    }
+
+    /**
+     * Interface for call state listener.
+     */
+    public interface CallStateChangedListener {
+        /**
+         * Callback invoked when device call state changes.
+         * <p>
+         * Reports the state of Telephony (mobile) calls on the device for the registered s
+         * ubscription.
+         * <p>
+         * Note: the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to all subIds.
+         * <p>
+         * Note: The state returned here may differ from that returned by
+         * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
+         * calling {@link TelephonyManager#getCallState()} from within this callback may return a
+         * different state than the callback reports.
+         *
+         * @param state call state
+         * @param phoneNumber call phone number. If application does not have
+         * {@link android.Manifest.permission#READ_CALL_LOG} permission or carrier
+         * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be
+         * passed as an argument.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_CALL_LOG)
+        public void onCallStateChanged(@CallState int state, @Nullable String phoneNumber);
+    }
+
+    /**
+     * Interface for data connection state listener.
+     */
+    public interface DataConnectionStateChangedListener {
+        /**
+         * Callback invoked when connection state changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @see TelephonyManager#DATA_DISCONNECTED
+         * @see TelephonyManager#DATA_CONNECTING
+         * @see TelephonyManager#DATA_CONNECTED
+         * @see TelephonyManager#DATA_SUSPENDED
+         *
+         * @param state is the current state of data connection.
+         * @param networkType is the current network type of data connection.
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onDataConnectionStateChanged(@DataState int state,
+                                                 @NetworkType int networkType);
+    }
+
+    /**
+     * Interface for data activity state listener.
+     */
+    public interface DataActivityListener {
+        /**
+         * Callback invoked when data activity state changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @see TelephonyManager#DATA_ACTIVITY_NONE
+         * @see TelephonyManager#DATA_ACTIVITY_IN
+         * @see TelephonyManager#DATA_ACTIVITY_OUT
+         * @see TelephonyManager#DATA_ACTIVITY_INOUT
+         * @see TelephonyManager#DATA_ACTIVITY_DORMANT
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onDataActivity(@DataActivityType int direction);
+    }
+
+    /**
+     * Interface for network signal strengths listener.
+     */
+    public interface SignalStrengthsChangedListener {
+        /**
+         * Callback invoked when network signal strengths changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength);
+    }
+
+    /**
+     * Interface for network signal strengths listener which always reported from modem.
+     */
+    public interface AlwaysReportedSignalStrengthChangedListener {
+        /**
+         * Callback always invoked from modem when network signal strengths changes on the
+         * registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
+        public void onSignalStrengthsChanged(@NonNull SignalStrength signalStrength);
+    }
+
+    /**
+     * Interface for cell info listener.
+     */
+    public interface CellInfoChangedListener {
+        /**
+         * Callback invoked when a observed cell info has changed or new cells have been added
+         * or removed on the registered subscription.
+         * Note, the registration subscription ID s from {@link TelephonyManager} object
+         * which registersPhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param cellInfo is the list of currently visible cells.
+         */
+        @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION)
+        public void onCellInfoChanged(@NonNull List<CellInfo> cellInfo);
+    }
+
+    /**
+     * Interface for precise device call state listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface PreciseCallStateChangedListener {
+        /**
+         * Callback invoked when precise device call state changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param callState {@link PreciseCallState}
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onPreciseCallStateChanged(@NonNull PreciseCallState callState);
+    }
+
+    /**
+     * Interface for call disconnect cause listener.
+     */
+    public interface CallDisconnectCauseChangedListener {
+        /**
+         * Callback invoked when call disconnect cause changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param disconnectCause {@link DisconnectCause}.
+         * @param preciseDisconnectCause {@link PreciseDisconnectCause}.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause,
+                @PreciseDisconnectCauses int preciseDisconnectCause);
+    }
+
+    /**
+     * Interface for IMS call disconnect cause listener.
+     */
+    public interface ImsCallDisconnectCauseChangedListener {
+        /**
+         * Callback invoked when IMS call disconnect cause changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
+         *
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo);
+    }
+
+    /**
+     * Interface for precise data connection state listener.
+     */
+    public interface PreciseDataConnectionStateChangedListener {
+        /**
+         * Callback providing update about the default/internet data connection on the registered
+         * subscription.
+         *
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * <p>Requires permission {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}
+         * or the calling app has carrier privileges
+         * (see {@link TelephonyManager#hasCarrierPrivileges}).
+         *
+         * @param dataConnectionState {@link PreciseDataConnectionState}
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onPreciseDataConnectionStateChanged(
+                @NonNull PreciseDataConnectionState dataConnectionState);
+    }
+
+    /**
+     * Interface for Single Radio Voice Call Continuity listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface SrvccStateChangedListener {
+        /**
+         * Callback invoked when there has been a change in the Single Radio Voice Call Continuity
+         * (SRVCC) state for the currently active call on the registered subscription.
+         *
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         */
+        @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+        public void onSrvccStateChanged(@SrvccState int srvccState);
+    }
+
+    /**
+     * Interface for SIM voice activation state listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface VoiceActivationStateChangedListener {
+        /**
+         * Callback invoked when the SIM voice activation state has changed on the registered
+         * subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param state is the current SIM voice activation state
+         */
+        @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+        public void onVoiceActivationStateChanged(@SimActivationState int state);
+
+    }
+
+    /**
+     * Interface for SIM data activation state listener.
+     */
+    public interface DataActivationStateChangedListener {
+        /**
+         * Callback invoked when the SIM data activation state has changed on the registered
+         * subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param state is the current SIM data activation state
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onDataActivationStateChanged(@SimActivationState int state);
+    }
+
+    /**
+     * Interface for user mobile data state listener.
+     */
+    public interface UserMobileDataStateChangedListener {
+        /**
+         * Callback invoked when the user mobile data state has changed on the registered
+         * subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param enabled indicates whether the current user mobile data state is enabled or
+         *                disabled.
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onUserMobileDataStateChanged(boolean enabled);
+    }
+
+    /**
+     * Interface for display info listener.
+     */
+    public interface DisplayInfoChangedListener {
+        /**
+         * Callback invoked when the display info has changed on the registered subscription.
+         * <p> The {@link TelephonyDisplayInfo} contains status information shown to the user
+         * based on carrier policy.
+         *
+         * @param telephonyDisplayInfo The display information.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+        public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo);
+    }
+
+    /**
+     * Interface for the current emergency number list listener.
+     */
+    public interface EmergencyNumberListChangedListener {
+        /**
+         * Callback invoked when the current emergency number list has changed on the registered
+         * subscription.
+         *
+         * Note, the registered subscription is associated with {@link TelephonyManager} object
+         * on which
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}
+         * was called.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * given subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param emergencyNumberList Map associating all active subscriptions on the device with
+         *                            the list of emergency numbers originating from that
+         *                            subscription.
+         *                            If there are no active subscriptions, the map will contain a
+         *                            single entry with
+         *                            {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} as
+         *                            the key and a list of emergency numbers as the value. If no
+         *                            emergency number information is available, the value will be
+         *                            empty.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+        public void onEmergencyNumberListChanged(
+                @NonNull Map<Integer, List<EmergencyNumber>> emergencyNumberList);
+    }
+
+    /**
+     * Interface for outgoing emergency call listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface OutgoingEmergencyCallListener {
+        /**
+         * Callback invoked when an outgoing call is placed to an emergency number.
+         *
+         * This method will be called when an emergency call is placed on any subscription
+         * (including the no-SIM case), regardless of which subscription this listener was
+         * registered on.
+         *
+         * The default implementation of this method calls
+         * {@link #onOutgoingEmergencyCall(EmergencyNumber)} for backwards compatibility purposes.
+         * Do not call {@code super(...)} from within your implementation unless you want
+         * {@link #onOutgoingEmergencyCall(EmergencyNumber)} to be called as well.
+         *
+         * @param placedEmergencyNumber The {@link EmergencyNumber} the emergency call was
+         *                              placed to.
+         * @param subscriptionId The subscription ID used to place the emergency call. If the
+         *                       emergency call was placed without a valid subscription
+         *                       (e.g. when there are no SIM cards in the device), this will be
+         *                       equal to {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID}.
+         */
+        @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+        public void onOutgoingEmergencyCall(@NonNull EmergencyNumber placedEmergencyNumber,
+                                     int subscriptionId);
+    }
+
+    /**
+     * Interface for outgoing emergency sms listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface OutgoingEmergencySmsListener {
+        /**
+         * Smsback invoked when an outgoing sms is sent to an emergency number.
+         *
+         * This method will be called when an emergency sms is sent on any subscription,
+         * regardless of which subscription this listener was registered on.
+         *
+         * The default implementation of this method calls
+         * {@link #onOutgoingEmergencySms(EmergencyNumber)} for backwards compatibility purposes. Do
+         * not call {@code super(...)} from within your implementation unless you want
+         * {@link #onOutgoingEmergencySms(EmergencyNumber)} to be called as well.
+         *
+         * @param sentEmergencyNumber The {@link EmergencyNumber} the emergency sms was sent to.
+         * @param subscriptionId The subscription ID used to send the emergency sms.
+         */
+        @RequiresPermission(Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION)
+        public void onOutgoingEmergencySms(@NonNull EmergencyNumber sentEmergencyNumber,
+                                    int subscriptionId);
+    }
+
+    /**
+     * Interface for phone capability listener.
+     *
+     */
+    public interface PhoneCapabilityChangedListener {
+        /**
+         * Callback invoked when phone capability changes.
+         * Note, this callback triggers regardless of registered subscription.
+         *
+         * @param capability the new phone capability
+         */
+        @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+        public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability);
+    }
+
+    /**
+     * Interface for active data subscription ID listener.
+     */
+    public interface ActiveDataSubscriptionIdChangedListener {
+        /**
+         * Callback invoked when active data subscription ID changes.
+         * Note, this callback triggers regardless of registered subscription.
+         *
+         * @param subId current subscription used to setup Cellular Internet data.
+         *              For example, it could be the current active opportunistic subscription
+         *              in use, or the subscription user selected as default data subscription in
+         *              DSDS mode.
+         */
+        @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+        public void onActiveDataSubscriptionIdChanged(int subId);
+    }
+
+    /**
+     * Interface for modem radio power state listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface RadioPowerStateChangedListener {
+        /**
+         * Callback invoked when modem radio power state changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param state the modem radio power state
+         */
+        @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+        public void onRadioPowerStateChanged(@RadioPowerState int state);
+    }
+
+    /**
+     * Interface for carrier network listener.
+     */
+    public interface CarrierNetworkChangeListener {
+        /**
+         * Callback invoked when telephony has received notice from a carrier
+         * app that a network action that could result in connectivity loss
+         * has been requested by an app using
+         * {@link android.service.carrier.CarrierService#notifyCarrierNetworkChange(boolean)}
+         *
+         * This is optional and is only used to allow the system to provide alternative UI while
+         * telephony is performing an action that may result in intentional, temporary network
+         * lack of connectivity.
+         *
+         * Note, this callback is pinned to the registered subscription and will be invoked when
+         * the notifying carrier app has carrier privilege rule on the registered
+         * subscription. {@link android.telephony.TelephonyManager#hasCarrierPrivileges}
+         *
+         * @param active If the carrier network change is or shortly will be active,
+         *               {@code true} indicate that showing alternative UI, {@code false} otherwise.
+         */
+        public void onCarrierNetworkChange(boolean active);
+    }
+
+    /**
+     * Interface for registration failures listener.
+     */
+    public interface RegistrationFailedListener {
+        /**
+         * Report that Registration or a Location/Routing/Tracking Area update has failed.
+         *
+         * <p>Indicate whenever a registration procedure, including a location, routing, or tracking
+         * area update fails. This includes procedures that do not necessarily result in a change of
+         * the modem's registration status. If the modem's registration status changes, that is
+         * reflected in the onNetworkStateChanged() and subsequent
+         * get{Voice/Data}RegistrationState().
+         *
+         * <p>Because registration failures are ephemeral, this callback is not sticky.
+         * Registrants will not receive the most recent past value when registering.
+         *
+         * @param cellIdentity the CellIdentity, which must include the globally unique identifier
+         *        for the cell (for example, all components of the CGI or ECGI).
+         * @param chosenPlmn a 5 or 6 digit alphanumeric PLMN (MCC|MNC) among those broadcast by the
+         *         cell that was chosen for the failed registration attempt.
+         * @param domain DOMAIN_CS, DOMAIN_PS or both in case of a combined procedure.
+         * @param causeCode the primary failure cause code of the procedure.
+         *        For GSM/UMTS (MM), values are in TS 24.008 Sec 10.5.95
+         *        For GSM/UMTS (GMM), values are in TS 24.008 Sec 10.5.147
+         *        For LTE (EMM), cause codes are TS 24.301 Sec 9.9.3.9
+         *        For NR (5GMM), cause codes are TS 24.501 Sec 9.11.3.2
+         *        Integer.MAX_VALUE if this value is unused.
+         * @param additionalCauseCode the cause code of any secondary/combined procedure
+         *                            if appropriate. For UMTS, if a combined attach succeeds for
+         *                            PS only, then the GMM cause code shall be included as an
+         *                            additionalCauseCode. For LTE (ESM), cause codes are in
+         *                            TS 24.301 9.9.4.4. Integer.MAX_VALUE if this value is unused.
+         */
+        @RequiresPermission(allOf = {
+                Manifest.permission.READ_PRECISE_PHONE_STATE,
+                Manifest.permission.ACCESS_FINE_LOCATION
+        })
+        public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
+                                         @NonNull String chosenPlmn, @Domain int domain,
+                                         int causeCode, int additionalCauseCode);
+    }
+
+    /**
+     * Interface for call attributes listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface CallAttributesChangedListener {
+        /**
+         * Callback invoked when the call attributes changes on the registered subscription.
+         * Note, the registration subscription ID comes from {@link TelephonyManager} object
+         * which registers PhoneStateListener by
+         * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
+         * If this TelephonyManager object was created with
+         * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+         * subscription ID. Otherwise, this callback applies to
+         * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+         *
+         * @param callAttributes the call attributes
+         */
+        @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+        void onCallAttributesChanged(@NonNull CallAttributes callAttributes);
+    }
+
+    /**
+     * Interface for barring information listener.
+     */
+    public interface BarringInfoChangedListener {
+        /**
+         * Report updated barring information for the current camped/registered cell.
+         *
+         * <p>Barring info is provided for all services applicable to the current camped/registered
+         * cell, for the registered PLMN and current access class/access category.
+         *
+         * @param barringInfo for all services on the current cell.
+         * @see android.telephony.BarringInfo
+         */
+        @RequiresPermission(allOf = {
+                Manifest.permission.READ_PRECISE_PHONE_STATE,
+                Manifest.permission.ACCESS_FINE_LOCATION
+        })
+        public void onBarringInfoChanged(@NonNull BarringInfo barringInfo);
+    }
+
+    /**
+     * Interface for current physical channel configuration listener.
+     * @hide
+     */
+    @SystemApi
+    public interface PhysicalChannelConfigChangedListener {
+        /**
+         * Callback invoked when the current physical channel configuration has changed
+         *
+         * @param configs List of the current {@link PhysicalChannelConfig}s
+         */
+        @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onPhysicalChannelConfigChanged(@NonNull List<PhysicalChannelConfig> configs);
+    }
+
+    /**
+     * Interface for data enabled listener.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface DataEnabledChangedListener {
+        /**
+         * Callback invoked when the data enabled changes.
+         *
+         * @param enabled {@code true} if data is enabled, otherwise disabled.
+         * @param reason Reason for data enabled/disabled.
+         *               See {@link TelephonyManager.DataEnabledReason}.
+         */
+        @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+        public void onDataEnabledChanged(boolean enabled,
+                                  @DataEnabledReason int reason);
     }
 
     /**
@@ -658,8 +1970,7 @@
      * 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()}.
+     * subId. Otherwise, this callback applies to all subIds.
      * <p>
      * Note: The state returned here may differ from that returned by
      * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
@@ -698,6 +2009,7 @@
      * same as above, but with the network type.  Both called.
      */
     public void onDataConnectionStateChanged(int state, int networkType) {
+        // default implementation empty
     }
 
     /**
@@ -745,6 +2057,7 @@
      * @param cellInfo is the list of currently visible cells.
      */
     public void onCellInfoChanged(List<CellInfo> cellInfo) {
+        // default implementation empty
     }
 
     /**
@@ -758,7 +2071,7 @@
      * @param callState {@link PreciseCallState}
      * @hide
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     @SystemApi
     public void onPreciseCallStateChanged(@NonNull PreciseCallState callState) {
         // default implementation empty
@@ -777,9 +2090,9 @@
      * @param preciseDisconnectCause {@link PreciseDisconnectCause}.
      *
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
-    public void onCallDisconnectCauseChanged(@Annotation.DisconnectCauses int disconnectCause,
-            int preciseDisconnectCause) {
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
+    public void onCallDisconnectCauseChanged(@DisconnectCauses int disconnectCause,
+            @PreciseDisconnectCauses int preciseDisconnectCause) {
         // default implementation empty
     }
 
@@ -795,7 +2108,7 @@
      * @param imsReasonInfo {@link ImsReasonInfo} contains details on why IMS call failed.
      *
      */
-    @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
+    @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE)
     public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
         // default implementation empty
     }
@@ -817,7 +2130,7 @@
      *
      * @param dataConnectionState {@link PreciseDataConnectionState}
      */
-    @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE))
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void onPreciseDataConnectionStateChanged(
             @NonNull PreciseDataConnectionState dataConnectionState) {
         // default implementation empty
@@ -855,6 +2168,7 @@
      */
     @SystemApi
     public void onSrvccStateChanged(@SrvccState int srvccState) {
+        // default implementation empty
 
     }
 
@@ -873,6 +2187,7 @@
      */
     @SystemApi
     public void onVoiceActivationStateChanged(@SimActivationState int state) {
+        // default implementation empty
     }
 
     /**
@@ -889,6 +2204,7 @@
      * @hide
      */
     public void onDataActivationStateChanged(@SimActivationState int state) {
+        // default implementation empty
     }
 
     /**
@@ -916,7 +2232,7 @@
      *
      * @param telephonyDisplayInfo The display information.
      */
-    @RequiresPermission((android.Manifest.permission.READ_PHONE_STATE))
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public void onDisplayInfoChanged(@NonNull TelephonyDisplayInfo telephonyDisplayInfo) {
         // default implementation empty
     }
@@ -1030,7 +2346,8 @@
     /**
      * Callback invoked when OEM hook raw event is received on the registered subscription.
      * Note, the registration subId comes from {@link TelephonyManager} object which registers
-     * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}.
+     * PhoneStateListener by
+     * {@link TelephonyManager#registerPhoneStateListener(Executor, PhoneStateListener)}.
      * If this TelephonyManager object was created with
      * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
      * subId. Otherwise, this callback applies to
@@ -1052,7 +2369,7 @@
      * @param capability the new phone capability
      * @hide
      */
-    public void onPhoneCapabilityChanged(PhoneCapability capability) {
+    public void onPhoneCapabilityChanged(@NonNull PhoneCapability capability) {
         // default implementation empty
     }
 
@@ -1096,7 +2413,8 @@
      * subId. Otherwise, this callback applies to
      * {@link SubscriptionManager#getDefaultSubscriptionId()}.
      *
-     * @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE}
+     * Requires permission {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
+     *
      * @param state the modem radio power state
      * @hide
      */
@@ -1453,18 +2771,16 @@
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(
                             () -> psl.onImsCallDisconnectCauseChanged(disconnectCause)));
-
         }
 
         public void onRegistrationFailed(@NonNull CellIdentity cellIdentity,
-                @NonNull String chosenPlmn, int domain,
-                int causeCode, int additionalCauseCode) {
+                @NonNull String chosenPlmn, int domain, int causeCode, int additionalCauseCode) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
 
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(() -> psl.onRegistrationFailed(
-                            cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
+                                cellIdentity, chosenPlmn, domain, causeCode, additionalCauseCode)));
             // default implementation empty
         }
 
@@ -1475,8 +2791,27 @@
             Binder.withCleanCallingIdentity(
                     () -> mExecutor.execute(() -> psl.onBarringInfoChanged(barringInfo)));
         }
-    }
 
+        public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) {
+            PhysicalChannelConfigChangedListener listener =
+                    (PhysicalChannelConfigChangedListener) mPhoneStateListenerWeakRef.get();
+            if (listener == null) return;
+
+            Binder.withCleanCallingIdentity(
+                    () -> mExecutor.execute(() -> listener.onPhysicalChannelConfigChanged(
+                            configs)));
+        }
+
+        public void onDataEnabledChanged(boolean enabled, @DataEnabledReason int reason) {
+                DataEnabledChangedListener listener =
+                        (DataEnabledChangedListener) mPhoneStateListenerWeakRef.get();
+                if (listener == null) return;
+
+                Binder.withCleanCallingIdentity(
+                        () -> mExecutor.execute(() -> listener.onDataEnabledChanged(
+                                enabled, reason)));
+        }
+    }
 
     private void log(String s) {
         Rlog.d(LOG_TAG, s);
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index 3673ae7..a9548b0 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -15,6 +15,7 @@
  */
 package android.telephony;
 
+import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -24,6 +25,9 @@
 import android.content.Context;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.telephony.Annotation.CallState;
@@ -37,6 +41,7 @@
 import android.telephony.Annotation.SrvccState;
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
+import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
@@ -45,6 +50,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -206,7 +212,7 @@
     }
 
     /**
-     * To check the SDK version for {@link #listenForSubscriber}.
+     * To check the SDK version for {@link #listenWithEventList}.
      */
     @ChangeId
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
@@ -218,23 +224,23 @@
      * @param pkg Package name
      * @param featureId Feature ID
      * @param listener Listener providing callback
-     * @param events Events
+     * @param events List events
      * @param notifyNow Whether to notify instantly
      */
-    public void listenForSubscriber(int subId, @NonNull String pkg, @NonNull String featureId,
-            @NonNull PhoneStateListener listener, int events, boolean notifyNow) {
+    public void listenWithEventList(int subId, @NonNull String pkg, @NonNull String featureId,
+            @NonNull PhoneStateListener listener, @NonNull int[] events, boolean notifyNow) {
         try {
             // subId from PhoneStateListener is deprecated Q on forward, use the subId from
             // TelephonyManager instance. Keep using subId from PhoneStateListener for pre-Q.
             if (Compatibility.isChangeEnabled(LISTEN_CODE_CHANGE)) {
                 // Since mSubId in PhoneStateListener is deprecated from Q on forward, this is
                 // the only place to set mSubId and its for "informational" only.
-                listener.mSubId = (events == PhoneStateListener.LISTEN_NONE)
+                listener.mSubId = (events.length == 0)
                         ? SubscriptionManager.INVALID_SUBSCRIPTION_ID : subId;
             } else if (listener.mSubId != null) {
                 subId = listener.mSubId;
             }
-            sRegistry.listenForSubscriber(
+            sRegistry.listenWithEventList(
                     subId, pkg, featureId, listener.callback, events, notifyNow);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
@@ -765,4 +771,366 @@
         }
     }
 
+    /**
+     * Notify {@link PhysicalChannelConfig} has changed for a specific subscription.
+     *
+     * @param subId the subId
+     * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
+     */
+    public void notifyPhysicalChannelConfigForSubscriber(
+            int subId, List<PhysicalChannelConfig> configs) {
+        try {
+            sRegistry.notifyPhysicalChannelConfigForSubscriber(subId, configs);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    /**
+     * Notify that the data enabled has changed.
+     *
+     * @param enabled True if data is enabled, otherwise disabled.
+     * @param reason Reason for data enabled/disabled. See {@code REASON_*} in
+     * {@link TelephonyManager}.
+     */
+    public void notifyDataEnabled(boolean enabled, @TelephonyManager.DataEnabledReason int reason) {
+        try {
+            sRegistry.notifyDataEnabled(enabled, reason);
+        } catch (RemoteException ex) {
+            // system server crash
+        }
+    }
+
+    public @NonNull Set<Integer> getEventsFromListener(@NonNull PhoneStateListener listener) {
+
+        Set<Integer> eventList = new ArraySet<>();
+
+        if (listener instanceof PhoneStateListener.ServiceStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.MessageWaitingIndicatorChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CallForwardingIndicatorChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CellLocationChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CallStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.DataConnectionStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.DataActivityListener) {
+            eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.SignalStrengthsChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.AlwaysReportedSignalStrengthChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CellInfoChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.PreciseCallStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CallDisconnectCauseChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.ImsCallDisconnectCauseChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.PreciseDataConnectionStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.SrvccStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.VoiceActivationStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.DataActivationStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.UserMobileDataStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.DisplayInfoChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.EmergencyNumberListChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.OutgoingEmergencyCallListener) {
+            eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL);
+        }
+
+        if (listener instanceof PhoneStateListener.OutgoingEmergencySmsListener) {
+            eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
+        }
+
+        if (listener instanceof PhoneStateListener.PhoneCapabilityChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.ActiveDataSubscriptionIdChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.RadioPowerStateChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.CarrierNetworkChangeListener) {
+            eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.RegistrationFailedListener) {
+            eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
+        }
+
+        if (listener instanceof PhoneStateListener.CallAttributesChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.BarringInfoChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.PhysicalChannelConfigChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
+        }
+
+        if (listener instanceof PhoneStateListener.DataEnabledChangedListener) {
+            eventList.add(PhoneStateListener.EVENT_DATA_ENABLED_CHANGED);
+        }
+
+        return eventList;
+    }
+
+    private @NonNull Set<Integer> getEventsFromBitmask(int eventMask) {
+
+        Set<Integer> eventList = new ArraySet<>();
+
+        if ((eventMask & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
+            eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
+            eventList.add(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CALL_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
+            eventList.add(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
+            eventList.add(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
+            eventList.add(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CELL_INFO_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
+            eventList.add(PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
+            eventList.add(PhoneStateListener.EVENT_OEM_HOOK_RAW);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
+            eventList.add(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
+            eventList.add(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
+            eventList.add(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
+            eventList.add(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
+            eventList.add(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
+            eventList.add(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL) != 0) {
+            eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS) != 0) {
+            eventList.add(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_REGISTRATION_FAILURE) != 0) {
+            eventList.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
+        }
+
+        if ((eventMask & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
+            eventList.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
+        }
+        return eventList;
+
+    }
+
+    /**
+     * Registers a listener object to receive notification of changes
+     * in specified telephony states.
+     * <p>
+     * To register a listener, pass a {@link PhoneStateListener} which implements
+     * interfaces of events. For example,
+     * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements
+     * {@link PhoneStateListener.ServiceStateChangedListener}.
+     *
+     * At registration, and when a specified telephony state changes, the telephony manager invokes
+     * the appropriate callback method on the listener object and passes the current (updated)
+     * values.
+     * <p>
+     *
+     * If this TelephonyManager object has been created with
+     * {@link TelephonyManager#createForSubscriptionId}, applies to the given subId.
+     * Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}.
+     * To listen events for multiple subIds, pass a separate listener object to
+     * each TelephonyManager object created with {@link TelephonyManager#createForSubscriptionId}.
+     *
+     * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
+     * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
+     * {@link SecurityException} will be thrown otherwise.
+     *
+     * This API should be used sparingly -- large numbers of listeners will cause system
+     * instability. If a process has registered too many listeners without unregistering them, it
+     * may encounter an {@link IllegalStateException} when trying to register more listeners.
+     *
+     * @param listener The {@link PhoneStateListener} object to register.
+     */
+    public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, int subId,
+            String pkgName, String attributionTag, @NonNull PhoneStateListener listener,
+            boolean notifyNow) {
+        listener.setExecutor(executor);
+        registerPhoneStateListener(subId, pkgName, attributionTag, listener,
+                getEventsFromListener(listener), notifyNow);
+    }
+
+    public void registerPhoneStateListenerWithEvents(int subId, String pkgName,
+            String attributionTag, @NonNull PhoneStateListener listener, int events,
+            boolean notifyNow) {
+        registerPhoneStateListener(
+                subId, pkgName, attributionTag, listener, getEventsFromBitmask(events), notifyNow);
+    }
+
+    private void registerPhoneStateListener(int subId,
+            String pkgName, String attributionTag, @NonNull PhoneStateListener listener,
+            @NonNull Set<Integer> events, boolean notifyNow) {
+        if (listener == null) {
+            throw new IllegalStateException("telephony service is null.");
+        }
+
+        listenWithEventList(subId, pkgName, attributionTag, listener,
+                events.stream().mapToInt(i -> i).toArray(), notifyNow);
+    }
+
+    /**
+     * Unregister an existing {@link PhoneStateListener}.
+     *
+     * @param listener The {@link PhoneStateListener} object to unregister.
+     */
+    public void unregisterPhoneStateListener(int subId, String pkgName, String attributionTag,
+                                             @NonNull PhoneStateListener listener,
+                                             boolean notifyNow) {
+        listenWithEventList(subId, pkgName, attributionTag, listener, new int[0], notifyNow);
+    }
 }
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 17d3ae4..471f2c2 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -24,11 +24,12 @@
 import android.icu.text.MeasureFormat;
 import android.icu.util.Measure;
 import android.icu.util.MeasureUnit;
-import android.net.NetworkUtils;
 import android.text.BidiFormatter;
 import android.text.TextUtils;
 import android.view.View;
 
+import com.android.net.module.util.Inet4AddressUtils;
+
 import java.util.Locale;
 
 /**
@@ -207,7 +208,7 @@
      */
     @Deprecated
     public static String formatIpAddress(int ipv4Address) {
-        return NetworkUtils.intToInetAddress(ipv4Address).getHostAddress();
+        return Inet4AddressUtils.intToInet4AddressHTL(ipv4Address).getHostAddress();
     }
 
     private static final int SECONDS_PER_MINUTE = 60;
diff --git a/core/java/android/view/textclassifier/OWNERS b/core/java/android/view/textclassifier/OWNERS
index ac80d9f..4bcdeea 100644
--- a/core/java/android/view/textclassifier/OWNERS
+++ b/core/java/android/view/textclassifier/OWNERS
@@ -6,3 +6,5 @@
 svetoslavganov@google.com
 augale@google.com
 joannechung@google.com
+tonymak@google.com
+licha@google.com
diff --git a/core/java/com/android/internal/net/VpnConfig.java b/core/java/com/android/internal/net/VpnConfig.java
index c0648ab..2e7629a 100644
--- a/core/java/com/android/internal/net/VpnConfig.java
+++ b/core/java/com/android/internal/net/VpnConfig.java
@@ -129,7 +129,7 @@
         String[] routes = routesStr.trim().split(" ");
         for (String route : routes) {
             //each route is ip/prefix
-            RouteInfo info = new RouteInfo(new IpPrefix(route), null);
+            RouteInfo info = new RouteInfo(new IpPrefix(route), null, null, RouteInfo.RTN_UNICAST);
             this.routes.add(info);
             updateAllowedFamilies(info.getDestination().getAddress());
         }
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index d2dc7c2..854fb17 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -23,6 +23,7 @@
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.TelephonyDisplayInfo;
 import android.telephony.PhoneCapability;
+import android.telephony.PhysicalChannelConfig;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 import android.telephony.ServiceState;
@@ -68,4 +69,6 @@
     void onRegistrationFailed(in CellIdentity cellIdentity,
              String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
     void onBarringInfoChanged(in BarringInfo barringInfo);
+    void onPhysicalChannelConfigChanged(in List<PhysicalChannelConfig> configs);
+    void onDataEnabledChanged(boolean enabled, int reason);
 }
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 5f2dcc3..2a73dac 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -41,16 +41,8 @@
             IOnSubscriptionsChangedListener callback);
     void removeOnSubscriptionsChangedListener(String pkg,
             IOnSubscriptionsChangedListener callback);
-    /**
-      * @deprecated Use {@link #listenWithFeature(String, String, IPhoneStateListener, int,
-      * boolean) instead
-      */
-    @UnsupportedAppUsage
-    void listen(String pkg, IPhoneStateListener callback, int events, boolean notifyNow);
-    void listenWithFeature(String pkg, String featureId, IPhoneStateListener callback, int events,
-            boolean notifyNow);
-    void listenForSubscriber(in int subId, String pkg, String featureId,
-            IPhoneStateListener callback, int events, boolean notifyNow);
+    void listenWithEventList(in int subId, String pkg, String featureId,
+            IPhoneStateListener callback, in int[] events, boolean notifyNow);
     @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
     void notifyCallStateForAllSubs(int state, String incomingNumber);
     void notifyCallState(in int phoneId, in int subId, int state, String incomingNumber);
@@ -99,4 +91,7 @@
     void notifyRegistrationFailed(int slotIndex, int subId, in CellIdentity cellIdentity,
             String chosenPlmn, int domain, int causeCode, int additionalCauseCode);
     void notifyBarringInfoChanged(int slotIndex, int subId, in BarringInfo barringInfo);
+    void notifyPhysicalChannelConfigForSubscriber(in int subId,
+            in List<PhysicalChannelConfig> configs);
+    void notifyDataEnabled(boolean enabled, int reason);
 }
diff --git a/core/java/com/android/internal/util/LocationPermissionChecker.java b/core/java/com/android/internal/util/LocationPermissionChecker.java
index cd8fc35..c583d5a 100644
--- a/core/java/com/android/internal/util/LocationPermissionChecker.java
+++ b/core/java/com/android/internal/util/LocationPermissionChecker.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.location.LocationManager;
+import android.net.NetworkStack;
 import android.os.Binder;
 import android.os.Build;
 import android.os.UserHandle;
@@ -147,6 +148,13 @@
             int uid, @Nullable String message) {
         checkPackage(uid, pkgName);
 
+        // Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK
+        // are granted a bypass.
+        if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid)
+                || checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) {
+            return SUCCEEDED;
+        }
+
         // Location mode must be enabled
         if (!isLocationModeEnabled()) {
             return ERROR_LOCATION_MODE_OFF;
@@ -259,4 +267,37 @@
         // We don't care about pid, pass in -1
         return mContext.checkPermission(permissionType, -1, uid);
     }
+
+    /**
+     * Returns true if the |uid| holds NETWORK_SETTINGS permission.
+     */
+    public boolean checkNetworkSettingsPermission(int uid) {
+        return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission.
+     */
+    public boolean checkNetworkSetupWizardPermission(int uid) {
+        return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * Returns true if the |uid| holds NETWORK_STACK permission.
+     */
+    public boolean checkNetworkStackPermission(int uid) {
+        return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
+     * Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission.
+     */
+    public boolean checkMainlineNetworkStackPermission(int uid) {
+        return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
 }
diff --git a/core/java/com/android/internal/widget/OWNERS b/core/java/com/android/internal/widget/OWNERS
index cca39ea..ae566c3 100644
--- a/core/java/com/android/internal/widget/OWNERS
+++ b/core/java/com/android/internal/widget/OWNERS
@@ -1 +1,7 @@
 per-file PointerLocationView.java = michaelwr@google.com, svv@google.com
+
+# LockSettings related
+per-file *LockPattern* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockScreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *Lockscreen* = file:/services/core/java/com/android/server/locksettings/OWNERS
+per-file *LockSettings* = file:/services/core/java/com/android/server/locksettings/OWNERS
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 22dd765..dc98aaf 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -1810,7 +1810,7 @@
       heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
       break;
   }
-  android_mallopt(M_SET_HEAP_TAGGING_LEVEL, &heap_tagging_level, sizeof(heap_tagging_level));
+  mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, heap_tagging_level);
   // Now that we've used the flag, clear it so that we don't pass unknown flags to the ART runtime.
   runtime_flags &= ~RuntimeFlags::MEMORY_TAG_LEVEL_MASK;
 
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2f1bcdc..4b3d82a 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -8968,6 +8968,11 @@
              changed at runtime by calling
              {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}. -->
         <attr name="tunerCount" format="integer" />
+        <!-- Attribute whether the TV input service can pause recording programs.
+             This value can be changed at runtime by calling
+             {@link android.media.tv.TvInputManager#updateTvInputInfo(android.media.tv.TvInputInfo)}
+             . -->
+        <attr name="canPauseRecording" format="boolean" />
     </declare-styleable>
 
     <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e00aff1..a0be068 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3043,6 +3043,7 @@
        =============================================================== -->
 
   <public-group type="attr" first-id="0x01010617">
+    <public name="canPauseRecording" />
     <!-- attribute definitions go here -->
   </public-group>
 
diff --git a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
index f9e3bc6..222471a 100644
--- a/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
+++ b/core/tests/bugreports/src/com/android/os/bugreports/tests/BugreportManagerTest.java
@@ -23,7 +23,10 @@
 import static org.junit.Assert.fail;
 
 import android.Manifest;
+import android.content.BroadcastReceiver;
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.BugreportManager;
 import android.os.BugreportManager.BugreportCallback;
 import android.os.BugreportParams;
@@ -31,7 +34,9 @@
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.StrictMode;
+import android.text.TextUtils;
 import android.util.Log;
 
 import androidx.annotation.NonNull;
@@ -53,10 +58,11 @@
 import org.junit.runners.JUnit4;
 
 import java.io.File;
+import java.io.IOException;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
 
-
 /**
  * Tests for BugreportManager API.
  */
@@ -67,8 +73,16 @@
 
     private static final String TAG = "BugreportManagerTest";
     private static final long BUGREPORT_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(10);
+    private static final long DUMPSTATE_STARTUP_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
     private static final long UIAUTOMATOR_TIMEOUT_MS = TimeUnit.SECONDS.toMillis(10);
 
+    // Sent by Shell when its bugreport finishes (contains final bugreport/screenshot file name
+    // associated with the bugreport).
+    private static final String INTENT_BUGREPORT_FINISHED =
+            "com.android.internal.intent.action.BUGREPORT_FINISHED";
+    private static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT";
+    private static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT";
+
     private Handler mHandler;
     private Executor mExecutor;
     private BugreportManager mBrm;
@@ -212,6 +226,48 @@
     }
 
     @Test
+    public void cancelBugreport_noReportStarted() throws Exception {
+        // Without the native DumpstateService running, we don't get a SecurityException.
+        mBrm.cancelBugreport();
+    }
+
+    @LargeTest
+    @Test
+    public void cancelBugreport_fromDifferentUid() throws Exception {
+        assertThat(Process.myUid()).isNotEqualTo(Process.SHELL_UID);
+
+        // Start a bugreport through ActivityManager's shell command - this starts a BR from the
+        // shell UID rather than our own.
+        BugreportBroadcastReceiver br = new BugreportBroadcastReceiver();
+        InstrumentationRegistry.getContext()
+                .registerReceiver(br, new IntentFilter(INTENT_BUGREPORT_FINISHED));
+        UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+                .executeShellCommand("am bug-report");
+
+        // The command triggers the report through a broadcast, so wait until dumpstate actually
+        // starts up, which may take a bit.
+        waitTillDumpstateRunningOrTimeout();
+
+        try {
+            mBrm.cancelBugreport();
+            fail("Expected cancelBugreport to throw SecurityException when report started by "
+                    + "different UID");
+        } catch (SecurityException expected) {
+        } finally {
+            // Do this in the finally block so that even if this test case fails, we don't break
+            // other test cases unexpectedly due to the still-running shell report.
+            try {
+                // The shell's BR is still running and should complete successfully.
+                br.waitForBugreportFinished();
+            } finally {
+                // The latch may fail for a number of reasons but we still need to unregister the
+                // BroadcastReceiver.
+                InstrumentationRegistry.getContext().unregisterReceiver(br);
+            }
+        }
+    }
+
+    @Test
     public void insufficientPermissions_throwsException() throws Exception {
         dropPermissions();
 
@@ -346,6 +402,28 @@
                 .adoptShellPermissionIdentity(Manifest.permission.DUMP);
     }
 
+    private static boolean isDumpstateRunning() {
+        String[] output;
+        try {
+            output =
+                    UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+                            .executeShellCommand("ps -A -o NAME | grep dumpstate")
+                            .trim()
+                            .split("\n");
+        } catch (IOException e) {
+            Log.w(TAG, "Failed to check if dumpstate is running", e);
+            return false;
+        }
+        for (String line : output) {
+            // Check for an exact match since there may be other things that contain "dumpstate" as
+            // a substring (e.g. the dumpstate HAL).
+            if (TextUtils.equals("dumpstate", line)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     private static void assertFdIsClosed(ParcelFileDescriptor pfd) {
         try {
             int fd = pfd.getFd();
@@ -364,18 +442,25 @@
         return System.currentTimeMillis();
     }
 
-    private static boolean shouldTimeout(long startTimeMs) {
-        return now() - startTimeMs >= BUGREPORT_TIMEOUT_MS;
+    private static void waitTillDumpstateRunningOrTimeout() throws Exception {
+        long startTimeMs = now();
+        while (!isDumpstateRunning()) {
+            Thread.sleep(500 /* .5s */);
+            if (now() - startTimeMs >= DUMPSTATE_STARTUP_TIMEOUT_MS) {
+                break;
+            }
+            Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms for dumpstate to start");
+        }
     }
 
     private static void waitTillDoneOrTimeout(BugreportCallbackImpl callback) throws Exception {
         long startTimeMs = now();
         while (!callback.isDone()) {
             Thread.sleep(1000 /* 1s */);
-            if (shouldTimeout(startTimeMs)) {
+            if (now() - startTimeMs >= BUGREPORT_TIMEOUT_MS) {
                 break;
             }
-            Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms");
+            Log.d(TAG, "Waited " + (now() - startTimeMs) + "ms for bugreport to finish");
         }
     }
 
@@ -450,6 +535,36 @@
         assertTrue(device.wait(Until.gone(consentTitleObj), UIAUTOMATOR_TIMEOUT_MS));
     }
 
+    private class BugreportBroadcastReceiver extends BroadcastReceiver {
+        Intent mBugreportFinishedIntent = null;
+        final CountDownLatch mLatch;
+
+        BugreportBroadcastReceiver() {
+            mLatch = new CountDownLatch(1);
+        }
+
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            setBugreportFinishedIntent(intent);
+            mLatch.countDown();
+        }
+
+        private void setBugreportFinishedIntent(Intent intent) {
+            mBugreportFinishedIntent = intent;
+        }
+
+        public Intent getBugreportFinishedIntent() {
+            return mBugreportFinishedIntent;
+        }
+
+        public void waitForBugreportFinished() throws Exception {
+            if (!mLatch.await(BUGREPORT_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+                throw new Exception("Failed to receive BUGREPORT_FINISHED in "
+                        + BUGREPORT_TIMEOUT_MS + " ms.");
+            }
+        }
+    }
+
     /**
      * A rule to change strict mode vm policy temporarily till test method finished.
      *
diff --git a/core/tests/coretests/src/android/view/autofill/OWNERS b/core/tests/coretests/src/android/view/autofill/OWNERS
new file mode 100644
index 0000000..9a30e82
--- /dev/null
+++ b/core/tests/coretests/src/android/view/autofill/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 351486
+
+include /core/java/android/view/autofill/OWNERS
diff --git a/core/tests/coretests/src/android/view/contentcapture/OWNERS b/core/tests/coretests/src/android/view/contentcapture/OWNERS
new file mode 100644
index 0000000..24561c5
--- /dev/null
+++ b/core/tests/coretests/src/android/view/contentcapture/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 544200
+
+include /core/java/android/view/contentcapture/OWNERS
diff --git a/core/tests/coretests/src/android/view/textclassifier/OWNERS b/core/tests/coretests/src/android/view/textclassifier/OWNERS
new file mode 100644
index 0000000..46b3cb8
--- /dev/null
+++ b/core/tests/coretests/src/android/view/textclassifier/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/service/textclassifier/OWNERS
diff --git a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
index 4c3eaeb..7175f56 100644
--- a/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
@@ -15,6 +15,8 @@
  */
 package com.android.internal.util;
 
+import static android.Manifest.permission.NETWORK_SETTINGS;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
@@ -82,6 +84,7 @@
     private int mAllowCoarseLocationApps;
     private int mFineLocationPermission;
     private int mAllowFineLocationApps;
+    private int mNetworkSettingsPermission;
     private int mCurrentUser;
     private boolean mIsLocationEnabled;
     private boolean mThrowSecurityException;
@@ -138,6 +141,7 @@
         mFineLocationPermission = PackageManager.PERMISSION_DENIED;
         mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
         mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+        mNetworkSettingsPermission = PackageManager.PERMISSION_DENIED;
     }
 
     private void setupMockInterface() {
@@ -151,6 +155,8 @@
                 .thenReturn(mCoarseLocationPermission);
         when(mMockContext.checkPermission(mManifestStringFine, -1, mUid))
                 .thenReturn(mFineLocationPermission);
+        when(mMockContext.checkPermission(NETWORK_SETTINGS, -1, mUid))
+                .thenReturn(mNetworkSettingsPermission);
         when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled);
     }
 
@@ -264,6 +270,21 @@
         assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result);
     }
 
+    @Test
+    public void testenforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings()
+            throws Exception {
+        mThrowSecurityException = false;
+        mIsLocationEnabled = false;
+        mNetworkSettingsPermission = PackageManager.PERMISSION_GRANTED;
+        setupTestCase();
+
+        final int result =
+                mChecker.checkLocationPermissionWithDetailInfo(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+        assertEquals(LocationPermissionChecker.SUCCEEDED, result);
+    }
+
+
     private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
         try {
             r.run();
diff --git a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
index 6c733ba..33e8ded 100644
--- a/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore2/KeyStoreCryptoOperationChunkedStreamer.java
@@ -139,7 +139,9 @@
             int inputConsumed = ArrayUtils.copy(input, inputOffset, mChunk, mChunkLength,
                     inputLength);
             inputLength -= inputConsumed;
-            inputOffset += inputOffset;
+            inputOffset += inputConsumed;
+            mChunkLength += inputConsumed;
+            if (mChunkLength < mChunkSizeMax) return output;
             byte[] o = mKeyStoreStream.update(mChunk);
             if (o != null) {
                 output = ArrayUtils.concat(output, o);
diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index 1fbb672..5d7fdff 100644
--- a/media/java/android/media/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -91,6 +91,8 @@
     // For the recording session
     void startRecording(in IBinder sessionToken, in Uri programUri, in Bundle params, int userId);
     void stopRecording(in IBinder sessionToken, int userId);
+    void pauseRecording(in IBinder sessionToken, in Bundle params, int userId);
+    void resumeRecording(in IBinder sessionToken, in Bundle params, int userId);
 
     // For TV input hardware binding
     List<TvInputHardwareInfo> getHardwareList();
diff --git a/media/java/android/media/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 24b87d5..158cf21 100644
--- a/media/java/android/media/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -58,4 +58,6 @@
     // For the recording session
     void startRecording(in Uri programUri, in Bundle params);
     void stopRecording();
+    void pauseRecording(in Bundle params);
+    void resumeRecording(in Bundle params);
 }
diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index e89d33d..abccf8d 100644
--- a/media/java/android/media/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -68,6 +68,8 @@
     private static final int DO_TIME_SHIFT_ENABLE_POSITION_TRACKING = 19;
     private static final int DO_START_RECORDING = 20;
     private static final int DO_STOP_RECORDING = 21;
+    private static final int DO_PAUSE_RECORDING = 22;
+    private static final int DO_RESUME_RECORDING = 23;
 
     private final boolean mIsRecordingSession;
     private final HandlerCaller mCaller;
@@ -224,6 +226,14 @@
                 mTvInputRecordingSessionImpl.stopRecording();
                 break;
             }
+            case DO_PAUSE_RECORDING: {
+                mTvInputRecordingSessionImpl.pauseRecording((Bundle) msg.obj);
+                break;
+            }
+            case DO_RESUME_RECORDING: {
+                mTvInputRecordingSessionImpl.resumeRecording((Bundle) msg.obj);
+                break;
+            }
             default: {
                 Log.w(TAG, "Unhandled message code: " + msg.what);
                 break;
@@ -363,6 +373,16 @@
         mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_STOP_RECORDING));
     }
 
+    @Override
+    public void pauseRecording(@Nullable Bundle params) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_PAUSE_RECORDING, params));
+    }
+
+    @Override
+    public void resumeRecording(@Nullable Bundle params) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RESUME_RECORDING, params));
+    }
+
     private final class TvInputEventReceiver extends InputEventReceiver {
         public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
diff --git a/media/java/android/media/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
index b12f7c5..1249e0d 100644
--- a/media/java/android/media/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -188,6 +188,17 @@
         mCableConnectionStatus = source.readInt();
     }
 
+    /** @hide */
+    public Builder toBuilder() {
+        return new Builder()
+            .deviceId(mDeviceId)
+            .type(mType)
+            .audioType(mAudioType)
+            .audioAddress(mAudioAddress)
+            .hdmiPortId(mHdmiPortId)
+            .cableConnectionStatus(mCableConnectionStatus);
+    }
+
     public static final class Builder {
         private Integer mDeviceId = null;
         private Integer mType = null;
diff --git a/media/java/android/media/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 195ad5b..54cb2bf 100644
--- a/media/java/android/media/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -143,6 +143,7 @@
     // Attributes from XML meta data.
     private final String mSetupActivity;
     private final boolean mCanRecord;
+    private final boolean mCanPauseRecording;
     private final int mTunerCount;
 
     // Attributes specific to HDMI
@@ -264,8 +265,8 @@
 
     private TvInputInfo(ResolveInfo service, String id, int type, boolean isHardwareInput,
             CharSequence label, int labelResId, Icon icon, Icon iconStandby, Icon iconDisconnected,
-            String setupActivity, boolean canRecord, int tunerCount, HdmiDeviceInfo hdmiDeviceInfo,
-            boolean isConnectedToHdmiSwitch,
+            String setupActivity, boolean canRecord, boolean canPauseRecording, int tunerCount,
+            HdmiDeviceInfo hdmiDeviceInfo, boolean isConnectedToHdmiSwitch,
             @HdmiAddressRelativePosition int hdmiConnectionRelativePosition, String parentId,
             Bundle extras) {
         mService = service;
@@ -279,6 +280,7 @@
         mIconDisconnected = iconDisconnected;
         mSetupActivity = setupActivity;
         mCanRecord = canRecord;
+        mCanPauseRecording = canPauseRecording;
         mTunerCount = tunerCount;
         mHdmiDeviceInfo = hdmiDeviceInfo;
         mIsConnectedToHdmiSwitch = isConnectedToHdmiSwitch;
@@ -386,6 +388,14 @@
     }
 
     /**
+     * Returns {@code true} if this TV input can pause recording TV programs,
+     * {@code false} otherwise.
+     */
+    public boolean canPauseRecording() {
+        return mCanPauseRecording;
+    }
+
+    /**
      * Returns domain-specific extras associated with this TV input.
      */
     public Bundle getExtras() {
@@ -571,6 +581,7 @@
                 && Objects.equals(mIconDisconnected, obj.mIconDisconnected)
                 && TextUtils.equals(mSetupActivity, obj.mSetupActivity)
                 && mCanRecord == obj.mCanRecord
+                && mCanPauseRecording == obj.mCanPauseRecording
                 && mTunerCount == obj.mTunerCount
                 && Objects.equals(mHdmiDeviceInfo, obj.mHdmiDeviceInfo)
                 && mIsConnectedToHdmiSwitch == obj.mIsConnectedToHdmiSwitch
@@ -606,6 +617,7 @@
         dest.writeParcelable(mIconDisconnected, flags);
         dest.writeString(mSetupActivity);
         dest.writeByte(mCanRecord ? (byte) 1 : 0);
+        dest.writeByte(mCanPauseRecording ? (byte) 1 : 0);
         dest.writeInt(mTunerCount);
         dest.writeParcelable(mHdmiDeviceInfo, flags);
         dest.writeByte(mIsConnectedToHdmiSwitch ? (byte) 1 : 0);
@@ -648,6 +660,7 @@
         mIconDisconnected = in.readParcelable(null);
         mSetupActivity = in.readString();
         mCanRecord = in.readByte() == 1;
+        mCanPauseRecording = in.readByte() == 1;
         mTunerCount = in.readInt();
         mHdmiDeviceInfo = in.readParcelable(null);
         mIsConnectedToHdmiSwitch = in.readByte() == 1;
@@ -695,6 +708,7 @@
         private Icon mIconDisconnected;
         private String mSetupActivity;
         private Boolean mCanRecord;
+        private Boolean mCanPauseRecording;
         private Integer mTunerCount;
         private TvInputHardwareInfo mTvInputHardwareInfo;
         private HdmiDeviceInfo mHdmiDeviceInfo;
@@ -879,6 +893,18 @@
         }
 
         /**
+         * Sets whether this TV input can pause recording TV programs or not.
+         *
+         * @param canPauseRecording Whether this TV input can pause recording TV programs.
+         * @return This Builder object to allow for chaining of calls to builder methods.
+         */
+        @NonNull
+        public Builder setCanPauseRecording(boolean canPauseRecording) {
+            this.mCanPauseRecording = canPauseRecording;
+            return this;
+        }
+
+        /**
          * Sets domain-specific extras associated with this TV input.
          *
          * @param extras Domain-specific extras associated with this TV input. Keys <em>must</em> be
@@ -927,7 +953,9 @@
             parseServiceMetadata(type);
             return new TvInputInfo(mResolveInfo, id, type, isHardwareInput, mLabel, mLabelResId,
                     mIcon, mIconStandby, mIconDisconnected, mSetupActivity,
-                    mCanRecord == null ? false : mCanRecord, mTunerCount == null ? 0 : mTunerCount,
+                    mCanRecord == null ? false : mCanRecord,
+                    mCanPauseRecording == null ? false : mCanPauseRecording,
+                    mTunerCount == null ? 0 : mTunerCount,
                     mHdmiDeviceInfo, isConnectedToHdmiSwitch, hdmiConnectionRelativePosition,
                     mParentId, mExtras);
         }
@@ -997,6 +1025,12 @@
                     mTunerCount = sa.getInt(
                             com.android.internal.R.styleable.TvInputService_tunerCount, 1);
                 }
+                if (mCanPauseRecording == null) {
+                    mCanPauseRecording = sa.getBoolean(
+                            com.android.internal.R.styleable.TvInputService_canPauseRecording,
+                            false);
+                }
+
                 sa.recycle();
             } catch (IOException | XmlPullParserException e) {
                 throw new IllegalStateException("Failed reading meta-data for " + si.packageName, e);
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index 98a01a4..6341dc2 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2476,6 +2476,40 @@
         }
 
         /**
+         * Pauses TV program recording in the current recording session.
+         *
+         * @param params A set of extra parameters which might be handled with this event.
+         */
+        void pauseRecording(@NonNull Bundle params) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.pauseRecording(mToken, params, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
+         * Resumes TV program recording in the current recording session.
+         *
+         * @param params A set of extra parameters which might be handled with this event.
+         */
+        void resumeRecording(@NonNull Bundle params) {
+            if (mToken == null) {
+                Log.w(TAG, "The session has been already released");
+                return;
+            }
+            try {
+                mService.resumeRecording(mToken, params, mUserId);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * Calls {@link TvInputService.Session#appPrivateCommand(String, Bundle)
          * TvInputService.Session.appPrivateCommand()} on the current TvView.
          *
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index abbf478..0fe9d50 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -1852,6 +1852,28 @@
 
 
         /**
+         * Called when the application requests to pause TV program recording. Recording must pause
+         * immediately when this method is called.
+         *
+         * If the pause request cannot be fulfilled, the session must call
+         * {@link #notifyError(int)}.
+         *
+         * @param params Domain-specific data for recording request.
+         */
+        public void onPauseRecording(@NonNull Bundle params) { }
+
+        /**
+         * Called when the application requests to resume TV program recording. Recording must
+         * resume immediately when this method is called.
+         *
+         * If the resume request cannot be fulfilled, the session must call
+         * {@link #notifyError(int)}.
+         *
+         * @param params Domain-specific data for recording request.
+         */
+        public void onResumeRecording(@NonNull Bundle params) { }
+
+        /**
          * Called when the application requests to release all the resources held by this recording
          * session.
          */
@@ -1903,6 +1925,22 @@
         }
 
         /**
+         * Calls {@link #onPauseRecording(Bundle)}.
+         *
+         */
+        void pauseRecording(@NonNull Bundle params) {
+            onPauseRecording(params);
+        }
+
+        /**
+         * Calls {@link #onResumeRecording(Bundle)}.
+         *
+         */
+        void resumeRecording(@NonNull Bundle params) {
+            onResumeRecording(params);
+        }
+
+        /**
          * Calls {@link #onAppPrivateCommand(String, Bundle)}.
          */
         void appPrivateCommand(String action, Bundle data) {
diff --git a/media/java/android/media/tv/TvRecordingClient.java b/media/java/android/media/tv/TvRecordingClient.java
index 23fadac..180e2bd 100644
--- a/media/java/android/media/tv/TvRecordingClient.java
+++ b/media/java/android/media/tv/TvRecordingClient.java
@@ -30,6 +30,7 @@
 import android.util.Pair;
 
 import java.util.ArrayDeque;
+import java.util.Objects;
 import java.util.Queue;
 
 /**
@@ -49,6 +50,8 @@
 
     private boolean mIsRecordingStarted;
     private boolean mIsTuned;
+    private boolean mIsPaused;
+    private boolean mIsRecordingStopping;
     private final Queue<Pair<String, Bundle>> mPendingAppPrivateCommands = new ArrayDeque<>();
 
     /**
@@ -113,17 +116,22 @@
         if (TextUtils.isEmpty(inputId)) {
             throw new IllegalArgumentException("inputId cannot be null or an empty string");
         }
-        if (mIsRecordingStarted) {
+        if (mIsRecordingStarted && !mIsPaused) {
             throw new IllegalStateException("tune failed - recording already started");
         }
         if (mSessionCallback != null && TextUtils.equals(mSessionCallback.mInputId, inputId)) {
             if (mSession != null) {
+                mSessionCallback.mChannelUri = channelUri;
                 mSession.tune(channelUri, params);
             } else {
                 mSessionCallback.mChannelUri = channelUri;
                 mSessionCallback.mConnectionParams = params;
             }
+            mIsTuned = false;
         } else {
+            if (mIsPaused) {
+                throw new IllegalStateException("tune failed - inputId is changed during pause");
+            }
             resetInternal();
             mSessionCallback = new MySessionCallback(inputId, channelUri, params);
             if (mTvInputManager != null) {
@@ -148,6 +156,8 @@
             mSession.release();
             mIsTuned = false;
             mIsRecordingStarted = false;
+            mIsPaused = false;
+            mIsRecordingStopping = false;
             mSession = null;
         }
     }
@@ -169,7 +179,8 @@
      *
      * @param programUri The URI for the TV program to record, built by
      *            {@link TvContract#buildProgramUri(long)}. Can be {@code null}.
-     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+     *            pause.
      */
     public void startRecording(@Nullable Uri programUri) {
         startRecording(programUri, Bundle.EMPTY);
@@ -195,11 +206,16 @@
      * @param params Domain-specific data for this request. Keys <em>must</em> be a scoped
      *            name, i.e. prefixed with a package name you own, so that different developers will
      *            not create conflicting keys.
-     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet.
+     * @throws IllegalStateException If {@link #tune} request hasn't been handled yet or during
+     *            pause.
      */
     public void startRecording(@Nullable Uri programUri, @NonNull Bundle params) {
-        if (!mIsTuned) {
-            throw new IllegalStateException("startRecording failed - not yet tuned");
+        if (mIsRecordingStopping || !mIsTuned || mIsPaused) {
+            throw new IllegalStateException("startRecording failed -"
+                    + "recording not yet stopped or not yet tuned or paused");
+        }
+        if (mIsRecordingStarted) {
+            Log.w(TAG, "startRecording failed - recording already started");
         }
         if (mSession != null) {
             mSession.startRecording(programUri, params);
@@ -225,6 +241,103 @@
         }
         if (mSession != null) {
             mSession.stopRecording();
+            if (mIsRecordingStarted) {
+                mIsRecordingStopping = true;
+            }
+        }
+    }
+
+    /**
+     * Pause TV program recording in the current recording session. Recording is expected to pause
+     * immediately when this method is called. If recording has not yet started in the current
+     * recording session, this method does nothing.
+     *
+     * <p>In pause status, the application can tune during recording. To continue recording,
+     * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+     * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+     * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+     *
+     * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+     * {@link RecordingCallback#onError(int)}.
+     */
+    public void pauseRecording() {
+        pauseRecording(Bundle.EMPTY);
+    }
+
+    /**
+     * Pause TV program recording in the current recording session. Recording is expected to pause
+     * immediately when this method is called. If recording has not yet started in the current
+     * recording session, this method does nothing.
+     *
+     * <p>In pause status, the application can tune during recording. To continue recording,
+     * please call {@link TvRecordingClient#resumeRecording()} to resume instead of
+     * {@link TvRecordingClient#startRecording(Uri)}. Application can stop
+     * the recording with {@link TvRecordingClient#stopRecording()} in recording pause status.
+     *
+     * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+     * {@link RecordingCallback#onError(int)}.
+     *
+     * @param params Domain-specific data for this request.
+     */
+    public void pauseRecording(@NonNull Bundle params) {
+        if (!mIsRecordingStarted || mIsRecordingStopping) {
+            throw new IllegalStateException(
+                    "pauseRecording failed - recording not yet started or stopping");
+        }
+        TvInputInfo info = mTvInputManager.getTvInputInfo(mSessionCallback.mInputId);
+        if (info == null || !info.canPauseRecording()) {
+            throw new UnsupportedOperationException(
+                    "pauseRecording failed - operation not supported");
+        }
+        if (mIsPaused) {
+            Log.w(TAG, "pauseRecording failed - recording already paused");
+        }
+        if (mSession != null) {
+            mSession.pauseRecording(params);
+            mIsPaused  = true;
+        }
+    }
+
+    /**
+     * Resume TV program recording only in recording pause status in the current recording session.
+     * Recording is expected to resume immediately when this method is called. If recording has not
+     * yet paused in the current recording session, this method does nothing.
+     *
+     * <p>When record is resumed, the recording is continue and can not re-tune. Application can
+     * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+     *
+     * <p>If the pause request cannot be fulfilled, the recording session will respond by calling
+     * {@link RecordingCallback#onError(int)}.
+     */
+    public void resumeRecording() {
+        resumeRecording(Bundle.EMPTY);
+    }
+
+    /**
+     * Resume TV program recording only in recording pause status in the current recording session.
+     * Recording is expected to resume immediately when this method is called. If recording has not
+     * yet paused in the current recording session, this method does nothing.
+     *
+     * <p>When record is resumed, the recording is continues and can not re-tune. Application can
+     * stop the recording with {@link TvRecordingClient#stopRecording()} after record resumed.
+     *
+     * <p>If the resume request cannot be fulfilled, the recording session will respond by calling
+     * {@link RecordingCallback#onError(int)}.
+     *
+     * @param params Domain-specific data for this request.
+     */
+    public void resumeRecording(@NonNull Bundle params) {
+        if (!mIsRecordingStarted || mIsRecordingStopping || !mIsTuned) {
+            throw new IllegalStateException(
+                    "resumeRecording failed - recording not yet started or stopping or "
+                            + "not yet tuned");
+        }
+        if (!mIsPaused) {
+            Log.w(TAG, "resumeRecording failed - recording not yet paused");
+        }
+        if (mSession != null) {
+            mSession.resumeRecording(params);
+            mIsPaused  = false;
         }
     }
 
@@ -367,6 +480,10 @@
                 Log.w(TAG, "onTuned - session not created");
                 return;
             }
+            if (mIsTuned || !Objects.equals(mChannelUri, channelUri)) {
+                Log.w(TAG, "onTuned - already tuned or not yet tuned to last channel");
+                return;
+            }
             mIsTuned = true;
             mCallback.onTuned(channelUri);
         }
@@ -382,6 +499,8 @@
             }
             mIsTuned = false;
             mIsRecordingStarted = false;
+            mIsPaused = false;
+            mIsRecordingStopping = false;
             mSessionCallback = null;
             mSession = null;
             if (mCallback != null) {
@@ -398,7 +517,13 @@
                 Log.w(TAG, "onRecordingStopped - session not created");
                 return;
             }
+            if (!mIsRecordingStarted) {
+                Log.w(TAG, "onRecordingStopped - recording not yet started");
+                return;
+            }
             mIsRecordingStarted = false;
+            mIsPaused = false;
+            mIsRecordingStopping = false;
             mCallback.onRecordingStopped(recordedProgramUri);
         }
 
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 8c2dfd4..4b6862c 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -346,6 +346,9 @@
     <uses-permission android:name="android.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS" />
     <uses-permission android:name="android.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS" />
 
+    <!-- Permission required for CTS test - CtsSensorPrivacyTestCases -->
+    <uses-permission android:name="android.permission.MANAGE_SENSOR_PRIVACY" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/services/CameraExtensionsProxy/OWNERS b/packages/services/CameraExtensionsProxy/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/packages/services/CameraExtensionsProxy/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 6b45abd..90a17e7 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -194,7 +194,6 @@
 import com.android.server.connectivity.DataConnectionStats;
 import com.android.server.connectivity.DnsManager;
 import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
-import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.KeepaliveTracker;
 import com.android.server.connectivity.LingerMonitor;
 import com.android.server.connectivity.MockableSystemProperties;
@@ -889,6 +888,13 @@
         }
 
         /**
+         * Get a reference to the system keystore.
+         */
+        public KeyStore getKeyStore() {
+            return KeyStore.getInstance();
+        }
+
+        /**
          * @see ProxyTracker
          */
         public ProxyTracker makeProxyTracker(@NonNull Context context,
@@ -918,14 +924,6 @@
             return new MultinetworkPolicyTracker(c, h, r);
         }
 
-        /**
-         * @see IpConnectivityMetrics.Logger
-         */
-        public IpConnectivityMetrics.Logger getMetricsLogger() {
-            return Objects.requireNonNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
-                    "no IpConnectivityMetrics service");
-        }
-
         public IBatteryStats getBatteryStatsService() {
             return BatteryStatsService.getService();
         }
@@ -990,7 +988,7 @@
         mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
 
         mNetd = netd;
-        mKeyStore = KeyStore.getInstance();
+        mKeyStore = mDeps.getKeyStore();
         mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
         mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mLocationPermissionChecker = new LocationPermissionChecker(mContext);
@@ -1653,7 +1651,6 @@
     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
         if (nai == null) return null;
         synchronized (nai) {
-            if (nai.networkCapabilities == null) return null;
             return networkCapabilitiesRestrictedForCallerPermissions(
                     nai.networkCapabilities, Binder.getCallingPid(), mDeps.getCallingUid());
         }
@@ -2777,7 +2774,6 @@
     }
 
     private boolean isLiveNetworkAgent(NetworkAgentInfo nai, int what) {
-        if (nai.network == null) return false;
         final NetworkAgentInfo officialNai = getNetworkAgentInfoForNetwork(nai.network);
         if (officialNai != null && officialNai.equals(nai)) return true;
         if (officialNai != null || VDBG) {
@@ -4993,16 +4989,21 @@
         mVpnBlockedUidRanges = newVpnBlockedUidRanges;
     }
 
+    private boolean isLockdownVpnEnabled() {
+        return mKeyStore.contains(Credentials.LOCKDOWN_VPN);
+    }
+
     @Override
     public boolean updateLockdownVpn() {
-        if (mDeps.getCallingUid() != Process.SYSTEM_UID) {
-            logw("Lockdown VPN only available to AID_SYSTEM");
+        if (mDeps.getCallingUid() != Process.SYSTEM_UID
+                && Binder.getCallingPid() != Process.myPid()) {
+            logw("Lockdown VPN only available to system process or AID_SYSTEM");
             return false;
         }
 
         synchronized (mVpns) {
             // Tear down existing lockdown if profile was removed
-            mLockdownEnabled = LockdownVpnTracker.isEnabled();
+            mLockdownEnabled = isLockdownVpnEnabled();
             if (mLockdownEnabled) {
                 byte[] profileTag = mKeyStore.get(Credentials.LOCKDOWN_VPN);
                 if (profileTag == null) {
@@ -5023,7 +5024,8 @@
                     logw("VPN for user " + user + " not ready yet. Skipping lockdown");
                     return false;
                 }
-                setLockdownTracker(new LockdownVpnTracker(mContext, this, mHandler, vpn, profile));
+                setLockdownTracker(
+                        new LockdownVpnTracker(mContext, this, mHandler, mKeyStore, vpn,  profile));
             } else {
                 setLockdownTracker(null);
             }
@@ -5111,7 +5113,7 @@
 
         synchronized (mVpns) {
             // Can't set always-on VPN if legacy VPN is already in lockdown mode.
-            if (LockdownVpnTracker.isEnabled()) {
+            if (isLockdownVpnEnabled()) {
                 return false;
             }
 
@@ -5217,7 +5219,7 @@
             }
             userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, mNetd, userId, mKeyStore);
             mVpns.put(userId, userVpn);
-            if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
+            if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) {
                 updateLockdownVpn();
             }
         }
@@ -5301,7 +5303,7 @@
     private void onUserUnlocked(int userId) {
         synchronized (mVpns) {
             // User present may be sent because of an unlock, which might mean an unlocked keystore.
-            if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
+            if (mUserManager.getUserInfo(userId).isPrimary() && isLockdownVpnEnabled()) {
                 updateLockdownVpn();
             } else {
                 startAlwaysOnVpn(userId);
@@ -6068,6 +6070,10 @@
     public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
             int currentScore, NetworkAgentConfig networkAgentConfig, int providerId) {
+        Objects.requireNonNull(networkInfo, "networkInfo must not be null");
+        Objects.requireNonNull(linkProperties, "linkProperties must not be null");
+        Objects.requireNonNull(networkCapabilities, "networkCapabilities must not be null");
+        Objects.requireNonNull(networkAgentConfig, "networkAgentConfig must not be null");
         if (networkCapabilities.hasTransport(TRANSPORT_TEST)) {
             enforceAnyPermissionOf(Manifest.permission.MANAGE_TEST_NETWORKS);
         } else {
@@ -6606,7 +6612,7 @@
         }
 
         // Don't modify caller's NetworkCapabilities.
-        NetworkCapabilities newNc = new NetworkCapabilities(nc);
+        final NetworkCapabilities newNc = new NetworkCapabilities(nc);
         if (nai.lastValidated) {
             newNc.addCapability(NET_CAPABILITY_VALIDATED);
         } else {
@@ -6694,26 +6700,21 @@
             notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
         }
 
-        // TODO : static analysis indicates that prevNc can't be null here (getAndSetNetworkCaps
-        // never returns null), so mark the relevant members and functions in nai as @NonNull and
-        // remove this test
-        if (prevNc != null) {
-            final boolean oldMetered = prevNc.isMetered();
-            final boolean newMetered = newNc.isMetered();
-            final boolean meteredChanged = oldMetered != newMetered;
+        final boolean oldMetered = prevNc.isMetered();
+        final boolean newMetered = newNc.isMetered();
+        final boolean meteredChanged = oldMetered != newMetered;
 
-            if (meteredChanged) {
-                maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
-                        mRestrictBackground, mVpnBlockedUidRanges, mVpnBlockedUidRanges);
-            }
+        if (meteredChanged) {
+            maybeNotifyNetworkBlocked(nai, oldMetered, newMetered, mRestrictBackground,
+                    mRestrictBackground, mVpnBlockedUidRanges, mVpnBlockedUidRanges);
+        }
 
-            final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING) !=
-                    newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
+        final boolean roamingChanged = prevNc.hasCapability(NET_CAPABILITY_NOT_ROAMING)
+                != newNc.hasCapability(NET_CAPABILITY_NOT_ROAMING);
 
-            // Report changes that are interesting for network statistics tracking.
-            if (meteredChanged || roamingChanged) {
-                notifyIfacesChangedForNetworkStats();
-            }
+        // Report changes that are interesting for network statistics tracking.
+        if (meteredChanged || roamingChanged) {
+            notifyIfacesChangedForNetworkStats();
         }
 
         // This network might have been underlying another network. Propagate its capabilities.
@@ -7588,10 +7589,6 @@
         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
             networkAgent.everConnected = true;
 
-            if (networkAgent.linkProperties == null) {
-                Log.wtf(TAG, networkAgent.toShortString() + " connected with null LinkProperties");
-            }
-
             // NetworkCapabilities need to be set before sending the private DNS config to
             // NetworkMonitor, otherwise NetworkMonitor cannot determine if validation is required.
             networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 3584772..5c34584 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1537,6 +1537,9 @@
             mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
 
         } else if (vol.type == VolumeInfo.TYPE_STUB) {
+            if (vol.disk.isStubVisible()) {
+                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+            }
             vol.mountUserId = mCurrentUserId;
             mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
         } else {
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 5f6e8df..5560f81 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -64,6 +64,7 @@
 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;
@@ -78,6 +79,7 @@
 import android.telephony.emergency.EmergencyNumber;
 import android.telephony.ims.ImsReasonInfo;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Pair;
 
@@ -99,10 +101,13 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * Since phone process can be restarted, this class provides a centralized place
@@ -142,14 +147,14 @@
         int callerUid;
         int callerPid;
 
-        int events;
+        Set<Integer> eventList;
 
         int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
         int phoneId = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
 
-        boolean matchPhoneStateListenerEvent(int events) {
-            return (callback != null) && ((events & this.events) != 0);
+        boolean matchPhoneStateListenerEvent(int event) {
+            return (callback != null) && (this.eventList.contains(event));
         }
 
         boolean matchOnSubscriptionsChangedListener() {
@@ -177,7 +182,7 @@
                     + onSubscriptionsChangedListenerCallback
                     + " onOpportunisticSubscriptionsChangedListenererCallback="
                     + onOpportunisticSubscriptionsChangedListenerCallback + " subId=" + subId
-                    + " phoneId=" + phoneId + " events=" + Integer.toHexString(events) + "}";
+                    + " phoneId=" + phoneId + " events=" + eventList + "}";
         }
     }
 
@@ -306,6 +311,12 @@
 
     private final LocalLog mListenLog = new LocalLog(200);
 
+    private List<PhysicalChannelConfig> mPhysicalChannelConfigs;
+
+    private boolean mIsDataEnabled = false;
+
+    private int mDataEnabledReason;
+
     /**
      * Per-phone map of precise data connection state. The key of the map is the pair of transport
      * type and APN setting. This is the cache to prevent redundant callbacks to the listeners.
@@ -315,39 +326,62 @@
     private List<Map<Pair<Integer, ApnSetting>, PreciseDataConnectionState>>
             mPreciseDataConnectionStates;
 
-    // Starting in Q, almost all cellular location requires FINE location enforcement.
-    // Prior to Q, cellular was available with COARSE location enforcement. Bits in this
-    // list will be checked for COARSE on apps targeting P or earlier and FINE on Q or later.
-    static final int ENFORCE_LOCATION_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_CELL_LOCATION
-                    | PhoneStateListener.LISTEN_CELL_INFO
-                    | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
-                    | PhoneStateListener.LISTEN_BARRING_INFO;
+    private static final Set<Integer> REQUIRE_PRECISE_PHONE_STATE_PERMISSION;
+    static {
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION = new HashSet<Integer>();
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_DATA_CONNECTION_REAL_TIME_INFO_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_REGISTRATION_FAILURE);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED);
+        REQUIRE_PRECISE_PHONE_STATE_PERMISSION.add(
+                PhoneStateListener.EVENT_DATA_ENABLED_CHANGED);
+    }
 
-    static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
-                    | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
-                    | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
-                    | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED;
+    private boolean isLocationPermissionRequired(Set<Integer> events) {
+        return events.contains(PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_CELL_INFO_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_REGISTRATION_FAILURE)
+                || events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED);
+    }
 
-    static final int ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_PRECISE_CALL_STATE
-                    | PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE
-                    | PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES
-                    | PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED
-                    | PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES
-                    | PhoneStateListener.LISTEN_REGISTRATION_FAILURE
-                    | PhoneStateListener.LISTEN_BARRING_INFO;
+    private boolean isPhoneStatePermissionRequired(Set<Integer> events) {
+        return events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED);
+    }
 
-    static final int READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL
-                    | PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS;
+    private boolean isPrecisePhoneStatePermissionRequired(Set<Integer> events) {
+        for (Integer requireEvent : REQUIRE_PRECISE_PHONE_STATE_PERMISSION) {
+            if (events.contains(requireEvent)) {
+                return true;
+            }
+        }
+        return false;
+    }
 
-    static final int READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK =
-            PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT
-                    | PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED
-                    | PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED
-                    | PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE;
+    private boolean isActiveEmergencySessionPermissionRequired(Set<Integer> events) {
+        return events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL)
+                || events.contains(PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS);
+    }
+
+    private boolean isPrivilegedPhoneStatePermissionRequired(Set<Integer> events) {
+        return events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
+                || events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED);
+    }
 
     private static final int MSG_USER_SWITCHED = 1;
     private static final int MSG_UPDATE_DEFAULT_SUB = 2;
@@ -495,6 +529,7 @@
             cutListToSize(mImsReasonInfo, mNumPhones);
             cutListToSize(mPreciseDataConnectionStates, mNumPhones);
             cutListToSize(mBarringInfo, mNumPhones);
+            cutListToSize(mPhysicalChannelConfigs, mNumPhones);
             return;
         }
 
@@ -528,6 +563,7 @@
             mPreciseDataConnectionStates.add(new ArrayMap<>());
             mBarringInfo.add(i, new BarringInfo());
             mTelephonyDisplayInfos[i] = null;
+            mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
         }
     }
 
@@ -588,6 +624,7 @@
         mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones];
         mBarringInfo = new ArrayList<>();
         mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones];
+        mPhysicalChannelConfigs = new ArrayList<>();
         for (int i = 0; i < numPhones; i++) {
             mCallState[i] =  TelephonyManager.CALL_STATE_IDLE;
             mDataActivity[i] = TelephonyManager.DATA_ACTIVITY_NONE;
@@ -617,6 +654,7 @@
             mPreciseDataConnectionStates.add(new ArrayMap<>());
             mBarringInfo.add(i, new BarringInfo());
             mTelephonyDisplayInfos[i] = null;
+            mPhysicalChannelConfigs.add(i, new PhysicalChannelConfig.Builder().build());
         }
 
         mAppOps = mContext.getSystemService(AppOpsManager.class);
@@ -659,7 +697,7 @@
             r.callingFeatureId = callingFeatureId;
             r.callerUid = Binder.getCallingUid();
             r.callerPid = Binder.getCallingPid();
-            r.events = 0;
+            r.eventList = new ArraySet<>();
             if (DBG) {
                 log("listen oscl:  Register r=" + r);
             }
@@ -713,7 +751,7 @@
             r.callingFeatureId = callingFeatureId;
             r.callerUid = Binder.getCallingUid();
             r.callerPid = Binder.getCallingPid();
-            r.events = 0;
+            r.eventList = new ArraySet<>();
             if (DBG) {
                 log("listen ooscl:  Register r=" + r);
             }
@@ -786,323 +824,337 @@
         }
     }
 
-    @Deprecated
     @Override
-    public void listen(String callingPackage, IPhoneStateListener callback, int events,
-            boolean notifyNow) {
-        listenWithFeature(callingPackage, null, callback, events, notifyNow);
-    }
-
-    @Override
-    public void listenWithFeature(String callingPackage, String callingFeatureId,
-            IPhoneStateListener callback, int events, boolean notifyNow) {
-        listenForSubscriber(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, callingPackage,
-                callingFeatureId, callback, events, notifyNow);
-    }
-
-    @Override
-    public void listenForSubscriber(int subId, String callingPackage, String callingFeatureId,
-            IPhoneStateListener callback, int events, boolean notifyNow) {
-        listen(callingPackage, callingFeatureId, callback, events, notifyNow, subId);
+    public void listenWithEventList(int subId, String callingPackage, String callingFeatureId,
+            IPhoneStateListener callback, int[] events, boolean notifyNow) {
+        Set<Integer> eventList = Arrays.stream(events).boxed().collect(Collectors.toSet());
+        listen(callingPackage, callingFeatureId, callback, eventList, notifyNow, subId);
     }
 
     private void listen(String callingPackage, @Nullable String callingFeatureId,
-            IPhoneStateListener callback, int events, boolean notifyNow, int subId) {
+            IPhoneStateListener callback, Set<Integer> events, boolean notifyNow, int subId) {
         int callerUserId = UserHandle.getCallingUserId();
         mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         String str = "listen: E pkg=" + pii(callingPackage) + " uid=" + Binder.getCallingUid()
-                + " events=0x" + Integer.toHexString(events) + " notifyNow=" + notifyNow + " subId="
-                + subId + " myUserId=" + UserHandle.myUserId() + " callerUserId=" + callerUserId;
+                + " events=" + events + " notifyNow=" + notifyNow
+                + " subId=" + subId + " myUserId=" + UserHandle.myUserId()
+                + " callerUserId=" + callerUserId;
         mListenLog.log(str);
         if (VDBG) {
             log(str);
         }
 
-        if (events != PhoneStateListener.LISTEN_NONE) {
-            // Checks permission and throws SecurityException for disallowed operations. For pre-M
-            // apps whose runtime permission has been revoked, we return immediately to skip sending
-            // events to the app without crashing it.
-            if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
-                    "listen")) {
+        if (events.isEmpty()) {
+            if (DBG) {
+                log("listen: Unregister");
+            }
+            events.clear();
+            remove(callback.asBinder());
+            return;
+        }
+
+        // Checks permission and throws SecurityException for disallowed operations. For pre-M
+        // apps whose runtime permission has been revoked, we return immediately to skip sending
+        // events to the app without crashing it.
+        if (!checkListenerPermission(events, subId, callingPackage, callingFeatureId,
+                "listen")) {
+            return;
+        }
+
+        int phoneId = getPhoneIdFromSubId(subId);
+        synchronized (mRecords) {
+            // register
+            IBinder b = callback.asBinder();
+            boolean doesLimitApply =
+                    Binder.getCallingUid() != Process.SYSTEM_UID
+                            && Binder.getCallingUid() != Process.PHONE_UID
+                            && Binder.getCallingUid() != Process.myUid();
+            Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
+
+            if (r == null) {
                 return;
             }
 
-            int phoneId = getPhoneIdFromSubId(subId);
-            synchronized (mRecords) {
-                // register
-                IBinder b = callback.asBinder();
-                boolean doesLimitApply =
-                        Binder.getCallingUid() != Process.SYSTEM_UID
-                        && Binder.getCallingUid() != Process.PHONE_UID
-                        && Binder.getCallingUid() != Process.myUid();
-                Record r = add(b, Binder.getCallingUid(), Binder.getCallingPid(), doesLimitApply);
-
-                if (r == null) {
-                    return;
+            r.context = mContext;
+            r.callback = callback;
+            r.callingPackage = callingPackage;
+            r.callingFeatureId = callingFeatureId;
+            r.callerUid = Binder.getCallingUid();
+            r.callerPid = Binder.getCallingPid();
+            // Legacy applications pass SubscriptionManager.DEFAULT_SUBSCRIPTION_ID,
+            // force all illegal subId to SubscriptionManager.DEFAULT_SUBSCRIPTION_ID
+            if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+                r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
+            } else {//APP specify subID
+                r.subId = subId;
+            }
+            r.phoneId = phoneId;
+            r.eventList = events;
+            if (DBG) {
+                log("listen:  Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
+            }
+            if (notifyNow && validatePhoneId(phoneId)) {
+                if (events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED)) {
+                    try {
+                        if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
+                        ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
+                        if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            r.callback.onServiceStateChanged(rawSs);
+                        } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            r.callback.onServiceStateChanged(
+                                    rawSs.createLocationInfoSanitizedCopy(false));
+                        } else {
+                            r.callback.onServiceStateChanged(
+                                    rawSs.createLocationInfoSanitizedCopy(true));
+                        }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
                 }
-
-                r.context = mContext;
-                r.callback = callback;
-                r.callingPackage = callingPackage;
-                r.callingFeatureId = callingFeatureId;
-                r.callerUid = Binder.getCallingUid();
-                r.callerPid = Binder.getCallingPid();
-                // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
-                // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
-                if (!SubscriptionManager.isValidSubscriptionId(subId)) {
-                    r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
-                 } else {//APP specify subID
-                    r.subId = subId;
+                if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) {
+                    try {
+                        if (mSignalStrength[phoneId] != null) {
+                            int gsmSignalStrength = mSignalStrength[phoneId]
+                                    .getGsmSignalStrength();
+                            r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
+                                    : gsmSignalStrength));
+                        }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
                 }
-                r.phoneId = phoneId;
-                r.events = events;
-                if (DBG) {
-                    log("listen:  Register r=" + r + " r.subId=" + r.subId + " phoneId=" + phoneId);
+                if (events.contains(
+                        PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) {
+                    try {
+                        r.callback.onMessageWaitingIndicatorChanged(
+                                mMessageWaiting[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
                 }
-                if (notifyNow && validatePhoneId(phoneId)) {
-                    if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
-                        try {
-                            if (VDBG) log("listen: call onSSC state=" + mServiceState[phoneId]);
-                            ServiceState rawSs = new ServiceState(mServiceState[phoneId]);
-                            if (checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                r.callback.onServiceStateChanged(rawSs);
-                            } else if (checkCoarseLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                r.callback.onServiceStateChanged(
-                                        rawSs.createLocationInfoSanitizedCopy(false));
-                            } else {
-                                r.callback.onServiceStateChanged(
-                                        rawSs.createLocationInfoSanitizedCopy(true));
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                if (events.contains(
+                        PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) {
+                    try {
+                        r.callback.onCallForwardingIndicatorChanged(
+                                mCallForwarding[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
-                        try {
-                            if (mSignalStrength[phoneId] != null) {
-                                int gsmSignalStrength = mSignalStrength[phoneId]
-                                        .getGsmSignalStrength();
-                                r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1
-                                        : gsmSignalStrength));
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (validateEventAndUserLocked(
+                        r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) {
+                    try {
+                        if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
+                        if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            // null will be translated to empty CellLocation object in client.
+                            r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
-                        try {
-                            r.callback.onMessageWaitingIndicatorChanged(
-                                    mMessageWaiting[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_CALL_STATE_CHANGED)) {
+                    try {
+                        r.callback.onCallStateChanged(mCallState[phoneId],
+                                getCallIncomingNumber(r, phoneId));
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
-                        try {
-                            r.callback.onCallForwardingIndicatorChanged(
-                                    mCallForwarding[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
-                        try {
-                            if (DBG_LOC) log("listen: mCellIdentity = " + mCellIdentity[phoneId]);
-                            if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
-                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                // null will be translated to empty CellLocation object in client.
-                                r.callback.onCellLocationChanged(mCellIdentity[phoneId]);
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
-                    if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) {
-                        try {
-                            r.callback.onCallStateChanged(mCallState[phoneId],
-                                     getCallIncomingNumber(r, phoneId));
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
-                    }
-                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
-                        try {
-                            r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
+                }
+                if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) {
+                    try {
+                        r.callback.onDataConnectionStateChanged(mDataConnectionState[phoneId],
                                 mDataConnectionNetworkType[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) {
-                        try {
-                            r.callback.onDataActivity(mDataActivity[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED)) {
+                    try {
+                        r.callback.onDataActivity(mDataActivity[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) {
-                        try {
-                            if (mSignalStrength[phoneId] != null) {
-                                r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)) {
+                    try {
+                        if (mSignalStrength[phoneId] != null) {
+                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
-                            != 0) {
-                        updateReportSignalStrengthDecision(r.subId);
-                        try {
-                            if (mSignalStrength[phoneId] != null) {
-                                r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (events.contains(
+                        PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
+                    updateReportSignalStrengthDecision(r.subId);
+                    try {
+                        if (mSignalStrength[phoneId] != null) {
+                            r.callback.onSignalStrengthsChanged(mSignalStrength[phoneId]);
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
-                        try {
-                            if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
-                                    + mCellInfo.get(phoneId));
-                            if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
-                                    && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
-                                r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (validateEventAndUserLocked(
+                        r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) {
+                    try {
+                        if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
+                                + mCellInfo.get(phoneId));
+                        if (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                                && checkFineLocationAccess(r, Build.VERSION_CODES.Q)) {
+                            r.callback.onCellInfoChanged(mCellInfo.get(phoneId));
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
-                        try {
-                            r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED)) {
+                    try {
+                        r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
-                        try {
-                            r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
-                                    mCallPreciseDisconnectCause[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_CALL_DISCONNECT_CAUSE_CHANGED)) {
+                    try {
+                        r.callback.onCallDisconnectCauseChanged(mCallDisconnectCause[phoneId],
+                                mCallPreciseDisconnectCause[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES) != 0) {
-                        try {
-                            r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)) {
+                    try {
+                        r.callback.onImsCallDisconnectCauseChanged(mImsReasonInfo.get(phoneId));
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
-                        try {
-                            for (PreciseDataConnectionState pdcs
-                                    : mPreciseDataConnectionStates.get(phoneId).values()) {
-                                r.callback.onPreciseDataConnectionStateChanged(pdcs);
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (events.contains(
+                        PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)) {
+                    try {
+                        for (PreciseDataConnectionState pdcs
+                                : mPreciseDataConnectionStates.get(phoneId).values()) {
+                            r.callback.onPreciseDataConnectionStateChanged(pdcs);
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) != 0) {
-                        try {
-                            r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED)) {
+                    try {
+                        r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) !=0) {
-                        try {
-                            r.callback.onVoiceActivationStateChanged(
-                                    mVoiceActivationState[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)) {
+                    try {
+                        r.callback.onVoiceActivationStateChanged(
+                                mVoiceActivationState[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE) !=0) {
-                        try {
-                            r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED)) {
+                    try {
+                        r.callback.onDataActivationStateChanged(mDataActivationState[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
-                        try {
-                            r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) {
+                    try {
+                        r.callback.onUserMobileDataStateChanged(mUserMobileDataState[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
-                        try {
-                            if (mTelephonyDisplayInfos[phoneId] != null) {
-                                r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]);
-                            }
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
+                }
+                if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) {
+                    try {
+                        if (mTelephonyDisplayInfos[phoneId] != null) {
+                            r.callback.onDisplayInfoChanged(mTelephonyDisplayInfos[phoneId]);
                         }
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST) != 0) {
-                        try {
-                            r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)) {
+                    try {
+                        r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) {
-                        try {
-                            r.callback.onPhoneCapabilityChanged(mPhoneCapability);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) {
+                    try {
+                        r.callback.onPhoneCapabilityChanged(mPhoneCapability);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener
-                            .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
-                        try {
-                            r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(
+                        PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) {
+                    try {
+                        r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED) != 0) {
-                        try {
-                            r.callback.onRadioPowerStateChanged(mRadioPowerState);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED)) {
+                    try {
+                        r.callback.onRadioPowerStateChanged(mRadioPowerState);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) != 0) {
-                        try {
-                            r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)) {
+                    try {
+                        r.callback.onSrvccStateChanged(mSrvccState[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED) != 0) {
-                        try {
-                            r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)) {
+                    try {
+                        r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
-                    if ((events & PhoneStateListener.LISTEN_BARRING_INFO) != 0) {
-                        BarringInfo barringInfo = mBarringInfo.get(phoneId);
-                        BarringInfo biNoLocation = barringInfo != null
-                                ? barringInfo.createLocationInfoSanitizedCopy() : null;
-                        if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
-                        try {
-                            r.callback.onBarringInfoChanged(
-                                    checkFineLocationAccess(r, Build.VERSION_CODES.BASE)
-                                            ? barringInfo : biNoLocation);
-                        } catch (RemoteException ex) {
-                            remove(r.binder);
-                        }
+                }
+                if (events.contains(PhoneStateListener.EVENT_BARRING_INFO_CHANGED)) {
+                    BarringInfo barringInfo = mBarringInfo.get(phoneId);
+                    BarringInfo biNoLocation = barringInfo != null
+                            ? barringInfo.createLocationInfoSanitizedCopy() : null;
+                    if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
+                    try {
+                        r.callback.onBarringInfoChanged(
+                                checkFineLocationAccess(r, Build.VERSION_CODES.BASE)
+                                        ? barringInfo : biNoLocation);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
+                }
+                if (events.contains(
+                        PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)) {
+                    try {
+                        r.callback.onPhysicalChannelConfigChanged(
+                                mPhysicalChannelConfigs);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
+                    }
+                }
+                if (events.contains(
+                        PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
+                    try {
+                        r.callback.onDataEnabledChanged(mIsDataEnabled, mDataEnabledReason);
+                    } catch (RemoteException ex) {
+                        remove(r.binder);
                     }
                 }
             }
-        } else {
-            if(DBG) log("listen: Unregister");
-            remove(callback.asBinder());
         }
     }
 
@@ -1114,7 +1166,7 @@
                 // If any of the system clients wants to always listen to signal strength,
                 // we need to set it on.
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) {
+                        PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
                     telephonyManager.createForSubscriptionId(subscriptionId)
                             .setAlwaysReportSignalStrength(true);
                     return;
@@ -1215,7 +1267,7 @@
                     // strength is removed from registry records, we need to check if
                     // the signal strength decision needs to update on its slot.
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)) {
+                            PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
                         updateReportSignalStrengthDecision(r.subId);
                     }
                     return;
@@ -1235,8 +1287,8 @@
 
         synchronized (mRecords) {
             for (Record r : mRecords) {
-                if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
-                        (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
+                if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED)
+                        && (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
                     try {
                         // Ensure the listener has read call log permission; if they do not return
                         // an empty phone number.
@@ -1270,9 +1322,9 @@
                 mCallState[phoneId] = state;
                 mCallIncomingNumber[phoneId] = incomingNumber;
                 for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
-                            (r.subId == subId) &&
-                            (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
+                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.EVENT_CALL_STATE_CHANGED)
+                            && (r.subId == subId)
+                            && (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
                         try {
                             String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId);
                             r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
@@ -1312,8 +1364,9 @@
                         log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId
                                 + " phoneId=" + phoneId + " state=" + state);
                     }
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SERVICE_STATE) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_SERVICE_STATE_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
 
                         try {
                             ServiceState stateToSend;
@@ -1374,7 +1427,7 @@
                     try {
                         if ((activationType == SIM_ACTIVATION_TYPE_VOICE)
                                 && r.matchPhoneStateListenerEvent(
-                                        PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE)
+                                        PhoneStateListener.EVENT_VOICE_ACTIVATION_STATE_CHANGED)
                                 && idMatch(r.subId, subId, phoneId)) {
                             if (DBG) {
                                 log("notifyVoiceActivationStateForPhoneId: callback.onVASC r=" + r
@@ -1385,7 +1438,7 @@
                         }
                         if ((activationType == SIM_ACTIVATION_TYPE_DATA)
                                 && r.matchPhoneStateListenerEvent(
-                                        PhoneStateListener.LISTEN_DATA_ACTIVATION_STATE)
+                                        PhoneStateListener.EVENT_DATA_ACTIVATION_STATE_CHANGED)
                                 && idMatch(r.subId, subId, phoneId)) {
                             if (DBG) {
                                 log("notifyDataActivationStateForPhoneId: callback.onDASC r=" + r
@@ -1424,9 +1477,11 @@
                         log("notifySignalStrengthForPhoneId: r=" + r + " subId=" + subId
                                 + " phoneId=" + phoneId + " ss=" + signalStrength);
                     }
-                    if ((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTHS)
+                    if ((r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)
                             || r.matchPhoneStateListenerEvent(
-                                    PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH))
+                                    PhoneStateListener.
+                                            EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG) {
@@ -1439,8 +1494,9 @@
                             mRemoveList.add(r.binder);
                         }
                     }
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SIGNAL_STRENGTH) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             int gsmSignalStrength = signalStrength.getGsmSignalStrength();
                             int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength);
@@ -1486,8 +1542,8 @@
                 }
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            PhoneStateListener.EVENT_CARRIER_NETWORK_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onCarrierNetworkChange(active);
                         } catch (RemoteException ex) {
@@ -1517,9 +1573,10 @@
             if (validatePhoneId(phoneId)) {
                 mCellInfo.set(phoneId, cellInfo);
                 for (Record r : mRecords) {
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO) &&
-                            idMatch(r.subId, subId, phoneId) &&
-                            (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                    if (validateEventAndUserLocked(
+                            r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)
+                            && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                     && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
                             if (DBG_LOC) {
@@ -1551,8 +1608,8 @@
                 mMessageWaiting[phoneId] = mwi;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onMessageWaitingIndicatorChanged(mwi);
                         } catch (RemoteException ex) {
@@ -1578,8 +1635,8 @@
                 mUserMobileDataState[phoneId] = state;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onUserMobileDataStateChanged(state);
                         } catch (RemoteException ex) {
@@ -1617,7 +1674,7 @@
                 mTelephonyDisplayInfos[phoneId] = telephonyDisplayInfo;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
+                            PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)
                             && idMatchWithoutDefaultPhoneCheck(r.subId, subId)) {
                         try {
                             r.callback.onDisplayInfoChanged(telephonyDisplayInfo);
@@ -1649,8 +1706,8 @@
                 mCallForwarding[phoneId] = cfi;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onCallForwardingIndicatorChanged(cfi);
                         } catch (RemoteException ex) {
@@ -1677,8 +1734,9 @@
                 mDataActivity[phoneId] = state;
                 for (Record r : mRecords) {
                     // Notify by correct subId.
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_DATA_ACTIVITY_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onDataActivity(state);
                         } catch (RemoteException ex) {
@@ -1725,7 +1783,7 @@
                     mLocalLog.log(str);
                     for (Record r : mRecords) {
                         if (r.matchPhoneStateListenerEvent(
-                                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE)
+                                PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)
                                 && idMatch(r.subId, subId, phoneId)) {
                             try {
                                 if (DBG) {
@@ -1747,12 +1805,10 @@
                         preciseState.getApnSetting());
                 PreciseDataConnectionState oldState = mPreciseDataConnectionStates.get(phoneId)
                         .remove(key);
-                log("Jack: oldState=" + oldState);
-                log("Jack: newState=" + preciseState);
                 if (!Objects.equals(oldState, preciseState)) {
                     for (Record r : mRecords) {
                         if (r.matchPhoneStateListenerEvent(
-                                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE)
+                                PhoneStateListener.EVENT_PRECISE_DATA_CONNECTION_STATE_CHANGED)
                                 && idMatch(r.subId, subId, phoneId)) {
                             try {
                                 r.callback.onPreciseDataConnectionStateChanged(preciseState);
@@ -1797,9 +1853,10 @@
             if (validatePhoneId(phoneId) && !Objects.equals(cellIdentity, mCellIdentity[phoneId])) {
                 mCellIdentity[phoneId] = cellIdentity;
                 for (Record r : mRecords) {
-                    if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION) &&
-                            idMatch(r.subId, subId, phoneId) &&
-                            (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
+                    if (validateEventAndUserLocked(
+                            r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)
+                            && (checkCoarseLocationAccess(r, Build.VERSION_CODES.BASE)
                                     && checkFineLocationAccess(r, Build.VERSION_CODES.Q))) {
                         try {
                             if (DBG_LOC) {
@@ -1850,7 +1907,8 @@
                 }
 
                 for (Record r : mRecords) {
-                    if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE)
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_PRECISE_CALL_STATE_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onPreciseCallStateChanged(mPreciseCallState[phoneId]);
@@ -1859,7 +1917,7 @@
                         }
                     }
                     if (notifyCallAttributes && r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
+                            PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
@@ -1908,7 +1966,7 @@
                 mImsReasonInfo.set(phoneId, imsReasonInfo);
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_IMS_CALL_DISCONNECT_CAUSES)
+                            PhoneStateListener.EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
@@ -1940,8 +1998,8 @@
                 mSrvccState[phoneId] = state;
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_SRVCC_STATE_CHANGED) &&
-                            idMatch(r.subId, subId, phoneId)) {
+                            PhoneStateListener.EVENT_SRVCC_STATE_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
                                 log("notifySrvccStateChanged: mSrvccState=" + state + " r=" + r);
@@ -1969,7 +2027,7 @@
                         log("notifyOemHookRawEventForSubscriber:  r=" + r + " subId=" + subId);
                     }
                     if ((r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT))
+                            PhoneStateListener.EVENT_OEM_HOOK_RAW))
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onOemHookRawEvent(rawData);
@@ -1997,7 +2055,7 @@
 
             for (Record r : mRecords) {
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) {
+                        PhoneStateListener.EVENT_PHONE_CAPABILITY_CHANGED)) {
                     try {
                         r.callback.onPhoneCapabilityChanged(capability);
                     } catch (RemoteException ex) {
@@ -2022,7 +2080,7 @@
         synchronized (mRecords) {
             for (Record r : mRecords) {
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) {
+                        PhoneStateListener.EVENT_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGED)) {
                     try {
                         r.callback.onActiveDataSubIdChanged(activeDataSubId);
                     } catch (RemoteException ex) {
@@ -2049,7 +2107,7 @@
 
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_RADIO_POWER_STATE_CHANGED)
+                            PhoneStateListener.EVENT_RADIO_POWER_STATE_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onRadioPowerStateChanged(state);
@@ -2078,7 +2136,7 @@
 
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST)
+                            PhoneStateListener.EVENT_EMERGENCY_NUMBER_LIST_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onEmergencyNumberListChanged(mEmergencyNumberList);
@@ -2110,7 +2168,7 @@
             for (Record r : mRecords) {
                 // Send to all listeners regardless of subscription
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_CALL)) {
+                        PhoneStateListener.EVENT_OUTGOING_EMERGENCY_CALL)) {
                     try {
                         r.callback.onOutgoingEmergencyCall(emergencyNumber, subId);
                     } catch (RemoteException ex) {
@@ -2134,7 +2192,7 @@
                 for (Record r : mRecords) {
                     // Send to all listeners regardless of subscription
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_OUTGOING_EMERGENCY_SMS)) {
+                            PhoneStateListener.EVENT_OUTGOING_EMERGENCY_SMS)) {
                         try {
                             r.callback.onOutgoingEmergencySms(emergencyNumber, subId);
                         } catch (RemoteException ex) {
@@ -2164,7 +2222,7 @@
 
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_CALL_ATTRIBUTES_CHANGED)
+                            PhoneStateListener.EVENT_CALL_ATTRIBUTES_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
@@ -2195,7 +2253,7 @@
             if (validatePhoneId(phoneId)) {
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_REGISTRATION_FAILURE)
+                            PhoneStateListener.EVENT_REGISTRATION_FAILURE)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             r.callback.onRegistrationFailed(
@@ -2238,7 +2296,7 @@
                 if (VDBG) log("listen: call onBarringInfoChanged=" + barringInfo);
                 for (Record r : mRecords) {
                     if (r.matchPhoneStateListenerEvent(
-                            PhoneStateListener.LISTEN_BARRING_INFO)
+                            PhoneStateListener.EVENT_BARRING_INFO_CHANGED)
                             && idMatch(r.subId, subId, phoneId)) {
                         try {
                             if (DBG_LOC) {
@@ -2258,6 +2316,81 @@
         }
     }
 
+    /**
+     * Send a notification to registrants that the configs of physical channel has changed for
+     * a particular subscription.
+     *
+     * @param subId the subId
+     * @param configs a list of {@link PhysicalChannelConfig}, the configs of physical channel.
+     */
+    public void notifyPhysicalChannelConfigForSubscriber(
+            int subId, List<PhysicalChannelConfig> configs) {
+        if (!checkNotifyPermission("notifyPhysicalChannelConfig()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyPhysicalChannelConfig: subId=" + subId + " configs=" + configs);
+        }
+
+        synchronized (mRecords) {
+            int phoneId = SubscriptionManager.getPhoneId(subId);
+            if (validatePhoneId(phoneId)) {
+                mPhysicalChannelConfigs.set(phoneId, configs.get(phoneId));
+                for (Record r : mRecords) {
+                    if (r.matchPhoneStateListenerEvent(
+                            PhoneStateListener.EVENT_PHYSICAL_CHANNEL_CONFIG_CHANGED)
+                            && idMatch(r.subId, subId, phoneId)) {
+                        try {
+                            if (DBG_LOC) {
+                                log("notifyPhysicalChannelConfig: "
+                                        + "mPhysicalChannelConfigs="
+                                        + configs + " r=" + r);
+                            }
+                            r.callback.onPhysicalChannelConfigChanged(configs);
+                        } catch (RemoteException ex) {
+                            mRemoveList.add(r.binder);
+                        }
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
+    /**
+     * Notify that the data enabled has changed.
+     *
+     * @param enabled True if data is enabled, otherwise disabled.
+     * @param reason  Reason for data enabled/disabled. See {@code DATA_*} in
+     *                {@link TelephonyManager}.
+     */
+    public void notifyDataEnabled(boolean enabled,
+                                  @TelephonyManager.DataEnabledReason int reason) {
+        if (!checkNotifyPermission("notifyDataEnabled()")) {
+            return;
+        }
+
+        if (VDBG) {
+            log("notifyDataEnabled: enabled=" + enabled + " reason=" + reason);
+        }
+
+        mIsDataEnabled = enabled;
+        mDataEnabledReason = reason;
+        synchronized (mRecords) {
+            for (Record r : mRecords) {
+                if (r.matchPhoneStateListenerEvent(
+                        PhoneStateListener.EVENT_DATA_ENABLED_CHANGED)) {
+                    try {
+                        r.callback.onDataEnabledChanged(enabled, reason);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
 
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
@@ -2310,6 +2443,9 @@
             pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
             pw.println("mDefaultPhoneId=" + mDefaultPhoneId);
             pw.println("mDefaultSubId=" + mDefaultSubId);
+            pw.println("mPhysicalChannelConfigs=" + mPhysicalChannelConfigs);
+            pw.println("mIsDataEnabled=" + mIsDataEnabled);
+            pw.println("mDataEnabledReason=" + mDataEnabledReason);
 
             pw.decreaseIndent();
 
@@ -2538,22 +2674,29 @@
                 == PackageManager.PERMISSION_GRANTED;
     }
 
-    private boolean checkListenerPermission(int events, int subId, String callingPackage,
+    private boolean checkListenerPermission(Set<Integer> events, int subId, String callingPackage,
             @Nullable String callingFeatureId, String message) {
         LocationAccessPolicy.LocationPermissionQuery.Builder locationQueryBuilder =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
-                .setCallingPackage(callingPackage)
-                .setMethod(message + " events: " + events)
-                .setCallingPid(Binder.getCallingPid())
-                .setCallingUid(Binder.getCallingUid());
+                        .setCallingPackage(callingPackage)
+                        .setMethod(message + " events: " + events)
+                        .setCallingPid(Binder.getCallingPid())
+                        .setCallingUid(Binder.getCallingUid());
 
-        if ((events & ENFORCE_LOCATION_PERMISSION_MASK) != 0) {
+        boolean shouldCheckLocationPermissions = false;
+
+        if (isLocationPermissionRequired(events)) {
             // Everything that requires fine location started in Q. So far...
             locationQueryBuilder.setMinSdkVersionForFine(Build.VERSION_CODES.Q);
             // If we're enforcing fine starting in Q, we also want to enforce coarse even for
             // older SDK versions.
             locationQueryBuilder.setMinSdkVersionForCoarse(0);
+            shouldCheckLocationPermissions = true;
+        }
 
+        boolean isPermissionCheckSuccessful = true;
+
+        if (shouldCheckLocationPermissions) {
             LocationAccessPolicy.LocationPermissionResult result =
                     LocationAccessPolicy.checkLocationPermission(
                             mContext, locationQueryBuilder.build());
@@ -2562,18 +2705,18 @@
                     throw new SecurityException("Unable to listen for events " + events + " due to "
                             + "insufficient location permissions.");
                 case DENIED_SOFT:
-                    return false;
+                    isPermissionCheckSuccessful = false;
             }
         }
 
-        if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
+        if (isPhoneStatePermissionRequired(events)) {
             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
                     mContext, subId, callingPackage, callingFeatureId, message)) {
-                return false;
+                isPermissionCheckSuccessful = false;
             }
         }
 
-        if ((events & ENFORCE_PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
+        if (isPrecisePhoneStatePermissionRequired(events)) {
             // check if calling app has either permission READ_PRECISE_PHONE_STATE
             // or with carrier privileges
             try {
@@ -2584,47 +2727,46 @@
             }
         }
 
-        if ((events & READ_ACTIVE_EMERGENCY_SESSION_PERMISSION_MASK) != 0) {
+        if (isActiveEmergencySessionPermissionRequired(events)) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
         }
 
-        if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
+        if ((events.contains(PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED))) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null);
         }
 
-        if ((events & READ_PRIVILEGED_PHONE_STATE_PERMISSION_MASK) != 0) {
+        if (isPrivilegedPhoneStatePermissionRequired(events)) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
-
-        return true;
+        return isPermissionCheckSuccessful;
     }
 
     private void handleRemoveListLocked() {
         int size = mRemoveList.size();
         if (VDBG) log("handleRemoveListLocked: mRemoveList.size()=" + size);
         if (size > 0) {
-            for (IBinder b: mRemoveList) {
+            for (IBinder b : mRemoveList) {
                 remove(b);
             }
             mRemoveList.clear();
         }
     }
 
-    private boolean validateEventsAndUserLocked(Record r, int events) {
+    private boolean validateEventAndUserLocked(Record r, int event) {
         int foregroundUser;
         long callingIdentity = Binder.clearCallingIdentity();
         boolean valid = false;
         try {
             foregroundUser = ActivityManager.getCurrentUser();
             valid = UserHandle.getUserId(r.callerUid) == foregroundUser
-                    && r.matchPhoneStateListenerEvent(events);
+                    && r.matchPhoneStateListenerEvent(event);
             if (DBG | DBG_LOC) {
-                log("validateEventsAndUserLocked: valid=" + valid
+                log("validateEventAndUserLocked: valid=" + valid
                         + " r.callerUid=" + r.callerUid + " foregroundUser=" + foregroundUser
-                        + " r.events=" + r.events + " events=" + events);
+                        + " r.eventList=" + r.eventList + " event=" + event);
             }
         } finally {
             Binder.restoreCallingIdentity(callingIdentity);
@@ -2677,6 +2819,11 @@
         }
     }
 
+    /**
+     * Note -- this method should only be used at the site of a permission check if you need to
+     * explicitly allow apps below a certain SDK level access regardless of location permissions.
+     * If you don't need app compat logic, use {@link #checkFineLocationAccess(Record)}.
+     */
     private boolean checkFineLocationAccess(Record r, int minSdk) {
         LocationAccessPolicy.LocationPermissionQuery query =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
@@ -2695,6 +2842,11 @@
         });
     }
 
+    /**
+     * Note -- this method should only be used at the site of a permission check if you need to
+     * explicitly allow apps below a certain SDK level access regardless of location permissions.
+     * If you don't need app compat logic, use {@link #checkCoarseLocationAccess(Record)}.
+     */
     private boolean checkCoarseLocationAccess(Record r, int minSdk) {
         LocationAccessPolicy.LocationPermissionQuery query =
                 new LocationAccessPolicy.LocationPermissionQuery.Builder()
@@ -2714,9 +2866,14 @@
     }
 
     private void checkPossibleMissNotify(Record r, int phoneId) {
-        int events = r.events;
+        Set<Integer> events = r.eventList;
 
-        if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
+        if (events == null || events.isEmpty()) {
+            log("checkPossibleMissNotify: events = null.");
+            return;
+        }
+
+        if ((events.contains(PhoneStateListener.EVENT_SERVICE_STATE_CHANGED))) {
             try {
                 if (VDBG) log("checkPossibleMissNotify: onServiceStateChanged state=" +
                         mServiceState[phoneId]);
@@ -2735,8 +2892,9 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0
-                || (events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTHS_CHANGED)
+                || events.contains(
+                PhoneStateListener.EVENT_ALWAYS_REPORTED_SIGNAL_STRENGTH_CHANGED)) {
             try {
                 if (mSignalStrength[phoneId] != null) {
                     SignalStrength signalStrength = mSignalStrength[phoneId];
@@ -2751,7 +2909,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_SIGNAL_STRENGTH_CHANGED)) {
             try {
                 if (mSignalStrength[phoneId] != null) {
                     int gsmSignalStrength = mSignalStrength[phoneId]
@@ -2768,7 +2926,7 @@
             }
         }
 
-        if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
+        if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_INFO_CHANGED)) {
             try {
                 if (DBG_LOC) {
                     log("checkPossibleMissNotify: onCellInfoChanged[" + phoneId + "] = "
@@ -2783,7 +2941,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_USER_MOBILE_DATA_STATE) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_USER_MOBILE_DATA_STATE_CHANGED)) {
             try {
                 if (VDBG) {
                     log("checkPossibleMissNotify: onUserMobileDataStateChanged phoneId="
@@ -2795,7 +2953,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_DISPLAY_INFO_CHANGED)) {
             try {
                 if (VDBG) {
                     log("checkPossibleMissNotify: onDisplayInfoChanged phoneId="
@@ -2809,7 +2967,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_MESSAGE_WAITING_INDICATOR_CHANGED)) {
             try {
                 if (VDBG) {
                     log("checkPossibleMissNotify: onMessageWaitingIndicatorChanged phoneId="
@@ -2822,7 +2980,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_CALL_FORWARDING_INDICATOR_CHANGED)) {
             try {
                 if (VDBG) {
                     log("checkPossibleMissNotify: onCallForwardingIndicatorChanged phoneId="
@@ -2835,7 +2993,7 @@
             }
         }
 
-        if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_LOCATION)) {
+        if (validateEventAndUserLocked(r, PhoneStateListener.EVENT_CELL_LOCATION_CHANGED)) {
             try {
                 if (DBG_LOC) {
                     log("checkPossibleMissNotify: onCellLocationChanged mCellIdentity = "
@@ -2851,7 +3009,7 @@
             }
         }
 
-        if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
+        if (events.contains(PhoneStateListener.EVENT_DATA_CONNECTION_STATE_CHANGED)) {
             try {
                 if (DBG) {
                     log("checkPossibleMissNotify: onDataConnectionStateChanged(mDataConnectionState"
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index c1b1b6a..952193b 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -246,11 +246,6 @@
             return;
         }
 
-        if (mNetwork.linkProperties == null) {
-            Log.e(TAG, "startClat: Can't start clat with null LinkProperties");
-            return;
-        }
-
         String baseIface = mNetwork.linkProperties.getInterfaceName();
         if (baseIface == null) {
             Log.e(TAG, "startClat: Can't start clat on null interface");
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index b0a73f1..ba6cbcd 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -136,12 +136,12 @@
     // This Network object should always be used if possible, so as to encourage reuse of the
     // enclosed socket factory and connection pool.  Avoid creating other Network objects.
     // This Network object is always valid.
-    public final Network network;
-    public LinkProperties linkProperties;
+    @NonNull public final Network network;
+    @NonNull public LinkProperties linkProperties;
     // This should only be modified by ConnectivityService, via setNetworkCapabilities().
     // TODO: make this private with a getter.
-    public NetworkCapabilities networkCapabilities;
-    public final NetworkAgentConfig networkAgentConfig;
+    @NonNull public NetworkCapabilities networkCapabilities;
+    @NonNull public final NetworkAgentConfig networkAgentConfig;
 
     // Underlying networks declared by the agent. Only set if supportsUnderlyingNetworks is true.
     // The networks in this list might be declared by a VPN app using setUnderlyingNetworks and are
@@ -329,6 +329,12 @@
             Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
             IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber,
             int creatorUid) {
+        Objects.requireNonNull(net);
+        Objects.requireNonNull(info);
+        Objects.requireNonNull(lp);
+        Objects.requireNonNull(nc);
+        Objects.requireNonNull(context);
+        Objects.requireNonNull(config);
         networkAgent = na;
         network = net;
         networkInfo = info;
@@ -536,19 +542,22 @@
         }
 
         @Override
-        public void sendNetworkCapabilities(NetworkCapabilities nc) {
+        public void sendNetworkCapabilities(@NonNull NetworkCapabilities nc) {
+            Objects.requireNonNull(nc);
             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED,
                     new Pair<>(NetworkAgentInfo.this, nc)).sendToTarget();
         }
 
         @Override
-        public void sendLinkProperties(LinkProperties lp) {
+        public void sendLinkProperties(@NonNull LinkProperties lp) {
+            Objects.requireNonNull(lp);
             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_PROPERTIES_CHANGED,
                     new Pair<>(NetworkAgentInfo.this, lp)).sendToTarget();
         }
 
         @Override
-        public void sendNetworkInfo(NetworkInfo info) {
+        public void sendNetworkInfo(@NonNull NetworkInfo info) {
+            Objects.requireNonNull(info);
             mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_INFO_CHANGED,
                     new Pair<>(NetworkAgentInfo.this, info)).sendToTarget();
         }
@@ -603,7 +612,7 @@
      *
      * @return the old capabilities of this network.
      */
-    public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
+    @NonNull public synchronized NetworkCapabilities getAndSetNetworkCapabilities(
             @NonNull final NetworkCapabilities nc) {
         final NetworkCapabilities oldNc = networkCapabilities;
         networkCapabilities = nc;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index a65f809..fb1e819 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -439,6 +439,11 @@
         mEnableTeardown = enableTeardown;
     }
 
+    @VisibleForTesting
+    public boolean getEnableTeardown() {
+        return mEnableTeardown;
+    }
+
     /**
      * Update current state, dispatching event to listeners.
      */
@@ -2146,6 +2151,11 @@
 
         // Start a new LegacyVpnRunner and we are done!
         mVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile);
+        startLegacyVpnRunner();
+    }
+
+    @VisibleForTesting
+    protected void startLegacyVpnRunner() {
         mVpnRunner.start();
     }
 
diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java
index ea1d8da..ea2788c 100644
--- a/services/core/java/com/android/server/net/LockdownVpnTracker.java
+++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java
@@ -34,7 +34,6 @@
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
 import android.os.Handler;
-import android.security.Credentials;
 import android.security.KeyStore;
 import android.text.TextUtils;
 import android.util.Log;
@@ -70,6 +69,7 @@
     @NonNull private final Handler mHandler;
     @NonNull private final Vpn mVpn;
     @NonNull private final VpnProfile mProfile;
+    @NonNull private final KeyStore mKeyStore;
 
     @NonNull private final Object mStateLock = new Object();
 
@@ -81,13 +81,10 @@
 
     private int mErrorCount;
 
-    public static boolean isEnabled() {
-        return KeyStore.getInstance().contains(Credentials.LOCKDOWN_VPN);
-    }
-
     public LockdownVpnTracker(@NonNull Context context,
             @NonNull ConnectivityService connService,
             @NonNull Handler handler,
+            @NonNull KeyStore keyStore,
             @NonNull Vpn vpn,
             @NonNull VpnProfile profile) {
         mContext = Objects.requireNonNull(context);
@@ -95,6 +92,7 @@
         mHandler = Objects.requireNonNull(handler);
         mVpn = Objects.requireNonNull(vpn);
         mProfile = Objects.requireNonNull(profile);
+        mKeyStore = Objects.requireNonNull(keyStore);
         mNotificationManager = mContext.getSystemService(NotificationManager.class);
 
         final Intent configIntent = new Intent(ACTION_VPN_SETTINGS);
@@ -157,7 +155,7 @@
                 try {
                     // Use the privileged method because Lockdown VPN is initiated by the system, so
                     // no additional permission checks are necessary.
-                    mVpn.startLegacyVpnPrivileged(mProfile, KeyStore.getInstance(), egressProp);
+                    mVpn.startLegacyVpnPrivileged(mProfile, mKeyStore, egressProp);
                 } catch (IllegalStateException e) {
                     mAcceptedEgressIface = null;
                     Log.e(TAG, "Failed to start VPN", e);
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index dd507a3..01eeb31 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -94,9 +94,12 @@
 
     @Override
     @RequiresPermission(android.Manifest.permission.DUMP)
-    public void cancelBugreport() {
+    public void cancelBugreport(int callingUidUnused, String callingPackage) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP,
                 "cancelBugreport");
+        int callingUid = Binder.getCallingUid();
+        mAppOps.checkPackage(callingUid, callingPackage);
+
         synchronized (mLock) {
             IDumpstate ds = getDumpstateBinderServiceLocked();
             if (ds == null) {
@@ -104,7 +107,11 @@
                 return;
             }
             try {
-                ds.cancelBugreport();
+                // Note: this may throw SecurityException back out to the caller if they aren't
+                // allowed to cancel the report, in which case we should NOT be setting ctl.stop,
+                // since that would unintentionally kill some other app's bugreport, which we
+                // specifically disallow.
+                ds.cancelBugreport(callingUid, callingPackage);
             } catch (RemoteException e) {
                 Slog.e(TAG, "RemoteException in cancelBugreport", e);
             }
@@ -182,7 +189,7 @@
             // lifecycle correctly. If we don't subsequent callers will get
             // BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS error.
             // Note that listener will be notified by the death recipient below.
-            cancelBugreport();
+            cancelBugreport(callingUid, callingPackage);
         }
     }
 
diff --git a/services/core/java/com/android/server/storage/StorageSessionController.java b/services/core/java/com/android/server/storage/StorageSessionController.java
index 0d059ae..8345424 100644
--- a/services/core/java/com/android/server/storage/StorageSessionController.java
+++ b/services/core/java/com/android/server/storage/StorageSessionController.java
@@ -361,7 +361,11 @@
         }
     }
 
+    private static boolean isSupportedVolume(VolumeInfo vol) {
+        return isEmulatedOrPublic(vol) || vol.type == VolumeInfo.TYPE_STUB;
+    }
+
     private boolean shouldHandle(@Nullable VolumeInfo vol) {
-        return mIsFuseEnabled && !mIsResetting && (vol == null || isEmulatedOrPublic(vol));
+        return mIsFuseEnabled && !mIsResetting && (vol == null || isSupportedVolume(vol));
     }
 }
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 42f12eb..0772503 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -51,7 +51,8 @@
     public interface Callback {
         void onDeviceAvailable(TvInputHardwareInfo info, TvStreamConfig[] configs);
         void onDeviceUnavailable(int deviceId);
-        void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs);
+        void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+                int cableConnectionStatus);
         void onFirstFrameCaptured(int deviceId, int streamId);
     }
 
@@ -142,8 +143,9 @@
         mHandler.obtainMessage(EVENT_DEVICE_UNAVAILABLE, deviceId, 0).sendToTarget();
     }
 
-    private void streamConfigsChangedFromNative(int deviceId) {
-        mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId, 0).sendToTarget();
+    private void streamConfigsChangedFromNative(int deviceId, int cableConnectionStatus) {
+        mHandler.obtainMessage(EVENT_STREAM_CONFIGURATION_CHANGED, deviceId,
+            cableConnectionStatus).sendToTarget();
     }
 
     private void firstFrameCapturedFromNative(int deviceId, int streamId) {
@@ -184,6 +186,7 @@
             case EVENT_STREAM_CONFIGURATION_CHANGED: {
                 TvStreamConfig[] configs;
                 int deviceId = msg.arg1;
+                int cableConnectionStatus = msg.arg2;
                 synchronized (mLock) {
                     if (DEBUG) {
                         Slog.d(TAG, "EVENT_STREAM_CONFIGURATION_CHANGED: deviceId = " + deviceId);
@@ -191,7 +194,7 @@
                     retrieveStreamConfigsLocked(deviceId);
                     configs = mStreamConfigs.get(deviceId);
                 }
-                mCallback.onStreamConfigurationChanged(deviceId, configs);
+                mCallback.onStreamConfigurationChanged(deviceId, configs, cableConnectionStatus);
                 break;
             }
 
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 2314afc..3dfb99e 100755
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -156,6 +156,7 @@
         synchronized (mLock) {
             Connection connection = new Connection(info);
             connection.updateConfigsLocked(configs);
+            connection.updateCableConnectionStatusLocked(info.getCableConnectionStatus());
             mConnections.put(info.getDeviceId(), connection);
             buildHardwareListLocked();
             mHandler.obtainMessage(
@@ -202,7 +203,8 @@
     }
 
     @Override
-    public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs) {
+    public void onStreamConfigurationChanged(int deviceId, TvStreamConfig[] configs,
+            int cableConnectionStatus) {
         synchronized (mLock) {
             Connection connection = mConnections.get(deviceId);
             if (connection == null) {
@@ -211,12 +213,22 @@
                 return;
             }
             int previousConfigsLength = connection.getConfigsLengthLocked();
+            int previousCableConnectionStatus = connection.getInputStateLocked();
             connection.updateConfigsLocked(configs);
             String inputId = mHardwareInputIdMap.get(deviceId);
-            if (inputId != null
-                    && (previousConfigsLength == 0) != (connection.getConfigsLengthLocked() == 0)) {
-                mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
-                    connection.getInputStateLocked(), 0, inputId).sendToTarget();
+            if (inputId != null) {
+                if (connection.updateCableConnectionStatusLocked(cableConnectionStatus)) {
+                    if (previousCableConnectionStatus != connection.getInputStateLocked()) {
+                        mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+                            connection.getInputStateLocked(), 0, inputId).sendToTarget();
+                    }
+                } else {
+                    if ((previousConfigsLength == 0)
+                            != (connection.getConfigsLengthLocked() == 0)) {
+                        mHandler.obtainMessage(ListenerHandler.STATE_CHANGED,
+                            connection.getInputStateLocked(), 0, inputId).sendToTarget();
+                    }
+                }
             }
             ITvInputHardwareCallback callback = connection.getCallbackLocked();
             if (callback != null) {
@@ -624,7 +636,7 @@
     }
 
     private class Connection implements IBinder.DeathRecipient {
-        private final TvInputHardwareInfo mHardwareInfo;
+        private TvInputHardwareInfo mHardwareInfo;
         private TvInputInfo mInfo;
         private TvInputHardwareImpl mHardware = null;
         private ITvInputHardwareCallback mCallback;
@@ -633,6 +645,7 @@
         private Integer mResolvedUserId = null;
         private Runnable mOnFirstFrameCaptured;
         private ResourceClientProfile mResourceClientProfile = null;
+        private boolean mIsCableConnectionStatusUpdated = false;
 
         public Connection(TvInputHardwareInfo hardwareInfo) {
             mHardwareInfo = hardwareInfo;
@@ -735,6 +748,17 @@
                     + " }";
         }
 
+        public boolean updateCableConnectionStatusLocked(int cableConnectionStatus) {
+            // Update connection status only if it's not default value
+            if (cableConnectionStatus != TvInputHardwareInfo.CABLE_CONNECTION_STATUS_UNKNOWN
+                    || mIsCableConnectionStatusUpdated) {
+                mIsCableConnectionStatusUpdated = true;
+                mHardwareInfo = mHardwareInfo.toBuilder()
+                    .cableConnectionStatus(cableConnectionStatus).build();
+            }
+            return mIsCableConnectionStatusUpdated;
+        }
+
         private int getConfigsLengthLocked() {
             return mConfigs == null ? 0 : mConfigs.length;
         }
@@ -742,7 +766,9 @@
         private int getInputStateLocked() {
             int configsLength = getConfigsLengthLocked();
             if (configsLength > 0) {
-                return INPUT_STATE_CONNECTED;
+                if (!mIsCableConnectionStatusUpdated) {
+                    return INPUT_STATE_CONNECTED;
+                }
             }
             switch (mHardwareInfo.getCableConnectionStatus()) {
                 case TvInputHardwareInfo.CABLE_CONNECTION_STATUS_CONNECTED:
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 6cd0258..d858ae4 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -20,6 +20,7 @@
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED;
 import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
@@ -1728,6 +1729,46 @@
         }
 
         @Override
+        public void pauseRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "pauseRecording");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .pauseRecording(params);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in pauseRecording", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void resumeRecording(IBinder sessionToken, @NonNull Bundle params, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "resumeRecording");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .resumeRecording(params);
+                    } catch (RemoteException | SessionNotFoundException e) {
+                        Slog.e(TAG, "error in resumeRecording", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public List<TvInputHardwareInfo> getHardwareList() throws RemoteException {
             if (mContext.checkCallingPermission(android.Manifest.permission.TV_INPUT_HARDWARE)
                     != PackageManager.PERMISSION_GRANTED) {
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index 4e1a234..a5311f3 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -261,7 +261,7 @@
 
     void onDeviceAvailable(const TvInputDeviceInfo& info);
     void onDeviceUnavailable(int deviceId);
-    void onStreamConfigurationsChanged(int deviceId);
+    void onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus);
     void onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded);
 
 private:
@@ -519,7 +519,7 @@
             deviceId);
 }
 
-void JTvInputHal::onStreamConfigurationsChanged(int deviceId) {
+void JTvInputHal::onStreamConfigurationsChanged(int deviceId, int cableConnectionStatus) {
     {
         Mutex::Autolock autoLock(&mLock);
         KeyedVector<int, Connection>& connections = mConnections.editValueFor(deviceId);
@@ -529,10 +529,8 @@
         connections.clear();
     }
     JNIEnv* env = AndroidRuntime::getJNIEnv();
-    env->CallVoidMethod(
-            mThiz,
-            gTvInputHalClassInfo.streamConfigsChanged,
-            deviceId);
+    env->CallVoidMethod(mThiz, gTvInputHalClassInfo.streamConfigsChanged, deviceId,
+                        cableConnectionStatus);
 }
 
 void JTvInputHal::onCaptured(int deviceId, int streamId, uint32_t seq, bool succeeded) {
@@ -572,7 +570,8 @@
             mHal->onDeviceUnavailable(mEvent.deviceInfo.deviceId);
         } break;
         case TvInputEventType::STREAM_CONFIGURATIONS_CHANGED: {
-            mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId);
+            int cableConnectionStatus = static_cast<int>(mEvent.deviceInfo.cableConnectionStatus);
+            mHal->onStreamConfigurationsChanged(mEvent.deviceInfo.deviceId, cableConnectionStatus);
         } break;
         default:
             ALOGE("Unrecognizable event");
@@ -688,9 +687,8 @@
             "deviceAvailableFromNative", "(Landroid/media/tv/TvInputHardwareInfo;)V");
     GET_METHOD_ID(
             gTvInputHalClassInfo.deviceUnavailable, clazz, "deviceUnavailableFromNative", "(I)V");
-    GET_METHOD_ID(
-            gTvInputHalClassInfo.streamConfigsChanged, clazz,
-            "streamConfigsChangedFromNative", "(I)V");
+    GET_METHOD_ID(gTvInputHalClassInfo.streamConfigsChanged, clazz,
+                  "streamConfigsChangedFromNative", "(II)V");
     GET_METHOD_ID(
             gTvInputHalClassInfo.firstFrameCaptured, clazz,
             "firstFrameCapturedFromNative", "(II)V");
diff --git a/services/searchui/OWNERS b/services/searchui/OWNERS
new file mode 100644
index 0000000..92835c2
--- /dev/null
+++ b/services/searchui/OWNERS
@@ -0,0 +1,2 @@
+hyunyoungs@google.com
+sfufa@google.com
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 724a9e4..e55720c 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -109,6 +109,20 @@
  */
 public abstract class Connection extends Conferenceable {
 
+    /**@hide*/
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = "STATE_", value = {
+            STATE_INITIALIZING,
+            STATE_NEW,
+            STATE_RINGING,
+            STATE_DIALING,
+            STATE_ACTIVE,
+            STATE_HOLDING,
+            STATE_DISCONNECTED,
+            STATE_PULLING_CALL
+    })
+    public @interface ConnectionState {}
+
     /**
      * The connection is initializing. This is generally the first state for a {@code Connection}
      * returned by a {@link ConnectionService}.
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index b785037..6571858 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -28,8 +28,6 @@
 /**
  * Define capability of a modem group. That is, the capabilities
  * are shared between those modems defined by list of modem IDs.
- *
- * @hide
  */
 public final class PhoneCapability implements Parcelable {
     // Hardcoded default DSDS capability.
diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java
index af62ba4..327d631 100644
--- a/telephony/java/android/telephony/PhysicalChannelConfig.java
+++ b/telephony/java/android/telephony/PhysicalChannelConfig.java
@@ -17,6 +17,8 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.NetworkType;
@@ -26,12 +28,10 @@
 import java.util.Arrays;
 import java.util.Objects;
 
-/**
- * @hide
- */
 public final class PhysicalChannelConfig implements Parcelable {
 
     // TODO(b/72993578) consolidate these enums in a central location.
+    /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({CONNECTION_PRIMARY_SERVING, CONNECTION_SECONDARY_SERVING, CONNECTION_UNKNOWN})
     public @interface ConnectionStatus {}
@@ -47,7 +47,13 @@
     public static final int CONNECTION_SECONDARY_SERVING = 2;
 
     /** Connection status is unknown. */
-    public static final int CONNECTION_UNKNOWN = Integer.MAX_VALUE;
+    public static final int CONNECTION_UNKNOWN = -1;
+
+    /** Channel number is unknown. */
+    public static final int CHANNEL_NUMBER_UNKNOWN = -1;
+
+    /** Physical Cell Id is unknown. */
+    public static final int PHYSICAL_CELL_ID_UNKNOWN = -1;
 
     /**
      * Connection status of the cell.
@@ -75,7 +81,7 @@
     private int mFrequencyRange;
 
     /**
-     * The absolute radio frequency channel number, {@link Integer#MAX_VALUE} if unknown.
+     * The absolute radio frequency channel number, {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
      */
     private int mChannelNumber;
 
@@ -86,7 +92,7 @@
     private int[] mContextIds;
 
     /**
-     * The physical cell identifier for this cell - PCI, PSC, {@link Integer#MAX_VALUE} if known.
+     * The physical cell identifier for this cell - PCI, PSC, {@link #PHYSICAL_CELL_ID_UNKNOWN}
      */
     private int mPhysicalCellId;
 
@@ -96,7 +102,7 @@
     }
 
     @Override
-    public void writeToParcel(Parcel dest, int flags) {
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mCellConnectionStatus);
         dest.writeInt(mCellBandwidthDownlinkKhz);
         dest.writeInt(mRat);
@@ -120,6 +126,7 @@
      * physical channel has no data call mapped to it.
      *
      * @return an integer list indicates the data call ids.
+     * @hide
      */
     public int[] getContextIds() {
         return mContextIds;
@@ -131,6 +138,7 @@
      * @see {@link ServiceState#FREQUENCY_RANGE_MID}
      * @see {@link ServiceState#FREQUENCY_RANGE_HIGH}
      * @see {@link ServiceState#FREQUENCY_RANGE_MMWAVE}
+     * @hide
      */
     @ServiceState.FrequencyRange
     public int getFrequencyRange() {
@@ -139,7 +147,7 @@
 
     /**
      * @return the absolute radio frequency channel number for this physical channel,
-     * {@link Integer#MAX_VALUE} if unknown.
+     * {@link #CHANNEL_NUMBER_UNKNOWN} if unknown.
      */
     public int getChannelNumber() {
         return mChannelNumber;
@@ -152,18 +160,20 @@
      * In EUTRAN, this value is physical layer cell identity. The range is [0, 503].
      * Reference: 3GPP TS 36.211 section 6.11.
      *
-     * In 5G RAN, this value is physical layer cell identity. The range is [0, 1008].
+     * In 5G RAN, this value is physical layer cell identity. The range is [0, 1007].
      * Reference: 3GPP TS 38.211 section 7.4.2.1.
      *
-     * @return the physical cell identifier for this cell, {@link Integer#MAX_VALUE} if unknown.
+     * @return the physical cell identifier for this cell, {@link #PHYSICAL_CELL_ID_UNKNOWN}
+     * if {@link android.telephony.CellInfo#UNAVAILABLE}.
      */
+    @IntRange(from = 0, to = 1007)
     public int getPhysicalCellId() {
         return mPhysicalCellId;
     }
 
     /**The radio technology for this physical channel. */
     @NetworkType
-    public int getRat() {
+    public int getNetworkType() {
         return mRat;
     }
 
@@ -181,7 +191,10 @@
         return mCellConnectionStatus;
     }
 
-    /** @return String representation of the connection status */
+    /**
+     * @return String representation of the connection status
+     * @hide
+     */
     private String getConnectionStatusString() {
         switch(mCellConnectionStatus) {
             case CONNECTION_PRIMARY_SERVING:
@@ -274,7 +287,10 @@
         mPhysicalCellId = builder.mPhysicalCellId;
     }
 
-    /** The builder of {@code PhysicalChannelConfig}. */
+    /**
+     * The builder of {@code PhysicalChannelConfig}.
+     * @hide
+     */
     public static final class Builder {
         private int mRat;
         private int mFrequencyRange;
@@ -284,60 +300,51 @@
         private int[] mContextIds;
         private int mPhysicalCellId;
 
-        /** @hide */
         public Builder() {
             mRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
             mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
-            mChannelNumber = Integer.MAX_VALUE;
+            mChannelNumber = CHANNEL_NUMBER_UNKNOWN;
             mCellBandwidthDownlinkKhz = 0;
             mCellConnectionStatus = CONNECTION_UNKNOWN;
             mContextIds = new int[0];
-            mPhysicalCellId = Integer.MAX_VALUE;
+            mPhysicalCellId = PHYSICAL_CELL_ID_UNKNOWN;
         }
 
-        /** @hide */
         public PhysicalChannelConfig build() {
             return new PhysicalChannelConfig(this);
         }
 
-        /** @hide */
         public Builder setRat(int rat) {
             this.mRat = rat;
             return this;
         }
 
-        /** @hide */
         public Builder setFrequencyRange(int frequencyRange) {
             this.mFrequencyRange = frequencyRange;
             return this;
         }
 
-        /** @hide */
         public Builder setChannelNumber(int channelNumber) {
             this.mChannelNumber = channelNumber;
             return this;
         }
 
-        /** @hide */
         public Builder setCellBandwidthDownlinkKhz(int cellBandwidthDownlinkKhz) {
             this.mCellBandwidthDownlinkKhz = cellBandwidthDownlinkKhz;
             return this;
         }
 
-        /** @hide */
         public Builder setCellConnectionStatus(int connectionStatus) {
             this.mCellConnectionStatus = connectionStatus;
             return this;
         }
 
-        /** @hide */
         public Builder setContextIds(int[] contextIds) {
             if (contextIds != null) Arrays.sort(contextIds);
             this.mContextIds = contextIds;
             return this;
         }
 
-        /** @hide */
         public Builder setPhysicalCellId(int physicalCellId) {
             this.mPhysicalCellId = physicalCellId;
             return this;
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
index 8a472ad..bb9c0da3 100644
--- a/telephony/java/android/telephony/SignalThresholdInfo.java
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -28,13 +28,11 @@
 
 /**
  * Defines the threshold value of the signal strength.
- * @hide
  */
 public final class SignalThresholdInfo implements Parcelable {
 
     /**
      * Unknown signal measurement type.
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_UNKNOWN = 0;
 
@@ -44,7 +42,6 @@
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#GERAN},
      *           {@link AccessNetworkConstants.AccessNetworkType#CDMA2000}
      * Reference: 3GPP TS 27.007 section 8.5.
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_RSSI = 1;
 
@@ -53,7 +50,6 @@
      * Range: -120 dBm to -25 dBm;
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#UTRAN}
      * Reference: 3GPP TS 25.123, section 9.1.1.1
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_RSCP = 2;
 
@@ -62,7 +58,6 @@
      * Range: -140 dBm to -44 dBm;
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
      * Reference: 3GPP TS 36.133 9.1.4
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_RSRP = 3;
 
@@ -71,7 +66,6 @@
      * Range: -34 dB to 3 dB;
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
      * Reference: 3GPP TS 36.133 9.1.7
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_RSRQ = 4;
 
@@ -79,7 +73,6 @@
      * Reference Signal Signal to Noise Ratio
      * Range: -20 dB to 30 dB;
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#EUTRAN}
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_RSSNR = 5;
 
@@ -88,7 +81,6 @@
      * Range: -140 dBm to -44 dBm.
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
      * Reference: 3GPP TS 38.215.
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRP = 6;
 
@@ -97,7 +89,6 @@
      * Range: -43 dB to 20 dB.
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
      * Reference: 3GPP TS 38.133 section 10.1.11.1.
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_SSRSRQ = 7;
 
@@ -106,7 +97,6 @@
      * Range: -23 dB to 40 dB
      * Used RAN: {@link AccessNetworkConstants.AccessNetworkType#NGRAN}
      * Reference: 3GPP TS 38.215 section 5.1.*, 3GPP TS 38.133 section 10.1.16.1.
-     * @hide
      */
     public static final int SIGNAL_MEASUREMENT_TYPE_SSSINR = 8;
 
@@ -316,8 +306,6 @@
 
     /**
      * Builder class to create {@link SignalThresholdInfo} objects.
-     *
-     * @hide
      */
     public static final class Builder {
         private int mRan = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
@@ -378,12 +366,22 @@
         }
 
         /**
-         * Set the signal threshold values of the corresponding signal measurement type.
+         * Set the signal strength thresholds of the corresponding signal measurement type.
          *
          * The range and unit must reference specific SignalMeasurementType.
          *
          * @param thresholds array of integer as the signal threshold values
          * @return the builder to facilitate the chaining
+         *
+         * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+         * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+         * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+         * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+         * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+         * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+         * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+         * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
+         * @see #getThresholds() for more details on signal strength thresholds
          */
         public @NonNull Builder setThresholds(@NonNull int[] thresholds) {
             Objects.requireNonNull(thresholds, "thresholds must not be null");
@@ -423,8 +421,6 @@
      * Get the radio access network type.
      *
      * @return radio access network type
-     *
-     * @hide
      */
     public @AccessNetworkConstants.RadioAccessNetworkType int getRadioAccessNetworkType() {
         return mRan;
@@ -434,8 +430,6 @@
      * Get the signal measurement type.
      *
      * @return the SignalMeasurementType value
-     *
-     * @hide
      */
     public @SignalMeasurementType int getSignalMeasurementType() {
         return mSignalMeasurementType;
@@ -457,11 +451,24 @@
     }
 
     /**
-     * Get the signal threshold values.
+     * Get the signal strength thresholds.
+     *
+     * Signal strength thresholds are a list of integer used for suggesting signal level and signal
+     * reporting criteria. The range and unit must reference specific SignalMeasurementType.
+     *
+     * Please refer to https://source.android.com/devices/tech/connect/signal-strength on how signal
+     * strength thresholds are used for signal strength reporting.
      *
      * @return array of integer of the signal thresholds
      *
-     * @hide
+     * @see #SIGNAL_MEASUREMENT_TYPE_RSSI
+     * @see #SIGNAL_MEASUREMENT_TYPE_RSCP
+     * @see #SIGNAL_MEASUREMENT_TYPE_RSRP
+     * @see #SIGNAL_MEASUREMENT_TYPE_RSRQ
+     * @see #SIGNAL_MEASUREMENT_TYPE_RSSNR
+     * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRP
+     * @see #SIGNAL_MEASUREMENT_TYPE_SSRSRQ
+     * @see #SIGNAL_MEASUREMENT_TYPE_SSSINR
      */
     public @NonNull int[] getThresholds() {
         return mThresholds.clone();
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index cedd6f3..f39ee09 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -124,6 +124,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Executor;
 import java.util.function.Consumer;
@@ -155,6 +156,7 @@
 public class TelephonyManager {
     private static final String TAG = "TelephonyManager";
 
+    private TelephonyRegistryManager mTelephonyRegistryMgr;
     /**
      * To expand the error codes for {@link TelephonyManager#updateAvailableNetworks} and
      * {@link TelephonyManager#setPreferredOpportunisticDataSubscription}.
@@ -5569,8 +5571,7 @@
     //
 
     /**
-     * Registers a listener object to receive notification of changes
-     * in specified telephony states.
+     * Registers a listener object to receive notification of changes in specified telephony states.
      * <p>
      * To register a listener, pass a {@link PhoneStateListener} and specify at least one telephony
      * state of interest in the events argument.
@@ -5580,13 +5581,15 @@
      * values.
      * <p>
      * To un-register a listener, pass the listener object and set the events argument to
-     * {@link PhoneStateListener#LISTEN_NONE LISTEN_NONE} (0).
+     * {@link PhoneStateListener#LISTEN_NONE} (0).
      *
      * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
      * applies to the given subId. Otherwise, applies to
-     * {@link SubscriptionManager#getDefaultSubscriptionId()}. To listen events for multiple subIds,
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. To listen events for multiple subIds,
      * pass a separate listener object to each TelephonyManager object created with
-     * {@link #createForSubscriptionId}.
+     * {@link #createForSubscriptionId}. Only {@link PhoneStateListener#LISTEN_CALL_STATE} event can
+     * be used to receive changes for all subIds through
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}.
      *
      * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
      * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
@@ -5596,23 +5599,28 @@
      * instability. If a process has registered too many listeners without unregistering them, it
      * may encounter an {@link IllegalStateException} when trying to register more listeners.
      *
-     * @param listener The {@link PhoneStateListener} object to register
-     *                 (or unregister)
-     * @param events The telephony state(s) of interest to the listener,
-     *               as a bitwise-OR combination of {@link PhoneStateListener}
-     *               LISTEN_ flags.
+     * @param listener The {@link PhoneStateListener} object to register (or unregister)
+     * @param events The telephony state(s) of interest to the listener, as a bitwise-OR combination
+     *               of {@link PhoneStateListener} LISTEN_ flags.
+     * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}.
      */
+    @Deprecated
     public void listen(PhoneStateListener listener, int events) {
-        if (mContext == null) return;
-        boolean notifyNow = (getITelephony() != null);
-        TelephonyRegistryManager telephonyRegistry =
-                (TelephonyRegistryManager)
-                        mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
-        if (telephonyRegistry != null) {
-            telephonyRegistry.listenForSubscriber(mSubId, getOpPackageName(), getAttributionTag(),
-                    listener, events, notifyNow);
+        if (!listener.isExecutorSet()) {
+            throw new IllegalStateException("PhoneStateListener should be created on a thread "
+                    + "with Looper.myLooper() != null");
+        }
+        boolean notifyNow = getITelephony() != null;
+        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+        if (mTelephonyRegistryMgr != null) {
+            if (events != PhoneStateListener.LISTEN_NONE) {
+                mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId,
+                        getOpPackageName(), getAttributionTag(), listener, events, notifyNow);
+            } else {
+                unregisterPhoneStateListener(listener);
+            }
         } else {
-            Rlog.w(TAG, "telephony registry not ready.");
+            throw new IllegalStateException("telephony service is null.");
         }
     }
 
@@ -14593,4 +14601,71 @@
             e.execute(() -> callback.onAuthenticationFailure(GBA_FAILURE_REASON_FEATURE_NOT_READY));
         }
     }
+
+    /**
+     * Registers a listener object to receive notification of changes in specified telephony states.
+     * <p>
+     * To register a listener, pass a {@link PhoneStateListener} which implements
+     * interfaces of events. For example,
+     * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements
+     * {@link PhoneStateListener.ServiceStateChangedListener}.
+     *
+     * At registration, and when a specified telephony state changes, the telephony manager invokes
+     * the appropriate callback method on the listener object and passes the current (updated)
+     * values.
+     * <p>
+     *
+     * If this TelephonyManager object has been created with {@link #createForSubscriptionId},
+     * applies to the given subId. Otherwise, applies to
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. To listen events for multiple subIds,
+     * pass a separate listener object to each TelephonyManager object created with
+     * {@link #createForSubscriptionId}. Only {@link PhoneStateListener.CallStateChangedListener}
+     * can be used to receive changes for all subIds through
+     * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}.
+     *
+     * Note: if you call this method while in the middle of a binder transaction, you <b>must</b>
+     * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A
+     * {@link SecurityException} will be thrown otherwise.
+     *
+     * This API should be used sparingly -- large numbers of listeners will cause system
+     * instability. If a process has registered too many listeners without unregistering them, it
+     * may encounter an {@link IllegalStateException} when trying to register more listeners.
+     *
+     * @param executor The executor of where the callback will execute.
+     * @param listener The {@link PhoneStateListener} object to register.
+     */
+    public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull PhoneStateListener listener) {
+        if (executor == null || listener == null) {
+            throw new IllegalArgumentException("PhoneStateListener and executor must be non-null");
+        }
+        mTelephonyRegistryMgr = (TelephonyRegistryManager)
+                mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE);
+        if (mTelephonyRegistryMgr != null) {
+            mTelephonyRegistryMgr.registerPhoneStateListener(executor, mSubId,
+                    getOpPackageName(), getAttributionTag(), listener, getITelephony() != null);
+        } else {
+            throw new IllegalStateException("telephony service is null.");
+        }
+    }
+
+    /**
+     * Unregister an existing {@link PhoneStateListener}.
+     *
+     * @param listener The {@link PhoneStateListener} object to unregister.
+     */
+    public void unregisterPhoneStateListener(@NonNull PhoneStateListener listener) {
+
+        if (mContext == null) {
+            throw new IllegalStateException("telephony service is null.");
+        }
+
+        mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class);
+        if (mTelephonyRegistryMgr != null) {
+            mTelephonyRegistryMgr.unregisterPhoneStateListener(mSubId, getOpPackageName(),
+                    getAttributionTag(), listener, getITelephony() != null);
+        } else {
+            throw new IllegalStateException("telephony service is null.");
+        }
+    }
 }
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
index 8e18751..16c4865 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/ConnectivityServiceIntegrationTest.kt
@@ -46,8 +46,6 @@
 import com.android.server.LocalServices
 import com.android.server.NetworkAgentWrapper
 import com.android.server.TestNetIdManager
-import com.android.server.connectivity.DefaultNetworkMetrics
-import com.android.server.connectivity.IpConnectivityMetrics
 import com.android.server.connectivity.MockableSystemProperties
 import com.android.server.connectivity.ProxyTracker
 import com.android.server.net.NetworkPolicyManagerInternal
@@ -92,10 +90,6 @@
     private lateinit var netd: INetd
     @Mock
     private lateinit var dnsResolver: IDnsResolver
-    @Mock
-    private lateinit var metricsLogger: IpConnectivityMetrics.Logger
-    @Mock
-    private lateinit var defaultMetrics: DefaultNetworkMetrics
     @Spy
     private var context = TestableContext(realContext)
 
@@ -149,7 +143,6 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        doReturn(defaultMetrics).`when`(metricsLogger).defaultNetworkMetrics()
         doNothing().`when`(context).sendStickyBroadcastAsUser(any(), any(), any())
 
         networkStackClient = TestNetworkStackClient(realContext)
@@ -173,7 +166,6 @@
     private fun makeDependencies(): ConnectivityService.Dependencies {
         val deps = spy(ConnectivityService.Dependencies())
         doReturn(networkStackClient).`when`(deps).networkStack
-        doReturn(metricsLogger).`when`(deps).metricsLogger
         doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
         doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
         doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 4a282e8..5a375d2 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -21,6 +21,7 @@
 import static android.app.PendingIntent.FLAG_IMMUTABLE;
 import static android.content.Intent.ACTION_USER_ADDED;
 import static android.content.Intent.ACTION_USER_REMOVED;
+import static android.content.Intent.ACTION_USER_UNLOCKED;
 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
 import static android.content.pm.PackageManager.MATCH_ANY_USER;
@@ -221,6 +222,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.security.Credentials;
 import android.security.KeyStore;
 import android.system.Os;
 import android.telephony.TelephonyManager;
@@ -237,14 +239,13 @@
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnInfo;
+import com.android.internal.net.VpnProfile;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.ConnectivityService.ConnectivityDiagnosticsCallbackInfo;
 import com.android.server.connectivity.ConnectivityConstants;
-import com.android.server.connectivity.DefaultNetworkMetrics;
-import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.MockableSystemProperties;
 import com.android.server.connectivity.Nat464Xlat;
 import com.android.server.connectivity.NetworkAgentInfo;
@@ -281,6 +282,7 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -367,8 +369,6 @@
     private HandlerThread mAlarmManagerThread;
     private TestNetIdManager mNetIdManager;
 
-    @Mock IpConnectivityMetrics.Logger mMetricsService;
-    @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
     @Mock DeviceIdleInternal mDeviceIdleInternal;
     @Mock INetworkManagementService mNetworkManagementService;
     @Mock INetworkStatsService mStatsService;
@@ -388,6 +388,7 @@
     @Mock MockableSystemProperties mSystemProperties;
     @Mock EthernetManager mEthernetManager;
     @Mock NetworkPolicyManager mNetworkPolicyManager;
+    @Mock KeyStore mKeyStore;
 
     private ArgumentCaptor<ResolverParamsParcel> mResolverParamsParcelCaptor =
             ArgumentCaptor.forClass(ResolverParamsParcel.class);
@@ -1066,6 +1067,15 @@
         private int mVpnType = VpnManager.TYPE_VPN_SERVICE;
         private VpnInfo mVpnInfo;
 
+        // These ConditionVariables allow tests to wait for LegacyVpnRunner to be stopped/started.
+        // TODO: this scheme is ad-hoc and error-prone because it does not fail if, for example, the
+        // test expects two starts in a row, or even if the production code calls start twice in a
+        // row. find a better solution. Simply putting a method to create a LegacyVpnRunner into
+        // Vpn.Dependencies doesn't work because LegacyVpnRunner is not a static class and has
+        // extensive access into the internals of Vpn.
+        private ConditionVariable mStartLegacyVpnCv = new ConditionVariable();
+        private ConditionVariable mStopVpnRunnerCv = new ConditionVariable();
+
         public MockVpn(int userId) {
             super(startHandlerThreadAndReturnLooper(), mServiceContext,
                     new Dependencies() {
@@ -1079,7 +1089,7 @@
                             return mDeviceIdleInternal;
                         }
                     },
-                    mNetworkManagementService, mMockNetd, userId, mock(KeyStore.class));
+                    mNetworkManagementService, mMockNetd, userId, mKeyStore);
         }
 
         public void setUids(Set<UidRange> uids) {
@@ -1191,10 +1201,44 @@
             }
             mAgentRegistered = false;
             setUids(null);
+            // Remove NET_CAPABILITY_INTERNET or MockNetworkAgent will refuse to connect later on.
+            mNetworkCapabilities.removeCapability(NET_CAPABILITY_INTERNET);
             mInterface = null;
         }
 
         @Override
+        public void startLegacyVpnRunner() {
+            mStartLegacyVpnCv.open();
+        }
+
+        public void expectStartLegacyVpnRunner() {
+            assertTrue("startLegacyVpnRunner not called after " + TIMEOUT_MS + " ms",
+                    mStartLegacyVpnCv.block(TIMEOUT_MS));
+
+            // startLegacyVpn calls stopVpnRunnerPrivileged, which will open mStopVpnRunnerCv, just
+            // before calling startLegacyVpnRunner. Restore mStopVpnRunnerCv, so the test can expect
+            // that the VpnRunner is stopped and immediately restarted by calling
+            // expectStartLegacyVpnRunner() and expectStopVpnRunnerPrivileged() back-to-back.
+            mStopVpnRunnerCv = new ConditionVariable();
+        }
+
+        @Override
+        public void stopVpnRunnerPrivileged() {
+            if (mVpnRunner != null) {
+                super.stopVpnRunnerPrivileged();
+                disconnect();
+                mStartLegacyVpnCv = new ConditionVariable();
+            }
+            mVpnRunner = null;
+            mStopVpnRunnerCv.open();
+        }
+
+        public void expectStopVpnRunnerPrivileged() {
+            assertTrue("stopVpnRunnerPrivileged not called after " + TIMEOUT_MS + " ms",
+                    mStopVpnRunnerCv.block(TIMEOUT_MS));
+        }
+
+        @Override
         public synchronized VpnInfo getVpnInfo() {
             if (mVpnInfo != null) return mVpnInfo;
 
@@ -1275,10 +1319,19 @@
         }
     }
 
-    private static final int VPN_USER = 0;
-    private static final int APP1_UID = UserHandle.getUid(VPN_USER, 10100);
-    private static final int APP2_UID = UserHandle.getUid(VPN_USER, 10101);
-    private static final int VPN_UID = UserHandle.getUid(VPN_USER, 10043);
+    private static final int PRIMARY_USER = 0;
+    private static final int APP1_UID = UserHandle.getUid(PRIMARY_USER, 10100);
+    private static final int APP2_UID = UserHandle.getUid(PRIMARY_USER, 10101);
+    private static final int VPN_UID = UserHandle.getUid(PRIMARY_USER, 10043);
+    private static final UserInfo PRIMARY_USER_INFO = new UserInfo(PRIMARY_USER, "",
+            UserInfo.FLAG_PRIMARY);
+
+    private static final int RESTRICTED_USER = 1;
+    private static final UserInfo RESTRICTED_USER_INFO = new UserInfo(RESTRICTED_USER, "",
+            UserInfo.FLAG_RESTRICTED);
+    static {
+        RESTRICTED_USER_INFO.restrictedProfileParentId = PRIMARY_USER;
+    }
 
     @Before
     public void setUp() throws Exception {
@@ -1287,12 +1340,14 @@
         mContext = InstrumentationRegistry.getContext();
 
         MockitoAnnotations.initMocks(this);
-        when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
 
-        when(mUserManager.getAliveUsers()).thenReturn(
-                Arrays.asList(new UserInfo[] {
-                        new UserInfo(VPN_USER, "", 0),
-                }));
+        when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO));
+        when(mUserManager.getUserInfo(PRIMARY_USER)).thenReturn(PRIMARY_USER_INFO);
+        // canHaveRestrictedProfile does not take a userId. It applies to the userId of the context
+        // it was started from, i.e., PRIMARY_USER.
+        when(mUserManager.canHaveRestrictedProfile()).thenReturn(true);
+        when(mUserManager.getUserInfo(RESTRICTED_USER)).thenReturn(RESTRICTED_USER_INFO);
+
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
@@ -1334,6 +1389,9 @@
         verify(mNetworkPolicyManager).registerListener(policyListenerCaptor.capture());
         mPolicyListener = policyListenerCaptor.getValue();
 
+        mServiceContext.setPermission(
+                Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
+
         // Create local CM before sending system ready so that we can answer
         // getSystemService() correctly.
         mCm = new WrappedConnectivityManager(InstrumentationRegistry.getContext(), mService);
@@ -1362,9 +1420,9 @@
         doReturn(mNetworkStack).when(deps).getNetworkStack();
         doReturn(mSystemProperties).when(deps).getSystemProperties();
         doReturn(mock(ProxyTracker.class)).when(deps).makeProxyTracker(any(), any());
-        doReturn(mMetricsService).when(deps).getMetricsLogger();
         doReturn(true).when(deps).queryUserAccess(anyInt(), anyInt());
         doReturn(mBatteryStatsService).when(deps).getBatteryStatsService();
+        doReturn(mKeyStore).when(deps).getKeyStore();
         doAnswer(inv -> {
             mPolicyTracker = new WrappedMultinetworkPolicyTracker(
                     inv.getArgument(0), inv.getArgument(1), inv.getArgument(2));
@@ -1530,10 +1588,9 @@
         }
 
         public void expectNoBroadcast(int timeoutMs) throws Exception {
-            waitForIdle();
             try {
                 final Intent intent = get(timeoutMs, TimeUnit.MILLISECONDS);
-                fail("Unexpected broadcast: " + intent.getAction());
+                fail("Unexpected broadcast: " + intent.getAction() + " " + intent.getExtras());
             } catch (TimeoutException expected) {
             } finally {
                 mServiceContext.unregisterReceiver(mReceiver);
@@ -2074,10 +2131,6 @@
 
     @Test
     public void testOwnerUidCannotChange() throws Exception {
-        // Owner UIDs are not visible without location permission.
-        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
-                Manifest.permission.ACCESS_FINE_LOCATION);
-
         final NetworkCapabilities ncTemplate = new NetworkCapabilities();
         final int originalOwnerUid = Process.myUid();
         ncTemplate.setOwnerUid(originalOwnerUid);
@@ -2097,6 +2150,10 @@
         mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
         waitForIdle();
 
+        // Owner UIDs are not visible without location permission.
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
+
         // Check that the capability change has been applied but the owner UID is not modified.
         NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
         assertEquals(originalOwnerUid, nc.getOwnerUid());
@@ -6315,7 +6372,7 @@
     }
 
     @Test
-    public void testVpnRestrictedUsers() throws Exception {
+    public void testRestrictedProfileAffectsVpnUidRanges() throws Exception {
         // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
         mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
                 PERMISSION_GRANTED);
@@ -6347,19 +6404,11 @@
         callback.expectCapabilitiesThat(mWiFiNetworkAgent, (caps)
                 -> caps.hasCapability(NET_CAPABILITY_VALIDATED));
 
-        // Create a fake restricted profile whose parent is our user ID.
-        final int userId = UserHandle.getUserId(uid);
-        when(mUserManager.canHaveRestrictedProfile()).thenReturn(true);
-        final int restrictedUserId = userId + 1;
-        final UserInfo info = new UserInfo(restrictedUserId, "user", UserInfo.FLAG_RESTRICTED);
-        info.restrictedProfileParentId = userId;
-        assertTrue(info.isRestricted());
-        when(mUserManager.getUserInfo(restrictedUserId)).thenReturn(info);
-        when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, restrictedUserId))
-                .thenReturn(UserHandle.getUid(restrictedUserId, VPN_UID));
+        when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
+                .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
 
         final Intent addedIntent = new Intent(ACTION_USER_ADDED);
-        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
+        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
 
         // Send a USER_ADDED broadcast for it.
         // The BroadcastReceiver for this broadcast checks that is being run on the handler thread.
@@ -6371,7 +6420,7 @@
         callback.expectCapabilitiesThat(mMockVpn, (caps)
                 -> caps.getUids().size() == 2
                 && caps.getUids().contains(new UidRange(uid, uid))
-                && caps.getUids().contains(UidRange.createForUser(restrictedUserId))
+                && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
                 && caps.hasTransport(TRANSPORT_VPN)
                 && caps.hasTransport(TRANSPORT_WIFI));
 
@@ -6381,13 +6430,13 @@
         callback.expectCapabilitiesThat(mMockVpn, (caps)
                 -> caps.getUids().size() == 2
                 && caps.getUids().contains(new UidRange(uid, uid))
-                && caps.getUids().contains(UidRange.createForUser(restrictedUserId))
+                && caps.getUids().contains(UidRange.createForUser(RESTRICTED_USER))
                 && caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_WIFI));
 
         // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
         final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
-        removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, restrictedUserId);
+        removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
         handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
 
         // Expect that the VPN gains the UID range for the restricted user, and that the capability
@@ -6397,53 +6446,68 @@
                 && caps.getUids().contains(new UidRange(uid, uid))
                 && caps.hasTransport(TRANSPORT_VPN)
                 && !caps.hasTransport(TRANSPORT_WIFI));
+    }
 
-        // Test lockdown with restricted profiles.
+    @Test
+    public void testLockdownVpnWithRestrictedProfiles() throws Exception {
+        // NETWORK_SETTINGS is necessary to see the UID ranges in NetworkCapabilities.
         mServiceContext.setPermission(
                 Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
         mServiceContext.setPermission(
-                Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
-        mServiceContext.setPermission(
                 Manifest.permission.NETWORK_SETTINGS, PERMISSION_GRANTED);
 
+        final NetworkRequest request = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
+                .build();
+        final TestNetworkCallback callback = new TestNetworkCallback();
+        mCm.registerNetworkCallback(request, callback);
+
+        final int uid = Process.myUid();
+
         // Connect wifi and check that UIDs in the main and restricted profiles have network access.
-        mMockVpn.disconnect();
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true /* validated */);
-        final int restrictedUid = UserHandle.getUid(restrictedUserId, 42 /* appId */);
+        final int restrictedUid = UserHandle.getUid(RESTRICTED_USER, 42 /* appId */);
         assertNotNull(mCm.getActiveNetworkForUid(uid));
         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
 
         // Enable always-on VPN lockdown. The main user loses network access because no VPN is up.
         final ArrayList<String> allowList = new ArrayList<>();
-        mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        mService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE, true /* lockdown */,
+                allowList);
         waitForIdle();
         assertNull(mCm.getActiveNetworkForUid(uid));
+        // This is arguably overspecified: a UID that is not running doesn't have an active network.
+        // But it's useful to check that non-default users do not lose network access, and to prove
+        // that the loss of connectivity below is indeed due to the restricted profile coming up.
         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
 
         // Start the restricted profile, and check that the UID within it loses network access.
-        when(mUserManager.getAliveUsers()).thenReturn(
-                Arrays.asList(new UserInfo[] {
-                        new UserInfo(userId, "", 0),
-                        info
-                }));
+        when(mPackageManager.getPackageUidAsUser(ALWAYS_ON_PACKAGE, RESTRICTED_USER))
+                .thenReturn(UserHandle.getUid(RESTRICTED_USER, VPN_UID));
+        when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO,
+                RESTRICTED_USER_INFO));
         // TODO: check that VPN app within restricted profile still has access, etc.
+        final Intent addedIntent = new Intent(ACTION_USER_ADDED);
+        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
+        final Handler handler = new Handler(mCsHandlerThread.getLooper());
         handler.post(() -> mServiceContext.sendBroadcast(addedIntent));
         waitForIdle();
         assertNull(mCm.getActiveNetworkForUid(uid));
         assertNull(mCm.getActiveNetworkForUid(restrictedUid));
 
         // Stop the restricted profile, and check that the UID within it has network access again.
-        when(mUserManager.getAliveUsers()).thenReturn(
-                Arrays.asList(new UserInfo[] {
-                        new UserInfo(userId, "", 0),
-                }));
+        when(mUserManager.getAliveUsers()).thenReturn(Arrays.asList(PRIMARY_USER_INFO));
+
+        // Send a USER_REMOVED broadcast and expect to lose the UID range for the restricted user.
+        final Intent removedIntent = new Intent(ACTION_USER_REMOVED);
+        removedIntent.putExtra(Intent.EXTRA_USER_HANDLE, RESTRICTED_USER);
         handler.post(() -> mServiceContext.sendBroadcast(removedIntent));
         waitForIdle();
         assertNull(mCm.getActiveNetworkForUid(uid));
         assertNotNull(mCm.getActiveNetworkForUid(restrictedUid));
 
-        mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        mService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */, allowList);
         waitForIdle();
     }
 
@@ -6784,6 +6848,7 @@
         final int userId = UserHandle.getUserId(uid);
         final ArrayList<String> allowList = new ArrayList<>();
         mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        waitForIdle();
 
         UidRangeParcel firstHalf = new UidRangeParcel(1, VPN_UID - 1);
         UidRangeParcel secondHalf = new UidRangeParcel(VPN_UID + 1, 99999);
@@ -6805,10 +6870,10 @@
 
         // Disable lockdown, expect to see the network unblocked.
         mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
-        expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
         callback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
         defaultCallback.expectBlockedStatusCallback(false, mWiFiNetworkAgent);
         vpnUidCallback.assertNoCallback();
+        expectNetworkRejectNonSecureVpn(inOrder, false, firstHalf, secondHalf);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetworkForUid(VPN_UID));
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
@@ -6851,9 +6916,11 @@
         // Disable lockdown, remove our UID from the allowlist, and re-enable lockdown.
         // Everything should now be blocked.
         mService.setAlwaysOnVpnPackage(userId, null, false /* lockdown */, allowList);
+        waitForIdle();
         expectNetworkRejectNonSecureVpn(inOrder, false, piece1, piece2, piece3);
         allowList.clear();
         mService.setAlwaysOnVpnPackage(userId, ALWAYS_ON_PACKAGE, true /* lockdown */, allowList);
+        waitForIdle();
         expectNetworkRejectNonSecureVpn(inOrder, true, firstHalf, secondHalf);
         defaultCallback.expectBlockedStatusCallback(true, mWiFiNetworkAgent);
         assertBlockedCallbackInAnyOrder(callback, true, mWiFiNetworkAgent, mCellNetworkAgent);
@@ -6931,6 +6998,194 @@
         mCm.unregisterNetworkCallback(vpnUidCallback);
     }
 
+    private void setupLegacyLockdownVpn() {
+        final String profileName = "testVpnProfile";
+        final byte[] profileTag = profileName.getBytes(StandardCharsets.UTF_8);
+        when(mKeyStore.contains(Credentials.LOCKDOWN_VPN)).thenReturn(true);
+        when(mKeyStore.get(Credentials.LOCKDOWN_VPN)).thenReturn(profileTag);
+
+        final VpnProfile profile = new VpnProfile(profileName);
+        profile.name = "My VPN";
+        profile.server = "192.0.2.1";
+        profile.dnsServers = "8.8.8.8";
+        profile.type = VpnProfile.TYPE_IPSEC_XAUTH_PSK;
+        final byte[] encodedProfile = profile.encode();
+        when(mKeyStore.get(Credentials.VPN + profileName)).thenReturn(encodedProfile);
+    }
+
+    @Test
+    public void testLegacyLockdownVpn() throws Exception {
+        final NetworkRequest request = new NetworkRequest.Builder().clearCapabilities().build();
+        final TestNetworkCallback callback = new TestNetworkCallback();
+        mCm.registerNetworkCallback(request, callback);
+
+        final TestNetworkCallback defaultCallback = new TestNetworkCallback();
+        mCm.registerDefaultNetworkCallback(defaultCallback);
+
+        // Pretend lockdown VPN was configured.
+        setupLegacyLockdownVpn();
+
+        // LockdownVpnTracker disables the Vpn teardown code and enables lockdown.
+        // Check the VPN's state before it does so.
+        assertTrue(mMockVpn.getEnableTeardown());
+        assertFalse(mMockVpn.getLockdown());
+
+        // Send a USER_UNLOCKED broadcast so CS starts LockdownVpnTracker.
+        final int userId = UserHandle.getUserId(Process.myUid());
+        final Intent addedIntent = new Intent(ACTION_USER_UNLOCKED);
+        addedIntent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+        final Handler handler = new Handler(mCsHandlerThread.getLooper());
+        handler.post(() -> mServiceContext.sendBroadcast(addedIntent));
+        waitForIdle();
+
+        // Lockdown VPN disables teardown and enables lockdown.
+        assertFalse(mMockVpn.getEnableTeardown());
+        assertTrue(mMockVpn.getLockdown());
+
+        // Bring up a network.
+        // Expect nothing to happen because the network does not have an IPv4 default route: legacy
+        // VPN only supports IPv4.
+        final LinkProperties cellLp = new LinkProperties();
+        cellLp.setInterfaceName("rmnet0");
+        cellLp.addLinkAddress(new LinkAddress("2001:db8::1/64"));
+        cellLp.addRoute(new RouteInfo(new IpPrefix("::/0"), null, "rmnet0"));
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellNetworkAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        waitForIdle();
+        assertNull(mMockVpn.getAgent());
+
+        // Add an IPv4 address. Ideally the VPN should start, but it doesn't because nothing calls
+        // LockdownVpnTracker#handleStateChangedLocked. This is a bug.
+        // TODO: consider fixing this.
+        cellLp.addLinkAddress(new LinkAddress("192.0.2.2/25"));
+        cellLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "rmnet0"));
+        mCellNetworkAgent.sendLinkProperties(cellLp);
+        callback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LINK_PROPERTIES_CHANGED, mCellNetworkAgent);
+        waitForIdle();
+        assertNull(mMockVpn.getAgent());
+
+        // Disconnect, then try again with a network that supports IPv4 at connection time.
+        // Expect lockdown VPN to come up.
+        ExpectedBroadcast b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        mCellNetworkAgent.disconnect();
+        callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        b1.expectBroadcast();
+
+        // When lockdown VPN is active, the NetworkInfo state in CONNECTIVITY_ACTION is overwritten
+        // with the state of the VPN network. So expect a CONNECTING broadcast.
+        b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTING);
+        mCellNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR, cellLp);
+        mCellNetworkAgent.connect(false /* validated */);
+        callback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mCellNetworkAgent);
+        b1.expectBroadcast();
+        assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
+
+        // TODO: it would be nice if we could simply rely on the production code here, and have
+        // LockdownVpnTracker start the VPN, have the VPN code register its NetworkAgent with
+        // ConnectivityService, etc. That would require duplicating a fair bit of code from the
+        // Vpn tests around how to mock out LegacyVpnRunner. But even if we did that, this does not
+        // work for at least two reasons:
+        // 1. In this test, calling registerNetworkAgent does not actually result in an agent being
+        //    registered. This is because nothing calls onNetworkMonitorCreated, which is what
+        //    actually ends up causing handleRegisterNetworkAgent to be called. Code in this test
+        //    that wants to register an agent must use TestNetworkAgentWrapper.
+        // 2. Even if we exposed Vpn#agentConnect to the test, and made MockVpn#agentConnect call
+        //    the TestNetworkAgentWrapper code, this would deadlock because the
+        //    TestNetworkAgentWrapper code cannot be called on the handler thread since it calls
+        //    waitForIdle().
+        mMockVpn.expectStartLegacyVpnRunner();
+        b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
+        ExpectedBroadcast b2 = expectConnectivityAction(TYPE_MOBILE, DetailedState.CONNECTED);
+        mMockVpn.establishForMyUid();
+        callback.expectAvailableThenValidatedCallbacks(mMockVpn);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+        b1.expectBroadcast();
+        b2.expectBroadcast();
+        assertActiveNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+
+        // Switch default network from cell to wifi. Expect VPN to disconnect and reconnect.
+        final LinkProperties wifiLp = new LinkProperties();
+        wifiLp.setInterfaceName("wlan0");
+        wifiLp.addLinkAddress(new LinkAddress("192.0.2.163/25"));
+        wifiLp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0"), null, "wlan0"));
+        mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, wifiLp);
+
+        b1 = expectConnectivityAction(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        // Wifi is CONNECTING because the VPN isn't up yet.
+        b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTING);
+        ExpectedBroadcast b3 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
+        mWiFiNetworkAgent.connect(false /* validated */);
+        b1.expectBroadcast();
+        b2.expectBroadcast();
+        b3.expectBroadcast();
+        mMockVpn.expectStopVpnRunnerPrivileged();
+        mMockVpn.expectStartLegacyVpnRunner();
+
+        // TODO: why is wifi not blocked? Is this because something calls prepare()?
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCapabilitiesThat(mMockVpn, (nc) -> nc.hasTransport(TRANSPORT_WIFI));
+        defaultCallback.expectCapabilitiesThat(mMockVpn, (nc) -> nc.hasTransport(TRANSPORT_WIFI));
+        callback.expectCallback(CallbackEntry.LOST, mMockVpn);
+        defaultCallback.expectCallback(CallbackEntry.LOST, mMockVpn);
+        defaultCallback.expectAvailableCallbacksUnvalidatedAndBlocked(mWiFiNetworkAgent);
+
+        // While the VPN is reconnecting on the new network, everything is blocked.
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.BLOCKED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.BLOCKED);
+
+        // The VPN comes up again on wifi.
+        b1 = expectConnectivityAction(TYPE_VPN, DetailedState.CONNECTED);
+        b2 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
+        mMockVpn.establishForMyUid();
+        callback.expectAvailableThenValidatedCallbacks(mMockVpn);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mMockVpn);
+        b1.expectBroadcast();
+        b2.expectBroadcast();
+
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+
+        // Disconnect cell. Nothing much happens since it's not the default network.
+        // Whenever LockdownVpnTracker is connected, it will send a connected broadcast any time any
+        // NetworkInfo is updated. This is probably a bug.
+        // TODO: consider fixing this.
+        b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.CONNECTED);
+        mCellNetworkAgent.disconnect();
+        b1.expectBroadcast();
+        callback.expectCallback(CallbackEntry.LOST, mCellNetworkAgent);
+        defaultCallback.assertNoCallback();
+
+        assertActiveNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_MOBILE, DetailedState.DISCONNECTED);
+        assertNetworkInfo(TYPE_WIFI, DetailedState.CONNECTED);
+        assertNetworkInfo(TYPE_VPN, DetailedState.CONNECTED);
+
+        b1 = expectConnectivityAction(TYPE_WIFI, DetailedState.DISCONNECTED);
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackEntry.LOST, mWiFiNetworkAgent);
+        b1.expectBroadcast();
+        callback.expectCapabilitiesThat(mMockVpn, (nc) -> !nc.hasTransport(TRANSPORT_WIFI));
+        b2 = expectConnectivityAction(TYPE_VPN, DetailedState.DISCONNECTED);
+        mMockVpn.expectStopVpnRunnerPrivileged();
+        callback.expectCallback(CallbackEntry.LOST, mMockVpn);
+        b2.expectBroadcast();
+    }
+
     @Test
     public final void testLoseTrusted() throws Exception {
         final NetworkRequest trustedRequest = new NetworkRequest.Builder()
@@ -7605,7 +7860,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
         mMockVpn.establish(lp, VPN_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
 
@@ -7633,7 +7888,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
 
@@ -7649,7 +7904,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
         mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
 
@@ -7664,7 +7919,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
         mMockVpn.establish(lp, VPN_UID, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, VPN_UID);
 
@@ -7716,7 +7971,7 @@
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
         // The uid range needs to cover the test app so the network is visible to it.
-        final UidRange vpnRange = UidRange.createForUser(VPN_USER);
+        final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
         final Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
         mMockVpn.establish(lp, VPN_UID, vpnRanges);
         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -7781,8 +8036,22 @@
         naExtraInfo.unregister();
     }
 
+    // To avoid granting location permission bypass.
+    private void denyAllLocationPrivilegedPermissions() {
+        mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
+                PERMISSION_DENIED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
+                PERMISSION_DENIED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
+                PERMISSION_DENIED);
+        mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
+                PERMISSION_DENIED);
+    }
+
     private void setupLocationPermissions(
             int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
+        denyAllLocationPrivilegedPermissions();
+
         final ApplicationInfo applicationInfo = new ApplicationInfo();
         applicationInfo.targetSdkVersion = targetSdk;
         when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
@@ -7900,7 +8169,7 @@
 
     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
             throws Exception {
-        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(VPN_USER));
+        final Set<UidRange> vpnRange = Collections.singleton(UidRange.createForUser(PRIMARY_USER));
         mMockVpn.establish(new LinkProperties(), vpnOwnerUid, vpnRange);
         assertVpnUidRangesUpdated(true, vpnRange, vpnOwnerUid);
         mMockVpn.setVpnType(vpnType);
@@ -8104,11 +8373,18 @@
         assertTrue(mService.mConnectivityDiagnosticsCallbacks.containsKey(mIBinder));
     }
 
+    public NetworkAgentInfo fakeMobileNai(NetworkCapabilities nc) {
+        final NetworkInfo info = new NetworkInfo(TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_LTE,
+                ConnectivityManager.getNetworkTypeName(TYPE_MOBILE),
+                TelephonyManager.getNetworkTypeName(TelephonyManager.NETWORK_TYPE_LTE));
+        return new NetworkAgentInfo(null, new Network(NET_ID), info, new LinkProperties(),
+                nc, 0, mServiceContext, null, new NetworkAgentConfig(), mService, null, null, null,
+                0, INVALID_UID);
+    }
+
     @Test
     public void testCheckConnectivityDiagnosticsPermissionsNetworkStack() throws Exception {
-        final NetworkAgentInfo naiWithoutUid =
-                new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
+        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
 
         mServiceContext.setPermission(
                 android.Manifest.permission.NETWORK_STACK, PERMISSION_GRANTED);
@@ -8121,9 +8397,7 @@
 
     @Test
     public void testCheckConnectivityDiagnosticsPermissionsWrongUidPackageName() throws Exception {
-        final NetworkAgentInfo naiWithoutUid =
-                new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
+        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
 
         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
 
@@ -8136,9 +8410,7 @@
 
     @Test
     public void testCheckConnectivityDiagnosticsPermissionsNoLocationPermission() throws Exception {
-        final NetworkAgentInfo naiWithoutUid =
-                new NetworkAgentInfo(null, null, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
+        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
 
         mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
 
@@ -8151,22 +8423,17 @@
 
     @Test
     public void testCheckConnectivityDiagnosticsPermissionsActiveVpn() throws Exception {
-        final Network network = new Network(NET_ID);
-        final NetworkAgentInfo naiWithoutUid =
-                new NetworkAgentInfo(null, network, null, null, new NetworkCapabilities(), 0,
-                        mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
-
-        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
-                Manifest.permission.ACCESS_FINE_LOCATION);
+        final NetworkAgentInfo naiWithoutUid = fakeMobileNai(new NetworkCapabilities());
 
         mMockVpn.establishForMyUid();
         assertUidRangesUpdatedForMyUid(true);
 
         // Wait for networks to connect and broadcasts to be sent before removing permissions.
         waitForIdle();
-        mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED);
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
 
-        assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
+        assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {naiWithoutUid.network}));
         waitForIdle();
         assertTrue(
                 "Active VPN permission not applied",
@@ -8187,9 +8454,7 @@
     public void testCheckConnectivityDiagnosticsPermissionsNetworkAdministrator() throws Exception {
         final NetworkCapabilities nc = new NetworkCapabilities();
         nc.setAdministratorUids(new int[] {Process.myUid()});
-        final NetworkAgentInfo naiWithUid =
-                new NetworkAgentInfo(null, null, null, null, nc, 0, mServiceContext, null, null,
-                        mService, null, null, null, 0, INVALID_UID);
+        final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
 
         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
@@ -8206,9 +8471,7 @@
         final NetworkCapabilities nc = new NetworkCapabilities();
         nc.setOwnerUid(Process.myUid());
         nc.setAdministratorUids(new int[] {Process.myUid()});
-        final NetworkAgentInfo naiWithUid =
-                new NetworkAgentInfo(null, null, null, null, nc, 0, mServiceContext, null, null,
-                        mService, null, null, null, 0, INVALID_UID);
+        final NetworkAgentInfo naiWithUid = fakeMobileNai(nc);
 
         setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
                 Manifest.permission.ACCESS_FINE_LOCATION);
@@ -8475,7 +8738,7 @@
         lp.setInterfaceName("tun0");
         lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
         lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
-        final UidRange vpnRange = UidRange.createForUser(VPN_USER);
+        final UidRange vpnRange = UidRange.createForUser(PRIMARY_USER);
         Set<UidRange> vpnRanges = Collections.singleton(vpnRange);
         mMockVpn.establish(lp, VPN_UID, vpnRanges);
         assertVpnUidRangesUpdated(true, vpnRanges, VPN_UID);
@@ -8491,4 +8754,20 @@
         assertVpnUidRangesUpdated(true, newRanges, VPN_UID);
         assertVpnUidRangesUpdated(false, vpnRanges, VPN_UID);
     }
+
+    @Test
+    public void testInvalidRequestTypes() {
+        final int[] invalidReqTypeInts = new int[] {-1, NetworkRequest.Type.NONE.ordinal(),
+                NetworkRequest.Type.LISTEN.ordinal(), NetworkRequest.Type.values().length};
+        final NetworkCapabilities nc = new NetworkCapabilities().addTransportType(TRANSPORT_WIFI);
+
+        for (int reqTypeInt : invalidReqTypeInts) {
+            assertThrows("Expect throws for invalid request type " + reqTypeInt,
+                    IllegalArgumentException.class,
+                    () -> mService.requestNetwork(nc, reqTypeInt, null, 0, null,
+                            ConnectivityManager.TYPE_NONE, mContext.getPackageName(),
+                            getAttributionTag())
+            );
+        }
+    }
 }
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 96c56e3..4d151af 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -34,7 +34,9 @@
 import android.net.ConnectivityManager;
 import android.net.IDnsResolver;
 import android.net.INetd;
+import android.net.LinkProperties;
 import android.net.Network;
+import android.net.NetworkAgentConfig;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
 import android.net.NetworkProvider;
@@ -353,9 +355,10 @@
         NetworkCapabilities caps = new NetworkCapabilities();
         caps.addCapability(0);
         caps.addTransportType(transport);
-        NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info, null,
-                caps, 50, mCtx, null, null /* config */, mConnService, mNetd, mDnsResolver, mNMS,
-                NetworkProvider.ID_NONE, Binder.getCallingUid());
+        NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
+                new LinkProperties(), caps, 50, mCtx, null, new NetworkAgentConfig() /* config */,
+                mConnService, mNetd, mDnsResolver, mNMS, NetworkProvider.ID_NONE,
+                Binder.getCallingUid());
         nai.everValidated = true;
         return nai;
     }
diff --git a/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
new file mode 100644
index 0000000..3156190
--- /dev/null
+++ b/tests/vcn/java/android/net/vcn/VcnTransportInfoTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.vcn;
+
+import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNull;
+
+import android.net.wifi.WifiInfo;
+import android.os.Parcel;
+
+import org.junit.Test;
+
+public class VcnTransportInfoTest {
+    private static final int SUB_ID = 1;
+    private static final int NETWORK_ID = 5;
+    private static final WifiInfo WIFI_INFO =
+            new WifiInfo.Builder().setNetworkId(NETWORK_ID).build();
+
+    private static final VcnTransportInfo CELL_UNDERLYING_INFO = new VcnTransportInfo(SUB_ID);
+    private static final VcnTransportInfo WIFI_UNDERLYING_INFO = new VcnTransportInfo(WIFI_INFO);
+
+    @Test
+    public void testGetWifiInfo() {
+        assertEquals(WIFI_INFO, WIFI_UNDERLYING_INFO.getWifiInfo());
+
+        assertNull(CELL_UNDERLYING_INFO.getWifiInfo());
+    }
+
+    @Test
+    public void testGetSubId() {
+        assertEquals(SUB_ID, CELL_UNDERLYING_INFO.getSubId());
+
+        assertEquals(INVALID_SUBSCRIPTION_ID, WIFI_UNDERLYING_INFO.getSubId());
+    }
+
+    @Test
+    public void testEquals() {
+        assertEquals(CELL_UNDERLYING_INFO, CELL_UNDERLYING_INFO);
+        assertEquals(WIFI_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+        assertNotEquals(CELL_UNDERLYING_INFO, WIFI_UNDERLYING_INFO);
+    }
+
+    @Test
+    public void testParcelUnparcel() {
+        verifyParcelingIsNull(CELL_UNDERLYING_INFO);
+        verifyParcelingIsNull(WIFI_UNDERLYING_INFO);
+    }
+
+    private void verifyParcelingIsNull(VcnTransportInfo vcnTransportInfo) {
+        Parcel parcel = Parcel.obtain();
+        vcnTransportInfo.writeToParcel(parcel, 0 /* flags */);
+        assertNull(VcnTransportInfo.CREATOR.createFromParcel(parcel));
+    }
+}