Merge "Request MANAGE_EXTERNAL_STORAGE permission"
diff --git a/Android.bp b/Android.bp
index 3046b20..a211d26 100644
--- a/Android.bp
+++ b/Android.bp
@@ -658,7 +658,10 @@
     name: "framework-tethering-annotations",
     srcs: [
         "core/java/android/annotation/NonNull.java",
+        "core/java/android/annotation/Nullable.java",
+        "core/java/android/annotation/RequiresPermission.java",
         "core/java/android/annotation/SystemApi.java",
+        "core/java/android/annotation/TestApi.java",
     ],
 }
 // Build ext.jar
@@ -1061,7 +1064,11 @@
     "--hide MissingPermission --hide BroadcastBehavior " +
     "--hide HiddenSuperclass --hide DeprecationMismatch --hide UnavailableSymbol " +
     "--hide SdkConstant --hide HiddenTypeParameter --hide Todo --hide Typo " +
-    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.*"
+    "--force-convert-to-warning-nullability-annotations +*:-android.*:+android.icu.*:-dalvik.* " +
+    "--api-lint-ignore-prefix android.icu. " +
+    "--api-lint-ignore-prefix java. " +
+    "--api-lint-ignore-prefix junit. " +
+    "--api-lint-ignore-prefix org. "
 
 build = [
     "StubLibraries.bp",
diff --git a/apex/sdkextensions/OWNERS b/apex/sdkextensions/OWNERS
index feb2742..a6e5522 100644
--- a/apex/sdkextensions/OWNERS
+++ b/apex/sdkextensions/OWNERS
@@ -1 +1,2 @@
+dariofreni@google.com
 hansson@google.com
diff --git a/apex/sdkextensions/framework/Android.bp b/apex/sdkextensions/framework/Android.bp
index dd17473..245a96b 100644
--- a/apex/sdkextensions/framework/Android.bp
+++ b/apex/sdkextensions/framework/Android.bp
@@ -32,6 +32,7 @@
     libs: [ "framework-annotations-lib" ],
     permitted_packages: [ "android.os.ext" ],
     installable: true,
+    plugins: ["java_api_finder"],
     visibility: [
         "//frameworks/base/apex/sdkextensions",
         "//frameworks/base/apex/sdkextensions/testing",
diff --git a/api/current.txt b/api/current.txt
index 9b6dcc7..c9744c2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9873,6 +9873,7 @@
     field public static final String STORAGE_STATS_SERVICE = "storagestats";
     field public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final String TELECOM_SERVICE = "telecom";
+    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TELEPHONY_SERVICE = "phone";
     field public static final String TELEPHONY_SUBSCRIPTION_SERVICE = "telephony_subscription_service";
     field public static final String TEXT_CLASSIFICATION_SERVICE = "textclassification";
@@ -29139,6 +29140,7 @@
     method public int getLinkDownstreamBandwidthKbps();
     method public int getLinkUpstreamBandwidthKbps();
     method @Nullable public android.net.NetworkSpecifier getNetworkSpecifier();
+    method public int getOwnerUid();
     method public int getSignalStrength();
     method @Nullable public android.net.TransportInfo getTransportInfo();
     method public boolean hasCapability(int);
@@ -29148,6 +29150,7 @@
     method @NonNull public android.net.NetworkCapabilities setLinkDownstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setLinkUpstreamBandwidthKbps(int);
     method @NonNull public android.net.NetworkCapabilities setNetworkSpecifier(@NonNull android.net.NetworkSpecifier);
+    method public void setOwnerUid(int);
     method @NonNull public android.net.NetworkCapabilities setSignalStrength(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkCapabilities> CREATOR;
@@ -35397,7 +35400,7 @@
     method public boolean isSustainedPerformanceModeSupported();
     method public boolean isWakeLockLevelSupported(int);
     method public android.os.PowerManager.WakeLock newWakeLock(int, String);
-    method public void reboot(@Nullable String);
+    method @RequiresPermission(android.Manifest.permission.REBOOT) public void reboot(@Nullable String);
     method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
     field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
@@ -43567,6 +43570,7 @@
     method public void registerCallback(android.telecom.Call.Callback);
     method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
     method public void reject(boolean, String);
+    method public void reject(int);
     method public void removeExtras(java.util.List<java.lang.String>);
     method public void removeExtras(java.lang.String...);
     method public void respondToRttRequest(int, boolean);
@@ -43582,6 +43586,8 @@
     field public static final String EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS = "android.telecom.extra.LAST_EMERGENCY_CALLBACK_TIME_MILLIS";
     field public static final String EXTRA_SILENT_RINGING_REQUESTED = "android.telecom.extra.SILENT_RINGING_REQUESTED";
     field public static final String EXTRA_SUGGESTED_PHONE_ACCOUNTS = "android.telecom.extra.SUGGESTED_PHONE_ACCOUNTS";
+    field public static final int REJECT_REASON_DECLINED = 1; // 0x1
+    field public static final int REJECT_REASON_UNWANTED = 2; // 0x2
     field public static final int STATE_ACTIVE = 4; // 0x4
     field public static final int STATE_AUDIO_PROCESSING = 12; // 0xc
     field public static final int STATE_CONNECTING = 9; // 0x9
@@ -43849,6 +43855,7 @@
     method public void onPostDialContinue(boolean);
     method public void onPullExternalCall();
     method public void onReject();
+    method public void onReject(int);
     method public void onReject(String);
     method public void onSeparate();
     method public void onShowIncomingCallUi();
@@ -46384,13 +46391,20 @@
 
   public final class ImsException extends java.lang.Exception {
     method public int getCode();
+    field public static final int CODE_ERROR_INVALID_SUBSCRIPTION = 3; // 0x3
     field public static final int CODE_ERROR_SERVICE_UNAVAILABLE = 1; // 0x1
     field public static final int CODE_ERROR_UNSPECIFIED = 0; // 0x0
     field public static final int CODE_ERROR_UNSUPPORTED_OPERATION = 2; // 0x2
   }
 
+  public class ImsManager {
+    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
+    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
+    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
+    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
+  }
+
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
-    method @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public void getRegistrationTransportType(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getVoWiFiModeSetting();
diff --git a/api/system-current.txt b/api/system-current.txt
index 9acd67f..1ab457e 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -93,6 +93,7 @@
     field public static final String INTERNAL_SYSTEM_WINDOW = "android.permission.INTERNAL_SYSTEM_WINDOW";
     field public static final String INVOKE_CARRIER_SETUP = "android.permission.INVOKE_CARRIER_SETUP";
     field public static final String KILL_UID = "android.permission.KILL_UID";
+    field public static final String LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = "android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH";
     field public static final String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
     field public static final String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
     field public static final String LOOP_RADIO = "android.permission.LOOP_RADIO";
@@ -1576,6 +1577,7 @@
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
     field public static final String CONTEXTHUB_SERVICE = "contexthub";
+    field public static final String ETHERNET_SERVICE = "ethernet";
     field public static final String EUICC_CARD_SERVICE = "euicc_card";
     field public static final String HDMI_CONTROL_SERVICE = "hdmi_control";
     field public static final String NETD_SERVICE = "netd";
@@ -1590,7 +1592,6 @@
     field public static final String STATS_MANAGER = "stats";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String SYSTEM_UPDATE_SERVICE = "system_update";
-    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TELEPHONY_REGISTRY_SERVICE = "telephony_registry";
     field public static final String TETHERING_SERVICE = "tethering";
     field public static final String VR_SERVICE = "vrmanager";
@@ -3285,10 +3286,12 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
     field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
     field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+    field public static final long FUNCTION_NCM = 1024L; // 0x400L
     field public static final long FUNCTION_NONE = 0L; // 0x0L
     field public static final long FUNCTION_RNDIS = 32L; // 0x20L
     field public static final String USB_CONFIGURED = "configured";
     field public static final String USB_CONNECTED = "connected";
+    field public static final String USB_FUNCTION_NCM = "ncm";
     field public static final String USB_FUNCTION_RNDIS = "rndis";
   }
 
@@ -4340,44 +4343,57 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createNattKeepalive(@NonNull android.net.Network, @NonNull android.os.ParcelFileDescriptor, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method @NonNull @RequiresPermission(android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD) public android.net.SocketKeepalive createSocketKeepalive(@NonNull android.net.Network, @NonNull java.net.Socket, @NonNull java.util.concurrent.Executor, @NonNull android.net.SocketKeepalive.Callback);
     method @Deprecated @RequiresPermission("android.permission.NETWORK_SETTINGS") public String getCaptivePortalServerUrl();
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
-    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void getLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEntitlementResultListener);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public boolean isTetheringSupported();
     method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public int registerNetworkProvider(@NonNull android.net.NetworkProvider);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
     method @Deprecated public void requestNetwork(@NonNull android.net.NetworkRequest, @NonNull android.net.ConnectivityManager.NetworkCallback, int, int, @NonNull android.os.Handler);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(anyOf={android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, "android.permission.NETWORK_STACK"}) public boolean shouldAvoidBadWifi();
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(@NonNull android.net.Network, @NonNull android.os.Bundle);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void startTethering(int, boolean, android.net.ConnectivityManager.OnStartTetheringCallback, android.os.Handler);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void stopTethering(int);
     method @RequiresPermission(android.Manifest.permission.NETWORK_FACTORY) public void unregisterNetworkProvider(@NonNull android.net.NetworkProvider);
-    method @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void unregisterTetheringEventCallback(@NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
     field public static final String EXTRA_CAPTIVE_PORTAL_PROBE_SPEC = "android.net.extra.CAPTIVE_PORTAL_PROBE_SPEC";
     field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
     field public static final int TETHERING_BLUETOOTH = 2; // 0x2
     field public static final int TETHERING_USB = 1; // 0x1
     field public static final int TETHERING_WIFI = 0; // 0x0
-    field public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
-    field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
-    field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+    field @Deprecated public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN = 13; // 0xd
+    field @Deprecated public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field @Deprecated public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
     field public static final int TYPE_NONE = -1; // 0xffffffff
     field @Deprecated public static final int TYPE_WIFI_P2P = 13; // 0xd
   }
 
-  public abstract static class ConnectivityManager.OnStartTetheringCallback {
-    ctor public ConnectivityManager.OnStartTetheringCallback();
-    method public void onTetheringFailed();
-    method public void onTetheringStarted();
+  @Deprecated public abstract static class ConnectivityManager.OnStartTetheringCallback {
+    ctor @Deprecated public ConnectivityManager.OnStartTetheringCallback();
+    method @Deprecated public void onTetheringFailed();
+    method @Deprecated public void onTetheringStarted();
   }
 
-  public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
-    method public void onTetheringEntitlementResult(int);
+  @Deprecated public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
+    method @Deprecated public void onTetheringEntitlementResult(int);
   }
 
-  public abstract static class ConnectivityManager.OnTetheringEventCallback {
-    ctor public ConnectivityManager.OnTetheringEventCallback();
-    method public void onUpstreamChanged(@Nullable android.net.Network);
+  @Deprecated public abstract static class ConnectivityManager.OnTetheringEventCallback {
+    ctor @Deprecated public ConnectivityManager.OnTetheringEventCallback();
+    method @Deprecated public void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
+  public class EthernetManager {
+    method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+  }
+
+  public static interface EthernetManager.TetheredInterfaceCallback {
+    method public void onAvailable(@NonNull String);
+    method public void onUnavailable();
+  }
+
+  public static class EthernetManager.TetheredInterfaceRequest {
+    method public void release();
   }
 
   public class InvalidPacketException extends java.lang.Exception {
@@ -4449,13 +4465,18 @@
 
   public class LinkAddress implements android.os.Parcelable {
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public LinkAddress(@NonNull String);
     ctor public LinkAddress(@NonNull String, int, int);
+    method public long getDeprecationTime();
+    method public long getExpirationTime();
     method public boolean isGlobalPreferred();
     method public boolean isIpv4();
     method public boolean isIpv6();
     method public boolean isSameAddressAs(@Nullable android.net.LinkAddress);
+    field public static final long LIFETIME_PERMANENT = 9223372036854775807L; // 0x7fffffffffffffffL
+    field public static final long LIFETIME_UNKNOWN = -1L; // 0xffffffffffffffffL
   }
 
   public final class LinkProperties implements android.os.Parcelable {
@@ -4716,6 +4737,101 @@
     method public boolean satisfiedBy(android.net.NetworkSpecifier);
   }
 
+  public final class TetheredClient implements android.os.Parcelable {
+    ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+    method @NonNull public android.net.MacAddress getMacAddress();
+    method public int getTetheringType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+  }
+
+  public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.LinkAddress getAddress();
+    method @Nullable public String getHostname();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+  }
+
+  public class TetheringManager {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+    method @RequiresPermission(anyOf={android.Manifest.permission.TETHER_PRIVILEGED, android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+    field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
+    field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
+    field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+    field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+    field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_ETHERNET = 5; // 0x5
+    field public static final int TETHERING_INVALID = -1; // 0xffffffff
+    field public static final int TETHERING_NCM = 4; // 0x4
+    field public static final int TETHERING_USB = 1; // 0x1
+    field public static final int TETHERING_WIFI = 0; // 0x0
+    field public static final int TETHERING_WIFI_P2P = 3; // 0x3
+    field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
+    field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
+    field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
+    field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
+    field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
+    field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
+    field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
+    field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
+    field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+    field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
+    field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
+    field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
+    field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+    field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
+    field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
+  }
+
+  public static interface TetheringManager.OnTetheringEntitlementResultListener {
+    method public void onTetheringEntitlementResult(int);
+  }
+
+  public abstract static class TetheringManager.StartTetheringCallback {
+    ctor public TetheringManager.StartTetheringCallback();
+    method public void onTetheringFailed(int);
+    method public void onTetheringStarted();
+  }
+
+  public abstract static class TetheringManager.TetheringEventCallback {
+    ctor public TetheringManager.TetheringEventCallback();
+    method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+    method public void onError(@NonNull String, int);
+    method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
+    method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public void onTetheringSupported(boolean);
+    method public void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
+  @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
+    ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+  }
+
+  public static class TetheringManager.TetheringRequest {
+  }
+
+  public static class TetheringManager.TetheringRequest.Builder {
+    ctor public TetheringManager.TetheringRequest.Builder(int);
+    method @NonNull public android.net.TetheringManager.TetheringRequest build();
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+  }
+
   public class TrafficStats {
     method public static void setThreadStatsTagApp();
     method public static void setThreadStatsTagBackup();
@@ -7086,7 +7202,73 @@
   }
 
   public static final class Telephony.SimInfo {
+    field public static final String ACCESS_RULES = "access_rules";
+    field public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS = "access_rules_from_carrier_configs";
+    field public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types";
+    field public static final String CARD_ID = "card_id";
+    field public static final String CARRIER_ID = "carrier_id";
+    field public static final String CARRIER_NAME = "carrier_name";
+    field public static final String CB_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
+    field public static final String CB_ALERT_SOUND_DURATION = "alert_sound_duration";
+    field public static final String CB_ALERT_SPEECH = "enable_alert_speech";
+    field public static final String CB_ALERT_VIBRATE = "enable_alert_vibrate";
+    field public static final String CB_AMBER_ALERT = "enable_cmas_amber_alerts";
+    field public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts";
+    field public static final String CB_CMAS_TEST_ALERT = "enable_cmas_test_alerts";
+    field public static final String CB_EMERGENCY_ALERT = "enable_emergency_alerts";
+    field public static final String CB_ETWS_TEST_ALERT = "enable_etws_test_alerts";
+    field public static final String CB_EXTREME_THREAT_ALERT = "enable_cmas_extreme_threat_alerts";
+    field public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
+    field public static final String CB_SEVERE_THREAT_ALERT = "enable_cmas_severe_threat_alerts";
+    field public static final String COLOR = "color";
     field @NonNull public static final android.net.Uri CONTENT_URI;
+    field public static final String DATA_ENABLED_OVERRIDE_RULES = "data_enabled_override_rules";
+    field public static final String DATA_ROAMING = "data_roaming";
+    field public static final int DATA_ROAMING_DEFAULT = 0; // 0x0
+    field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
+    field public static final int DATA_ROAMING_ENABLE = 1; // 0x1
+    field public static final String DISPLAY_NAME = "display_name";
+    field public static final String EHPLMNS = "ehplmns";
+    field public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
+    field public static final String GROUP_OWNER = "group_owner";
+    field public static final String GROUP_UUID = "group_uuid";
+    field public static final String HPLMNS = "hplmns";
+    field public static final String ICC_ID = "icc_id";
+    field public static final String IMSI = "imsi";
+    field public static final String IMS_RCS_UCE_ENABLED = "ims_rcs_uce_enabled";
+    field public static final String ISO_COUNTRY_CODE = "iso_country_code";
+    field public static final String IS_EMBEDDED = "is_embedded";
+    field public static final String IS_OPPORTUNISTIC = "is_opportunistic";
+    field public static final String IS_REMOVABLE = "is_removable";
+    field public static final String MCC = "mcc";
+    field public static final String MCC_STRING = "mcc_string";
+    field public static final String MNC = "mnc";
+    field public static final String MNC_STRING = "mnc_string";
+    field public static final String NAME_SOURCE = "name_source";
+    field public static final int NAME_SOURCE_CARRIER = 3; // 0x3
+    field public static final int NAME_SOURCE_DEFAULT = 0; // 0x0
+    field public static final int NAME_SOURCE_SIM_PNN = 4; // 0x4
+    field public static final int NAME_SOURCE_SIM_SPN = 1; // 0x1
+    field public static final int NAME_SOURCE_USER_INPUT = 2; // 0x2
+    field public static final String NUMBER = "number";
+    field public static final String PROFILE_CLASS = "profile_class";
+    field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
+    field public static final int PROFILE_CLASS_OPERATIONAL = 2; // 0x2
+    field public static final int PROFILE_CLASS_PROVISIONING = 1; // 0x1
+    field public static final int PROFILE_CLASS_TESTING = 0; // 0x0
+    field public static final int PROFILE_CLASS_UNSET = -1; // 0xffffffff
+    field public static final int SIM_NOT_INSERTED = -1; // 0xffffffff
+    field public static final String SIM_SLOT_INDEX = "sim_id";
+    field public static final String SUBSCRIPTION_TYPE = "subscription_type";
+    field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0
+    field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1
+    field public static final String UICC_APPLICATIONS_ENABLED = "uicc_applications_enabled";
+    field public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id";
+    field public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+    field public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
+    field public static final String WFC_IMS_MODE = "wfc_ims_mode";
+    field public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
+    field public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
   }
 
   public static final class Telephony.Sms.Intents {
@@ -8823,6 +9005,7 @@
     method public int getSleepTimeMillis();
     method public long getTimestamp();
     method @NonNull public java.util.List<android.telephony.ModemActivityInfo.TransmitPower> getTransmitPowerInfo();
+    method public boolean isValid();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ModemActivityInfo> CREATOR;
     field public static final int TX_POWER_LEVELS = 5; // 0x5
@@ -8920,6 +9103,7 @@
     method public void onRadioPowerStateChanged(int);
     method public void onSrvccStateChanged(int);
     method public void onVoiceActivationStateChanged(int);
+    field @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH = 512; // 0x200
     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
@@ -9292,6 +9476,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void enableVideoCalling(boolean);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
     method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -9365,9 +9550,12 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void requestNumberVerification(@NonNull android.telephony.PhoneNumberRange, long, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.NumberVerificationCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetAllCarrierActions();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void resetCarrierKeysForImsiEncryption();
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @WorkerThread public void resetIms(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean resetRadioConfig();
     method @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL) public void resetSettings();
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAlwaysReportSignalStrength(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -9394,6 +9582,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateTestOtaEmergencyNumberDbFilePath(@NonNull String);
     field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_ANOMALY_REPORTED = "android.telephony.action.ANOMALY_REPORTED";
     field public static final String ACTION_EMERGENCY_ASSISTANCE = "android.telephony.action.EMERGENCY_ASSISTANCE";
+    field public static final String ACTION_SERVICE_PROVIDERS_UPDATED = "android.telephony.action.SERVICE_PROVIDERS_UPDATED";
     field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
     field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
     field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
@@ -9406,7 +9595,12 @@
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
     field public static final String EXTRA_ANOMALY_DESCRIPTION = "android.telephony.extra.ANOMALY_DESCRIPTION";
     field public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
+    field public static final String EXTRA_DATA_SPN = "android.telephony.extra.DATA_SPN";
+    field public static final String EXTRA_PLMN = "android.telephony.extra.PLMN";
+    field public static final String EXTRA_SHOW_PLMN = "android.telephony.extra.SHOW_PLMN";
+    field public static final String EXTRA_SHOW_SPN = "android.telephony.extra.SHOW_SPN";
     field public static final String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
+    field public static final String EXTRA_SPN = "android.telephony.extra.SPN";
     field public static final String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
     field public static final int INVALID_EMERGENCY_NUMBER_DB_VERSION = -1; // 0xffffffff
@@ -9995,15 +10189,12 @@
   }
 
   public class ImsManager {
-    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
     field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
-    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
   }
 
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+    method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getVoWiFiRoamingModeSetting();
@@ -10371,8 +10562,8 @@
     method public int describeContents();
     method @NonNull public java.util.List<java.lang.String> getCapableExtensionTags();
     method @NonNull public android.net.Uri getContactUri();
-    method @Nullable public android.net.Uri getServiceUri(int);
-    method public boolean isCapable(int);
+    method @Nullable public android.net.Uri getServiceUri(long);
+    method public boolean isCapable(long);
     method public boolean isCapable(@NonNull String);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field public static final int CAPABILITY_CALL_COMPOSER = 4194304; // 0x400000
@@ -10394,6 +10585,7 @@
     field public static final int CAPABILITY_IMAGE_SHARE = 256; // 0x100
     field public static final int CAPABILITY_IP_VIDEO_CALL = 16384; // 0x4000
     field public static final int CAPABILITY_IP_VOICE_CALL = 8192; // 0x2000
+    field public static final int CAPABILITY_MMTEL_CALL_COMPOSER = 1073741824; // 0x40000000
     field public static final int CAPABILITY_PLUG_IN = 268435456; // 0x10000000
     field public static final int CAPABILITY_POST_CALL = 8388608; // 0x800000
     field public static final int CAPABILITY_RCS_VIDEO_CALL = 1048576; // 0x100000
@@ -10402,6 +10594,7 @@
     field public static final int CAPABILITY_SHARED_MAP = 16777216; // 0x1000000
     field public static final int CAPABILITY_SHARED_SKETCH = 33554432; // 0x2000000
     field public static final int CAPABILITY_SOCIAL_PRESENCE = 2048; // 0x800
+    field public static final int CAPABILITY_STANDALONE_CHAT_BOT = 536870912; // 0x20000000
     field public static final int CAPABILITY_VIDEO_SHARE = 1024; // 0x400
     field public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = 512; // 0x200
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactUceCapability> CREATOR;
@@ -10409,12 +10602,43 @@
 
   public static class RcsContactUceCapability.Builder {
     ctor public RcsContactUceCapability.Builder(@NonNull android.net.Uri);
-    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int, @NonNull android.net.Uri);
-    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(int);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long, @NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long);
     method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(@NonNull String);
     method @NonNull public android.telephony.ims.RcsContactUceCapability build();
   }
 
+  public class RcsUceAdapter {
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getUcePublishState() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
+    field public static final int ERROR_ALREADY_IN_QUEUE = 13; // 0xd
+    field public static final int ERROR_FORBIDDEN = 6; // 0x6
+    field public static final int ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final int ERROR_INSUFFICIENT_MEMORY = 11; // 0xb
+    field public static final int ERROR_LOST_NETWORK = 12; // 0xc
+    field public static final int ERROR_NOT_AUTHORIZED = 5; // 0x5
+    field public static final int ERROR_NOT_AVAILABLE = 3; // 0x3
+    field public static final int ERROR_NOT_ENABLED = 2; // 0x2
+    field public static final int ERROR_NOT_FOUND = 7; // 0x7
+    field public static final int ERROR_NOT_REGISTERED = 4; // 0x4
+    field public static final int ERROR_REQUEST_TIMEOUT = 10; // 0xa
+    field public static final int ERROR_REQUEST_TOO_LARGE = 8; // 0x8
+    field public static final int PUBLISH_STATE_200_OK = 1; // 0x1
+    field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2
+    field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6
+    field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4
+    field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3; // 0x3
+  }
+
+  public static class RcsUceAdapter.CapabilitiesCallback {
+    ctor public RcsUceAdapter.CapabilitiesCallback();
+    method public void onCapabilitiesReceived(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>);
+    method public void onError(int);
+  }
+
 }
 
 package android.telephony.ims.feature {
@@ -10504,6 +10728,8 @@
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method @NonNull public android.telephony.ims.stub.RcsSipOptionsImplBase getOptionsExchangeImpl();
+    method @NonNull public android.telephony.ims.stub.RcsPresenceExchangeImplBase getPresenceExchangeImpl();
     method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
@@ -10696,6 +10922,71 @@
     field public static final int INVALID_RESULT = -1; // 0xffffffff
   }
 
+  public class RcsCapabilityExchange {
+    ctor public RcsCapabilityExchange();
+    method public final void onCommandUpdate(int, int) throws android.telephony.ims.ImsException;
+    field public static final int COMMAND_CODE_FETCH_ERROR = 4; // 0x4
+    field public static final int COMMAND_CODE_GENERIC_FAILURE = 2; // 0x2
+    field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6; // 0x6
+    field public static final int COMMAND_CODE_INVALID_PARAM = 3; // 0x3
+    field public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7; // 0x7
+    field public static final int COMMAND_CODE_NOT_FOUND = 9; // 0x9
+    field public static final int COMMAND_CODE_NOT_SUPPORTED = 8; // 0x8
+    field public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11; // 0xb
+    field public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10; // 0xa
+    field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
+    field public static final int COMMAND_CODE_SUCCESS = 1; // 0x1
+  }
+
+  public class RcsPresenceExchangeImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsPresenceExchangeImplBase();
+    method public final void onCapabilityRequestResponse(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>, int) throws android.telephony.ims.ImsException;
+    method public final void onNetworkResponse(int, @NonNull String, int) throws android.telephony.ims.ImsException;
+    method public final void onNotifyUpdateCapabilites(int) throws android.telephony.ims.ImsException;
+    method public final void onUnpublish() throws android.telephony.ims.ImsException;
+    method public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, int);
+    method public void updateCapabilities(@NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; // 0x0
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; // 0x6
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; // 0x5
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; // 0x3
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; // 0x4
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; // 0x8
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; // 0x1
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; // 0x2
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; // 0xa
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; // 0xb
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; // 0x7
+    field public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; // 0x9
+    field public static final int RESPONSE_FORBIDDEN = 3; // 0x3
+    field public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2; // 0x2
+    field public static final int RESPONSE_NOT_FOUND = 4; // 0x4
+    field public static final int RESPONSE_NOT_REGISTERED = 1; // 0x1
+    field public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7; // 0x7
+    field public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8; // 0x8
+    field public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6; // 0x6
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+  }
+
+  public class RcsSipOptionsImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsSipOptionsImplBase();
+    method public final void onCapabilityRequestResponse(int, @NonNull String, @Nullable android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public final void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public void respondToCapabilityRequest(@NonNull String, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    method public void respondToCapabilityRequestWithError(@NonNull android.net.Uri, int, @NonNull String, int);
+    method public void sendCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int RESPONSE_BAD_REQUEST = 5; // 0x5
+    field public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; // 0x4
+    field public static final int RESPONSE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_NOT_FOUND = 3; // 0x3
+    field public static final int RESPONSE_REQUEST_TIMEOUT = 2; // 0x2
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+    field public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; // 0x1
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/api/system-lint-baseline.txt b/api/system-lint-baseline.txt
index 432a5fd..306b8af 100644
--- a/api/system-lint-baseline.txt
+++ b/api/system-lint-baseline.txt
@@ -1,4 +1,14 @@
 // Baseline format: 1.0
+// Tethering broadcast action / extras cannot change name for backwards compatibility
+ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED:
+    Inconsistent action value; expected `android.net.action.TETHER_STATE_CHANGED`, was `android.net.conn.TETHER_STATE_CHANGED`
+ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER:
+    Inconsistent extra value; expected `android.net.extra.ACTIVE_TETHER`, was `tetherArray`
+ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER:
+    Inconsistent extra value; expected `android.net.extra.AVAILABLE_TETHER`, was `availableArray`
+ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER:
+    Inconsistent extra value; expected `android.net.extra.ERRORED_TETHER`, was `erroredArray`
+
 ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
     
 
diff --git a/api/test-current.txt b/api/test-current.txt
index 98b224d..b9d53db 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -653,11 +653,11 @@
     method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
     field public static final String BUGREPORT_SERVICE = "bugreport";
     field public static final String CONTENT_CAPTURE_MANAGER_SERVICE = "content_capture";
+    field public static final String ETHERNET_SERVICE = "ethernet";
     field public static final String NETWORK_STACK_SERVICE = "network_stack";
     field public static final String PERMISSION_SERVICE = "permission";
     field public static final String ROLLBACK_SERVICE = "rollback";
     field public static final String STATUS_BAR_SERVICE = "statusbar";
-    field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
     field public static final String TEST_NETWORK_SERVICE = "test_network";
   }
 
@@ -1393,6 +1393,19 @@
     field public static final String EXTRA_CAPTIVE_PORTAL_USER_AGENT = "android.net.extra.CAPTIVE_PORTAL_USER_AGENT";
   }
 
+  public class EthernetManager {
+    method @NonNull public android.net.EthernetManager.TetheredInterfaceRequest requestTetheredInterface(@NonNull android.net.EthernetManager.TetheredInterfaceCallback);
+  }
+
+  public static interface EthernetManager.TetheredInterfaceCallback {
+    method public void onAvailable(@NonNull String);
+    method public void onUnavailable();
+  }
+
+  public static class EthernetManager.TetheredInterfaceRequest {
+    method public void release();
+  }
+
   public final class IpPrefix implements android.os.Parcelable {
     ctor public IpPrefix(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public IpPrefix(@NonNull String);
@@ -1404,9 +1417,12 @@
 
   public class LinkAddress implements android.os.Parcelable {
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int);
+    ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int, int, int, long, long);
     ctor public LinkAddress(@NonNull java.net.InetAddress, @IntRange(from=0, to=128) int);
     ctor public LinkAddress(@NonNull String);
     ctor public LinkAddress(@NonNull String, int, int);
+    method public long getDeprecationTime();
+    method public long getExpirationTime();
     method public boolean isGlobalPreferred();
     method public boolean isIpv4();
     method public boolean isIpv6();
@@ -1506,6 +1522,101 @@
     method public void teardownTestNetwork(@NonNull android.net.Network);
   }
 
+  public final class TetheredClient implements android.os.Parcelable {
+    ctor public TetheredClient(@NonNull android.net.MacAddress, @NonNull java.util.Collection<android.net.TetheredClient.AddressInfo>, int);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.net.TetheredClient.AddressInfo> getAddresses();
+    method @NonNull public android.net.MacAddress getMacAddress();
+    method public int getTetheringType();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient> CREATOR;
+  }
+
+  public static final class TetheredClient.AddressInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public android.net.LinkAddress getAddress();
+    method @Nullable public String getHostname();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.TetheredClient.AddressInfo> CREATOR;
+  }
+
+  public class TetheringManager {
+    method @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.TetheringEventCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void requestLatestTetheringEntitlementResult(int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.OnTetheringEntitlementResultListener);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(@NonNull android.net.TetheringManager.TetheringRequest, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void startTethering(int, @NonNull java.util.concurrent.Executor, @NonNull android.net.TetheringManager.StartTetheringCallback);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopAllTethering();
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.WRITE_SETTINGS}) public void stopTethering(int);
+    method @RequiresPermission(anyOf={"android.permission.TETHER_PRIVILEGED", android.Manifest.permission.ACCESS_NETWORK_STATE}) public void unregisterTetheringEventCallback(@NonNull android.net.TetheringManager.TetheringEventCallback);
+    field public static final String ACTION_TETHER_STATE_CHANGED = "android.net.conn.TETHER_STATE_CHANGED";
+    field public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
+    field public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
+    field public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
+    field public static final String EXTRA_ERRORED_TETHER = "erroredArray";
+    field public static final int TETHERING_BLUETOOTH = 2; // 0x2
+    field public static final int TETHERING_ETHERNET = 5; // 0x5
+    field public static final int TETHERING_INVALID = -1; // 0xffffffff
+    field public static final int TETHERING_NCM = 4; // 0x4
+    field public static final int TETHERING_USB = 1; // 0x1
+    field public static final int TETHERING_WIFI = 0; // 0x0
+    field public static final int TETHERING_WIFI_P2P = 3; // 0x3
+    field public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; // 0xc
+    field public static final int TETHER_ERROR_DISABLE_NAT_ERROR = 9; // 0x9
+    field public static final int TETHER_ERROR_ENABLE_NAT_ERROR = 8; // 0x8
+    field public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; // 0xd
+    field public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; // 0xa
+    field public static final int TETHER_ERROR_MASTER_ERROR = 5; // 0x5
+    field public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; // 0xf
+    field public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; // 0xe
+    field public static final int TETHER_ERROR_NO_ERROR = 0; // 0x0
+    field public static final int TETHER_ERROR_PROVISION_FAILED = 11; // 0xb
+    field public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; // 0x2
+    field public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; // 0x6
+    field public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; // 0x4
+    field public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; // 0x1
+    field public static final int TETHER_ERROR_UNSUPPORTED = 3; // 0x3
+    field public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; // 0x7
+  }
+
+  public static interface TetheringManager.OnTetheringEntitlementResultListener {
+    method public void onTetheringEntitlementResult(int);
+  }
+
+  public abstract static class TetheringManager.StartTetheringCallback {
+    ctor public TetheringManager.StartTetheringCallback();
+    method public void onTetheringFailed(int);
+    method public void onTetheringStarted();
+  }
+
+  public abstract static class TetheringManager.TetheringEventCallback {
+    ctor public TetheringManager.TetheringEventCallback();
+    method public void onClientsChanged(@NonNull java.util.Collection<android.net.TetheredClient>);
+    method public void onError(@NonNull String, int);
+    method @Deprecated public void onTetherableInterfaceRegexpsChanged(@NonNull android.net.TetheringManager.TetheringInterfaceRegexps);
+    method public void onTetherableInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public void onTetheredInterfacesChanged(@NonNull java.util.List<java.lang.String>);
+    method public void onTetheringSupported(boolean);
+    method public void onUpstreamChanged(@Nullable android.net.Network);
+  }
+
+  @Deprecated public static class TetheringManager.TetheringInterfaceRegexps {
+    ctor @Deprecated public TetheringManager.TetheringInterfaceRegexps(@NonNull String[], @NonNull String[], @NonNull String[]);
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableBluetoothRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableUsbRegexs();
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getTetherableWifiRegexs();
+  }
+
+  public static class TetheringManager.TetheringRequest {
+  }
+
+  public static class TetheringManager.TetheringRequest.Builder {
+    ctor public TetheringManager.TetheringRequest.Builder(int);
+    method @NonNull public android.net.TetheringManager.TetheringRequest build();
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setExemptFromEntitlementCheck(boolean);
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder setSilentProvisioning(boolean);
+    method @NonNull @RequiresPermission("android.permission.TETHER_PRIVILEGED") public android.net.TetheringManager.TetheringRequest.Builder useStaticIpv4Addresses(@NonNull android.net.LinkAddress);
+  }
+
   public class TrafficStats {
     method public static long getLoopbackRxBytes();
     method public static long getLoopbackRxPackets();
@@ -3304,15 +3415,12 @@
   }
 
   public class ImsManager {
-    method @NonNull public android.telephony.ims.ImsMmTelManager getImsMmTelManager(int);
     method @NonNull public android.telephony.ims.ImsRcsManager getImsRcsManager(int);
     field public static final String ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION = "com.android.internal.intent.action.ACTION_FORBIDDEN_NO_SERVICE_AUTHORIZATION";
-    field public static final String ACTION_WFC_IMS_REGISTRATION_ERROR = "android.telephony.ims.action.WFC_IMS_REGISTRATION_ERROR";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_MESSAGE";
-    field public static final String EXTRA_WFC_REGISTRATION_FAILURE_TITLE = "android.telephony.ims.extra.WFC_REGISTRATION_FAILURE_TITLE";
   }
 
   public class ImsMmTelManager implements android.telephony.ims.RegistrationManager {
+    method @Deprecated @NonNull @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public static android.telephony.ims.ImsMmTelManager createForSubscriptionId(int);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getFeatureState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>) throws android.telephony.ims.ImsException;
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void getRegistrationState(@NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getVoWiFiRoamingModeSetting();
@@ -3672,6 +3780,87 @@
     method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
+  public final class RcsContactUceCapability implements android.os.Parcelable {
+    method public int describeContents();
+    method @NonNull public java.util.List<java.lang.String> getCapableExtensionTags();
+    method @NonNull public android.net.Uri getContactUri();
+    method @Nullable public android.net.Uri getServiceUri(long);
+    method public boolean isCapable(long);
+    method public boolean isCapable(@NonNull String);
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field public static final int CAPABILITY_CALL_COMPOSER = 4194304; // 0x400000
+    field public static final int CAPABILITY_CHAT_BOT = 67108864; // 0x4000000
+    field public static final int CAPABILITY_CHAT_BOT_ROLE = 134217728; // 0x8000000
+    field public static final int CAPABILITY_CHAT_SESSION = 2; // 0x2
+    field public static final int CAPABILITY_CHAT_SESSION_STORE_FORWARD = 4; // 0x4
+    field public static final int CAPABILITY_CHAT_STANDALONE = 1; // 0x1
+    field public static final int CAPABILITY_DISCOVERY_VIA_PRESENCE = 4096; // 0x1000
+    field public static final int CAPABILITY_FILE_TRANSFER = 8; // 0x8
+    field public static final int CAPABILITY_FILE_TRANSFER_HTTP = 64; // 0x40
+    field public static final int CAPABILITY_FILE_TRANSFER_SMS = 128; // 0x80
+    field public static final int CAPABILITY_FILE_TRANSFER_STORE_FORWARD = 32; // 0x20
+    field public static final int CAPABILITY_FILE_TRANSFER_THUMBNAIL = 16; // 0x10
+    field public static final int CAPABILITY_GEOLOCATION_PULL = 131072; // 0x20000
+    field public static final int CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER = 262144; // 0x40000
+    field public static final int CAPABILITY_GEOLOCATION_PUSH = 32768; // 0x8000
+    field public static final int CAPABILITY_GEOLOCATION_PUSH_SMS = 65536; // 0x10000
+    field public static final int CAPABILITY_IMAGE_SHARE = 256; // 0x100
+    field public static final int CAPABILITY_IP_VIDEO_CALL = 16384; // 0x4000
+    field public static final int CAPABILITY_IP_VOICE_CALL = 8192; // 0x2000
+    field public static final int CAPABILITY_MMTEL_CALL_COMPOSER = 1073741824; // 0x40000000
+    field public static final int CAPABILITY_PLUG_IN = 268435456; // 0x10000000
+    field public static final int CAPABILITY_POST_CALL = 8388608; // 0x800000
+    field public static final int CAPABILITY_RCS_VIDEO_CALL = 1048576; // 0x100000
+    field public static final int CAPABILITY_RCS_VIDEO_ONLY_CALL = 2097152; // 0x200000
+    field public static final int CAPABILITY_RCS_VOICE_CALL = 524288; // 0x80000
+    field public static final int CAPABILITY_SHARED_MAP = 16777216; // 0x1000000
+    field public static final int CAPABILITY_SHARED_SKETCH = 33554432; // 0x2000000
+    field public static final int CAPABILITY_SOCIAL_PRESENCE = 2048; // 0x800
+    field public static final int CAPABILITY_STANDALONE_CHAT_BOT = 536870912; // 0x20000000
+    field public static final int CAPABILITY_VIDEO_SHARE = 1024; // 0x400
+    field public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = 512; // 0x200
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactUceCapability> CREATOR;
+  }
+
+  public static class RcsContactUceCapability.Builder {
+    ctor public RcsContactUceCapability.Builder(@NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long, @NonNull android.net.Uri);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(long);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability.Builder add(@NonNull String);
+    method @NonNull public android.telephony.ims.RcsContactUceCapability build();
+  }
+
+  public class RcsUceAdapter {
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public int getUcePublishState() throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public boolean isUceSettingEnabled() throws android.telephony.ims.ImsException;
+    method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public void requestCapabilities(@NonNull java.util.concurrent.Executor, @NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
+    field public static final int ERROR_ALREADY_IN_QUEUE = 13; // 0xd
+    field public static final int ERROR_FORBIDDEN = 6; // 0x6
+    field public static final int ERROR_GENERIC_FAILURE = 1; // 0x1
+    field public static final int ERROR_INSUFFICIENT_MEMORY = 11; // 0xb
+    field public static final int ERROR_LOST_NETWORK = 12; // 0xc
+    field public static final int ERROR_NOT_AUTHORIZED = 5; // 0x5
+    field public static final int ERROR_NOT_AVAILABLE = 3; // 0x3
+    field public static final int ERROR_NOT_ENABLED = 2; // 0x2
+    field public static final int ERROR_NOT_FOUND = 7; // 0x7
+    field public static final int ERROR_NOT_REGISTERED = 4; // 0x4
+    field public static final int ERROR_REQUEST_TIMEOUT = 10; // 0xa
+    field public static final int ERROR_REQUEST_TOO_LARGE = 8; // 0x8
+    field public static final int PUBLISH_STATE_200_OK = 1; // 0x1
+    field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2
+    field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6
+    field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4
+    field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3; // 0x3
+  }
+
+  public static class RcsUceAdapter.CapabilitiesCallback {
+    ctor public RcsUceAdapter.CapabilitiesCallback();
+    method public void onCapabilitiesReceived(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>);
+    method public void onError(int);
+  }
+
 }
 
 package android.telephony.ims.feature {
@@ -3761,6 +3950,8 @@
   public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
     ctor public RcsFeature();
     method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
+    method @NonNull public android.telephony.ims.stub.RcsSipOptionsImplBase getOptionsExchangeImpl();
+    method @NonNull public android.telephony.ims.stub.RcsPresenceExchangeImplBase getPresenceExchangeImpl();
     method public final void notifyCapabilitiesStatusChanged(@NonNull android.telephony.ims.feature.RcsFeature.RcsImsCapabilities);
     method public void onFeatureReady();
     method public void onFeatureRemoved();
@@ -3953,6 +4144,71 @@
     field public static final int INVALID_RESULT = -1; // 0xffffffff
   }
 
+  public class RcsCapabilityExchange {
+    ctor public RcsCapabilityExchange();
+    method public final void onCommandUpdate(int, int) throws android.telephony.ims.ImsException;
+    field public static final int COMMAND_CODE_FETCH_ERROR = 4; // 0x4
+    field public static final int COMMAND_CODE_GENERIC_FAILURE = 2; // 0x2
+    field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6; // 0x6
+    field public static final int COMMAND_CODE_INVALID_PARAM = 3; // 0x3
+    field public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7; // 0x7
+    field public static final int COMMAND_CODE_NOT_FOUND = 9; // 0x9
+    field public static final int COMMAND_CODE_NOT_SUPPORTED = 8; // 0x8
+    field public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11; // 0xb
+    field public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10; // 0xa
+    field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
+    field public static final int COMMAND_CODE_SUCCESS = 1; // 0x1
+  }
+
+  public class RcsPresenceExchangeImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsPresenceExchangeImplBase();
+    method public final void onCapabilityRequestResponse(@NonNull java.util.List<android.telephony.ims.RcsContactUceCapability>, int) throws android.telephony.ims.ImsException;
+    method public final void onNetworkResponse(int, @NonNull String, int) throws android.telephony.ims.ImsException;
+    method public final void onNotifyUpdateCapabilites(int) throws android.telephony.ims.ImsException;
+    method public final void onUnpublish() throws android.telephony.ims.ImsException;
+    method public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, int);
+    method public void updateCapabilities(@NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; // 0x0
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; // 0x6
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; // 0x5
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; // 0x3
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; // 0x4
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8; // 0x8
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1; // 0x1
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2; // 0x2
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; // 0xa
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; // 0xb
+    field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; // 0x7
+    field public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9; // 0x9
+    field public static final int RESPONSE_FORBIDDEN = 3; // 0x3
+    field public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2; // 0x2
+    field public static final int RESPONSE_NOT_FOUND = 4; // 0x4
+    field public static final int RESPONSE_NOT_REGISTERED = 1; // 0x1
+    field public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7; // 0x7
+    field public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5; // 0x5
+    field public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8; // 0x8
+    field public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6; // 0x6
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+  }
+
+  public class RcsSipOptionsImplBase extends android.telephony.ims.stub.RcsCapabilityExchange {
+    ctor public RcsSipOptionsImplBase();
+    method public final void onCapabilityRequestResponse(int, @NonNull String, @Nullable android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public final void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int) throws android.telephony.ims.ImsException;
+    method public void respondToCapabilityRequest(@NonNull String, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    method public void respondToCapabilityRequestWithError(@NonNull android.net.Uri, int, @NonNull String, int);
+    method public void sendCapabilityRequest(@NonNull android.net.Uri, @NonNull android.telephony.ims.RcsContactUceCapability, int);
+    field public static final int RESPONSE_BAD_REQUEST = 5; // 0x5
+    field public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; // 0x4
+    field public static final int RESPONSE_GENERIC_FAILURE = -1; // 0xffffffff
+    field public static final int RESPONSE_NOT_FOUND = 3; // 0x3
+    field public static final int RESPONSE_REQUEST_TIMEOUT = 2; // 0x2
+    field public static final int RESPONSE_SUCCESS = 0; // 0x0
+    field public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; // 0x1
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/api/test-lint-baseline.txt b/api/test-lint-baseline.txt
index 3af392c..46f3aeb 100644
--- a/api/test-lint-baseline.txt
+++ b/api/test-lint-baseline.txt
@@ -5,6 +5,16 @@
     
 
 
+// Tethering broadcast action / extras cannot change name for backwards compatibility
+ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED:
+    Inconsistent action value; expected `android.net.action.TETHER_STATE_CHANGED`, was `android.net.conn.TETHER_STATE_CHANGED`
+ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER:
+    Inconsistent extra value; expected `android.net.extra.ACTIVE_TETHER`, was `tetherArray`
+ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER:
+    Inconsistent extra value; expected `android.net.extra.AVAILABLE_TETHER`, was `availableArray`
+ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER:
+    Inconsistent extra value; expected `android.net.extra.ERRORED_TETHER`, was `erroredArray`
+
 ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO:
     Inconsistent extra value; expected `android.telephony.ims.extra.ADDITIONAL_CALL_INFO`, was `AdditionalCallInfo`
 ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE:
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 1987440..9707405 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -366,12 +366,8 @@
     }
 
     private void runGetMaxPhones() throws RemoteException {
-        // This assumes the max number of SIMs is 2, which it currently is
-        if (TelephonyManager.MULTISIM_ALLOWED == mTelephonyManager.isMultiSimSupported()) {
-            System.out.println("2");
-        } else {
-            System.out.println("1");
-        }
+        // how many logical modems can be potentially active simultaneously
+        System.out.println(mTelephonyManager.getSupportedModemCount());
     }
 
     private void runSetEmergencyPhoneAccountPackageFilter() throws RemoteException {
diff --git a/core/java/android/annotation/SystemApi.java b/core/java/android/annotation/SystemApi.java
index 2cb93e4..ecbfed9 100644
--- a/core/java/android/annotation/SystemApi.java
+++ b/core/java/android/annotation/SystemApi.java
@@ -23,6 +23,7 @@
 import static java.lang.annotation.ElementType.PACKAGE;
 import static java.lang.annotation.ElementType.TYPE;
 
+import java.lang.annotation.Repeatable;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
@@ -40,39 +41,48 @@
  */
 @Target({TYPE, FIELD, METHOD, CONSTRUCTOR, ANNOTATION_TYPE, PACKAGE})
 @Retention(RetentionPolicy.RUNTIME)
+@Repeatable(SystemApi.Container.class) // TODO(b/146727827): make this non-repeatable
 public @interface SystemApi {
     enum Client {
         /**
          * Specifies that the intended clients of a SystemApi are privileged apps.
-         * This is the default value for {@link #client}. This implies
-         * MODULE_APPS and MODULE_LIBRARIES as well, which means that APIs will also
-         * be available to module apps and jars.
+         * This is the default value for {@link #client}.
+         * TODO Update the javadoc according to the final spec
          */
         PRIVILEGED_APPS,
 
         /**
-         * Specifies that the intended clients of a SystemApi are modules implemented
-         * as apps, like the NetworkStack app. This implies MODULE_LIBRARIES as well,
-         * which means that APIs will also be available to module jars.
+         * DO NOT USE. Use PRIVILEGED_APPS instead.
+         * (This would provide no further protection over PRIVILEGED_APPS; do not rely on it)
+         * @deprecated Use #PRIVILEGED_APPS instead
          */
+        @Deprecated
         MODULE_APPS,
 
         /**
          * Specifies that the intended clients of a SystemApi are modules implemented
          * as libraries, like the conscrypt.jar in the conscrypt APEX.
+         * TODO Update the javadoc according to the final spec
          */
-        MODULE_LIBRARIES
+        MODULE_LIBRARIES,
+
+        /**
+         * Specifies that the system API is available only in the system server process.
+         * Use this to expose APIs from code loaded by the system server process <em>but</em>
+         * not in <pre>BOOTCLASSPATH</pre>.
+         * TODO(b/148177503) Update "services-stubs" and actually use it.
+         */
+        SYSTEM_SERVER
     }
 
+    /** @deprecated do not use */
+    @Deprecated
     enum Process {
-        /**
-         * Specifies that the SystemAPI is available in every Java processes.
-         * This is the default value for {@link #process}.
-         */
+        /** @deprecated do not use */
         ALL,
 
         /**
-         * Specifies that the SystemAPI is available only in the system server process.
+         * @deprecated use Client#SYSTEM_SERVER instead
          */
         SYSTEM_SERVER
     }
@@ -83,7 +93,18 @@
     Client client() default android.annotation.SystemApi.Client.PRIVILEGED_APPS;
 
     /**
-     * The process(es) that this SystemAPI is available
+     * @deprecated use Client#SYSTEM_SERVER instead for system_server APIs
      */
+    @Deprecated
     Process process() default android.annotation.SystemApi.Process.ALL;
+
+
+    /**
+     * Container for {@link SystemApi} that allows it to be applied repeatedly to types.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(TYPE)
+    @interface Container {
+        SystemApi[] value();
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index bd0a39c..8415ecd 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -3236,18 +3236,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, listenUsingL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingL2capCoc(int transport)
-            throws IOException {
-        Log.e(TAG, "listenUsingL2capCoc: PLEASE USE THE OFFICIAL API, listenUsingL2capChannel");
-        return listenUsingL2capChannel();
-    }
-
-    /**
      * Create an insecure L2CAP Connection-oriented Channel (CoC) {@link BluetoothServerSocket} and
      * assign a dynamic PSM value. This socket can be used to listen for incoming connections. The
      * supported Bluetooth transport is LE only.
@@ -3294,19 +3282,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, listenUsingInsecureL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingInsecureL2capCoc(int transport)
-            throws IOException {
-        Log.e(TAG, "listenUsingInsecureL2capCoc: PLEASE USE THE OFFICIAL API, "
-                    + "listenUsingInsecureL2capChannel");
-        return listenUsingInsecureL2capChannel();
-    }
-
-    /**
      * Register a {@link #OnMetadataChangedListener} to receive update about metadata
      * changes for this {@link BluetoothDevice}.
      * Registration must be done when Bluetooth is ON and will last until
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 9fe4dd6..12dc814c 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -2172,17 +2172,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, createL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createL2capCocSocket(int transport, int psm) throws IOException {
-        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createL2capChannel");
-        return createL2capChannel(psm);
-    }
-
-    /**
      * Create a Bluetooth L2CAP Connection-oriented Channel (CoC) {@link BluetoothSocket} that can
      * be used to start a secure outgoing connection to the remote device with the same dynamic
      * protocol/service multiplexer (PSM) value. The supported Bluetooth transport is LE only.
@@ -2213,17 +2202,6 @@
     }
 
     /**
-     * TODO: Remove this hidden method once all the SL4A and other tests are updated to use the new
-     * API name, createInsecureL2capChannel.
-     * @hide
-     */
-    @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createInsecureL2capCocSocket(int transport, int psm) throws IOException {
-        Log.e(TAG, "createL2capCocSocket: PLEASE USE THE OFFICIAL API, createInsecureL2capChannel");
-        return createInsecureL2capChannel(psm);
-    }
-
-    /**
      * Set a keyed metadata of this {@link BluetoothDevice} to a
      * {@link String} value.
      * Only bonded devices's metadata will be persisted across Bluetooth
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 472d956..c3c7f97 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4022,16 +4022,16 @@
     public static final String LOWPAN_SERVICE = "lowpan";
 
     /**
-     * Use with {@link #getSystemService(String)} to retrieve a {@link
-     * android.net.EthernetManager} for handling management of
-     * Ethernet access.
+     * Use with {@link #getSystemService(String)} to retrieve a {@link android.net.EthernetManager}
+     * for handling management of Ethernet access.
      *
      * @see #getSystemService(String)
      * @see android.net.EthernetManager
      *
      * @hide
      */
-    @UnsupportedAppUsage
+    @SystemApi
+    @TestApi
     public static final String ETHERNET_SERVICE = "ethernet";
 
     /**
@@ -4854,10 +4854,7 @@
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
      * {@link android.telephony.ims.ImsManager}.
-     * @hide
      */
-    @SystemApi
-    @TestApi
     public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
 
     /**
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 67fdda3..b0d0b4c 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -262,6 +262,15 @@
     public static final String USB_FUNCTION_ACCESSORY = "accessory";
 
     /**
+     * Name of the NCM USB function.
+     * Used in extras for the {@link #ACTION_USB_STATE} broadcast
+     *
+     * {@hide}
+     */
+    @SystemApi
+    public static final String USB_FUNCTION_NCM = "ncm";
+
+    /**
      * Name of extra for {@link #ACTION_USB_PORT_CHANGED}
      * containing the {@link UsbPort} object for the port.
      *
@@ -367,8 +376,15 @@
      */
     public static final long FUNCTION_ADB = GadgetFunction.ADB;
 
+    /**
+     * Code for the ncm source usb function.
+     * {@hide}
+     */
+    @SystemApi
+    public static final long FUNCTION_NCM = 1 << 10;
+
     private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
-            | FUNCTION_MIDI;
+            | FUNCTION_MIDI | FUNCTION_NCM;
 
     private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
 
@@ -380,6 +396,7 @@
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
+        FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM);
     }
 
     private final Context mContext;
@@ -935,6 +952,9 @@
         if ((functions & FUNCTION_AUDIO_SOURCE) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE);
         }
+        if ((functions & FUNCTION_NCM) != 0) {
+            joiner.add(UsbManager.USB_FUNCTION_NCM);
+        }
         if ((functions & FUNCTION_ADB) != 0) {
             joiner.add(UsbManager.USB_FUNCTION_ADB);
         }
diff --git a/core/java/android/net/ConnectivityDiagnosticsManager.java b/core/java/android/net/ConnectivityDiagnosticsManager.java
index 4564813..b13e4b7 100644
--- a/core/java/android/net/ConnectivityDiagnosticsManager.java
+++ b/core/java/android/net/ConnectivityDiagnosticsManager.java
@@ -21,6 +21,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringDef;
 import android.content.Context;
+import android.os.Binder;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PersistableBundle;
@@ -544,6 +545,53 @@
                 };
     }
 
+    /** @hide */
+    @VisibleForTesting
+    public static class ConnectivityDiagnosticsBinder
+            extends IConnectivityDiagnosticsCallback.Stub {
+        @NonNull private final ConnectivityDiagnosticsCallback mCb;
+        @NonNull private final Executor mExecutor;
+
+        /** @hide */
+        @VisibleForTesting
+        public ConnectivityDiagnosticsBinder(
+                @NonNull ConnectivityDiagnosticsCallback cb, @NonNull Executor executor) {
+            this.mCb = cb;
+            this.mExecutor = executor;
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onConnectivityReport(@NonNull ConnectivityReport report) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onConnectivityReport(report);
+                });
+            });
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onDataStallSuspected(@NonNull DataStallReport report) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onDataStallSuspected(report);
+                });
+            });
+        }
+
+        /** @hide */
+        @VisibleForTesting
+        public void onNetworkConnectivityReported(
+                @NonNull Network network, boolean hasConnectivity) {
+            Binder.withCleanCallingIdentity(() -> {
+                mExecutor.execute(() -> {
+                    mCb.onNetworkConnectivityReported(network, hasConnectivity);
+                });
+            });
+        }
+    }
+
     /**
      * Abstract base class for Connectivity Diagnostics callbacks. Used for notifications about
      * network connectivity events. Must be extended by applications wanting notifications.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 11c1a9c..94eda01 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -33,6 +33,9 @@
 import android.content.Intent;
 import android.net.IpSecManager.UdpEncapsulationSocket;
 import android.net.SocketKeepalive.Callback;
+import android.net.TetheringManager.StartTetheringCallback;
+import android.net.TetheringManager.TetheringEventCallback;
+import android.net.TetheringManager.TetheringRequest;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
@@ -58,6 +61,7 @@
 import android.util.Log;
 import android.util.SparseIntArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.Protocol;
 
@@ -75,6 +79,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -484,34 +489,35 @@
      * enable if any.
      * @hide
      */
-    public static final String EXTRA_ADD_TETHER_TYPE = TetheringManager.EXTRA_ADD_TETHER_TYPE;
+    public static final String EXTRA_ADD_TETHER_TYPE = TetheringConstants.EXTRA_ADD_TETHER_TYPE;
 
     /**
      * Extra used for communicating with the TetherService. Includes the type of tethering for
      * which to cancel provisioning.
      * @hide
      */
-    public static final String EXTRA_REM_TETHER_TYPE = TetheringManager.EXTRA_REM_TETHER_TYPE;
+    public static final String EXTRA_REM_TETHER_TYPE = TetheringConstants.EXTRA_REM_TETHER_TYPE;
 
     /**
      * Extra used for communicating with the TetherService. True to schedule a recheck of tether
      * provisioning.
      * @hide
      */
-    public static final String EXTRA_SET_ALARM = TetheringManager.EXTRA_SET_ALARM;
+    public static final String EXTRA_SET_ALARM = TetheringConstants.EXTRA_SET_ALARM;
 
     /**
      * Tells the TetherService to run a provision check now.
      * @hide
      */
-    public static final String EXTRA_RUN_PROVISION = TetheringManager.EXTRA_RUN_PROVISION;
+    public static final String EXTRA_RUN_PROVISION = TetheringConstants.EXTRA_RUN_PROVISION;
 
     /**
      * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
      * which will receive provisioning results. Can be left empty.
      * @hide
      */
-    public static final String EXTRA_PROVISION_CALLBACK = TetheringManager.EXTRA_PROVISION_CALLBACK;
+    public static final String EXTRA_PROVISION_CALLBACK =
+            TetheringConstants.EXTRA_PROVISION_CALLBACK;
 
     /**
      * The absence of a connection type.
@@ -2369,10 +2375,12 @@
      *
      * @return an array of 0 or more Strings of tetherable interface names.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetherableIfaces() {
         return getTetheringManager().getTetherableIfaces();
     }
@@ -2382,10 +2390,12 @@
      *
      * @return an array of 0 or more String of currently tethered interface names.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetherableInterfacesChanged(List)} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetheredIfaces() {
         return getTetheringManager().getTetheredIfaces();
     }
@@ -2401,10 +2411,12 @@
      * @return an array of 0 or more String indicating the interface names
      *        which failed to tether.
      *
+     * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetheringErroredIfaces() {
         return getTetheringManager().getTetheringErroredIfaces();
     }
@@ -2413,9 +2425,11 @@
      * Get the set of tethered dhcp ranges.
      *
      * @return an array of 0 or more {@code String} of tethered dhcp ranges.
+     * @deprecated This API just return the default value which is not used in DhcpServer.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    @Deprecated
     public String[] getTetheredDhcpRanges() {
         return getTetheringManager().getTetheredDhcpRanges();
     }
@@ -2441,10 +2455,12 @@
      *
      * @param iface the interface name to tether.
      * @return error a {@code TETHER_ERROR} value indicating success or failure type
+     * @deprecated Use {@link TetheringManager#startTethering} instead
      *
      * {@hide}
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int tether(String iface) {
         return getTetheringManager().tether(iface);
     }
@@ -2468,6 +2484,7 @@
      * {@hide}
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int untether(String iface) {
         return getTetheringManager().untether(iface);
     }
@@ -2488,6 +2505,7 @@
      *
      * @return a boolean - {@code true} indicating Tethering is supported.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetheringSupported(boolean)} instead.
      * {@hide}
      */
     @SystemApi
@@ -2499,9 +2517,12 @@
 
     /**
      * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
+     *
+     * @deprecated Use {@link TetheringManager.StartTetheringCallback} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     public static abstract class OnStartTetheringCallback {
         /**
          * Called when tethering has been successfully started.
@@ -2518,9 +2539,12 @@
      * Convenient overload for
      * {@link #startTethering(int, boolean, OnStartTetheringCallback, Handler)} which passes a null
      * handler to run on the current thread's {@link Looper}.
+     *
+     * @deprecated Use {@link TetheringManager#startTethering} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback) {
@@ -2544,26 +2568,44 @@
      * @param callback an {@link OnStartTetheringCallback} which will be called to notify the caller
      *         of the result of trying to tether.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
+     *
+     * @deprecated Use {@link TetheringManager#startTethering} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback, Handler handler) {
         Preconditions.checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
 
-        ResultReceiver wrappedCallback = new ResultReceiver(handler) {
+        final Executor executor = new Executor() {
             @Override
-            protected void onReceiveResult(int resultCode, Bundle resultData) {
-                if (resultCode == TETHER_ERROR_NO_ERROR) {
-                    callback.onTetheringStarted();
+            public void execute(Runnable command) {
+                if (handler == null) {
+                    command.run();
                 } else {
-                    callback.onTetheringFailed();
+                    handler.post(command);
                 }
             }
         };
 
-        getTetheringManager().startTethering(type, wrappedCallback, showProvisioningUi);
+        final StartTetheringCallback tetheringCallback = new StartTetheringCallback() {
+            @Override
+            public void onTetheringStarted() {
+                callback.onTetheringStarted();
+            }
+
+            @Override
+            public void onTetheringFailed(final int resultCode) {
+                callback.onTetheringFailed();
+            }
+        };
+
+        final TetheringRequest request = new TetheringRequest.Builder(type)
+                .setSilentProvisioning(!showProvisioningUi).build();
+
+        getTetheringManager().startTethering(request, executor, tetheringCallback);
     }
 
     /**
@@ -2574,9 +2616,12 @@
      *         {@link ConnectivityManager.TETHERING_WIFI},
      *         {@link ConnectivityManager.TETHERING_USB}, or
      *         {@link ConnectivityManager.TETHERING_BLUETOOTH}.
+     *
+     * @deprecated Use {@link TetheringManager#stopTethering} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void stopTethering(int type) {
         getTetheringManager().stopTethering(type);
@@ -2586,9 +2631,11 @@
      * Callback for use with {@link registerTetheringEventCallback} to find out tethering
      * upstream status.
      *
-     *@hide
+     * @deprecated Use {@link TetheringManager#OnTetheringEventCallback} instead.
+     * @hide
      */
     @SystemApi
+    @Deprecated
     public abstract static class OnTetheringEventCallback {
 
         /**
@@ -2601,6 +2648,10 @@
         public void onUpstreamChanged(@Nullable Network network) {}
     }
 
+    @GuardedBy("mTetheringEventCallbacks")
+    private final ArrayMap<OnTetheringEventCallback, TetheringEventCallback>
+            mTetheringEventCallbacks = new ArrayMap<>();
+
     /**
      * Start listening to tethering change events. Any new added callback will receive the last
      * tethering status right away. If callback is registered when tethering has no upstream or
@@ -2609,16 +2660,30 @@
      *
      * @param executor the executor on which callback will be invoked.
      * @param callback the callback to be called when tethering has change events.
+     *
+     * @deprecated Use {@link TetheringManager#registerTetheringEventCallback} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void registerTetheringEventCallback(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull final OnTetheringEventCallback callback) {
         Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
 
-        getTetheringManager().registerTetheringEventCallback(executor, callback);
+        final TetheringEventCallback tetherCallback =
+                new TetheringEventCallback() {
+                    @Override
+                    public void onUpstreamChanged(@Nullable Network network) {
+                        callback.onUpstreamChanged(network);
+                    }
+                };
+
+        synchronized (mTetheringEventCallbacks) {
+            mTetheringEventCallbacks.put(callback, tetherCallback);
+            getTetheringManager().registerTetheringEventCallback(executor, tetherCallback);
+        }
     }
 
     /**
@@ -2626,13 +2691,21 @@
      * {@link #registerTetheringEventCallback}.
      *
      * @param callback previously registered callback.
+     *
+     * @deprecated Use {@link TetheringManager#unregisterTetheringEventCallback} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void unregisterTetheringEventCallback(
             @NonNull final OnTetheringEventCallback callback) {
-        getTetheringManager().unregisterTetheringEventCallback(callback);
+        Objects.requireNonNull(callback, "The callback must be non-null");
+        synchronized (mTetheringEventCallbacks) {
+            final TetheringEventCallback tetherCallback =
+                    mTetheringEventCallbacks.remove(callback);
+            getTetheringManager().unregisterTetheringEventCallback(tetherCallback);
+        }
     }
 
 
@@ -2644,10 +2717,12 @@
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable usb interfaces.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetherableUsbRegexs() {
         return getTetheringManager().getTetherableUsbRegexs();
     }
@@ -2660,10 +2735,12 @@
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable wifi interfaces.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetherableWifiRegexs() {
         return getTetheringManager().getTetherableWifiRegexs();
     }
@@ -2676,10 +2753,13 @@
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable bluetooth interfaces.
      *
+     * @deprecated Use {@link TetheringEventCallback#onTetherableInterfaceRegexpsChanged(
+     *TetheringManager.TetheringInterfaceRegexps)} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public String[] getTetherableBluetoothRegexs() {
         return getTetheringManager().getTetherableBluetoothRegexs();
     }
@@ -2698,45 +2778,114 @@
      *
      * @param enable a boolean - {@code true} to enable tethering
      * @return error a {@code TETHER_ERROR} value indicating success or failure type
+     * @deprecated Use {@link TetheringManager#startTethering} instead
      *
      * {@hide}
      */
     @UnsupportedAppUsage
+    @Deprecated
     public int setUsbTethering(boolean enable) {
         return getTetheringManager().setUsbTethering(enable);
     }
 
-    /** {@hide} */
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_NO_ERROR}.
+     * {@hide}
+     */
     @SystemApi
-    public static final int TETHER_ERROR_NO_ERROR           = 0;
-    /** {@hide} */
-    public static final int TETHER_ERROR_UNKNOWN_IFACE      = 1;
-    /** {@hide} */
-    public static final int TETHER_ERROR_SERVICE_UNAVAIL    = 2;
-    /** {@hide} */
-    public static final int TETHER_ERROR_UNSUPPORTED        = 3;
-    /** {@hide} */
-    public static final int TETHER_ERROR_UNAVAIL_IFACE      = 4;
-    /** {@hide} */
-    public static final int TETHER_ERROR_MASTER_ERROR       = 5;
-    /** {@hide} */
-    public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
-    /** {@hide} */
-    public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
-    /** {@hide} */
-    public static final int TETHER_ERROR_ENABLE_NAT_ERROR     = 8;
-    /** {@hide} */
-    public static final int TETHER_ERROR_DISABLE_NAT_ERROR    = 9;
-    /** {@hide} */
-    public static final int TETHER_ERROR_IFACE_CFG_ERROR      = 10;
-    /** {@hide} */
+    @Deprecated
+    public static final int TETHER_ERROR_NO_ERROR = TetheringManager.TETHER_ERROR_NO_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNKNOWN_IFACE}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_UNKNOWN_IFACE =
+            TetheringManager.TETHER_ERROR_UNKNOWN_IFACE;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_SERVICE_UNAVAIL}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_SERVICE_UNAVAIL =
+            TetheringManager.TETHER_ERROR_SERVICE_UNAVAIL;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNSUPPORTED}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_UNSUPPORTED = TetheringManager.TETHER_ERROR_UNSUPPORTED;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNAVAIL_IFACE}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_UNAVAIL_IFACE =
+            TetheringManager.TETHER_ERROR_UNAVAIL_IFACE;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_MASTER_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_MASTER_ERROR = TetheringManager.TETHER_ERROR_MASTER_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_TETHER_IFACE_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_TETHER_IFACE_ERROR =
+            TetheringManager.TETHER_ERROR_TETHER_IFACE_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_UNTETHER_IFACE_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR =
+            TetheringManager.TETHER_ERROR_UNTETHER_IFACE_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENABLE_NAT_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_ENABLE_NAT_ERROR =
+            TetheringManager.TETHER_ERROR_ENABLE_NAT_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_DISABLE_NAT_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_DISABLE_NAT_ERROR =
+            TetheringManager.TETHER_ERROR_DISABLE_NAT_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_IFACE_CFG_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_IFACE_CFG_ERROR =
+            TetheringManager.TETHER_ERROR_IFACE_CFG_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_PROVISION_FAILED}.
+     * {@hide}
+     */
     @SystemApi
-    public static final int TETHER_ERROR_PROVISION_FAILED     = 11;
-    /** {@hide} */
-    public static final int TETHER_ERROR_DHCPSERVER_ERROR     = 12;
-    /** {@hide} */
+    @Deprecated
+    public static final int TETHER_ERROR_PROVISION_FAILED =
+            TetheringManager.TETHER_ERROR_PROVISION_FAILED;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_DHCPSERVER_ERROR}.
+     * {@hide}
+     */
+    @Deprecated
+    public static final int TETHER_ERROR_DHCPSERVER_ERROR =
+            TetheringManager.TETHER_ERROR_DHCPSERVER_ERROR;
+    /**
+     * @deprecated Use {@link TetheringManager#TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
+     * {@hide}
+     */
     @SystemApi
-    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN  = 13;
+    @Deprecated
+    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN =
+            TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
 
     /**
      * Get a more detailed error code after a Tethering or Untethering
@@ -2746,10 +2895,12 @@
      * @return error The error code of the last error tethering or untethering the named
      *               interface
      *
+     * @deprecated Use {@link TetheringEventCallback#onError(String, int)} instead.
      * {@hide}
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     @UnsupportedAppUsage
+    @Deprecated
     public int getLastTetherError(String iface) {
         return getTetheringManager().getLastTetherError(iface);
     }
@@ -2767,9 +2918,12 @@
     /**
      * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
      * entitlement succeeded.
+     *
+     * @deprecated Use {@link TetheringManager#OnTetheringEntitlementResultListener} instead.
      * @hide
      */
     @SystemApi
+    @Deprecated
     public interface OnTetheringEntitlementResultListener  {
         /**
          * Called to notify entitlement result.
@@ -2799,9 +2953,11 @@
      * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
      *         notify the caller of the result of entitlement check. The listener may be called zero
      *         or one time.
+     * @deprecated Use {@link TetheringManager#requestLatestTetheringEntitlementResult} instead.
      * {@hide}
      */
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void getLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
             @NonNull @CallbackExecutor Executor executor,
diff --git a/core/java/android/net/EthernetManager.java b/core/java/android/net/EthernetManager.java
index fd015b4..a3899b7 100644
--- a/core/java/android/net/EthernetManager.java
+++ b/core/java/android/net/EthernetManager.java
@@ -16,7 +16,10 @@
 
 package android.net;
 
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
@@ -24,12 +27,15 @@
 import android.os.RemoteException;
 
 import java.util.ArrayList;
+import java.util.Objects;
 
 /**
  * A class representing the IP configuration of the Ethernet network.
  *
  * @hide
  */
+@SystemApi
+@TestApi
 @SystemService(Context.ETHERNET_SERVICE)
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
@@ -37,7 +43,7 @@
 
     private final Context mContext;
     private final IEthernetManager mService;
-    private final Handler mHandler = new Handler() {
+    private final Handler mHandler = new Handler(ConnectivityThread.getInstanceLooper()) {
         @Override
         public void handleMessage(Message msg) {
             if (msg.what == MSG_AVAILABILITY_CHANGED) {
@@ -60,12 +66,14 @@
 
     /**
      * A listener interface to receive notification on changes in Ethernet.
+     * @hide
      */
     public interface Listener {
         /**
          * Called when Ethernet port's availability is changed.
          * @param iface Ethernet interface name
          * @param isAvailable {@code true} if Ethernet port exists.
+         * @hide
          */
         @UnsupportedAppUsage
         void onAvailabilityChanged(String iface, boolean isAvailable);
@@ -76,6 +84,7 @@
      * Applications will almost always want to use
      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
      * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
+     * @hide
      */
     public EthernetManager(Context context, IEthernetManager service) {
         mContext = context;
@@ -85,6 +94,7 @@
     /**
      * Get Ethernet configuration.
      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
+     * @hide
      */
     @UnsupportedAppUsage
     public IpConfiguration getConfiguration(String iface) {
@@ -97,6 +107,7 @@
 
     /**
      * Set Ethernet configuration.
+     * @hide
      */
     @UnsupportedAppUsage
     public void setConfiguration(String iface, IpConfiguration config) {
@@ -109,6 +120,7 @@
 
     /**
      * Indicates whether the system currently has one or more Ethernet interfaces.
+     * @hide
      */
     @UnsupportedAppUsage
     public boolean isAvailable() {
@@ -119,6 +131,7 @@
      * Indicates whether the system has given interface.
      *
      * @param iface Ethernet interface name
+     * @hide
      */
     @UnsupportedAppUsage
     public boolean isAvailable(String iface) {
@@ -133,6 +146,7 @@
      * Adds a listener.
      * @param listener A {@link Listener} to add.
      * @throws IllegalArgumentException If the listener is null.
+     * @hide
      */
     @UnsupportedAppUsage
     public void addListener(Listener listener) {
@@ -151,6 +165,7 @@
 
     /**
      * Returns an array of available Ethernet interface names.
+     * @hide
      */
     @UnsupportedAppUsage
     public String[] getAvailableInterfaces() {
@@ -165,6 +180,7 @@
      * Removes a listener.
      * @param listener A {@link Listener} to remove.
      * @throws IllegalArgumentException If the listener is null.
+     * @hide
      */
     @UnsupportedAppUsage
     public void removeListener(Listener listener) {
@@ -180,4 +196,78 @@
             }
         }
     }
+
+    /**
+     * A request for a tethered interface.
+     */
+    public static class TetheredInterfaceRequest {
+        private final IEthernetManager mService;
+        private final ITetheredInterfaceCallback mCb;
+
+        private TetheredInterfaceRequest(@NonNull IEthernetManager service,
+                @NonNull ITetheredInterfaceCallback cb) {
+            this.mService = service;
+            this.mCb = cb;
+        }
+
+        /**
+         * Release the request, causing the interface to revert back from tethering mode if there
+         * is no other requestor.
+         */
+        public void release() {
+            try {
+                mService.releaseTetheredInterface(mCb);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
+     */
+    public interface TetheredInterfaceCallback {
+        /**
+         * Called when the tethered interface is available.
+         * @param iface The name of the interface.
+         */
+        void onAvailable(@NonNull String iface);
+
+        /**
+         * Called when the tethered interface is now unavailable.
+         */
+        void onUnavailable();
+    }
+
+    /**
+     * Request a tethered interface in tethering mode.
+     *
+     * <p>When this method is called and there is at least one ethernet interface available, the
+     * system will designate one to act as a tethered interface. If there is already a tethered
+     * interface, the existing interface will be used.
+     * @param callback A callback to be called once the request has been fulfilled.
+     */
+    @NonNull
+    public TetheredInterfaceRequest requestTetheredInterface(
+            @NonNull TetheredInterfaceCallback callback) {
+        Objects.requireNonNull(callback, "Callback must be non-null");
+        final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
+            @Override
+            public void onAvailable(String iface) {
+                callback.onAvailable(iface);
+            }
+
+            @Override
+            public void onUnavailable() {
+                callback.onUnavailable();
+            }
+        };
+
+        try {
+            mService.requestTetheredInterface(cbInternal);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        return new TetheredInterfaceRequest(mService, cbInternal);
+    }
 }
diff --git a/core/java/android/net/IConnectivityDiagnosticsCallback.aidl b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
new file mode 100644
index 0000000..3a161bf
--- /dev/null
+++ b/core/java/android/net/IConnectivityDiagnosticsCallback.aidl
@@ -0,0 +1,28 @@
+/**
+ *
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.ConnectivityDiagnosticsManager;
+import android.net.Network;
+
+/** @hide */
+oneway interface IConnectivityDiagnosticsCallback {
+    void onConnectivityReport(in ConnectivityDiagnosticsManager.ConnectivityReport report);
+    void onDataStallSuspected(in ConnectivityDiagnosticsManager.DataStallReport report);
+    void onNetworkConnectivityReported(in Network n, boolean hasConnectivity);
+}
\ No newline at end of file
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 186196bd..3e9e7fa 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -18,6 +18,7 @@
 
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
+import android.net.IConnectivityDiagnosticsCallback;
 import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkAgentConfig;
@@ -211,5 +212,9 @@
     boolean isCallerCurrentAlwaysOnVpnApp();
     boolean isCallerCurrentAlwaysOnVpnLockdownApp();
 
+    void registerConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback,
+            in NetworkRequest request);
+    void unregisterConnectivityDiagnosticsCallback(in IConnectivityDiagnosticsCallback callback);
+
     IBinder startOrGetTestNetworkService();
 }
diff --git a/core/java/android/net/IEthernetManager.aidl b/core/java/android/net/IEthernetManager.aidl
index 94960b5..ccc6e35 100644
--- a/core/java/android/net/IEthernetManager.aidl
+++ b/core/java/android/net/IEthernetManager.aidl
@@ -18,6 +18,7 @@
 
 import android.net.IpConfiguration;
 import android.net.IEthernetServiceListener;
+import android.net.ITetheredInterfaceCallback;
 
 /**
  * Interface that answers queries about, and allows changing
@@ -32,4 +33,6 @@
     boolean isAvailable(String iface);
     void addListener(in IEthernetServiceListener listener);
     void removeListener(in IEthernetServiceListener listener);
+    void requestTetheredInterface(in ITetheredInterfaceCallback callback);
+    void releaseTetheredInterface(in ITetheredInterfaceCallback callback);
 }
diff --git a/core/java/android/net/ITetheredInterfaceCallback.aidl b/core/java/android/net/ITetheredInterfaceCallback.aidl
new file mode 100644
index 0000000..e3d0759
--- /dev/null
+++ b/core/java/android/net/ITetheredInterfaceCallback.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/** @hide */
+interface ITetheredInterfaceCallback {
+    void onAvailable(in String iface);
+    void onUnavailable();
+}
\ No newline at end of file
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index bf8b38f..a9d7f17 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -19,6 +19,7 @@
 import static android.system.OsConstants.IFA_F_DADFAILED;
 import static android.system.OsConstants.IFA_F_DEPRECATED;
 import static android.system.OsConstants.IFA_F_OPTIMISTIC;
+import static android.system.OsConstants.IFA_F_PERMANENT;
 import static android.system.OsConstants.IFA_F_TENTATIVE;
 import static android.system.OsConstants.RT_SCOPE_HOST;
 import static android.system.OsConstants.RT_SCOPE_LINK;
@@ -34,6 +35,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 import android.util.Pair;
 
 import java.net.Inet4Address;
@@ -41,6 +43,7 @@
 import java.net.InetAddress;
 import java.net.InterfaceAddress;
 import java.net.UnknownHostException;
+import java.util.Objects;
 
 /**
  * Identifies an IP address on a network link.
@@ -58,6 +61,21 @@
  * </ul>
  */
 public class LinkAddress implements Parcelable {
+
+    /**
+     * Indicates the deprecation or expiration time is unknown
+     * @hide
+     */
+    @SystemApi
+    public static final long LIFETIME_UNKNOWN = -1;
+
+    /**
+     * Indicates this address is permanent.
+     * @hide
+     */
+    @SystemApi
+    public static final long LIFETIME_PERMANENT = Long.MAX_VALUE;
+
     /**
      * IPv4 or IPv6 address.
      */
@@ -71,7 +89,9 @@
     private int prefixLength;
 
     /**
-     * Address flags. A bitmask of IFA_F_* values.
+     * Address flags. A bitmask of {@code IFA_F_*} values. Note that {@link #getFlags()} may not
+     * return these exact values. For example, it may set or clear the {@code IFA_F_DEPRECATED}
+     * flag depending on the current preferred lifetime.
      */
     private int flags;
 
@@ -81,6 +101,23 @@
     private int scope;
 
     /**
+     * The time, as reported by {@link SystemClock#elapsedRealtime}, when this LinkAddress will be
+     * or was deprecated. At the time existing connections can still use this address until it
+     * expires, but new connections should use the new address. {@link #LIFETIME_UNKNOWN} indicates
+     * this information is not available. {@link #LIFETIME_PERMANENT} indicates this
+     * {@link LinkAddress} will never be deprecated.
+     */
+    private long deprecationTime;
+
+    /**
+     * The time, as reported by {@link SystemClock#elapsedRealtime}, when this {@link LinkAddress}
+     * will expire and be removed from the interface. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never expire.
+     */
+    private long expirationTime;
+
+    /**
      * Utility function to determines the scope of a unicast address. Per RFC 4291 section 2.5 and
      * RFC 6724 section 3.2.
      * @hide
@@ -152,7 +189,8 @@
     /**
      * Utility function for the constructors.
      */
-    private void init(InetAddress address, int prefixLength, int flags, int scope) {
+    private void init(InetAddress address, int prefixLength, int flags, int scope,
+                      long deprecationTime, long expirationTime) {
         if (address == null ||
                 address.isMulticastAddress() ||
                 prefixLength < 0 ||
@@ -161,15 +199,42 @@
             throw new IllegalArgumentException("Bad LinkAddress params " + address +
                     "/" + prefixLength);
         }
+
+        // deprecation time and expiration time must be both provided, or neither.
+        if ((deprecationTime == LIFETIME_UNKNOWN) != (expirationTime == LIFETIME_UNKNOWN)) {
+            throw new IllegalArgumentException(
+                    "Must not specify only one of deprecation time and expiration time");
+        }
+
+        // deprecation time needs to be a positive value.
+        if (deprecationTime != LIFETIME_UNKNOWN && deprecationTime < 0) {
+            throw new IllegalArgumentException("invalid deprecation time " + deprecationTime);
+        }
+
+        // expiration time needs to be a positive value.
+        if (expirationTime != LIFETIME_UNKNOWN && expirationTime < 0) {
+            throw new IllegalArgumentException("invalid expiration time " + expirationTime);
+        }
+
+        // expiration time can't be earlier than deprecation time
+        if (deprecationTime != LIFETIME_UNKNOWN && expirationTime != LIFETIME_UNKNOWN
+                && expirationTime < deprecationTime) {
+            throw new IllegalArgumentException("expiration earlier than deprecation ("
+                    + deprecationTime + ", " + expirationTime + ")");
+        }
+
         this.address = address;
         this.prefixLength = prefixLength;
         this.flags = flags;
         this.scope = scope;
+        this.deprecationTime = deprecationTime;
+        this.expirationTime = expirationTime;
     }
 
     /**
      * Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with
      * the specified flags and scope. Flags and scope are not checked for validity.
+     *
      * @param address The IP address.
      * @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
      * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
@@ -181,7 +246,39 @@
     @TestApi
     public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
             int flags, int scope) {
-        init(address, prefixLength, flags, scope);
+        init(address, prefixLength, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
+    }
+
+    /**
+     * Constructs a new {@code LinkAddress} from an {@code InetAddress}, prefix length, with
+     * the specified flags, scope, deprecation time, and expiration time. Flags and scope are not
+     * checked for validity. The value of the {@code IFA_F_DEPRECATED} and {@code IFA_F_PERMANENT}
+     * flag will be adjusted based on the passed-in lifetimes.
+     *
+     * @param address The IP address.
+     * @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
+     * @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
+     * @param scope An integer defining the scope in which the address is unique (e.g.,
+     *              {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}).
+     * @param deprecationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when
+     *                        this {@link LinkAddress} will be or was deprecated. At the time
+     *                        existing connections can still use this address until it expires, but
+     *                        new connections should use the new address. {@link #LIFETIME_UNKNOWN}
+     *                        indicates this information is not available.
+     *                        {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will
+     *                        never be deprecated.
+     * @param expirationTime The time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     *                       {@link LinkAddress} will expire and be removed from the interface.
+     *                       {@link #LIFETIME_UNKNOWN} indicates this information is not available.
+     *                       {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress} will
+     *                       never expire.
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
+                       int flags, int scope, long deprecationTime, long expirationTime) {
+        init(address, prefixLength, flags, scope, deprecationTime, expirationTime);
     }
 
     /**
@@ -237,7 +334,7 @@
         // This may throw an IllegalArgumentException; catching it is the caller's responsibility.
         // TODO: consider rejecting mapped IPv4 addresses such as "::ffff:192.0.2.5/24".
         Pair<InetAddress, Integer> ipAndMask = NetworkUtils.parseIpAndMask(address);
-        init(ipAndMask.first, ipAndMask.second, flags, scope);
+        init(ipAndMask.first, ipAndMask.second, flags, scope, LIFETIME_UNKNOWN, LIFETIME_UNKNOWN);
     }
 
     /**
@@ -265,10 +362,12 @@
             return false;
         }
         LinkAddress linkAddress = (LinkAddress) obj;
-        return this.address.equals(linkAddress.address) &&
-            this.prefixLength == linkAddress.prefixLength &&
-            this.flags == linkAddress.flags &&
-            this.scope == linkAddress.scope;
+        return this.address.equals(linkAddress.address)
+                && this.prefixLength == linkAddress.prefixLength
+                && this.flags == linkAddress.flags
+                && this.scope == linkAddress.scope
+                && this.deprecationTime == linkAddress.deprecationTime
+                && this.expirationTime == linkAddress.expirationTime;
     }
 
     /**
@@ -276,7 +375,7 @@
      */
     @Override
     public int hashCode() {
-        return address.hashCode() + 11 * prefixLength + 19 * flags + 43 * scope;
+        return Objects.hash(address, prefixLength, flags, scope, deprecationTime, expirationTime);
     }
 
     /**
@@ -329,6 +428,25 @@
      * Returns the flags of this {@code LinkAddress}.
      */
     public int getFlags() {
+        int flags = this.flags;
+        if (deprecationTime != LIFETIME_UNKNOWN) {
+            if (SystemClock.elapsedRealtime() >= deprecationTime) {
+                flags |= IFA_F_DEPRECATED;
+            } else {
+                // If deprecation time is in the future, or permanent.
+                flags &= ~IFA_F_DEPRECATED;
+            }
+        }
+
+        if (expirationTime == LIFETIME_PERMANENT) {
+            flags |= IFA_F_PERMANENT;
+        } else if (expirationTime != LIFETIME_UNKNOWN) {
+            // If we know this address expired or will expire in the future, then this address
+            // should not be permanent.
+            flags &= ~IFA_F_PERMANENT;
+        }
+
+        // Do no touch the original flags. Return the adjusted flags here.
         return flags;
     }
 
@@ -340,7 +458,42 @@
     }
 
     /**
-     * Returns true if this {@code LinkAddress} is global scope and preferred.
+     * Get the deprecation time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     * {@link LinkAddress} will be or was deprecated. At the time existing connections can still use
+     * this address until it expires, but new connections should use the new address.
+     *
+     * @return The deprecation time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never be deprecated.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public long getDeprecationTime() {
+        return deprecationTime;
+    }
+
+    /**
+     * Get the expiration time, as reported by {@link SystemClock#elapsedRealtime}, when this
+     * {@link LinkAddress} will expire and be removed from the interface.
+     *
+     * @return The expiration time in milliseconds. {@link #LIFETIME_UNKNOWN} indicates this
+     * information is not available. {@link #LIFETIME_PERMANENT} indicates this {@link LinkAddress}
+     * will never expire.
+     *
+     * @hide
+     */
+    @SystemApi
+    @TestApi
+    public long getExpirationTime() {
+        return expirationTime;
+    }
+
+    /**
+     * Returns true if this {@code LinkAddress} is global scope and preferred (i.e., not currently
+     * deprecated).
+     *
      * @hide
      */
     @TestApi
@@ -352,6 +505,7 @@
          * state has cleared either DAD has succeeded or failed, and both
          * flags are cleared regardless).
          */
+        int flags = getFlags();
         return (scope == RT_SCOPE_UNIVERSE
                 && !isIpv6ULA()
                 && (flags & (IFA_F_DADFAILED | IFA_F_DEPRECATED)) == 0L
@@ -373,6 +527,8 @@
         dest.writeInt(prefixLength);
         dest.writeInt(this.flags);
         dest.writeInt(scope);
+        dest.writeLong(deprecationTime);
+        dest.writeLong(expirationTime);
     }
 
     /**
@@ -392,7 +548,10 @@
                 int prefixLength = in.readInt();
                 int flags = in.readInt();
                 int scope = in.readInt();
-                return new LinkAddress(address, prefixLength, flags, scope);
+                long deprecationTime = in.readLong();
+                long expirationTime = in.readLong();
+                return new LinkAddress(address, prefixLength, flags, scope, deprecationTime,
+                        expirationTime);
             }
 
             public LinkAddress[] newArray(int size) {
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 6207661..f94bdb7 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -26,6 +26,7 @@
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
@@ -58,7 +59,6 @@
  */
 public final class NetworkCapabilities implements Parcelable {
     private static final String TAG = "NetworkCapabilities";
-    private static final int INVALID_UID = -1;
 
     // Set to true when private DNS is broken.
     private boolean mPrivateDnsBroken;
@@ -85,8 +85,8 @@
         mTransportInfo = null;
         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
         mUids = null;
-        mEstablishingVpnAppUid = INVALID_UID;
         mAdministratorUids.clear();
+        mOwnerUid = Process.INVALID_UID;
         mSSID = null;
         mPrivateDnsBroken = false;
     }
@@ -104,8 +104,8 @@
         mTransportInfo = nc.mTransportInfo;
         mSignalStrength = nc.mSignalStrength;
         setUids(nc.mUids); // Will make the defensive copy
-        mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
         setAdministratorUids(nc.mAdministratorUids);
+        mOwnerUid = nc.mOwnerUid;
         mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         mSSID = nc.mSSID;
         mPrivateDnsBroken = nc.mPrivateDnsBroken;
@@ -810,31 +810,26 @@
     }
 
     /**
-     * UID of the app that manages this network, or INVALID_UID if none/unknown.
+     * UID of the app that owns this network, or INVALID_UID if none/unknown.
      *
-     * This field keeps track of the UID of the app that created this network and is in charge
-     * of managing it. In the practice, it is used to store the UID of VPN apps so it is named
-     * accordingly, but it may be renamed if other mechanisms are offered for third party apps
-     * to create networks.
-     *
-     * Because this field is only used in the services side (and to avoid apps being able to
-     * set this to whatever they want), this field is not parcelled and will not be conserved
-     * across the IPC boundary.
-     * @hide
+     * <p>This field keeps track of the UID of the app that created this network and is in charge of
+     * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
+     * VPN, or Carrier Service app managing a cellular data connection.
      */
-    private int mEstablishingVpnAppUid = INVALID_UID;
+    private int mOwnerUid = Process.INVALID_UID;
 
     /**
-     * Set the UID of the managing app.
-     * @hide
+     * Set the UID of the owner app.
      */
-    public void setEstablishingVpnAppUid(final int uid) {
-        mEstablishingVpnAppUid = uid;
+    public void setOwnerUid(final int uid) {
+        mOwnerUid = uid;
     }
 
-    /** @hide */
-    public int getEstablishingVpnAppUid() {
-        return mEstablishingVpnAppUid;
+    /**
+     * Retrieves the UID of the owner app.
+     */
+    public int getOwnerUid() {
+        return mOwnerUid;
     }
 
     /**
@@ -1157,7 +1152,7 @@
      * member is null, then the network is not restricted by app UID. If it's an empty list, then
      * it means nobody can use it.
      * As a special exception, the app managing this network (as identified by its UID stored in
-     * mEstablishingVpnAppUid) can always see this network. This is embodied by a special check in
+     * mOwnerUid) can always see this network. This is embodied by a special check in
      * satisfiedByUids. That still does not mean the network necessarily <strong>applies</strong>
      * to the app that manages it as determined by #appliesToUid.
      * <p>
@@ -1264,7 +1259,7 @@
      * in the passed nc (representing the UIDs that this network is available to).
      * <p>
      * As a special exception, the UID that created the passed network (as represented by its
-     * mEstablishingVpnAppUid field) always satisfies a NetworkRequest requiring it (of LISTEN
+     * mOwnerUid field) always satisfies a NetworkRequest requiring it (of LISTEN
      * or REQUEST types alike), even if the network does not apply to it. That is so a VPN app
      * can see its own network when it listens for it.
      * <p>
@@ -1275,7 +1270,7 @@
     public boolean satisfiedByUids(@NonNull NetworkCapabilities nc) {
         if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
         for (UidRange requiredRange : mUids) {
-            if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
+            if (requiredRange.contains(nc.mOwnerUid)) return true;
             if (!nc.appliesToUidRange(requiredRange)) {
                 return false;
             }
@@ -1541,6 +1536,7 @@
         dest.writeString(mSSID);
         dest.writeBoolean(mPrivateDnsBroken);
         dest.writeList(mAdministratorUids);
+        dest.writeInt(mOwnerUid);
     }
 
     public static final @android.annotation.NonNull Creator<NetworkCapabilities> CREATOR =
@@ -1562,6 +1558,7 @@
                 netCap.mSSID = in.readString();
                 netCap.mPrivateDnsBroken = in.readBoolean();
                 netCap.setAdministratorUids(in.readArrayList(null));
+                netCap.mOwnerUid = in.readInt();
                 return netCap;
             }
             @Override
@@ -1611,8 +1608,8 @@
                 sb.append(" Uids: <").append(mUids).append(">");
             }
         }
-        if (mEstablishingVpnAppUid != INVALID_UID) {
-            sb.append(" EstablishingAppUid: ").append(mEstablishingVpnAppUid);
+        if (mOwnerUid != Process.INVALID_UID) {
+            sb.append(" OwnerUid: ").append(mOwnerUid);
         }
 
         if (!mAdministratorUids.isEmpty()) {
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index febc36c..68c2764 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1409,6 +1409,7 @@
      * @throws UnsupportedOperationException if userspace reboot was requested on a device that
      *                                       doesn't support it.
      */
+    @RequiresPermission(permission.REBOOT)
     public void reboot(@Nullable String reason) {
         if (REBOOT_USERSPACE.equals(reason) && !isRebootingUserspaceSupported()) {
             throw new UnsupportedOperationException(
@@ -1428,6 +1429,7 @@
      * </p>
      * @hide
      */
+    @RequiresPermission(permission.REBOOT)
     public void rebootSafeMode() {
         try {
             mService.rebootSafeMode(false, true);
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index 92fecad..bbc936d 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -193,4 +193,5 @@
     void startCheckpoint(int numTries) = 85;
     boolean needsCheckpoint() = 86;
     void abortChanges(in String message, boolean retry) = 87;
+    void clearUserKeyAuth(int userId, int serialNumber, in byte[] token, in byte[] secret) = 88;
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dd08070..b22db2e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -81,7 +81,6 @@
 import android.os.UserHandle;
 import android.provider.SettingsValidators.Validator;
 import android.speech.tts.TextToSpeech;
-import android.telephony.SubscriptionManager;
 import android.text.TextUtils;
 import android.util.AndroidException;
 import android.util.ArrayMap;
@@ -13321,16 +13320,17 @@
 
         /**
          * Whether the Volte is enabled. If this setting is not set then we use the Carrier Config
-         * value {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
+         * value
+         * {@link android.telephony.CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
          * <p>
          * Type: int (0 for false, 1 for true)
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#ENHANCED_4G_MODE_ENABLED}
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#ENHANCED_4G_MODE_ENABLED}
          * instead.
          */
         @Deprecated
         public static final String ENHANCED_4G_MODE_ENABLED =
-                SubscriptionManager.ENHANCED_4G_MODE_ENABLED;
+                Telephony.SimInfo.ENHANCED_4G_MODE_ENABLED;
 
         /**
          * Whether VT (Video Telephony over IMS) is enabled
@@ -13338,10 +13338,10 @@
          * Type: int (0 for false, 1 for true)
          *
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#VT_IMS_ENABLED} instead.
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#VT_IMS_ENABLED} instead.
          */
         @Deprecated
-        public static final String VT_IMS_ENABLED = SubscriptionManager.VT_IMS_ENABLED;
+        public static final String VT_IMS_ENABLED = Telephony.SimInfo.VT_IMS_ENABLED;
 
         /**
          * Whether WFC is enabled
@@ -13349,10 +13349,10 @@
          * Type: int (0 for false, 1 for true)
          *
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ENABLED} instead.
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#WFC_IMS_ENABLED} instead.
          */
         @Deprecated
-        public static final String WFC_IMS_ENABLED = SubscriptionManager.WFC_IMS_ENABLED;
+        public static final String WFC_IMS_ENABLED = Telephony.SimInfo.WFC_IMS_ENABLED;
 
         /**
          * WFC mode on home/non-roaming network.
@@ -13360,10 +13360,10 @@
          * Type: int - 2=Wi-Fi preferred, 1=Cellular preferred, 0=Wi-Fi only
          *
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_MODE} instead.
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#WFC_IMS_MODE} instead.
          */
         @Deprecated
-        public static final String WFC_IMS_MODE = SubscriptionManager.WFC_IMS_MODE;
+        public static final String WFC_IMS_MODE = Telephony.SimInfo.WFC_IMS_MODE;
 
         /**
          * WFC mode on roaming network.
@@ -13371,11 +13371,11 @@
          * Type: int - see {@link #WFC_IMS_MODE} for values
          *
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ROAMING_MODE}
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#WFC_IMS_ROAMING_MODE}
          * instead.
          */
         @Deprecated
-        public static final String WFC_IMS_ROAMING_MODE = SubscriptionManager.WFC_IMS_ROAMING_MODE;
+        public static final String WFC_IMS_ROAMING_MODE = Telephony.SimInfo.WFC_IMS_ROAMING_MODE;
 
         /**
          * Whether WFC roaming is enabled
@@ -13383,12 +13383,12 @@
          * Type: int (0 for false, 1 for true)
          *
          * @hide
-         * @deprecated Use {@link android.telephony.SubscriptionManager#WFC_IMS_ROAMING_ENABLED}
+         * @deprecated Use {@link android.provider.Telephony.SimInfo#WFC_IMS_ROAMING_ENABLED}
          * instead
          */
         @Deprecated
         public static final String WFC_IMS_ROAMING_ENABLED =
-                SubscriptionManager.WFC_IMS_ROAMING_ENABLED;
+                Telephony.SimInfo.WFC_IMS_ROAMING_ENABLED;
 
         /**
          * Whether user can enable/disable LTE as a preferred network. A carrier might control
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 90ac821..1611d28 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -37,11 +37,13 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.telephony.CarrierConfigManager;
 import android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.SmsMessage;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.telephony.UiccAccessRule;
 import android.text.TextUtils;
 import android.util.Patterns;
 
@@ -4928,5 +4930,414 @@
          */
         @NonNull
         public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
+
+        /**
+         * TelephonyProvider unique key column name is the subscription id.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id";
+
+        /**
+         * TelephonyProvider column name for a unique identifier for the subscription within the
+         * specific subscription type. For example, it contains SIM ICC Identifier subscriptions
+         * on Local SIMs. and Mac-address for Remote-SIM Subscriptions for Bluetooth devices.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String ICC_ID = "icc_id";
+
+        /**
+         * TelephonyProvider column name for user SIM_SlOT_INDEX
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String SIM_SLOT_INDEX = "sim_id";
+
+        /**
+         * SIM is not inserted
+         */
+        public static final int SIM_NOT_INSERTED = -1;
+
+        /**
+         * TelephonyProvider column name Subscription-type.
+         * <P>Type: INTEGER (int)</P> {@link #SUBSCRIPTION_TYPE_LOCAL_SIM} for Local-SIM
+         * Subscriptions, {@link #SUBSCRIPTION_TYPE_REMOTE_SIM} for Remote-SIM Subscriptions.
+         * Default value is 0.
+         */
+        public static final String SUBSCRIPTION_TYPE = "subscription_type";
+
+        /**
+         * This constant is to designate a subscription as a Local-SIM Subscription.
+         * <p> A Local-SIM can be a physical SIM inserted into a sim-slot in the device, or eSIM on
+         * the device.
+         * </p>
+         */
+        public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0;
+
+        /**
+         * This constant is to designate a subscription as a Remote-SIM Subscription.
+         * <p>
+         * A Remote-SIM subscription is for a SIM on a phone connected to this device via some
+         * connectivity mechanism, for example bluetooth. Similar to Local SIM, this subscription
+         * can be used for SMS, Voice and data by proxying data through the connected device.
+         * Certain data of the SIM, such as IMEI, are not accessible for Remote SIMs.
+         * </p>
+         *
+         * <p>
+         * A Remote-SIM is available only as long the phone stays connected to this device.
+         * When the phone disconnects, Remote-SIM subscription is removed from this device and is
+         * no longer known. All data associated with the subscription, such as stored SMS, call
+         * logs, contacts etc, are removed from this device.
+         * </p>
+         *
+         * <p>
+         * If the phone re-connects to this device, a new Remote-SIM subscription is created for
+         * the phone. The Subscription Id associated with the new subscription is different from
+         * the Subscription Id of the previous Remote-SIM subscription created (and removed) for the
+         * phone; i.e., new Remote-SIM subscription treats the reconnected phone as a Remote-SIM
+         * that was never seen before.
+         * </p>
+         */
+        public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1;
+
+        /**
+         * TelephonyProvider column name data_enabled_override_rules.
+         * It's a list of rules for overriding data enabled settings. The syntax is
+         * For example, "mms=nonDefault" indicates enabling data for mms in non-default
+         * subscription.
+         * "default=nonDefault&inVoiceCall" indicates enabling data for internet in non-default
+         * subscription and while is in voice call.
+         *
+         * Default value is empty string.
+         */
+        public static final String DATA_ENABLED_OVERRIDE_RULES = "data_enabled_override_rules";
+
+        /**
+         * TelephonyProvider column name for user displayed name.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String DISPLAY_NAME = "display_name";
+
+        /**
+         * TelephonyProvider column name for the service provider name for the SIM.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String CARRIER_NAME = "carrier_name";
+
+        /**
+         * TelephonyProvider column name for source of the user displayed name.
+         * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below
+         */
+        public static final String NAME_SOURCE = "name_source";
+
+        /** The name_source is the default, which is from the carrier id. */
+        public static final int NAME_SOURCE_DEFAULT = 0;
+
+        /**
+         * The name_source is from SIM EF_SPN.
+         */
+        public static final int NAME_SOURCE_SIM_SPN = 1;
+
+        /**
+         * The name_source is from user input
+         */
+        public static final int NAME_SOURCE_USER_INPUT = 2;
+
+        /**
+         * The name_source is carrier (carrier app, carrier config, etc.)
+         */
+        public static final int NAME_SOURCE_CARRIER = 3;
+
+        /**
+         * The name_source is from SIM EF_PNN.
+         */
+        public static final int NAME_SOURCE_SIM_PNN = 4;
+
+        /**
+         * TelephonyProvider column name for the color of a SIM.
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String COLOR = "color";
+
+        /** TelephonyProvider column name for the default color of a SIM {@hide} */
+        public static final int COLOR_DEFAULT = 0;
+
+        /**
+         * TelephonyProvider column name for the phone number of a SIM.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String NUMBER = "number";
+
+        /**
+         * TelephonyProvider column name for the number display format of a SIM.
+         * <P>Type: INTEGER (int)</P>
+         * @hide
+         */
+        public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
+
+        /**
+         * TelephonyProvider column name for the default display format of a SIM
+         * @hide
+         */
+        public static final int DISPLAY_NUMBER_DEFAULT = 1;
+
+        /**
+         * TelephonyProvider column name for whether data roaming is enabled.
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String DATA_ROAMING = "data_roaming";
+
+        /** Indicates that data roaming is enabled for a subscription */
+        public static final int DATA_ROAMING_ENABLE = 1;
+
+        /** Indicates that data roaming is disabled for a subscription */
+        public static final int DATA_ROAMING_DISABLE = 0;
+
+        /** TelephonyProvider column name for default data roaming setting: disable */
+        public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
+
+        /**
+         * TelephonyProvider column name for subscription carrier id.
+         * @see TelephonyManager#getSimCarrierId()
+         * <p>Type: INTEGER (int) </p>
+         */
+        public static final String CARRIER_ID = "carrier_id";
+
+        /**
+         * A comma-separated list of EHPLMNs associated with the subscription
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String EHPLMNS = "ehplmns";
+
+        /**
+         * A comma-separated list of HPLMNs associated with the subscription
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String HPLMNS = "hplmns";
+
+        /**
+         * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String MCC_STRING = "mcc_string";
+
+        /**
+         * TelephonyProvider column name for the MNC associated with a SIM, stored as a string.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String MNC_STRING = "mnc_string";
+
+        /**
+         * TelephonyProvider column name for the MCC associated with a SIM.
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String MCC = "mcc";
+
+        /**
+         * TelephonyProvider column name for the MNC associated with a SIM.
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String MNC = "mnc";
+
+        /**
+         * TelephonyProvider column name for the iso country code associated with a SIM.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String ISO_COUNTRY_CODE = "iso_country_code";
+
+        /**
+         * TelephonyProvider column name for the sim provisioning status associated with a SIM.
+         * <P>Type: INTEGER (int)</P>
+         * @hide
+         */
+        public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status";
+
+        /** The sim is provisioned {@hide} */
+        public static final int SIM_PROVISIONED = 0;
+
+        /**
+         * TelephonyProvider column name for whether a subscription is embedded (that is, present on
+         * an eSIM).
+         * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded.
+         */
+        public static final String IS_EMBEDDED = "is_embedded";
+
+        /**
+         * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of
+         * the current enabled profile on the card, while for eUICC card it is the EID of the card.
+         * <P>Type: TEXT (String)</P>
+         */
+        public static final String CARD_ID = "card_id";
+
+        /**
+         * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
+         * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1.
+         * <p>TYPE: BLOB
+         */
+        public static final String ACCESS_RULES = "access_rules";
+
+        /**
+         * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
+         * {@link UiccAccessRule#encodeRules} but for the rules that come from CarrierConfigs.
+         * Only present if there are access rules in CarrierConfigs
+         * <p>TYPE: BLOB
+         */
+        public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS =
+                "access_rules_from_carrier_configs";
+
+        /**
+         * TelephonyProvider column name identifying whether an embedded subscription is on a
+         * removable card. Such subscriptions are marked inaccessible as soon as the current card
+         * is removed. Otherwise, they will remain accessible unless explicitly deleted. Only
+         * present if {@link #IS_EMBEDDED} is 1.
+         * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable.
+         */
+        public static final String IS_REMOVABLE = "is_removable";
+
+        /** TelephonyProvider column name for extreme threat in CB settings */
+        public static final String CB_EXTREME_THREAT_ALERT = "enable_cmas_extreme_threat_alerts";
+
+        /** TelephonyProvider column name for severe threat in CB settings */
+        public static final String CB_SEVERE_THREAT_ALERT = "enable_cmas_severe_threat_alerts";
+
+        /** TelephonyProvider column name for amber alert in CB settings */
+        public static final String CB_AMBER_ALERT = "enable_cmas_amber_alerts";
+
+        /** TelephonyProvider column name for emergency alert in CB settings */
+        public static final String CB_EMERGENCY_ALERT = "enable_emergency_alerts";
+
+        /** TelephonyProvider column name for alert sound duration in CB settings */
+        public static final String CB_ALERT_SOUND_DURATION = "alert_sound_duration";
+
+        /** TelephonyProvider column name for alert reminder interval in CB settings */
+        public static final String CB_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
+
+        /** TelephonyProvider column name for enabling vibrate in CB settings */
+        public static final String CB_ALERT_VIBRATE = "enable_alert_vibrate";
+
+        /** TelephonyProvider column name for enabling alert speech in CB settings */
+        public static final String CB_ALERT_SPEECH = "enable_alert_speech";
+
+        /** TelephonyProvider column name for ETWS test alert in CB settings */
+        public static final String CB_ETWS_TEST_ALERT = "enable_etws_test_alerts";
+
+        /** TelephonyProvider column name for enable channel50 alert in CB settings */
+        public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts";
+
+        /** TelephonyProvider column name for CMAS test alert in CB settings */
+        public static final String CB_CMAS_TEST_ALERT = "enable_cmas_test_alerts";
+
+        /** TelephonyProvider column name for Opt out dialog in CB settings */
+        public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
+
+        /**
+         * TelephonyProvider column name for enable Volte.
+         *
+         * If this setting is not initialized (set to -1)  then we use the Carrier Config value
+         * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
+         */
+        public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
+
+        /** TelephonyProvider column name for enable VT (Video Telephony over IMS) */
+        public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+
+        /** TelephonyProvider column name for enable Wifi calling */
+        public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
+
+        /** TelephonyProvider column name for Wifi calling mode */
+        public static final String WFC_IMS_MODE = "wfc_ims_mode";
+
+        /** TelephonyProvider column name for Wifi calling mode in roaming */
+        public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
+
+        /** TelephonyProvider column name for enable Wifi calling in roaming */
+        public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
+
+        /**
+         * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this
+         * subscription.
+         */
+        public static final String IMS_RCS_UCE_ENABLED = "ims_rcs_uce_enabled";
+
+        /**
+         * TelephonyProvider column name for whether a subscription is opportunistic, that is,
+         * whether the network it connects to is limited in functionality or coverage.
+         * For example, CBRS.
+         * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic.
+         */
+        public static final String IS_OPPORTUNISTIC = "is_opportunistic";
+
+        /**
+         * TelephonyProvider column name for group ID. Subscriptions with same group ID
+         * are considered bundled together, and should behave as a single subscription at
+         * certain scenarios.
+         */
+        public static final String GROUP_UUID = "group_uuid";
+
+        /**
+         * TelephonyProvider column name for group owner. It's the package name who created
+         * the subscription group.
+         */
+        public static final String GROUP_OWNER = "group_owner";
+
+        /**
+         * TelephonyProvider column name for whether a subscription is metered or not, that is,
+         * whether the network it connects to charges for subscription or not. For example, paid
+         * CBRS or unpaid.
+         * @hide
+         */
+        public static final String IS_METERED = "is_metered";
+
+        /**
+         * TelephonyProvider column name for the profile class of a subscription
+         * Only present if {@link #IS_EMBEDDED} is 1.
+         * <P>Type: INTEGER (int)</P>
+         */
+        public static final String PROFILE_CLASS = "profile_class";
+
+        /**
+         * A testing profile can be pre-loaded or downloaded onto
+         * the eUICC and provides connectivity to test equipment
+         * for the purpose of testing the device and the eUICC. It
+         * is not intended to store any operator credentials.
+         */
+        public static final int PROFILE_CLASS_TESTING = 0;
+
+        /**
+         * A provisioning profile is pre-loaded onto the eUICC and
+         * provides connectivity to a mobile network solely for the
+         * purpose of provisioning profiles.
+         */
+        public static final int PROFILE_CLASS_PROVISIONING = 1;
+
+        /**
+         * An operational profile can be pre-loaded or downloaded
+         * onto the eUICC and provides services provided by the
+         * operator.
+         */
+        public static final int PROFILE_CLASS_OPERATIONAL = 2;
+
+        /**
+         * The profile class is unset. This occurs when profile class
+         * info is not available. The subscription either has no profile
+         * metadata or the profile metadata did not encode profile class.
+         */
+        public static final int PROFILE_CLASS_UNSET = -1;
+
+        /** Default profile class */
+        public static final int PROFILE_CLASS_DEFAULT = PROFILE_CLASS_UNSET;
+
+        /**
+         * IMSI (International Mobile Subscriber Identity).
+         * <P>Type: TEXT </P>
+         */
+        public static final String IMSI = "imsi";
+
+        /** Whether uicc applications is set to be enabled or disabled. By default it's enabled. */
+        public static final String UICC_APPLICATIONS_ENABLED = "uicc_applications_enabled";
+
+        /**
+         * TelephonyProvider column name for allowed network types. Indicate which network types
+         * are allowed. Default is -1.
+         */
+        public static final String ALLOWED_NETWORK_TYPES = "allowed_network_types";
     }
 }
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index f886cf5..03e7361 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -168,6 +168,16 @@
     public static final int LISTEN_SIGNAL_STRENGTHS                         = 0x00000100;
 
     /**
+     * Listen for always reported changes of the network signal strengths (cellular),
+     * even in some situations such as the screen of the device is off.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
+    @SystemApi
+    public static final int LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH          = 0x00000200;
+
+    /**
      * Listen for changes to observed cell info.
      *
      * @see #onCellInfoChanged
diff --git a/core/java/com/android/internal/util/ConnectivityUtil.java b/core/java/com/android/internal/util/LocationPermissionChecker.java
similarity index 71%
rename from core/java/com/android/internal/util/ConnectivityUtil.java
rename to core/java/com/android/internal/util/LocationPermissionChecker.java
index b1d4fa0..dc318b4 100644
--- a/core/java/com/android/internal/util/ConnectivityUtil.java
+++ b/core/java/com/android/internal/util/LocationPermissionChecker.java
@@ -33,28 +33,59 @@
 
 
 /**
- * Utility methods for common functionality using by different networks.
+ * The methods used for location permission and location mode checking.
  *
  * @hide
  */
-public class ConnectivityUtil {
+public class LocationPermissionChecker {
 
-    private static final String TAG = "ConnectivityUtil";
+    private static final String TAG = "LocationPermissionChecker";
 
     private final Context mContext;
-    private final AppOpsManager mAppOps;
+    private final AppOpsManager mAppOpsManager;
     private final UserManager mUserManager;
+    private final LocationManager mLocationManager;
 
-    public ConnectivityUtil(Context context) {
+    public LocationPermissionChecker(Context context) {
         mContext = context;
-        mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
+        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+        mLocationManager =
+            (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
     }
 
     /**
-     * API to determine if the caller has fine/coarse location permission (depending on
-     * config/targetSDK level) and the location mode is enabled for the user. SecurityException is
-     * thrown if the caller has no permission or the location mode is disabled.
+     * Check location permission granted by the caller.
+     *
+     * This API check if the location mode enabled for the caller and the caller has
+     * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION.
+     *
+     * @param pkgName package name of the application requesting access
+     * @param featureId The feature in the package
+     * @param uid The uid of the package
+     * @param message A message describing why the permission was checked. Only needed if this is
+     *                not inside of a two-way binder call from the data receiver
+     *
+     * @return {@code true} returns if the caller has location permission and the location mode is
+     *         enabled.
+     */
+    public boolean checkLocationPermission(String pkgName, @Nullable String featureId,
+            int uid, @Nullable String message) {
+        try {
+            enforceLocationPermission(pkgName, featureId, uid, message);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Enforce the caller has location permission.
+     *
+     * This API determines if the location mode enabled for the caller and the caller has
+     * ACCESS_COARSE_LOCATION permission is targetSDK<29, otherwise, has ACCESS_FINE_LOCATION.
+     * SecurityException is thrown if the caller has no permission or the location mode is disabled.
+     *
      * @param pkgName package name of the application requesting access
      * @param featureId The feature in the package
      * @param uid The uid of the package
@@ -62,31 +93,21 @@
      *                not inside of a two-way binder call from the data receiver
      */
     public void enforceLocationPermission(String pkgName, @Nullable String featureId, int uid,
-            @Nullable String message)
-            throws SecurityException {
+            @Nullable String message) throws SecurityException {
+
         checkPackage(uid, pkgName);
 
         // Location mode must be enabled
         if (!isLocationModeEnabled()) {
-            // Location mode is disabled, scan results cannot be returned
             throw new SecurityException("Location mode is disabled for the device");
         }
 
         // LocationAccess by App: caller must have Coarse/Fine Location permission to have access to
         // location information.
-        boolean canAppPackageUseLocation = checkCallersLocationPermission(pkgName, featureId,
-                uid, /* coarseForTargetSdkLessThanQ */ true, message);
-
-        // If neither caller or app has location access, there is no need to check
-        // any other permissions. Deny access to scan results.
-        if (!canAppPackageUseLocation) {
+        if (!checkCallersLocationPermission(pkgName, featureId,
+                uid, /* coarseForTargetSdkLessThanQ */ true, message)) {
             throw new SecurityException("UID " + uid + " has no location permission");
         }
-        // If the User or profile is current, permission is granted
-        // Otherwise, uid must have INTERACT_ACROSS_USERS_FULL permission.
-        if (!isCurrentProfile(uid) && !checkInteractAcrossUsersFull(uid)) {
-            throw new SecurityException("UID " + uid + " profile not permitted");
-        }
     }
 
     /**
@@ -104,6 +125,7 @@
      */
     public boolean checkCallersLocationPermission(String pkgName, @Nullable String featureId,
             int uid, boolean coarseForTargetSdkLessThanQ, @Nullable String message) {
+
         boolean isTargetSdkLessThanQ = isTargetSdkLessThan(pkgName, Build.VERSION_CODES.Q, uid);
 
         String permissionType = Manifest.permission.ACCESS_FINE_LOCATION;
@@ -111,8 +133,7 @@
             // Having FINE permission implies having COARSE permission (but not the reverse)
             permissionType = Manifest.permission.ACCESS_COARSE_LOCATION;
         }
-        if (getUidPermission(permissionType, uid)
-                == PackageManager.PERMISSION_DENIED) {
+        if (getUidPermission(permissionType, uid) == PackageManager.PERMISSION_DENIED) {
             return false;
         }
 
@@ -134,10 +155,8 @@
      * Retrieves a handle to LocationManager (if not already done) and check if location is enabled.
      */
     public boolean isLocationModeEnabled() {
-        LocationManager locationManager =
-                (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
         try {
-            return locationManager.isLocationEnabledForUser(UserHandle.of(
+            return mLocationManager.isLocationEnabledForUser(UserHandle.of(
                     getCurrentUser()));
         } catch (Exception e) {
             Log.e(TAG, "Failure to get location mode via API, falling back to settings", e);
@@ -166,28 +185,15 @@
 
     private boolean noteAppOpAllowed(String op, String pkgName, @Nullable String featureId,
             int uid, @Nullable String message) {
-        return mAppOps.noteOp(op, uid, pkgName) == AppOpsManager.MODE_ALLOWED;
+        return mAppOpsManager.noteOp(op, uid, pkgName) == AppOpsManager.MODE_ALLOWED;
     }
 
-    private void checkPackage(int uid, String pkgName) throws SecurityException {
+    private void checkPackage(int uid, String pkgName)
+            throws SecurityException {
         if (pkgName == null) {
             throw new SecurityException("Checking UID " + uid + " but Package Name is Null");
         }
-        mAppOps.checkPackage(uid, pkgName);
-    }
-
-    private boolean isCurrentProfile(int uid) {
-        UserHandle currentUser = UserHandle.of(getCurrentUser());
-        UserHandle callingUser = UserHandle.getUserHandleForUid(uid);
-        return currentUser.equals(callingUser)
-                || mUserManager.isSameProfileGroup(
-                        currentUser.getIdentifier(), callingUser.getIdentifier());
-    }
-
-    private boolean checkInteractAcrossUsersFull(int uid) {
-        return getUidPermission(
-                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, uid)
-                == PackageManager.PERMISSION_GRANTED;
+        mAppOpsManager.checkPackage(uid, pkgName);
     }
 
     @VisibleForTesting
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5c204ab..6960aef 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2082,6 +2082,11 @@
     <permission android:name="android.permission.READ_ACTIVE_EMERGENCY_SESSION"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi Allows listen permission to always reported signal strength.
+         @hide Used internally. -->
+    <permission android:name="android.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH"
+        android:protectionLevel="signature|telephony" />
+
     <!-- @SystemApi Protects the ability to register any PhoneAccount with
          PhoneAccount#CAPABILITY_SIM_SUBSCRIPTION. This capability indicates that the PhoneAccount
          corresponds to a device SIM.
@@ -4695,6 +4700,19 @@
     <permission android:name="android.permission.ACCESS_SHARED_LIBRARIES"
                 android:protectionLevel="signature|installer" />
 
+    <!-- Allows an app to log compat change usage.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.LOG_COMPAT_CHANGE"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to read compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+    <!-- Allows an app to override compat change config.
+         @hide  <p>Not for use by third-party applications.</p> -->
+    <permission android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG"
+                android:protectionLevel="signature" />
+
     <!-- Allows input events to be monitored. Very dangerous!  @hide -->
     <permission android:name="android.permission.MONITOR_INPUT"
                 android:protectionLevel="signature" />
diff --git a/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
similarity index 83%
rename from core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
rename to core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
index 5564712..6a0a3dc 100644
--- a/core/tests/utiltests/src/com/android/internal/util/ConnectivityUtilTest.java
+++ b/core/tests/utiltests/src/com/android/internal/util/LocationPermissionCheckerTest.java
@@ -27,6 +27,7 @@
 import static org.mockito.Mockito.when;
 
 import android.Manifest;
+import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -47,8 +48,8 @@
 
 import java.util.HashMap;
 
-/** Unit tests for {@link ConnectivityUtil}. */
-public class ConnectivityUtilTest {
+/** Unit tests for {@link LocationPermissionChecker}. */
+public class LocationPermissionCheckerTest {
 
     public static final String TAG = "ConnectivityUtilTest";
 
@@ -84,18 +85,7 @@
     private boolean mThrowSecurityException;
     private Answer<Integer> mReturnPermission;
     private HashMap<String, Integer> mPermissionsList = new HashMap<String, Integer>();
-
-    private class TestConnectivityUtil extends ConnectivityUtil {
-
-        TestConnectivityUtil(Context context) {
-            super(context);
-        }
-
-        @Override
-        protected int getCurrentUser() {
-            return mCurrentUser;
-        }
-    }
+    private LocationPermissionChecker mChecker;
 
     @Before
     public void setUp() {
@@ -140,11 +130,12 @@
         mThrowSecurityException = true;
         mMockApplInfo.targetSdkVersion = Build.VERSION_CODES.M;
         mIsLocationEnabled = false;
-        mCurrentUser = UserHandle.USER_SYSTEM;
+        mCurrentUser = ActivityManager.getCurrentUser();
         mCoarseLocationPermission = PackageManager.PERMISSION_DENIED;
         mFineLocationPermission = PackageManager.PERMISSION_DENIED;
         mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
         mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
+        mChecker = new LocationPermissionChecker(mMockContext);
     }
 
     private void setupMockInterface() {
@@ -188,8 +179,7 @@
         mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
         mUid = mCurrentUser;
         setupTestCase();
-        new TestConnectivityUtil(mMockContext)
-                .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+        mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
     }
 
     @Test
@@ -202,8 +192,7 @@
         mAllowFineLocationApps = AppOpsManager.MODE_ALLOWED;
         mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
         setupTestCase();
-        new TestConnectivityUtil(mMockContext)
-                .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
+        mChecker.enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
     }
 
     @Test
@@ -216,22 +205,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
-    }
-
-    @Test
-    public void testenforceCanAccessScanResults_UserOrProfileNotCurrent() throws Exception {
-        mIsLocationEnabled = true;
-        mThrowSecurityException = false;
-        mCoarseLocationPermission = PackageManager.PERMISSION_GRANTED;
-        mAllowCoarseLocationApps = AppOpsManager.MODE_ALLOWED;
-        mWifiScanAllowApps = AppOpsManager.MODE_ALLOWED;
-        setupTestCase();
-
-        assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     @Test
@@ -240,8 +215,8 @@
         mIsLocationEnabled = true;
         setupTestCase();
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     @Test
@@ -255,8 +230,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
         verify(mMockAppOps, never()).noteOp(anyInt(), anyInt(), anyString());
     }
 
@@ -271,8 +246,8 @@
         setupTestCase();
 
         assertThrows(SecurityException.class,
-                () -> new TestConnectivityUtil(mMockContext)
-                        .enforceLocationPermission(TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
+                () -> mChecker.enforceLocationPermission(
+                        TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null));
     }
 
     private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 8631e86..d330732 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -19,16 +19,12 @@
 import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 import static android.telephony.PhoneStateListener.LISTEN_NONE;
 
-import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
-
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.ConnectivityManager;
 import android.net.wifi.WifiManager;
 import android.os.Handler;
-import android.os.SystemProperties;
-import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
@@ -37,20 +33,18 @@
 import android.text.TextUtils;
 import android.util.Log;
 
-import androidx.annotation.VisibleForTesting;
-
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.telephony.TelephonyProperties;
 import com.android.settingslib.WirelessUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 
-import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 
+import androidx.annotation.VisibleForTesting;
+
 /**
  * Controller that generates text including the carrier names and/or the status of all the SIM
  * interfaces in the device. Through a callback, the updates can be retrieved either as a list or
@@ -73,8 +67,6 @@
     private Context mContext;
     private CharSequence mSeparator;
     private WakefulnessLifecycle mWakefulnessLifecycle;
-    @VisibleForTesting
-    protected boolean mDisplayOpportunisticSubscriptionCarrierText;
     private final WakefulnessLifecycle.Observer mWakefulnessObserver =
             new WakefulnessLifecycle.Observer() {
                 @Override
@@ -173,9 +165,6 @@
         mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
         mSimSlotsNumber = getTelephonyManager().getSupportedModemCount();
         mSimErrorState = new boolean[mSimSlotsNumber];
-        updateDisplayOpportunisticSubscriptionCarrierText(SystemProperties.getBoolean(
-                TelephonyProperties.DISPLAY_OPPORTUNISTIC_SUBSCRIPTION_CARRIER_TEXT_PROPERTY_NAME,
-                false));
     }
 
     private TelephonyManager getTelephonyManager() {
@@ -255,63 +244,8 @@
         }
     }
 
-    /**
-     * @param subscriptions
-     */
-    private void filterMobileSubscriptionInSameGroup(List<SubscriptionInfo> subscriptions) {
-        if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
-            SubscriptionInfo info1 = subscriptions.get(0);
-            SubscriptionInfo info2 = subscriptions.get(1);
-            if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
-                // If both subscriptions are primary, show both.
-                if (!info1.isOpportunistic() && !info2.isOpportunistic()) return;
-
-                // If carrier required, always show signal bar of primary subscription.
-                // Otherwise, show whichever subscription is currently active for Internet.
-                boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
-                        .getBoolean(CarrierConfigManager
-                        .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
-                if (alwaysShowPrimary) {
-                    subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
-                } else {
-                    subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
-                            ? info2 : info1);
-                }
-
-            }
-        }
-    }
-
-    /**
-     * updates if opportunistic sub carrier text should be displayed or not
-     *
-     */
-    @VisibleForTesting
-    public void updateDisplayOpportunisticSubscriptionCarrierText(boolean isEnable) {
-        mDisplayOpportunisticSubscriptionCarrierText = isEnable;
-    }
-
     protected List<SubscriptionInfo> getSubscriptionInfo() {
-        List<SubscriptionInfo> subs;
-        if (mDisplayOpportunisticSubscriptionCarrierText) {
-            SubscriptionManager subscriptionManager = ((SubscriptionManager) mContext
-                    .getSystemService(
-                    Context.TELEPHONY_SUBSCRIPTION_SERVICE));
-            subs = subscriptionManager.getActiveSubscriptionInfoList(false);
-            if (subs == null) {
-                subs = new ArrayList<>();
-            } else {
-                filterMobileSubscriptionInSameGroup(subs);
-            }
-        } else {
-            subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
-            if (subs == null) {
-                subs = new ArrayList<>();
-            } else {
-                filterMobileSubscriptionInSameGroup(subs);
-            }
-        }
-        return subs;
+        return mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
     }
 
     protected void updateCarrierText() {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1fb50a9..0ede50d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -30,6 +30,7 @@
 import static android.os.BatteryManager.EXTRA_STATUS;
 import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
+import static com.android.internal.telephony.PhoneConstants.MAX_PHONE_COUNT_DUAL_SIM;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
@@ -77,6 +78,7 @@
 import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
+import android.telephony.CarrierConfigManager;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
@@ -257,6 +259,7 @@
     private boolean mLogoutEnabled;
     // If the user long pressed the lock icon, disabling face auth for the current session.
     private boolean mLockIconPressed;
+    private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
 
     /**
      * Short delay before restarting biometric authentication after a successful try
@@ -392,9 +395,11 @@
         }
     };
 
-    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+    @VisibleForTesting
+    public PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
         @Override
         public void onActiveDataSubscriptionIdChanged(int subId) {
+            mActiveMobileDataSubscription = subId;
             mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
         }
     };
@@ -496,7 +501,9 @@
         }
     }
 
-    /** @return List of SubscriptionInfo records, maybe empty but never null */
+    /**
+     * @return List of SubscriptionInfo records, maybe empty but never null.
+     */
     public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
         List<SubscriptionInfo> sil = mSubscriptionInfo;
         if (sil == null || forceReload) {
@@ -508,7 +515,42 @@
         } else {
             mSubscriptionInfo = sil;
         }
-        return mSubscriptionInfo;
+        return new ArrayList<>(mSubscriptionInfo);
+    }
+
+    /**
+     * This method returns filtered list of SubscriptionInfo from {@link #getSubscriptionInfo}.
+     * above. Maybe empty but never null.
+     *
+     * In DSDS mode if both subscriptions are grouped and one is opportunistic, we filter out one
+     * of them based on carrier config. e.g. In this case we should only show one carrier name
+     * on the status bar and quick settings.
+     */
+    public List<SubscriptionInfo> getFilteredSubscriptionInfo(boolean forceReload) {
+        List<SubscriptionInfo> subscriptions = getSubscriptionInfo(false);
+        if (subscriptions.size() == MAX_PHONE_COUNT_DUAL_SIM) {
+            SubscriptionInfo info1 = subscriptions.get(0);
+            SubscriptionInfo info2 = subscriptions.get(1);
+            if (info1.getGroupUuid() != null && info1.getGroupUuid().equals(info2.getGroupUuid())) {
+                // If both subscriptions are primary, show both.
+                if (!info1.isOpportunistic() && !info2.isOpportunistic()) return subscriptions;
+
+                // If carrier required, always show signal bar of primary subscription.
+                // Otherwise, show whichever subscription is currently active for Internet.
+                boolean alwaysShowPrimary = CarrierConfigManager.getDefaultConfig()
+                        .getBoolean(CarrierConfigManager
+                        .KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN);
+                if (alwaysShowPrimary) {
+                    subscriptions.remove(info1.isOpportunistic() ? info1 : info2);
+                } else {
+                    subscriptions.remove(info1.getSubscriptionId() == mActiveMobileDataSubscription
+                            ? info2 : info1);
+                }
+
+            }
+        }
+
+        return subscriptions;
     }
 
     @Override
@@ -2637,6 +2679,7 @@
                 pw.println("    " + mSubscriptionInfo.get(i));
             }
         }
+        pw.println("  Current active data subId=" + mActiveMobileDataSubscription);
         pw.println("  Service states:");
         for (int subId : mServiceStates.keySet()) {
             pw.println("    " + subId + "=" + mServiceStates.get(subId));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
index d1b3c3c..2a5ccdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/OperatorNameView.java
@@ -134,7 +134,7 @@
 
     private void updateText() {
         CharSequence displayText = null;
-        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
         final int N = subs.size();
         for (int i = 0; i < N; i++) {
             int subId = subs.get(i).getSubscriptionId();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
index 0d6178b..f2c0434 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/EmergencyCryptkeeperText.java
@@ -97,7 +97,7 @@
         boolean allSimsMissing = true;
         CharSequence displayText = null;
 
-        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+        List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(false);
         final int N = subs.size();
         for (int i = 0; i < N; i++) {
             int subId = subs.get(i).getSubscriptionId();
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
index 4d9ea29..5a8ff4b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/CarrierTextControllerTest.java
@@ -19,7 +19,7 @@
 
 import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
 import static android.telephony.SubscriptionManager.DATA_ROAMING_ENABLE;
-import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE;
+import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT;
 
 import static junit.framework.Assert.assertTrue;
 import static junit.framework.TestCase.assertFalse;
@@ -77,21 +77,16 @@
     private static final CharSequence AIRPLANE_MODE_TEXT = "Airplane mode";
     private static final String TEST_CARRIER = "TEST_CARRIER";
     private static final String TEST_CARRIER_2 = "TEST_CARRIER_2";
-    private static final String TEST_GROUP_UUID = "59b5c870-fc4c-47a4-a99e-9db826b48b24";
     private static final int TEST_CARRIER_ID = 1;
     private static final SubscriptionInfo TEST_SUBSCRIPTION = new SubscriptionInfo(0, "", 0,
-            TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "",
-            DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", false, TEST_GROUP_UUID,
-            TEST_CARRIER_ID, 0);
-    private static final SubscriptionInfo TEST_SUBSCRIPTION_2 = new SubscriptionInfo(0, "", 0,
-            TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "",
-            DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
+            TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT, 0xFFFFFF, "",
+            DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", false, null,
             TEST_CARRIER_ID, 0);
     private static final SubscriptionInfo TEST_SUBSCRIPTION_NULL = new SubscriptionInfo(0, "", 0,
-            TEST_CARRIER, null, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "", DATA_ROAMING_DISABLE,
+            TEST_CARRIER, null, NAME_SOURCE_DEFAULT, 0xFFFFFF, "", DATA_ROAMING_DISABLE,
             null, null, null, null, false, null, "");
     private static final SubscriptionInfo TEST_SUBSCRIPTION_ROAMING = new SubscriptionInfo(0, "", 0,
-            TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT_SOURCE, 0xFFFFFF, "",
+            TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT, 0xFFFFFF, "",
             DATA_ROAMING_ENABLE, null, null, null, null, false, null, "");
     @Mock
     private WifiManager mWifiManager;
@@ -136,7 +131,6 @@
                 mKeyguardUpdateMonitor);
         // This should not start listening on any of the real dependencies
         mCarrierTextController.setListening(mCarrierTextCallback);
-        mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText(false);
     }
 
     @Test
@@ -145,7 +139,7 @@
         reset(mCarrierTextCallback);
         List<SubscriptionInfo> list = new ArrayList<>();
         list.add(TEST_SUBSCRIPTION);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
         when(mKeyguardUpdateMonitor.getSimState(0)).thenReturn(IccCardConstants.State.READY);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -165,7 +159,7 @@
         reset(mCarrierTextCallback);
         List<SubscriptionInfo> list = new ArrayList<>();
         list.add(TEST_SUBSCRIPTION);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
         when(mKeyguardUpdateMonitor.getSimState(0)).thenReturn(IccCardConstants.State.READY);
         when(mKeyguardUpdateMonitor.getSimState(1)).thenReturn(
                 IccCardConstants.State.CARD_IO_ERROR);
@@ -198,7 +192,7 @@
     @Test
     public void testWrongSlots() {
         reset(mCarrierTextCallback);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(
                 new ArrayList<>());
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(
                 IccCardConstants.State.CARD_IO_ERROR);
@@ -212,7 +206,7 @@
     @Test
     public void testMoreSlotsThanSubs() {
         reset(mCarrierTextCallback);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(
                 new ArrayList<>());
 
         // STOPSHIP(b/130246708) This line makes sure that SubscriptionManager provides the
@@ -262,7 +256,7 @@
         List<SubscriptionInfo> list = new ArrayList<>();
         list.add(TEST_SUBSCRIPTION);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -286,7 +280,7 @@
         List<SubscriptionInfo> list = new ArrayList<>();
         list.add(TEST_SUBSCRIPTION_ROAMING);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -366,7 +360,7 @@
     @Test
     public void testCreateInfo_noSubscriptions() {
         reset(mCarrierTextCallback);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(
                 new ArrayList<>());
 
         ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -390,7 +384,7 @@
         list.add(TEST_SUBSCRIPTION);
         list.add(TEST_SUBSCRIPTION);
         when(mKeyguardUpdateMonitor.getSimState(anyInt())).thenReturn(IccCardConstants.State.READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -415,7 +409,7 @@
         when(mKeyguardUpdateMonitor.getSimState(anyInt()))
                 .thenReturn(IccCardConstants.State.READY)
                 .thenReturn(IccCardConstants.State.NOT_READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -440,7 +434,7 @@
         when(mKeyguardUpdateMonitor.getSimState(anyInt()))
                 .thenReturn(IccCardConstants.State.NOT_READY)
                 .thenReturn(IccCardConstants.State.READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
 
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
@@ -467,7 +461,7 @@
                 .thenReturn(IccCardConstants.State.READY)
                 .thenReturn(IccCardConstants.State.NOT_READY)
                 .thenReturn(IccCardConstants.State.READY);
-        when(mKeyguardUpdateMonitor.getSubscriptionInfo(anyBoolean())).thenReturn(list);
+        when(mKeyguardUpdateMonitor.getFilteredSubscriptionInfo(anyBoolean())).thenReturn(list);
         mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
 
         ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
@@ -482,30 +476,6 @@
                 captor.getValue().carrierText);
     }
 
-    @Test
-    public void testCarrierText_GroupedSubWithOpportunisticCarrierText() {
-        reset(mCarrierTextCallback);
-        List<SubscriptionInfo> list = new ArrayList<>();
-        list.add(TEST_SUBSCRIPTION);
-        list.add(TEST_SUBSCRIPTION_2);
-        when(mKeyguardUpdateMonitor.getSimState(anyInt()))
-            .thenReturn(IccCardConstants.State.READY);
-
-        mKeyguardUpdateMonitor.mServiceStates = new HashMap<>();
-        mCarrierTextController.updateDisplayOpportunisticSubscriptionCarrierText(true);
-        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
-
-        ArgumentCaptor<CarrierTextController.CarrierTextCallbackInfo> captor =
-                ArgumentCaptor.forClass(
-                CarrierTextController.CarrierTextCallbackInfo.class);
-
-        mCarrierTextController.updateCarrierText();
-        mTestableLooper.processAllMessages();
-        verify(mCarrierTextCallback).updateCarrierInfo(captor.capture());
-
-        assertEquals(TEST_CARRIER_2, captor.getValue().carrierText);
-    }
-
     public static class TestCarrierTextController extends CarrierTextController {
         private KeyguardUpdateMonitor mKUM;
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 21585ed..cfffcbc 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -16,15 +16,18 @@
 
 package com.android.keyguard;
 
+import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
+import static android.telephony.SubscriptionManager.NAME_SOURCE_DEFAULT;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -42,6 +45,7 @@
 import android.os.Bundle;
 import android.os.UserManager;
 import android.telephony.ServiceState;
+import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -62,6 +66,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 @SmallTest
@@ -73,7 +79,18 @@
 // new tests.
 @RunWithLooper(setAsMainLooper = true)
 public class KeyguardUpdateMonitorTest extends SysuiTestCase {
-
+    private static final String TEST_CARRIER = "TEST_CARRIER";
+    private static final String TEST_CARRIER_2 = "TEST_CARRIER_2";
+    private static final int TEST_CARRIER_ID = 1;
+    private static final String TEST_GROUP_UUID = "59b5c870-fc4c-47a4-a99e-9db826b48b24";
+    private static final SubscriptionInfo TEST_SUBSCRIPTION = new SubscriptionInfo(1, "", 0,
+            TEST_CARRIER, TEST_CARRIER, NAME_SOURCE_DEFAULT, 0xFFFFFF, "",
+            DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", false, TEST_GROUP_UUID,
+            TEST_CARRIER_ID, 0);
+    private static final SubscriptionInfo TEST_SUBSCRIPTION_2 = new SubscriptionInfo(2, "", 0,
+            TEST_CARRIER, TEST_CARRIER_2, NAME_SOURCE_DEFAULT, 0xFFFFFF, "",
+            DATA_ROAMING_DISABLE, null, null, null, null, false, null, "", true, TEST_GROUP_UUID,
+            TEST_CARRIER_ID, 0);
     @Mock
     private KeyguardUpdateMonitor.StrongAuthTracker mStrongAuthTracker;
     @Mock
@@ -92,6 +109,8 @@
     private DevicePolicyManager mDevicePolicyManager;
     @Mock
     private KeyguardBypassController mKeyguardBypassController;
+    @Mock
+    private SubscriptionManager mSubscriptionManager;
     private TestableLooper mTestableLooper;
     private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
@@ -119,6 +138,7 @@
         context.addMockSystemService(FaceManager.class, mFaceManager);
         context.addMockSystemService(UserManager.class, mUserManager);
         context.addMockSystemService(DevicePolicyManager.class, mDevicePolicyManager);
+        context.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
 
         mTestableLooper = TestableLooper.get(this);
         mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(context);
@@ -441,6 +461,22 @@
         assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
     }
 
+    @Test
+    public void testGetSubscriptionInfo_whenInGroupedSubWithOpportunistic() {
+        List<SubscriptionInfo> list = new ArrayList<>();
+        list.add(TEST_SUBSCRIPTION);
+        list.add(TEST_SUBSCRIPTION_2);
+        when(mSubscriptionManager.getActiveSubscriptionInfoList(anyBoolean())).thenReturn(list);
+        mKeyguardUpdateMonitor.mPhoneStateListener.onActiveDataSubscriptionIdChanged(
+                TEST_SUBSCRIPTION_2.getSubscriptionId());
+        mTestableLooper.processAllMessages();
+
+        List<SubscriptionInfo> listToVerify = mKeyguardUpdateMonitor
+                .getFilteredSubscriptionInfo(false);
+        assertThat(listToVerify.size()).isEqualTo(1);
+        assertThat(listToVerify.get(0)).isEqualTo(TEST_SUBSCRIPTION_2);
+    }
+
     private Intent putPhoneInfo(Intent intent, Bundle data, Boolean simInited) {
         int subscription = simInited
                 ? 1/* mock subid=1 */ : SubscriptionManager.DUMMY_SUBSCRIPTION_ID_BASE;
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index 264ce44..e0adb34d 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -19,7 +19,15 @@
     local_include_dir: "src",
     include_dirs: ["frameworks/base/core/java"], // For framework parcelables.
     srcs: [
-        "src/android/net/*.aidl",
+        // @JavaOnlyStableParcelable aidl declarations must not be listed here, as this would cause
+        // compilation to fail (b/148001843).
+        "src/android/net/IIntResultListener.aidl",
+        "src/android/net/ITetheringConnector.aidl",
+        "src/android/net/ITetheringEventCallback.aidl",
+        "src/android/net/TetheringCallbackStartedParcel.aidl",
+        "src/android/net/TetheringConfigurationParcel.aidl",
+        "src/android/net/TetheringRequestParcel.aidl",
+        "src/android/net/TetherStatesParcel.aidl",
     ],
     backend: {
         ndk: {
@@ -35,7 +43,9 @@
     name: "framework-tethering",
     sdk_version: "system_current",
     srcs: [
+        "src/android/net/TetheredClient.java",
         "src/android/net/TetheringManager.java",
+        "src/android/net/TetheringConstants.java",
         ":framework-tethering-annotations",
     ],
     static_libs: [
@@ -62,11 +72,16 @@
 filegroup {
     name: "framework-tethering-srcs",
     srcs: [
+        "src/android/net/TetheredClient.aidl",
+        "src/android/net/TetheredClient.java",
         "src/android/net/TetheringManager.java",
+        "src/android/net/TetheringConstants.java",
         "src/android/net/IIntResultListener.aidl",
         "src/android/net/ITetheringEventCallback.aidl",
         "src/android/net/ITetheringConnector.aidl",
+        "src/android/net/TetheringCallbackStartedParcel.aidl",
         "src/android/net/TetheringConfigurationParcel.aidl",
+        "src/android/net/TetheringRequestParcel.aidl",
         "src/android/net/TetherStatesParcel.aidl",
     ],
     path: "src"
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
index d30c399..5febe73 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringConnector.aidl
@@ -17,6 +17,7 @@
 
 import android.net.IIntResultListener;
 import android.net.ITetheringEventCallback;
+import android.net.TetheringRequestParcel;
 import android.os.ResultReceiver;
 
 /** @hide */
@@ -27,8 +28,8 @@
 
     void setUsbTethering(boolean enable, String callerPkg, IIntResultListener receiver);
 
-    void startTethering(int type, in ResultReceiver receiver, boolean showProvisioningUi,
-            String callerPkg);
+    void startTethering(in TetheringRequestParcel request, String callerPkg,
+            IIntResultListener receiver);
 
     void stopTethering(int type, String callerPkg, IIntResultListener receiver);
 
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
index 2836195..28a810d 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
+++ b/packages/Tethering/common/TetheringLib/src/android/net/ITetheringEventCallback.aidl
@@ -18,6 +18,7 @@
 
 import android.net.Network;
 import android.net.TetheringConfigurationParcel;
+import android.net.TetheringCallbackStartedParcel;
 import android.net.TetherStatesParcel;
 
 /**
@@ -26,8 +27,8 @@
  */
 oneway interface ITetheringEventCallback
 {
-    void onCallbackStarted(in Network network, in TetheringConfigurationParcel config,
-            in TetherStatesParcel states);
+    /** Called immediately after the callbacks are registered */
+    void onCallbackStarted(in TetheringCallbackStartedParcel parcel);
     void onCallbackStopped(int errorCode);
     void onUpstreamChanged(in Network network);
     void onConfigurationChanged(in TetheringConfigurationParcel config);
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
new file mode 100644
index 0000000..0b279b8
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.aidl
@@ -0,0 +1,18 @@
+/**
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+@JavaOnlyStableParcelable parcelable TetheredClient;
\ No newline at end of file
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
new file mode 100644
index 0000000..6514688
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheredClient.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Information on a tethered downstream client.
+ * @hide
+ */
+@SystemApi
+@TestApi
+public final class TetheredClient implements Parcelable {
+    @NonNull
+    private final MacAddress mMacAddress;
+    @NonNull
+    private final List<AddressInfo> mAddresses;
+    // TODO: use an @IntDef here
+    private final int mTetheringType;
+
+    public TetheredClient(@NonNull MacAddress macAddress,
+            @NonNull Collection<AddressInfo> addresses, int tetheringType) {
+        mMacAddress = macAddress;
+        mAddresses = new ArrayList<>(addresses);
+        mTetheringType = tetheringType;
+    }
+
+    private TetheredClient(@NonNull Parcel in) {
+        this(in.readParcelable(null), in.createTypedArrayList(AddressInfo.CREATOR), in.readInt());
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeParcelable(mMacAddress, flags);
+        dest.writeTypedList(mAddresses);
+        dest.writeInt(mTetheringType);
+    }
+
+    @NonNull
+    public MacAddress getMacAddress() {
+        return mMacAddress;
+    }
+
+    @NonNull
+    public List<AddressInfo> getAddresses() {
+        return new ArrayList<>(mAddresses);
+    }
+
+    public int getTetheringType() {
+        return mTetheringType;
+    }
+
+    /**
+     * Return a new {@link TetheredClient} that has all the attributes of this instance, plus the
+     * {@link AddressInfo} of the provided {@link TetheredClient}.
+     *
+     * <p>Duplicate addresses are removed.
+     * @hide
+     */
+    public TetheredClient addAddresses(@NonNull TetheredClient other) {
+        final HashSet<AddressInfo> newAddresses = new HashSet<>(
+                mAddresses.size() + other.mAddresses.size());
+        newAddresses.addAll(mAddresses);
+        newAddresses.addAll(other.mAddresses);
+        return new TetheredClient(mMacAddress, newAddresses, mTetheringType);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mMacAddress, mAddresses, mTetheringType);
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (!(obj instanceof TetheredClient)) return false;
+        final TetheredClient other = (TetheredClient) obj;
+        return mMacAddress.equals(other.mMacAddress)
+                && mAddresses.equals(other.mAddresses)
+                && mTetheringType == other.mTetheringType;
+    }
+
+    /**
+     * Information on an lease assigned to a tethered client.
+     */
+    public static final class AddressInfo implements Parcelable {
+        @NonNull
+        private final LinkAddress mAddress;
+        @Nullable
+        private final String mHostname;
+        // TODO: use LinkAddress expiration time once it is supported
+        private final long mExpirationTime;
+
+        /** @hide */
+        public AddressInfo(@NonNull LinkAddress address, @Nullable String hostname) {
+            this(address, hostname, 0);
+        }
+
+        /** @hide */
+        public AddressInfo(@NonNull LinkAddress address, String hostname, long expirationTime) {
+            this.mAddress = address;
+            this.mHostname = hostname;
+            this.mExpirationTime = expirationTime;
+        }
+
+        private AddressInfo(Parcel in) {
+            this(in.readParcelable(null),  in.readString(), in.readLong());
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeParcelable(mAddress, flags);
+            dest.writeString(mHostname);
+            dest.writeLong(mExpirationTime);
+        }
+
+        @NonNull
+        public LinkAddress getAddress() {
+            return mAddress;
+        }
+
+        @Nullable
+        public String getHostname() {
+            return mHostname;
+        }
+
+        /** @hide TODO: use expiration time in LinkAddress */
+        public long getExpirationTime() {
+            return mExpirationTime;
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mAddress, mHostname, mExpirationTime);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object obj) {
+            if (!(obj instanceof AddressInfo)) return false;
+            final AddressInfo other = (AddressInfo) obj;
+            // Use .equals() for addresses as all changes, including address expiry changes,
+            // should be included.
+            return other.mAddress.equals(mAddress)
+                    && Objects.equals(mHostname, other.mHostname)
+                    && mExpirationTime == other.mExpirationTime;
+        }
+
+        @NonNull
+        public static final Creator<AddressInfo> CREATOR = new Creator<AddressInfo>() {
+            @NonNull
+            @Override
+            public AddressInfo createFromParcel(@NonNull Parcel in) {
+                return new AddressInfo(in);
+            }
+
+            @NonNull
+            @Override
+            public AddressInfo[] newArray(int size) {
+                return new AddressInfo[size];
+            }
+        };
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Creator<TetheredClient> CREATOR = new Creator<TetheredClient>() {
+        @NonNull
+        @Override
+        public TetheredClient createFromParcel(@NonNull Parcel in) {
+            return new TetheredClient(in);
+        }
+
+        @NonNull
+        @Override
+        public TetheredClient[] newArray(int size) {
+            return new TetheredClient[size];
+        }
+    };
+}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl
new file mode 100644
index 0000000..14ee2d3
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringCallbackStartedParcel.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.Network;
+import android.net.TetheringConfigurationParcel;
+import android.net.TetherStatesParcel;
+
+/**
+ * Initial information reported by tethering upon callback registration.
+ * @hide
+ */
+parcelable TetheringCallbackStartedParcel {
+    boolean tetheringSupported;
+    Network upstreamNetwork;
+    TetheringConfigurationParcel config;
+    TetherStatesParcel states;
+}
\ No newline at end of file
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
new file mode 100644
index 0000000..00cf98e
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.ResultReceiver;
+
+/**
+ * Collections of constants for internal tethering usage.
+ *
+ * <p>These hidden constants are not in TetheringManager as they are not part of the API stubs
+ * generated for TetheringManager, which prevents the tethering module from linking them at
+ * build time.
+ * TODO: investigate changing the tethering build rules so that Tethering can reference hidden
+ * symbols from framework-tethering even when they are in a non-hidden class.
+ * @hide
+ */
+public class TetheringConstants {
+    /**
+     * Extra used for communicating with the TetherService. Includes the type of tethering to
+     * enable if any.
+     *
+     * {@hide}
+     */
+    public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+    /**
+     * Extra used for communicating with the TetherService. Includes the type of tethering for
+     * which to cancel provisioning.
+     *
+     * {@hide}
+     */
+    public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
+    /**
+     * Extra used for communicating with the TetherService. True to schedule a recheck of tether
+     * provisioning.
+     *
+     * {@hide}
+     */
+    public static final String EXTRA_SET_ALARM = "extraSetAlarm";
+    /**
+     * Tells the TetherService to run a provision check now.
+     *
+     * {@hide}
+     */
+    public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
+    /**
+     * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
+     * which will receive provisioning results. Can be left empty.
+     *
+     * {@hide}
+     */
+    public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+}
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 11e5718..37ce1d57 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -15,9 +15,14 @@
  */
 package android.net;
 
+import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
-import android.net.ConnectivityManager.OnTetheringEventCallback;
+import android.os.Bundle;
 import android.os.ConditionVariable;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -25,6 +30,12 @@
 import android.util.ArrayMap;
 import android.util.Log;
 
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -34,7 +45,8 @@
  *
  * @hide
  */
-// TODO: make it @SystemApi
+@SystemApi
+@TestApi
 public class TetheringManager {
     private static final String TAG = TetheringManager.class.getSimpleName();
     private static final int DEFAULT_TIMEOUT_MS = 60_000;
@@ -44,7 +56,7 @@
     private final ITetheringConnector mConnector;
     private final TetheringCallbackInternal mCallback;
     private final Context mContext;
-    private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+    private final ArrayMap<TetheringEventCallback, ITetheringEventCallback>
             mTetheringEventCallbacks = new ArrayMap<>();
 
     private TetheringConfigurationParcel mTetheringConfiguration;
@@ -72,7 +84,7 @@
      * gives a String[] listing all the interfaces currently in local-only
      * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
      */
-    public static final String EXTRA_ACTIVE_LOCAL_ONLY = "localOnlyArray";
+    public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
 
     /**
      * gives a String[] listing all the interfaces currently tethered
@@ -119,33 +131,16 @@
     public static final int TETHERING_WIFI_P2P = 3;
 
     /**
-     * Extra used for communicating with the TetherService. Includes the type of tethering to
-     * enable if any.
+     * Ncm local tethering type.
+     * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
      */
-    public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
+    public static final int TETHERING_NCM = 4;
 
     /**
-     * Extra used for communicating with the TetherService. Includes the type of tethering for
-     * which to cancel provisioning.
+     * Ethernet tethering type.
+     * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
      */
-    public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
-
-    /**
-     * Extra used for communicating with the TetherService. True to schedule a recheck of tether
-     * provisioning.
-     */
-    public static final String EXTRA_SET_ALARM = "extraSetAlarm";
-
-    /**
-     * Tells the TetherService to run a provision check now.
-     */
-    public static final String EXTRA_RUN_PROVISION = "extraRunProvision";
-
-    /**
-     * Extra used for communicating with the TetherService. Contains the {@link ResultReceiver}
-     * which will receive provisioning results. Can be left empty.
-     */
-    public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
+    public static final int TETHERING_ETHERNET = 5;
 
     public static final int TETHER_ERROR_NO_ERROR           = 0;
     public static final int TETHER_ERROR_UNKNOWN_IFACE      = 1;
@@ -160,12 +155,14 @@
     public static final int TETHER_ERROR_IFACE_CFG_ERROR      = 10;
     public static final int TETHER_ERROR_PROVISION_FAILED     = 11;
     public static final int TETHER_ERROR_DHCPSERVER_ERROR     = 12;
-    public static final int TETHER_ERROR_ENTITLEMENT_UNKONWN  = 13;
+    public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13;
     public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
     public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
 
     /**
      * Create a TetheringManager object for interacting with the tethering service.
+     *
+     * {@hide}
      */
     public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
         mContext = context;
@@ -229,10 +226,9 @@
         private final ConditionVariable mWaitForCallback = new ConditionVariable();
 
         @Override
-        public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
-                TetherStatesParcel states) {
-            mTetheringConfiguration = config;
-            mTetherStatesParcel = states;
+        public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
+            mTetheringConfiguration = parcel.config;
+            mTetherStatesParcel = parcel.states;
             mWaitForCallback.open();
         }
 
@@ -275,6 +271,8 @@
      *
      * @param iface the interface name to tether.
      * @return error a {@code TETHER_ERROR} value indicating success or failure type
+     *
+     * {@hide}
      */
     @Deprecated
     public int tether(@NonNull final String iface) {
@@ -296,6 +294,8 @@
      *
      * @deprecated The only usages is PanService. It uses this for legacy reasons
      * and will migrate away as soon as possible.
+     *
+     * {@hide}
      */
     @Deprecated
     public int untether(@NonNull final String iface) {
@@ -320,6 +320,8 @@
      * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is
      * used and an entitlement check is needed, downstream USB tethering will be enabled but will
      * not have any upstream.
+     *
+     * {@hide}
      */
     @Deprecated
     public int setUsbTethering(final boolean enable) {
@@ -338,27 +340,171 @@
     }
 
     /**
+     *  Use with {@link #startTethering} to specify additional parameters when starting tethering.
+     */
+    public static class TetheringRequest {
+        /** A configuration set for TetheringRequest. */
+        private final TetheringRequestParcel mRequestParcel;
+
+        private TetheringRequest(final TetheringRequestParcel request) {
+            mRequestParcel = request;
+        }
+
+        /** Builder used to create TetheringRequest. */
+        public static class Builder {
+            private final TetheringRequestParcel mBuilderParcel;
+
+            /** Default constructor of Builder. */
+            public Builder(final int type) {
+                mBuilderParcel = new TetheringRequestParcel();
+                mBuilderParcel.tetheringType = type;
+                mBuilderParcel.localIPv4Address = null;
+                mBuilderParcel.exemptFromEntitlementCheck = false;
+                mBuilderParcel.showProvisioningUi = true;
+            }
+
+            /**
+             * Configure tethering with static IPv4 assignment (with DHCP disabled).
+             *
+             * @param localIPv4Address The preferred local IPv4 address to use.
+             */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder useStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address) {
+                mBuilderParcel.localIPv4Address = localIPv4Address;
+                return this;
+            }
+
+            /** Start tethering without entitlement checks. */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder setExemptFromEntitlementCheck(boolean exempt) {
+                mBuilderParcel.exemptFromEntitlementCheck = exempt;
+                return this;
+            }
+
+            /** Start tethering without showing the provisioning UI. */
+            @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+            @NonNull
+            public Builder setSilentProvisioning(boolean silent) {
+                mBuilderParcel.showProvisioningUi = silent;
+                return this;
+            }
+
+            /** Build {@link TetheringRequest] with the currently set configuration. */
+            @NonNull
+            public TetheringRequest build() {
+                return new TetheringRequest(mBuilderParcel);
+            }
+        }
+
+        /**
+         * Get a TetheringRequestParcel from the configuration
+         * @hide
+         */
+        public TetheringRequestParcel getParcel() {
+            return mRequestParcel;
+        }
+
+        /** String of TetheringRequest detail. */
+        public String toString() {
+            return "TetheringRequest [ type= " + mRequestParcel.tetheringType
+                    + ", localIPv4Address= " + mRequestParcel.localIPv4Address
+                    + ", exemptFromEntitlementCheck= "
+                    + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= "
+                    + mRequestParcel.showProvisioningUi + " ]";
+        }
+    }
+
+    /**
+     * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
+     */
+    public abstract static class StartTetheringCallback {
+        /**
+         * Called when tethering has been successfully started.
+         */
+        public void onTetheringStarted() {}
+
+        /**
+         * Called when starting tethering failed.
+         *
+         * @param resultCode One of the {@code TETHER_ERROR_*} constants.
+         */
+        public void onTetheringFailed(final int resultCode) {}
+    }
+
+    /**
      * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
      * fails, stopTethering will be called automatically.
      *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
+     * @param request a {@link TetheringRequest} which can specify the preferred configuration.
+     * @param executor {@link Executor} to specify the thread upon which the callback of
+     *         TetheringRequest will be invoked.
+     * @param callback A callback that will be called to indicate the success status of the
+     *                 tethering start request.
      */
-    // TODO: improve the usage of ResultReceiver, b/145096122
-    public void startTethering(final int type, @NonNull final ResultReceiver receiver,
-            final boolean showProvisioningUi) {
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
+    public void startTethering(@NonNull final TetheringRequest request,
+            @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "startTethering caller:" + callerPkg);
 
+        final IIntResultListener listener = new IIntResultListener.Stub() {
+            @Override
+            public void onResult(final int resultCode) {
+                executor.execute(() -> {
+                    if (resultCode == TETHER_ERROR_NO_ERROR) {
+                        callback.onTetheringStarted();
+                    } else {
+                        callback.onTetheringFailed(resultCode);
+                    }
+                });
+            }
+        };
         try {
-            mConnector.startTethering(type, receiver, showProvisioningUi, callerPkg);
+            mConnector.startTethering(request.getParcel(), callerPkg, listener);
         } catch (RemoteException e) {
             throw new IllegalStateException(e);
         }
     }
 
     /**
+     * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
+     * fails, stopTethering will be called automatically.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
+     * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants.
+     * @param executor {@link Executor} to specify the thread upon which the callback of
+     *         TetheringRequest will be invoked.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
+    public void startTethering(int type, @NonNull final Executor executor,
+            @NonNull final StartTetheringCallback callback) {
+        startTethering(new TetheringRequest.Builder(type).build(), executor, callback);
+    }
+
+    /**
      * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
      * applicable.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
     public void stopTethering(final int type) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "stopTethering caller:" + callerPkg);
@@ -375,11 +521,69 @@
     }
 
     /**
+     * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
+     * entitlement succeeded.
+     */
+    public interface OnTetheringEntitlementResultListener  {
+        /**
+         * Called to notify entitlement result.
+         *
+         * @param resultCode an int value of entitlement result. It may be one of
+         *         {@link #TETHER_ERROR_NO_ERROR},
+         *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
+         *         {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
+         */
+        void onTetheringEntitlementResult(int resultCode);
+    }
+
+    /**
      * Request the latest value of the tethering entitlement check.
      *
-     * Note: Allow privileged apps who have TETHER_PRIVILEGED permission to access. If it turns
-     * out some such apps are observed to abuse this API, change to per-UID limits on this API
-     * if it's really needed.
+     * <p>This method will only return the latest entitlement result if it is available. If no
+     * cached entitlement result is available, and {@code showEntitlementUi} is false,
+     * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
+     * true, entitlement will be run.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
+     *
+     * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
+     * @param showEntitlementUi a boolean indicating whether to run UI-based entitlement check.
+     * @param executor the executor on which callback will be invoked.
+     * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
+     *         notify the caller of the result of entitlement check. The listener may be called zero
+     *         or one time.
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
+    public void requestLatestTetheringEntitlementResult(int type, boolean showEntitlementUi,
+            @NonNull Executor executor,
+            @NonNull final OnTetheringEntitlementResultListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException(
+                    "OnTetheringEntitlementResultListener cannot be null.");
+        }
+
+        ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) {
+            @Override
+            protected void onReceiveResult(int resultCode, Bundle resultData) {
+                executor.execute(() -> {
+                    listener.onTetheringEntitlementResult(resultCode);
+                });
+            }
+        };
+
+        requestLatestTetheringEntitlementResult(type, wrappedListener,
+                    showEntitlementUi);
+    }
+
+    /**
+     * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible
+     * with ConnectivityManager#getLatestTetheringEntitlementResult
+     *
+     * {@hide}
      */
     // TODO: improve the usage of ResultReceiver, b/145096122
     public void requestLatestTetheringEntitlementResult(final int type,
@@ -396,25 +600,161 @@
     }
 
     /**
+     * Callback for use with {@link registerTetheringEventCallback} to find out tethering
+     * upstream status.
+     */
+    public abstract static class TetheringEventCallback {
+        /**
+         * Called when tethering supported status changed.
+         *
+         * <p>This will be called immediately after the callback is registered, and may be called
+         * multiple times later upon changes.
+         *
+         * <p>Tethering may be disabled via system properties, device configuration, or device
+         * policy restrictions.
+         *
+         * @param supported The new supported status
+         */
+        public void onTetheringSupported(boolean supported) {}
+
+        /**
+         * Called when tethering upstream changed.
+         *
+         * <p>This will be called immediately after the callback is registered, and may be called
+         * multiple times later upon changes.
+         *
+         * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
+         * have any upstream.
+         */
+        public void onUpstreamChanged(@Nullable Network network) {}
+
+        /**
+         * Called when there was a change in tethering interface regular expressions.
+         *
+         * <p>This will be called immediately after the callback is registered, and may be called
+         * multiple times later upon changes.
+         * @param reg The new regular expressions.
+         * @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
+         */
+        @Deprecated
+        public void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
+
+        /**
+         * Called when there was a change in the list of tetherable interfaces.
+         *
+         * <p>This will be called immediately after the callback is registered, and may be called
+         * multiple times later upon changes.
+         * @param interfaces The list of tetherable interfaces.
+         */
+        public void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
+
+        /**
+         * Called when there was a change in the list of tethered interfaces.
+         *
+         * <p>This will be called immediately after the callback is registered, and may be called
+         * multiple times later upon changes.
+         * @param interfaces The list of tethered interfaces.
+         */
+        public void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
+
+        /**
+         * Called when an error occurred configuring tethering.
+         *
+         * <p>This will be called immediately after the callback is registered if the latest status
+         * on the interface is an error, and may be called multiple times later upon changes.
+         * @param ifName Name of the interface.
+         * @param error One of {@code TetheringManager#TETHER_ERROR_*}.
+         */
+        public void onError(@NonNull String ifName, int error) {}
+
+        /**
+         * Called when the list of tethered clients changes.
+         *
+         * <p>This callback provides best-effort information on connected clients based on state
+         * known to the system, however the list cannot be completely accurate (and should not be
+         * used for security purposes). For example, clients behind a bridge and using static IP
+         * assignments are not visible to the tethering device; or even when using DHCP, such
+         * clients may still be reported by this callback after disconnection as the system cannot
+         * determine if they are still connected.
+         * @param clients The new set of tethered clients; the collection is not ordered.
+         */
+        public void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
+    }
+
+    /**
+     * Regular expressions used to identify tethering interfaces.
+     * @deprecated Referencing interfaces by regular expressions is a deprecated mechanism.
+     */
+    @Deprecated
+    public static class TetheringInterfaceRegexps {
+        private final String[] mTetherableBluetoothRegexs;
+        private final String[] mTetherableUsbRegexs;
+        private final String[] mTetherableWifiRegexs;
+
+        public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs,
+                @NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) {
+            mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone();
+            mTetherableUsbRegexs = tetherableUsbRegexs.clone();
+            mTetherableWifiRegexs = tetherableWifiRegexs.clone();
+        }
+
+        @NonNull
+        public List<String> getTetherableBluetoothRegexs() {
+            return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs));
+        }
+
+        @NonNull
+        public List<String> getTetherableUsbRegexs() {
+            return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs));
+        }
+
+        @NonNull
+        public List<String> getTetherableWifiRegexs() {
+            return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs));
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs,
+                    mTetherableWifiRegexs);
+        }
+
+        @Override
+        public boolean equals(@Nullable Object obj) {
+            if (!(obj instanceof TetheringInterfaceRegexps)) return false;
+            final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj;
+            return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs)
+                    && Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs)
+                    && Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs);
+        }
+    }
+
+    /**
      * Start listening to tethering change events. Any new added callback will receive the last
      * tethering status right away. If callback is registered,
-     * {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
+     * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
      * has no upstream or disabled, the argument of callback will be null. The same callback object
      * cannot be registered twice.
      *
      * @param executor the executor on which callback will be invoked.
      * @param callback the callback to be called when tethering has change events.
      */
+    @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
     public void registerTetheringEventCallback(@NonNull Executor executor,
-            @NonNull OnTetheringEventCallback callback) {
+            @NonNull TetheringEventCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
 
         synchronized (mTetheringEventCallbacks) {
-            if (!mTetheringEventCallbacks.containsKey(callback)) {
+            if (mTetheringEventCallbacks.containsKey(callback)) {
                 throw new IllegalArgumentException("callback was already registered.");
             }
             final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+                // Only accessed with a lock on this object
+                private final HashMap<String, Integer> mErrorStates = new HashMap<>();
+                private String[] mLastTetherableInterfaces = null;
+                private String[] mLastTetheredInterfaces = null;
+
                 @Override
                 public void onUpstreamChanged(Network network) throws RemoteException {
                     executor.execute(() -> {
@@ -422,11 +762,45 @@
                     });
                 }
 
+                private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) {
+                    for (int i = 0; i < newStates.erroredIfaceList.length; i++) {
+                        final String iface = newStates.erroredIfaceList[i];
+                        final Integer lastError = mErrorStates.get(iface);
+                        final int newError = newStates.lastErrorList[i];
+                        if (newError != TETHER_ERROR_NO_ERROR
+                                && !Objects.equals(lastError, newError)) {
+                            callback.onError(iface, newError);
+                        }
+                        mErrorStates.put(iface, newError);
+                    }
+                }
+
+                private synchronized void maybeSendTetherableIfacesChangedCallback(
+                        final TetherStatesParcel newStates) {
+                    if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return;
+                    mLastTetherableInterfaces = newStates.availableList.clone();
+                    callback.onTetherableInterfacesChanged(
+                            Collections.unmodifiableList(Arrays.asList(mLastTetherableInterfaces)));
+                }
+
+                private synchronized void maybeSendTetheredIfacesChangedCallback(
+                        final TetherStatesParcel newStates) {
+                    if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return;
+                    mLastTetheredInterfaces = newStates.tetheredList.clone();
+                    callback.onTetheredInterfacesChanged(
+                            Collections.unmodifiableList(Arrays.asList(mLastTetheredInterfaces)));
+                }
+
+                // Called immediately after the callbacks are registered.
                 @Override
-                public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
-                        TetherStatesParcel states) {
+                public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
                     executor.execute(() -> {
-                        callback.onUpstreamChanged(network);
+                        callback.onTetheringSupported(parcel.tetheringSupported);
+                        callback.onUpstreamChanged(parcel.upstreamNetwork);
+                        sendErrorCallbacks(parcel.states);
+                        sendRegexpsChanged(parcel.config);
+                        maybeSendTetherableIfacesChangedCallback(parcel.states);
+                        maybeSendTetheredIfacesChangedCallback(parcel.states);
                     });
                 }
 
@@ -437,11 +811,26 @@
                     });
                 }
 
-                @Override
-                public void onConfigurationChanged(TetheringConfigurationParcel config) { }
+                private void sendRegexpsChanged(TetheringConfigurationParcel parcel) {
+                    callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps(
+                            parcel.tetherableBluetoothRegexs,
+                            parcel.tetherableUsbRegexs,
+                            parcel.tetherableWifiRegexs));
+                }
 
                 @Override
-                public void onTetherStatesChanged(TetherStatesParcel states) { }
+                public void onConfigurationChanged(TetheringConfigurationParcel config) {
+                    executor.execute(() -> sendRegexpsChanged(config));
+                }
+
+                @Override
+                public void onTetherStatesChanged(TetherStatesParcel states) {
+                    executor.execute(() -> {
+                        sendErrorCallbacks(states);
+                        maybeSendTetherableIfacesChangedCallback(states);
+                        maybeSendTetheredIfacesChangedCallback(states);
+                    });
+                }
             };
             try {
                 mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
@@ -458,7 +847,11 @@
      *
      * @param callback previously registered callback.
      */
-    public void unregisterTetheringEventCallback(@NonNull final OnTetheringEventCallback callback) {
+    @RequiresPermission(anyOf = {
+            Manifest.permission.TETHER_PRIVILEGED,
+            Manifest.permission.ACCESS_NETWORK_STATE
+    })
+    public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
 
@@ -482,6 +875,7 @@
      * @param iface The name of the interface of interest
      * @return error The error code of the last error tethering or untethering the named
      *               interface
+     * @hide
      */
     public int getLastTetherError(@NonNull final String iface) {
         mCallback.waitForStarted();
@@ -503,6 +897,7 @@
      *
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable usb interfaces.
+     * @hide
      */
     public @NonNull String[] getTetherableUsbRegexs() {
         mCallback.waitForStarted();
@@ -516,6 +911,7 @@
      *
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable wifi interfaces.
+     * @hide
      */
     public @NonNull String[] getTetherableWifiRegexs() {
         mCallback.waitForStarted();
@@ -529,6 +925,7 @@
      *
      * @return an array of 0 or more regular expression Strings defining
      *        what interfaces are considered tetherable bluetooth interfaces.
+     * @hide
      */
     public @NonNull String[] getTetherableBluetoothRegexs() {
         mCallback.waitForStarted();
@@ -540,6 +937,7 @@
      * device configuration and current interface existence.
      *
      * @return an array of 0 or more Strings of tetherable interface names.
+     * @hide
      */
     public @NonNull String[] getTetherableIfaces() {
         mCallback.waitForStarted();
@@ -552,6 +950,7 @@
      * Get the set of tethered interfaces.
      *
      * @return an array of 0 or more String of currently tethered interface names.
+     * @hide
      */
     public @NonNull String[] getTetheredIfaces() {
         mCallback.waitForStarted();
@@ -570,6 +969,7 @@
      *
      * @return an array of 0 or more String indicating the interface names
      *        which failed to tether.
+     * @hide
      */
     public @NonNull String[] getTetheringErroredIfaces() {
         mCallback.waitForStarted();
@@ -582,6 +982,7 @@
      * Get the set of tethered dhcp ranges.
      *
      * @deprecated This API just return the default value which is not used in DhcpServer.
+     * @hide
      */
     @Deprecated
     public @NonNull String[] getTetheredDhcpRanges() {
@@ -595,6 +996,7 @@
      * due to device configuration.
      *
      * @return a boolean - {@code true} indicating Tethering is supported.
+     * @hide
      */
     public boolean isTetheringSupported() {
         final String callerPkg = mContext.getOpPackageName();
@@ -613,7 +1015,14 @@
 
     /**
      * Stop all active tethering.
+     *
+     * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will
+     * fail if a tethering entitlement check is required.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.TETHER_PRIVILEGED,
+            android.Manifest.permission.WRITE_SETTINGS
+    })
     public void stopAllTethering() {
         final String callerPkg = mContext.getOpPackageName();
         Log.i(TAG, "stopAllTethering caller:" + callerPkg);
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
new file mode 100644
index 0000000..bf19d85
--- /dev/null
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringRequestParcel.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.LinkAddress;
+
+/**
+ * Configuration details for requesting tethering.
+ * @hide
+ */
+parcelable TetheringRequestParcel {
+    int tetheringType;
+    LinkAddress localIPv4Address;
+    boolean exemptFromEntitlementCheck;
+    boolean showProvisioningUi;
+}
diff --git a/packages/Tethering/res/values/config.xml b/packages/Tethering/res/values/config.xml
index 6fa1f77..379cd18 100644
--- a/packages/Tethering/res/values/config.xml
+++ b/packages/Tethering/res/values/config.xml
@@ -29,6 +29,12 @@
     </string-array>
 
     <!-- List of regexpressions describing the interface (if any) that represent tetherable
+         NCM interfaces.  If the device doesn't want to support tethering over NCM this should
+         be empty. -->
+    <string-array translatable="false" name="config_tether_ncm_regexs">
+    </string-array>
+
+    <!-- List of regexpressions describing the interface (if any) that represent tetherable
          Wifi interfaces.  If the device doesn't want to support tethering over Wifi this
          should be empty.  An example would be "softap.*" -->
     <string-array translatable="false" name="config_tether_wifi_regexs">
diff --git a/packages/Tethering/res/values/overlayable.xml b/packages/Tethering/res/values/overlayable.xml
index e089d9d..fe025c7 100644
--- a/packages/Tethering/res/values/overlayable.xml
+++ b/packages/Tethering/res/values/overlayable.xml
@@ -17,6 +17,7 @@
     <overlayable name="TetheringConfig">
         <policy type="product|system|vendor">
             <item type="array" name="config_tether_usb_regexs"/>
+            <item type="array" name="config_tether_ncm_regexs" />
             <item type="array" name="config_tether_wifi_regexs"/>
             <item type="array" name="config_tether_wifi_p2p_regexs"/>
             <item type="array" name="config_tether_bluetooth_regexs"/>
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index 0491ad7..190d2509 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -93,6 +93,8 @@
     private static final int WIFI_HOST_IFACE_PREFIX_LENGTH = 24;
     private static final String WIFI_P2P_IFACE_ADDR = "192.168.49.1";
     private static final int WIFI_P2P_IFACE_PREFIX_LENGTH = 24;
+    private static final String ETHERNET_IFACE_ADDR = "192.168.50.1";
+    private static final int ETHERNET_IFACE_PREFIX_LENGTH = 24;
 
     // TODO: have PanService use some visible version of this constant
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.44.1";
@@ -416,7 +418,8 @@
         final Inet4Address srvAddr;
         int prefixLen = 0;
         try {
-            if (mInterfaceType == TetheringManager.TETHERING_USB) {
+            if (mInterfaceType == TetheringManager.TETHERING_USB
+                    || mInterfaceType == TetheringManager.TETHERING_NCM) {
                 srvAddr = (Inet4Address) parseNumericAddress(USB_NEAR_IFACE_ADDR);
                 prefixLen = USB_PREFIX_LENGTH;
             } else if (mInterfaceType == TetheringManager.TETHERING_WIFI) {
@@ -425,6 +428,10 @@
             } else if (mInterfaceType == TetheringManager.TETHERING_WIFI_P2P) {
                 srvAddr = (Inet4Address) parseNumericAddress(WIFI_P2P_IFACE_ADDR);
                 prefixLen = WIFI_P2P_IFACE_PREFIX_LENGTH;
+            } else if (mInterfaceType == TetheringManager.TETHERING_ETHERNET) {
+                // TODO: randomize address for tethering too, similarly to wifi
+                srvAddr = (Inet4Address) parseNumericAddress(ETHERNET_IFACE_ADDR);
+                prefixLen = ETHERNET_IFACE_PREFIX_LENGTH;
             } else {
                 // BT configures the interface elsewhere: only start DHCP.
                 // TODO: make all tethering types behave the same way, and delete the bluetooth
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
index 1cabc8d..e81d6ac 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/EntitlementManager.java
@@ -16,14 +16,14 @@
 
 package com.android.server.connectivity.tethering;
 
-import static android.net.TetheringManager.EXTRA_ADD_TETHER_TYPE;
-import static android.net.TetheringManager.EXTRA_PROVISION_CALLBACK;
-import static android.net.TetheringManager.EXTRA_RUN_PROVISION;
+import static android.net.TetheringConstants.EXTRA_ADD_TETHER_TYPE;
+import static android.net.TetheringConstants.EXTRA_PROVISION_CALLBACK;
+import static android.net.TetheringConstants.EXTRA_RUN_PROVISION;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
 import static android.net.TetheringManager.TETHERING_INVALID;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
 import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
 
@@ -577,7 +577,7 @@
 
     private static String errorString(int value) {
         switch (value) {
-            case TETHER_ERROR_ENTITLEMENT_UNKONWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN";
+            case TETHER_ERROR_ENTITLEMENT_UNKNOWN: return "TETHER_ERROR_ENTITLEMENT_UNKONWN";
             case TETHER_ERROR_NO_ERROR: return "TETHER_ERROR_NO_ERROR";
             case TETHER_ERROR_PROVISION_FAILED: return "TETHER_ERROR_PROVISION_FAILED";
             default:
@@ -657,7 +657,7 @@
         }
 
         final int cacheValue = mEntitlementCacheValue.get(
-                downstream, TETHER_ERROR_ENTITLEMENT_UNKONWN);
+                downstream, TETHER_ERROR_ENTITLEMENT_UNKNOWN);
         if (cacheValue == TETHER_ERROR_NO_ERROR || !showEntitlementUi) {
             receiver.send(cacheValue, null);
         } else {
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 5bf41ce..5b35bb6 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
@@ -29,7 +30,9 @@
 import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
 import static android.net.TetheringManager.EXTRA_ERRORED_TETHER;
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
+import static android.net.TetheringManager.TETHERING_ETHERNET;
 import static android.net.TetheringManager.TETHERING_INVALID;
+import static android.net.TetheringManager.TETHERING_NCM;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHERING_WIFI_P2P;
@@ -66,6 +69,8 @@
 import android.content.res.Resources;
 import android.hardware.usb.UsbManager;
 import android.net.ConnectivityManager;
+import android.net.EthernetManager;
+import android.net.IIntResultListener;
 import android.net.INetd;
 import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
@@ -74,7 +79,9 @@
 import android.net.Network;
 import android.net.NetworkInfo;
 import android.net.TetherStatesParcel;
+import android.net.TetheringCallbackStartedParcel;
 import android.net.TetheringConfigurationParcel;
+import android.net.TetheringRequestParcel;
 import android.net.ip.IpServer;
 import android.net.shared.NetdUtils;
 import android.net.util.BaseNetdUnsolicitedEventListener;
@@ -107,6 +114,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.MessageUtils;
@@ -209,6 +217,13 @@
     private boolean mDataSaverEnabled = false;
     private String mWifiP2pTetherInterface = null;
 
+    @GuardedBy("mPublicSync")
+    private EthernetManager.TetheredInterfaceRequest mEthernetIfaceRequest;
+    @GuardedBy("mPublicSync")
+    private String mConfiguredEthernetIface;
+    @GuardedBy("mPublicSync")
+    private EthernetCallback mEthernetCallback;
+
     public Tethering(TetheringDependencies deps) {
         mLog.mark("Tethering.constructed");
         mDeps = deps;
@@ -405,6 +420,8 @@
             return TETHERING_USB;
         } else if (cfg.isBluetooth(iface)) {
             return TETHERING_BLUETOOTH;
+        } else if (cfg.isNcm(iface)) {
+            return TETHERING_NCM;
         }
         return TETHERING_INVALID;
     }
@@ -423,9 +440,10 @@
         }
     }
 
-    void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
-        mEntitlementMgr.startProvisioningIfNeeded(type, showProvisioningUi);
-        enableTetheringInternal(type, true /* enabled */, receiver);
+    void startTethering(final TetheringRequestParcel request, final IIntResultListener listener) {
+        mEntitlementMgr.startProvisioningIfNeeded(request.tetheringType,
+                request.showProvisioningUi);
+        enableTetheringInternal(request.tetheringType, true /* enabled */, listener);
     }
 
     void stopTethering(int type) {
@@ -437,29 +455,40 @@
      * Enables or disables tethering for the given type. If provisioning is required, it will
      * schedule provisioning rechecks for the specified interface.
      */
-    private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
+    private void enableTetheringInternal(int type, boolean enable,
+            final IIntResultListener listener) {
         int result;
         switch (type) {
             case TETHERING_WIFI:
                 result = setWifiTethering(enable);
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 break;
             case TETHERING_USB:
                 result = setUsbTethering(enable);
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 break;
             case TETHERING_BLUETOOTH:
-                setBluetoothTethering(enable, receiver);
+                setBluetoothTethering(enable, listener);
+                break;
+            case TETHERING_NCM:
+                result = setNcmTethering(enable);
+                sendTetherResult(listener, result);
+                break;
+            case TETHERING_ETHERNET:
+                result = setEthernetTethering(enable);
+                sendTetherResult(listener, result);
                 break;
             default:
                 Log.w(TAG, "Invalid tether type.");
-                sendTetherResult(receiver, TETHER_ERROR_UNKNOWN_IFACE);
+                sendTetherResult(listener, TETHER_ERROR_UNKNOWN_IFACE);
         }
     }
 
-    private void sendTetherResult(ResultReceiver receiver, int result) {
-        if (receiver != null) {
-            receiver.send(result, null);
+    private void sendTetherResult(final IIntResultListener listener, int result) {
+        if (listener != null) {
+            try {
+                listener.onResult(result);
+            } catch (RemoteException e) { }
         }
     }
 
@@ -485,12 +514,12 @@
         return TETHER_ERROR_MASTER_ERROR;
     }
 
-    private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
+    private void setBluetoothTethering(final boolean enable, final IIntResultListener listener) {
         final BluetoothAdapter adapter = mDeps.getBluetoothAdapter();
         if (adapter == null || !adapter.isEnabled()) {
             Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: "
                     + (adapter == null));
-            sendTetherResult(receiver, TETHER_ERROR_SERVICE_UNAVAIL);
+            sendTetherResult(listener, TETHER_ERROR_SERVICE_UNAVAIL);
             return;
         }
 
@@ -519,12 +548,63 @@
                 final int result = (((BluetoothPan) proxy).isTetheringOn() == enable)
                         ? TETHER_ERROR_NO_ERROR
                         : TETHER_ERROR_MASTER_ERROR;
-                sendTetherResult(receiver, result);
+                sendTetherResult(listener, result);
                 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
             }
         }, BluetoothProfile.PAN);
     }
 
+    private int setEthernetTethering(final boolean enable) {
+        final EthernetManager em = (EthernetManager) mContext.getSystemService(
+                Context.ETHERNET_SERVICE);
+        synchronized (mPublicSync) {
+            if (enable) {
+                mEthernetCallback = new EthernetCallback();
+                mEthernetIfaceRequest = em.requestTetheredInterface(mEthernetCallback);
+            } else {
+                if (mConfiguredEthernetIface != null) {
+                    stopEthernetTetheringLocked();
+                    mEthernetIfaceRequest.release();
+                }
+                mEthernetCallback = null;
+            }
+        }
+        return TETHER_ERROR_NO_ERROR;
+    }
+
+    private void stopEthernetTetheringLocked() {
+        if (mConfiguredEthernetIface == null) return;
+        changeInterfaceState(mConfiguredEthernetIface, IpServer.STATE_AVAILABLE);
+        stopTrackingInterfaceLocked(mConfiguredEthernetIface);
+        mConfiguredEthernetIface = null;
+    }
+
+    private class EthernetCallback implements EthernetManager.TetheredInterfaceCallback {
+        @Override
+        public void onAvailable(String iface) {
+            synchronized (mPublicSync) {
+                if (this != mEthernetCallback) {
+                    // Ethernet callback arrived after Ethernet tethering stopped. Ignore.
+                    return;
+                }
+                maybeTrackNewInterfaceLocked(iface, TETHERING_ETHERNET);
+                changeInterfaceState(iface, IpServer.STATE_TETHERED);
+                mConfiguredEthernetIface = iface;
+            }
+        }
+
+        @Override
+        public void onUnavailable() {
+            synchronized (mPublicSync) {
+                if (this != mEthernetCallback) {
+                    // onAvailable called after stopping Ethernet tethering.
+                    return;
+                }
+                stopEthernetTetheringLocked();
+            }
+        }
+    }
+
     int tether(String iface) {
         return tether(iface, IpServer.STATE_TETHERED);
     }
@@ -575,6 +655,7 @@
         stopTethering(TETHERING_WIFI_P2P);
         stopTethering(TETHERING_USB);
         stopTethering(TETHERING_BLUETOOTH);
+        stopTethering(TETHERING_ETHERNET);
     }
 
     int getLastTetherError(String iface) {
@@ -798,6 +879,7 @@
             final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
             final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
             final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+            final boolean ncmEnabled = intent.getBooleanExtra(USB_FUNCTION_NCM, false);
 
             mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
                     usbConnected, usbConfigured, rndisEnabled));
@@ -825,6 +907,8 @@
                 } else if (usbConfigured && rndisEnabled) {
                     // Tether if rndis is enabled and usb is configured.
                     tetherMatchingInterfaces(IpServer.STATE_TETHERED, TETHERING_USB);
+                } else if (usbConnected && ncmEnabled) {
+                    tetherMatchingInterfaces(IpServer.STATE_LOCAL_ONLY, TETHERING_NCM);
                 }
                 mRndisEnabled = usbConfigured && rndisEnabled;
             }
@@ -951,6 +1035,7 @@
                 mWrapper.showTetheredNotification(
                         R.drawable.stat_sys_tether_general, false);
                 mWrapper.untetherAll();
+                // TODO(b/148139325): send tetheringSupported on restriction change
             }
         }
     }
@@ -1125,6 +1210,16 @@
         return TETHER_ERROR_NO_ERROR;
     }
 
+    private int setNcmTethering(boolean enable) {
+        if (VDBG) Log.d(TAG, "setNcmTethering(" + enable + ")");
+        UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
+        synchronized (mPublicSync) {
+            usbManager.setCurrentFunctions(enable ? UsbManager.FUNCTION_NCM
+                    : UsbManager.FUNCTION_NONE);
+        }
+        return TETHER_ERROR_NO_ERROR;
+    }
+
     // TODO review API - figure out how to delete these entirely.
     String[] getTetheredIfaces() {
         ArrayList<String> list = new ArrayList<String>();
@@ -1844,9 +1939,13 @@
     void registerTetheringEventCallback(ITetheringEventCallback callback) {
         mHandler.post(() -> {
             mTetheringEventCallbacks.register(callback);
+            final TetheringCallbackStartedParcel parcel = new TetheringCallbackStartedParcel();
+            parcel.tetheringSupported = mDeps.isTetheringSupported();
+            parcel.upstreamNetwork = mTetherUpstream;
+            parcel.config = mConfig.toStableParcelable();
+            parcel.states = mTetherStatesParcel;
             try {
-                callback.onCallbackStarted(mTetherUpstream, mConfig.toStableParcelable(),
-                        mTetherStatesParcel);
+                callback.onCallbackStarted(parcel);
             } catch (RemoteException e) {
                 // Not really very much to do here.
             }
@@ -1881,6 +1980,7 @@
             for (int i = 0; i < length; i++) {
                 try {
                     mTetheringEventCallbacks.getBroadcastItem(i).onConfigurationChanged(config);
+                    // TODO(b/148139325): send tetheringSupported on configuration change
                 } catch (RemoteException e) {
                     // Not really very much to do here.
                 }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 068c346..7e9e26f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -83,6 +83,7 @@
     public final String[] tetherableWifiRegexs;
     public final String[] tetherableWifiP2pRegexs;
     public final String[] tetherableBluetoothRegexs;
+    public final String[] tetherableNcmRegexs;
     public final boolean isDunRequired;
     public final boolean chooseUpstreamAutomatically;
     public final Collection<Integer> preferredUpstreamIfaceTypes;
@@ -103,6 +104,7 @@
         Resources res = getResources(ctx, activeDataSubId);
 
         tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs);
+        tetherableNcmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs);
         // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
         // us an interface name. Careful consideration needs to be given to
         // implications for Settings and for provisioning checks.
@@ -156,6 +158,11 @@
         return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
     }
 
+    /** Check if interface is ncm */
+    public boolean isNcm(String iface) {
+        return matchesDownstreamRegexs(iface, tetherableNcmRegexs);
+    }
+
     /** Check whether no ui entitlement application is available.*/
     public boolean hasMobileHotspotProvisionApp() {
         return !TextUtils.isEmpty(provisioningAppNoUi);
@@ -170,6 +177,7 @@
         dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
         dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs);
         dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
+        dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs);
 
         pw.print("isDunRequired: ");
         pw.println(isDunRequired);
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
index cb7d392..7dc5c5f 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/TetheringService.java
@@ -33,6 +33,7 @@
 import android.net.ITetheringEventCallback;
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
+import android.net.TetheringRequestParcel;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.ip.IpServer;
@@ -143,11 +144,11 @@
         }
 
         @Override
-        public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi,
-                String callerPkg) {
-            if (checkAndNotifyCommonError(callerPkg, receiver)) return;
+        public void startTethering(TetheringRequestParcel request, String callerPkg,
+                IIntResultListener listener) {
+            if (checkAndNotifyCommonError(callerPkg, listener)) return;
 
-            mTethering.startTethering(type, receiver, showProvisioningUi);
+            mTethering.startTethering(request, listener);
         }
 
         @Override
diff --git a/packages/Tethering/tests/unit/Android.bp b/packages/Tethering/tests/unit/Android.bp
index 53782fed..13174c5 100644
--- a/packages/Tethering/tests/unit/Android.bp
+++ b/packages/Tethering/tests/unit/Android.bp
@@ -19,6 +19,7 @@
     certificate: "platform",
     srcs: [
         "src/**/*.java",
+        "src/**/*.kt",
     ],
     test_suites: [
         "device-tests",
diff --git a/packages/Tethering/tests/unit/AndroidManifest.xml b/packages/Tethering/tests/unit/AndroidManifest.xml
index 0a1cdd3..530bc07 100644
--- a/packages/Tethering/tests/unit/AndroidManifest.xml
+++ b/packages/Tethering/tests/unit/AndroidManifest.xml
@@ -16,6 +16,8 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack.tethering.tests.unit">
 
+    <uses-permission android:name="android.permission.TETHER_PRIVILEGED"/>
+
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
     </application>
diff --git a/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
new file mode 100644
index 0000000..83c19ec
--- /dev/null
+++ b/packages/Tethering/tests/unit/src/android/net/TetheredClientTest.kt
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net
+
+import android.net.InetAddresses.parseNumericAddress
+import android.net.TetheredClient.AddressInfo
+import android.net.TetheringManager.TETHERING_BLUETOOTH
+import android.net.TetheringManager.TETHERING_USB
+import androidx.test.filters.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.testutils.assertParcelSane
+import org.junit.Test
+import org.junit.runner.RunWith
+import kotlin.test.assertEquals
+import kotlin.test.assertNotEquals
+
+private val TEST_MACADDR = MacAddress.fromBytes(byteArrayOf(12, 23, 34, 45, 56, 67))
+private val TEST_OTHER_MACADDR = MacAddress.fromBytes(byteArrayOf(23, 34, 45, 56, 67, 78))
+private val TEST_ADDR1 = LinkAddress(parseNumericAddress("192.168.113.3"), 24)
+private val TEST_ADDR2 = LinkAddress(parseNumericAddress("fe80::1:2:3"), 64)
+private val TEST_ADDRINFO1 = AddressInfo(TEST_ADDR1, "test_hostname")
+private val TEST_ADDRINFO2 = AddressInfo(TEST_ADDR2, null)
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class TetheredClientTest {
+    @Test
+    fun testParceling() {
+        assertParcelSane(makeTestClient(), fieldCount = 3)
+    }
+
+    @Test
+    fun testEquals() {
+        assertEquals(makeTestClient(), makeTestClient())
+
+        // Different mac address
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_OTHER_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Different hostname
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(AddressInfo(TEST_ADDR1, "test_other_hostname"), TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Null hostname
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(AddressInfo(TEST_ADDR1, null), TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Missing address
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+
+        // Different type
+        assertNotEquals(makeTestClient(), TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_BLUETOOTH))
+    }
+
+    @Test
+    fun testAddAddresses() {
+        val client1 = TetheredClient(TEST_MACADDR, listOf(TEST_ADDRINFO1), TETHERING_USB)
+        val client2 = TetheredClient(TEST_OTHER_MACADDR, listOf(TEST_ADDRINFO2), TETHERING_USB)
+        assertEquals(TetheredClient(
+                TEST_MACADDR,
+                listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+                TETHERING_USB), client1.addAddresses(client2))
+    }
+
+    private fun makeTestClient() = TetheredClient(
+            TEST_MACADDR,
+            listOf(TEST_ADDRINFO1, TEST_ADDRINFO2),
+            TETHERING_BLUETOOTH)
+}
\ No newline at end of file
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
index 4f07461..3a1d4a6 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/EntitlementManagerTest.java
@@ -19,7 +19,7 @@
 import static android.net.TetheringManager.TETHERING_BLUETOOTH;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
-import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKONWN;
+import static android.net.TetheringManager.TETHER_ERROR_ENTITLEMENT_UNKNOWN;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
 import static android.net.TetheringManager.TETHER_ERROR_PROVISION_FAILED;
 import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
@@ -110,7 +110,7 @@
     }
 
     public class WrappedEntitlementManager extends EntitlementManager {
-        public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
+        public int fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
         public int uiProvisionCount = 0;
         public int silentProvisionCount = 0;
 
@@ -120,7 +120,7 @@
         }
 
         public void reset() {
-            fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKONWN;
+            fakeEntitlementResult = TETHER_ERROR_ENTITLEMENT_UNKNOWN;
             uiProvisionCount = 0;
             silentProvisionCount = 0;
         }
@@ -274,7 +274,7 @@
         receiver = new ResultReceiver(null) {
             @Override
             protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
+                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
                 mCallbacklatch.countDown();
             }
         };
@@ -343,7 +343,7 @@
         receiver = new ResultReceiver(null) {
             @Override
             protected void onReceiveResult(int resultCode, Bundle resultData) {
-                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKONWN, resultCode);
+                assertEquals(TETHER_ERROR_ENTITLEMENT_UNKNOWN, resultCode);
                 mCallbacklatch.countDown();
             }
         };
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index affd691..e7c3e55 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -18,6 +18,7 @@
 
 import static android.hardware.usb.UsbManager.USB_CONFIGURED;
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_NCM;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
 import static android.net.ConnectivityManager.ACTION_RESTRICT_BACKGROUND_CHANGED;
 import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED;
@@ -27,6 +28,7 @@
 import static android.net.TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY;
 import static android.net.TetheringManager.EXTRA_ACTIVE_TETHER;
 import static android.net.TetheringManager.EXTRA_AVAILABLE_TETHER;
+import static android.net.TetheringManager.TETHERING_NCM;
 import static android.net.TetheringManager.TETHERING_USB;
 import static android.net.TetheringManager.TETHERING_WIFI;
 import static android.net.TetheringManager.TETHER_ERROR_NO_ERROR;
@@ -86,7 +88,9 @@
 import android.net.NetworkRequest;
 import android.net.RouteInfo;
 import android.net.TetherStatesParcel;
+import android.net.TetheringCallbackStartedParcel;
 import android.net.TetheringConfigurationParcel;
+import android.net.TetheringRequestParcel;
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServer;
@@ -149,6 +153,7 @@
     private static final String TEST_USB_IFNAME = "test_rndis0";
     private static final String TEST_WLAN_IFNAME = "test_wlan0";
     private static final String TEST_P2P_IFNAME = "test_p2p-p2p0-0";
+    private static final String TEST_NCM_IFNAME = "test_ncm0";
     private static final String TETHERING_NAME = "Tethering";
 
     private static final int DHCPSERVER_START_TIMEOUT_MS = 1000;
@@ -250,9 +255,11 @@
                     ifName.equals(TEST_USB_IFNAME)
                             || ifName.equals(TEST_WLAN_IFNAME)
                             || ifName.equals(TEST_MOBILE_IFNAME)
-                            || ifName.equals(TEST_P2P_IFNAME));
+                            || ifName.equals(TEST_P2P_IFNAME)
+                            || ifName.equals(TEST_NCM_IFNAME));
             final String[] ifaces = new String[] {
-                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME};
+                    TEST_USB_IFNAME, TEST_WLAN_IFNAME, TEST_MOBILE_IFNAME, TEST_P2P_IFNAME,
+                    TEST_NCM_IFNAME};
             return new InterfaceParams(ifName, ArrayUtils.indexOf(ifaces, ifName) + IFINDEX_OFFSET,
                     MacAddress.ALL_ZEROS_ADDRESS);
         }
@@ -426,13 +433,16 @@
                 .thenReturn(new String[]{ "test_p2p-p2p\\d-.*" });
         when(mResources.getStringArray(R.array.config_tether_bluetooth_regexs))
                 .thenReturn(new String[0]);
+        when(mResources.getStringArray(R.array.config_tether_ncm_regexs))
+                .thenReturn(new String[] { "test_ncm\\d" });
         when(mResources.getIntArray(R.array.config_tether_upstream_types)).thenReturn(new int[0]);
         when(mResources.getBoolean(R.bool.config_tether_upstream_automatic)).thenReturn(false);
         when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
                 false);
         when(mNetd.interfaceGetList())
                 .thenReturn(new String[] {
-                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME});
+                        TEST_MOBILE_IFNAME, TEST_WLAN_IFNAME, TEST_USB_IFNAME, TEST_P2P_IFNAME,
+                        TEST_NCM_IFNAME});
         when(mResources.getString(R.string.config_wifi_tether_enable)).thenReturn("");
         mInterfaceConfiguration = new InterfaceConfigurationParcel();
         mInterfaceConfiguration.flags = new String[0];
@@ -467,6 +477,16 @@
         return new Tethering(mTetheringDependencies);
     }
 
+    private TetheringRequestParcel createTetheringRquestParcel(final int type) {
+        final TetheringRequestParcel request = new TetheringRequestParcel();
+        request.tetheringType = type;
+        request.localIPv4Address = null;
+        request.exemptFromEntitlementCheck = false;
+        request.showProvisioningUi = false;
+
+        return request;
+    }
+
     @After
     public void tearDown() {
         mServiceContext.unregisterReceiver(mBroadcastReceiver);
@@ -512,11 +532,16 @@
                 P2P_RECEIVER_PERMISSIONS_FOR_BROADCAST);
     }
 
-    private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
+    private void sendUsbBroadcast(boolean connected, boolean configured, boolean function,
+            int type) {
         final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
         intent.putExtra(USB_CONNECTED, connected);
         intent.putExtra(USB_CONFIGURED, configured);
-        intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
+        if (type == TETHERING_USB) {
+            intent.putExtra(USB_FUNCTION_RNDIS, function);
+        } else {
+            intent.putExtra(USB_FUNCTION_NCM, function);
+        }
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
@@ -566,13 +591,22 @@
         verifyNoMoreInteractions(mWifiManager);
     }
 
+    private void prepareNcmTethering() {
+        // Emulate startTethering(TETHERING_NCM) called
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_NCM), null);
+        mLooper.dispatchAll();
+        verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_NCM);
+
+        mTethering.interfaceStatusChanged(TEST_NCM_IFNAME, true);
+    }
+
     private void prepareUsbTethering(UpstreamNetworkState upstreamState) {
         when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
         when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
                 .thenReturn(upstreamState);
 
         // Emulate pressing the USB tethering button in Settings UI.
-        mTethering.startTethering(TETHERING_USB, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_USB), null);
         mLooper.dispatchAll();
         verify(mUsbManager, times(1)).setCurrentFunctions(UsbManager.FUNCTION_RNDIS);
 
@@ -588,7 +622,7 @@
         verifyNoMoreInteractions(mNetd);
 
         // Pretend we then receive USB configured broadcast.
-        sendUsbBroadcast(true, true, true);
+        sendUsbBroadcast(true, true, true, TETHERING_USB);
         mLooper.dispatchAll();
         // Now we should see the start of tethering mechanics (in this case:
         // tetherMatchingInterfaces() which starts by fetching all interfaces).
@@ -679,7 +713,7 @@
 
     private void runUsbTethering(UpstreamNetworkState upstreamState) {
         prepareUsbTethering(upstreamState);
-        sendUsbBroadcast(true, true, true);
+        sendUsbBroadcast(true, true, true, TETHERING_USB);
         mLooper.dispatchAll();
     }
 
@@ -802,6 +836,29 @@
         verify(mUpstreamNetworkMonitor, times(1)).setCurrentUpstream(upstreamState.network);
     }
 
+    private void runNcmTethering() {
+        prepareNcmTethering();
+        sendUsbBroadcast(true, true, true, TETHERING_NCM);
+        mLooper.dispatchAll();
+    }
+
+    @Test
+    public void workingNcmTethering() throws Exception {
+        runNcmTethering();
+
+        verify(mDhcpServer, timeout(DHCPSERVER_START_TIMEOUT_MS).times(1)).start(any());
+    }
+
+    @Test
+    public void workingNcmTethering_LegacyDhcp() {
+        when(mResources.getBoolean(R.bool.config_tether_enable_legacy_dhcp_server)).thenReturn(
+                true);
+        sendConfigurationChanged();
+        runNcmTethering();
+
+        verify(mIpServerDependencies, never()).makeDhcpServer(any(), any(), any());
+    }
+
     @Test
     public void workingLocalOnlyHotspotEnrichedApBroadcastWithIfaceChanged() throws Exception {
         workingLocalOnlyHotspotEnrichedApBroadcast(true);
@@ -818,7 +875,7 @@
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -845,7 +902,7 @@
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -922,7 +979,7 @@
         doThrow(new RemoteException()).when(mNetd).ipfwdEnableForwarding(TETHERING_NAME);
 
         // Emulate pressing the WiFi tethering button.
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         mLooper.dispatchAll();
         verify(mWifiManager, times(1)).startSoftAp(null);
         verifyNoMoreInteractions(mWifiManager);
@@ -1113,11 +1170,10 @@
         }
 
         @Override
-        public void onCallbackStarted(Network network, TetheringConfigurationParcel config,
-                TetherStatesParcel states) {
-            mActualUpstreams.add(network);
-            mTetheringConfigs.add(config);
-            mTetherStates.add(states);
+        public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
+            mActualUpstreams.add(parcel.upstreamNetwork);
+            mTetheringConfigs.add(parcel.config);
+            mTetherStates.add(parcel.states);
         }
 
         @Override
@@ -1188,7 +1244,7 @@
         tetherState = callback.pollTetherStatesChanged();
         assertArrayEquals(tetherState.availableList, new String[] {TEST_WLAN_IFNAME});
 
-        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mTethering.startTethering(createTetheringRquestParcel(TETHERING_WIFI), null);
         sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
         tetherState = callback.pollTetherStatesChanged();
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 11f0a04..478b87c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -66,6 +66,7 @@
 import android.net.ConnectionInfo;
 import android.net.ConnectivityManager;
 import android.net.ICaptivePortal;
+import android.net.IConnectivityDiagnosticsCallback;
 import android.net.IConnectivityManager;
 import android.net.IDnsResolver;
 import android.net.IIpConnectivityMetrics;
@@ -1625,7 +1626,8 @@
         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
     }
 
-    private NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
+    @VisibleForTesting
+    NetworkCapabilities networkCapabilitiesRestrictedForCallerPermissions(
             NetworkCapabilities nc, int callerPid, int callerUid) {
         final NetworkCapabilities newNc = new NetworkCapabilities(nc);
         if (!checkSettingsPermission(callerPid, callerUid)) {
@@ -1636,9 +1638,23 @@
             newNc.setNetworkSpecifier(newNc.getNetworkSpecifier().redact());
         }
         newNc.setAdministratorUids(Collections.EMPTY_LIST);
+
+        maybeSanitizeLocationInfoForCaller(newNc, callerUid);
+
         return newNc;
     }
 
+    private void maybeSanitizeLocationInfoForCaller(
+            NetworkCapabilities nc, int callerUid) {
+        // TODO(b/142072839): Conditionally reset the owner UID if the following
+        // conditions are not met:
+        // 1. The destination app is the network owner
+        // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
+        // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
+        // 3. The user's location toggle is on
+        nc.setOwnerUid(INVALID_UID);
+    }
+
     private LinkProperties linkPropertiesRestrictedForCallerPermissions(
             LinkProperties lp, int callerPid, int callerUid) {
         if (lp == null) return new LinkProperties();
@@ -1667,6 +1683,9 @@
             nc.setSingleUid(Binder.getCallingUid());
         }
         nc.setAdministratorUids(Collections.EMPTY_LIST);
+
+        // Clear owner UID; this can never come from an app.
+        nc.setOwnerUid(INVALID_UID);
     }
 
     private void restrictBackgroundRequestForCaller(NetworkCapabilities nc) {
@@ -5794,7 +5813,7 @@
         }
 
         final Set<UidRange> ranges = nai.networkCapabilities.getUids();
-        final int vpnAppUid = nai.networkCapabilities.getEstablishingVpnAppUid();
+        final int vpnAppUid = nai.networkCapabilities.getOwnerUid();
         // TODO: this create a window of opportunity for apps to receive traffic between the time
         // when the old rules are removed and the time when new rules are added. To fix this,
         // make eBPF support two whitelisted interfaces so here new rules can be added before the
@@ -5993,7 +6012,7 @@
         if (nc == null || lp == null) return false;
         return nai.isVPN()
                 && !nai.networkAgentConfig.allowBypass
-                && nc.getEstablishingVpnAppUid() != Process.SYSTEM_UID
+                && nc.getOwnerUid() != Process.SYSTEM_UID
                 && lp.getInterfaceName() != null
                 && (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute());
     }
@@ -6041,12 +6060,10 @@
             // TODO Fix this window by computing an accurate diff on Set<UidRange>, so the old range
             // to be removed will never overlap with the new range to be added.
             if (wasFiltering && !prevRanges.isEmpty()) {
-                mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges,
-                        prevNc.getEstablishingVpnAppUid());
+                mPermissionMonitor.onVpnUidRangesRemoved(iface, prevRanges, prevNc.getOwnerUid());
             }
             if (shouldFilter && !newRanges.isEmpty()) {
-                mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges,
-                        newNc.getEstablishingVpnAppUid());
+                mPermissionMonitor.onVpnUidRangesAdded(iface, newRanges, newNc.getOwnerUid());
             }
         } catch (Exception e) {
             // Never crash!
@@ -7307,4 +7324,20 @@
             return mTNS;
         }
     }
+
+    @Override
+    public void registerConnectivityDiagnosticsCallback(
+            @NonNull IConnectivityDiagnosticsCallback callback, @NonNull NetworkRequest request) {
+        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+        throw new UnsupportedOperationException(
+                "registerConnectivityDiagnosticsCallback not yet implemented");
+    }
+
+    @Override
+    public void unregisterConnectivityDiagnosticsCallback(
+            @NonNull IConnectivityDiagnosticsCallback callback) {
+        // TODO(b/146444622): implement register IConnectivityDiagnosticsCallback functionality
+        throw new UnsupportedOperationException(
+                "unregisterConnectivityDiagnosticsCallback not yet implemented");
+    }
 }
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 90b0c11..39ad354 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2788,6 +2788,24 @@
     }
 
     /*
+     * Clear disk encryption key bound to the associated token / secret pair. Removing the user
+     * binding of the Disk encryption key is done in two phases: first, this call will retrieve
+     * the disk encryption key using the provided token / secret pair and store it by
+     * encrypting it with a keymaster key not bound to the user, then fixateNewestUserKeyAuth
+     * is called to delete all other bindings of the disk encryption key.
+     */
+    @Override
+    public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
+        enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
+
+        try {
+            mVold.clearUserKeyAuth(userId, serialNumber, encodeBytes(token), encodeBytes(secret));
+        } catch (Exception e) {
+            Slog.wtf(TAG, e);
+        }
+    }
+
+    /*
      * Delete all disk encryption token/secret pairs except the most recently added one
      */
     @Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 62743aa..5eacb28 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -882,6 +882,10 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH)
+                            != 0) {
+                        updateReportSignalStrengthDecision(r.subId);
+                    }
                     if (validateEventsAndUserLocked(r, PhoneStateListener.LISTEN_CELL_INFO)) {
                         try {
                             if (DBG_LOC) log("listen: mCellInfo[" + phoneId + "] = "
@@ -1005,6 +1009,27 @@
         }
     }
 
+    private void updateReportSignalStrengthDecision(int subscriptionId) {
+        synchronized (mRecords) {
+            TelephonyManager telephonyManager = (TelephonyManager) mContext
+                    .getSystemService(Context.TELEPHONY_SERVICE);
+            for (Record r : mRecords) {
+                // 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)) {
+                    telephonyManager.createForSubscriptionId(subscriptionId)
+                            .setAlwaysReportSignalStrength(true);
+                    return;
+                }
+            }
+            // If none of the system clients wants to always listen to signal strength,
+            // we need to set it off.
+            telephonyManager.createForSubscriptionId(subscriptionId)
+                    .setAlwaysReportSignalStrength(false);
+        }
+    }
+
     private String getCallIncomingNumber(Record record, int phoneId) {
         // Only reveal the incoming number if the record has read call log permission.
         return record.canReadCallLog() ? mCallIncomingNumber[phoneId] : "";
@@ -1062,6 +1087,14 @@
                     }
 
                     mRecords.remove(i);
+
+                    // Every time a client that is registrating to always receive the signal
+                    // 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)) {
+                        updateReportSignalStrengthDecision(r.subId);
+                    }
                     return;
                 }
             }
@@ -2415,6 +2448,11 @@
                     android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION, null);
         }
 
+        if ((events & PhoneStateListener.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH) != 0) {
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.LISTEN_ALWAYS_REPORTED_SIGNAL_STRENGTH, null);
+        }
+
         if ((events & PhoneStateListener.LISTEN_OEM_HOOK_RAW_EVENT) != 0) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index f021008..5833d16 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -272,6 +272,7 @@
 
         static final int MSG_BG_START_TIMEOUT = 1;
         static final int MSG_UPDATE_FOREGROUND_APPS = 2;
+        static final int MSG_ENSURE_NOT_START_BG = 3;
 
         ServiceMap(Looper looper, int userId) {
             super(looper);
@@ -289,6 +290,11 @@
                 case MSG_UPDATE_FOREGROUND_APPS: {
                     updateForegroundApps(this);
                 } break;
+                case MSG_ENSURE_NOT_START_BG: {
+                    synchronized (mAm) {
+                        rescheduleDelayedStartsLocked();
+                    }
+                } break;
             }
         }
 
@@ -296,7 +302,9 @@
             if (mStartingBackground.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
                         "No longer background starting: " + r);
-                rescheduleDelayedStartsLocked();
+                removeMessages(MSG_ENSURE_NOT_START_BG);
+                Message msg = obtainMessage(MSG_ENSURE_NOT_START_BG);
+                sendMessage(msg);
             }
             if (mDelayedStartList.remove(r)) {
                 if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r);
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 029b7bc..e48169f 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,6 +16,11 @@
 
 package com.android.server.compat;
 
+import static android.Manifest.permission.LOG_COMPAT_CHANGE;
+import static android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG;
+import static android.Manifest.permission.READ_COMPAT_CHANGE_CONFIG;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
 import android.app.ActivityManager;
 import android.app.IActivityManager;
 import android.content.Context;
@@ -67,12 +72,14 @@
 
     @Override
     public void reportChange(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, appInfo.uid,
                 StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public void reportChangeByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeLogPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return;
@@ -82,11 +89,13 @@
 
     @Override
     public void reportChangeByUid(long changeId, int uid) {
+        checkCompatChangeLogPermission();
         reportChange(changeId, uid, StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__LOGGED);
     }
 
     @Override
     public boolean isChangeEnabled(long changeId, ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         if (mCompatConfig.isChangeEnabled(changeId, appInfo)) {
             reportChange(changeId, appInfo.uid,
                     StatsLog.APP_COMPATIBILITY_CHANGE_REPORTED__STATE__ENABLED);
@@ -99,6 +108,7 @@
 
     @Override
     public boolean isChangeEnabledByPackageName(long changeId, String packageName, int userId) {
+        checkCompatChangeReadPermission();
         ApplicationInfo appInfo = getApplicationInfo(packageName, userId);
         if (appInfo == null) {
             return true;
@@ -108,6 +118,7 @@
 
     @Override
     public boolean isChangeEnabledByUid(long changeId, int uid) {
+        checkCompatChangeReadPermission();
         String[] packages = mContext.getPackageManager().getPackagesForUid(uid);
         if (packages == null || packages.length == 0) {
             return true;
@@ -140,6 +151,7 @@
     @Override
     public void setOverrides(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
         killPackage(packageName);
     }
@@ -147,11 +159,13 @@
     @Override
     public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.addOverrides(overrides, packageName);
     }
 
     @Override
     public void clearOverrides(String packageName) throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
         killPackage(packageName);
     }
@@ -159,12 +173,14 @@
     @Override
     public void clearOverridesForTest(String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         mCompatConfig.removePackageOverrides(packageName);
     }
 
     @Override
     public boolean clearOverride(long changeId, String packageName)
             throws RemoteException, SecurityException {
+        checkCompatChangeOverridePermission();
         boolean existed = mCompatConfig.removeOverride(changeId, packageName);
         killPackage(packageName);
         return existed;
@@ -172,11 +188,13 @@
 
     @Override
     public CompatibilityChangeConfig getAppConfig(ApplicationInfo appInfo) {
+        checkCompatChangeReadPermission();
         return mCompatConfig.getAppConfig(appInfo);
     }
 
     @Override
     public CompatibilityChangeInfo[] listAllChanges() {
+        checkCompatChangeReadPermission();
         return mCompatConfig.dumpChanges();
     }
 
@@ -215,6 +233,7 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        checkCompatChangeReadPermission();
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, "platform_compat", pw)) return;
         mCompatConfig.dumpConfig(pw);
     }
@@ -276,4 +295,25 @@
             Binder.restoreCallingIdentity(identity);
         }
     }
+
+    private void checkCompatChangeLogPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(LOG_COMPAT_CHANGE)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot log compat change usage");
+        }
+    }
+
+    private void checkCompatChangeReadPermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(READ_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot read compat change");
+        }
+    }
+
+    private void checkCompatChangeOverridePermission() throws SecurityException {
+        if (mContext.checkCallingOrSelfPermission(OVERRIDE_COMPAT_CHANGE_CONFIG)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Cannot override compat change");
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 69ab47a..2933fab 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -950,7 +950,7 @@
         NetworkAgentConfig networkAgentConfig = new NetworkAgentConfig();
         networkAgentConfig.allowBypass = mConfig.allowBypass && !mLockdown;
 
-        mNetworkCapabilities.setEstablishingVpnAppUid(Binder.getCallingUid());
+        mNetworkCapabilities.setOwnerUid(Binder.getCallingUid());
         mNetworkCapabilities.setUids(createUserAndRestrictedProfilesRanges(mUserHandle,
                 mConfig.allowedApplications, mConfig.disallowedApplications));
         long token = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 9510db0..288484f 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -25,7 +25,6 @@
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
-import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
 import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
 import static com.android.internal.widget.LockPatternUtils.USER_FRP;
@@ -1511,7 +1510,7 @@
             if (credential != null) {
                 Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
             }
-            clearUserKeyProtection(userId);
+            clearUserKeyProtection(userId, null);
             getGateKeeperService().clearSecureUserId(userId);
             mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
             setKeystorePassword(null, userId);
@@ -1688,9 +1687,17 @@
         addUserKeyAuth(userId, token, secretFromCredential(credential));
     }
 
-    private void clearUserKeyProtection(int userId) throws RemoteException {
+    private void clearUserKeyProtection(int userId, byte[] secret) {
         if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
-        addUserKeyAuth(userId, null, null);
+        final UserInfo userInfo = mUserManager.getUserInfo(userId);
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            mStorageManager.clearUserKeyAuth(userId, userInfo.serialNumber, null, secret);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("clearUserKeyAuth failed user=" + userId);
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
     }
 
     private static byte[] secretFromCredential(byte[] credential) throws RemoteException {
@@ -2512,7 +2519,7 @@
             setAuthlessUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
             setKeystorePassword(auth.deriveKeyStorePassword(), userId);
         } else {
-            clearUserKeyProtection(userId);
+            clearUserKeyProtection(userId, null);
             setKeystorePassword(null, userId);
             getGateKeeperService().clearSecureUserId(userId);
         }
@@ -2532,23 +2539,12 @@
             return type == PersistentData.TYPE_SP || type == PersistentData.TYPE_SP_WEAVER;
         }
         long handle = getSyntheticPasswordHandleLocked(userId);
-        // This is a global setting
-        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
-                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
-      return enabled != 0 && handle != SyntheticPasswordManager.DEFAULT_HANDLE;
+        return handle != SyntheticPasswordManager.DEFAULT_HANDLE;
     }
 
     @VisibleForTesting
     protected boolean shouldMigrateToSyntheticPasswordLocked(int userId) {
-        long handle = getSyntheticPasswordHandleLocked(userId);
-        // This is a global setting
-        long enabled = getLong(SYNTHETIC_PASSWORD_ENABLED_KEY,
-                SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT, UserHandle.USER_SYSTEM);
-        return enabled != 0 && handle == SyntheticPasswordManager.DEFAULT_HANDLE;
-    }
-
-    private void enableSyntheticPasswordLocked() {
-        setLong(SYNTHETIC_PASSWORD_ENABLED_KEY, 1, UserHandle.USER_SYSTEM);
+        return true;
     }
 
     private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential,
@@ -2698,7 +2694,7 @@
             // during boot. Vold storage needs to be unlocked before manipulation of the keys can
             // succeed.
             unlockUserKey(userId, null, auth.deriveDiskEncryptionKey());
-            clearUserKeyProtection(userId);
+            clearUserKeyProtection(userId, auth.deriveDiskEncryptionKey());
             fixateNewestUserKeyAuth(userId);
             unlockKeystore(auth.deriveKeyStorePassword(), userId);
             setKeystorePassword(null, userId);
@@ -2829,7 +2825,6 @@
             throws RemoteException {
         if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
         synchronized (mSpManager) {
-            enableSyntheticPasswordLocked();
             // Migrate to synthetic password based credentials if the user has no password,
             // the token can then be activated immediately.
             AuthenticationToken auth = null;
diff --git a/services/tests/servicestests/AndroidManifest.xml b/services/tests/servicestests/AndroidManifest.xml
index 61fe01f..1e623e0 100644
--- a/services/tests/servicestests/AndroidManifest.xml
+++ b/services/tests/servicestests/AndroidManifest.xml
@@ -65,6 +65,8 @@
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
     <uses-permission android:name="android.permission.SUSPEND_APPS"/>
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD"/>
+    <uses-permission android:name="android.permission.READ_COMPAT_CHANGE_CONFIG"/>
+    <uses-permission android:name="android.permission.LOG_COMPAT_CHANGE"/>
     <uses-permission android:name="android.permission.MANAGE_BIND_INSTANT_SERVICE"/>
     <uses-permission android:name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
     <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
diff --git a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
index 4d229ef..625766a 100644
--- a/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
+++ b/services/tests/servicestests/src/com/android/server/WatchdogDiagnosticsTest.java
@@ -157,6 +157,8 @@
             String expected =
                     "TestThread2 annotated stack trace:\n" +
                     "    at java.lang.Object.wait(Native Method)\n" +
+                    "    at java.lang.Object.wait(Object.java:442)\n" +
+                    "    at java.lang.Object.wait(Object.java:568)\n" +
                     "    at com.android.server.WatchdogDiagnosticsTest$TestThread2.y(" +
                             "WatchdogDiagnosticsTest.java:91)\n" +
                     "    - locked <HASH> (a java.lang.String)\n" +
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 842cdd5..2aaf759 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -215,6 +215,18 @@
             }
         }).when(sm).addUserKeyAuth(anyInt(), anyInt(), any(), any());
 
+        doAnswer(new Answer<Void>() {
+            @Override
+            public Void answer(InvocationOnMock invocation) throws Throwable {
+                Object[] args = invocation.getArguments();
+                mStorageManager.clearUserKeyAuth((int) args[0] /* userId */,
+                        (int) args[1] /* serialNumber */,
+                        (byte[]) args[2] /* token */,
+                        (byte[]) args[3] /* secret */);
+                return null;
+            }
+        }).when(sm).clearUserKeyAuth(anyInt(), anyInt(), any(), any());
+
         doAnswer(
                 new Answer<Void>() {
             @Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
index 1ae1fa6..102bac1 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/FakeStorageManager.java
@@ -36,6 +36,15 @@
         getUserAuth(userId).add(new Pair<>(token, secret));
     }
 
+    public void clearUserKeyAuth(int userId, int serialNumber, byte[] token, byte[] secret) {
+        ArrayList<Pair<byte[], byte[]>> auths = getUserAuth(userId);
+        if (token == null && secret == null) {
+            return;
+        }
+        auths.remove(new Pair<>(token, secret));
+        auths.add(new Pair<>(null, null));
+    }
+
     public void fixateNewestUserKeyAuth(int userId) {
         ArrayList<Pair<byte[], byte[]>> auths = mAuth.get(userId);
         Pair<byte[], byte[]> latest = auths.get(auths.size() - 1);
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index d9b1320..33f7924 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -103,31 +103,6 @@
         return mService.getLong(SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId) != 0;
     }
 
-    @Test
-    public void testPasswordMigration() throws RemoteException {
-        final byte[] password = "testPasswordMigration-password".getBytes();
-
-        disableSyntheticPassword();
-        mService.setLockCredential(password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        long sid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
-        enableSyntheticPassword();
-        // Performs migration
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                password, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                    .getResponseCode());
-        assertEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-        assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
-
-        // SP-based verification
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(password,
-                LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
-        assertArrayNotEquals(primaryStorageKey,
-                mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
-    }
-
     protected void initializeCredentialUnderSP(byte[] password, int userId) throws RemoteException {
         enableSyntheticPassword();
         int quality = password != null ? PASSWORD_QUALITY_ALPHABETIC
@@ -270,86 +245,6 @@
     }
 
     @Test
-    public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
-        final byte[] UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd".getBytes();
-        disableSyntheticPassword();
-        mService.setLockCredential(UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        mService.setSeparateProfileChallengeEnabled(MANAGED_PROFILE_USER_ID, false, null);
-        final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
-        final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
-        final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
-        assertTrue(primarySid != 0);
-        assertTrue(profileSid != 0);
-        assertTrue(profileSid != primarySid);
-
-        // do migration
-        enableSyntheticPassword();
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
-
-        // verify
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                UnifiedPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
-        assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-        assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
-        assertArrayNotEquals(primaryStorageKey,
-                mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
-        assertArrayNotEquals(profileStorageKey,
-                mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
-        assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
-        assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
-    }
-
-    @Test
-    public void testManagedProfileSeparateChallengeMigration() throws RemoteException {
-        final byte[] primaryPassword =
-                "testManagedProfileSeparateChallengeMigration-primary".getBytes();
-        final byte[] profilePassword =
-                "testManagedProfileSeparateChallengeMigration-profile".getBytes();
-        disableSyntheticPassword();
-        mService.setLockCredential(primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID, false);
-        mService.setLockCredential(profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
-                PASSWORD_QUALITY_ALPHABETIC, MANAGED_PROFILE_USER_ID, false);
-        final long primarySid = mGateKeeperService.getSecureUserId(PRIMARY_USER_ID);
-        final long profileSid = mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID);
-        final byte[] primaryStorageKey = mStorageManager.getUserUnlockToken(PRIMARY_USER_ID);
-        final byte[] profileStorageKey = mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID);
-        assertTrue(primarySid != 0);
-        assertTrue(profileSid != 0);
-        assertTrue(profileSid != primarySid);
-
-        // do migration
-        enableSyntheticPassword();
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, MANAGED_PROFILE_USER_ID).getResponseCode());
-
-        // verify
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                primaryPassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
-                        .getResponseCode());
-        assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
-                profilePassword, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                0, MANAGED_PROFILE_USER_ID).getResponseCode());
-        assertEquals(primarySid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
-        assertEquals(profileSid, mGateKeeperService.getSecureUserId(MANAGED_PROFILE_USER_ID));
-        assertArrayNotEquals(primaryStorageKey,
-                mStorageManager.getUserUnlockToken(PRIMARY_USER_ID));
-        assertArrayNotEquals(profileStorageKey,
-                mStorageManager.getUserUnlockToken(MANAGED_PROFILE_USER_ID));
-        assertTrue(hasSyntheticPassword(PRIMARY_USER_ID));
-        assertTrue(hasSyntheticPassword(MANAGED_PROFILE_USER_ID));
-    }
-
-    @Test
     public void testTokenBasedResetPassword() throws RemoteException {
         final byte[] password = "password".getBytes();
         final byte[] pattern = "123654".getBytes();
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index acf51f3..f54f8d1 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -265,6 +265,29 @@
     public static final String EVENT_HANDOVER_FAILED =
             "android.telecom.event.HANDOVER_FAILED";
 
+
+    /**
+     * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+     * call because they have declined to answer it.  This typically means that they are unable
+     * to answer the call at this time and would prefer it be sent to voicemail.
+     */
+    public static final int REJECT_REASON_DECLINED = 1;
+
+    /**
+     * Reject reason used with {@link #reject(int)} to indicate that the user is rejecting this
+     * call because it is an unwanted call.  This allows the user to indicate that they are
+     * rejecting a call because it is likely a nuisance call.
+     */
+    public static final int REJECT_REASON_UNWANTED = 2;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "REJECT_REASON_" },
+            value = {REJECT_REASON_DECLINED, REJECT_REASON_UNWANTED})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface RejectReason {};
+
     public static class Details {
         /** @hide */
         @Retention(RetentionPolicy.SOURCE)
@@ -1520,6 +1543,16 @@
     }
 
     /**
+     * Instructs the {@link ConnectionService} providing this {@link #STATE_RINGING} call that the
+     * user has chosen to reject the call and has indicated a reason why the call is being rejected.
+     *
+     * @param rejectReason the reason the call is being rejected.
+     */
+    public void reject(@RejectReason int rejectReason) {
+        mInCallAdapter.rejectCall(mTelecomCallId, rejectReason);
+    }
+
+    /**
      * Instructs this {@code Call} to disconnect.
      */
     public void disconnect() {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index c934625..72c66d2 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -3037,6 +3037,17 @@
     public void onReject() {}
 
     /**
+     * Notifies this Connection, which is in {@link #STATE_RINGING}, of a request to reject.
+     * <p>
+     * For managed {@link ConnectionService}s, this will be called when the user rejects a call via
+     * the default dialer's {@link InCallService} using {@link Call#reject(int)}.
+     * @param rejectReason the reason the user provided for rejecting the call.
+     */
+    public void onReject(@android.telecom.Call.RejectReason int rejectReason) {
+        // to be implemented by ConnectionService.
+    }
+
+    /**
      * Notifies this Connection, which is in {@link #STATE_RINGING}, of
      * a request to reject with a message.
      */
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 440f044..00c2918 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -194,6 +194,7 @@
     private static final int MSG_CREATE_CONFERENCE = 35;
     private static final int MSG_CREATE_CONFERENCE_COMPLETE = 36;
     private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
+    private static final int MSG_REJECT_WITH_REASON = 38;
 
     private static Connection sNullConnection;
 
@@ -450,6 +451,21 @@
         }
 
         @Override
+        public void rejectWithReason(String callId,
+                @android.telecom.Call.RejectReason int rejectReason, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_REJECT);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.argi1 = rejectReason;
+                args.arg2 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_REJECT_WITH_REASON, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void rejectWithMessage(String callId, String message, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_REJECT_MESSAGE);
             try {
@@ -1053,6 +1069,17 @@
                     }
                     break;
                 }
+                case MSG_REJECT_WITH_REASON: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_REJECT);
+                    try {
+                        reject((String) args.arg1, args.argi1);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_REJECT_WITH_MESSAGE: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg3,
@@ -1981,6 +2008,11 @@
         findConnectionForAction(callId, "reject").onReject(rejectWithMessage);
     }
 
+    private void reject(String callId, @android.telecom.Call.RejectReason int rejectReason) {
+        Log.d(this, "reject %s with reason %d", callId, rejectReason);
+        findConnectionForAction(callId, "reject").onReject(rejectReason);
+    }
+
     private void silence(String callId) {
         Log.d(this, "silence %s", callId);
         findConnectionForAction(callId, "silence").onSilence();
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 2612468..594c1eb 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -89,6 +89,19 @@
     }
 
     /**
+     * Instructs Telecom to reject the specified call.
+     *
+     * @param callId The identifier of the call to reject.
+     * @param rejectReason The reason the call was rejected.
+     */
+    public void rejectCall(String callId, @Call.RejectReason int rejectReason) {
+        try {
+            mAdapter.rejectCallWithReason(callId, rejectReason);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Instructs Telecom to disconnect the specified call.
      *
      * @param callId The identifier of the call to disconnect.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 96f2483..4249dff 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -77,6 +77,8 @@
 
     void reject(String callId, in Session.Info sessionInfo);
 
+    void rejectWithReason(String callId, int rejectReason, in Session.Info sessionInfo);
+
     void rejectWithMessage(String callId, String message, in Session.Info sessionInfo);
 
     void disconnect(String callId, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 60745e4..eb2d714 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -34,6 +34,8 @@
 
     void rejectCall(String callId, boolean rejectWithMessage, String textMessage);
 
+    void rejectCallWithReason(String callId, int rejectReason);
+
     void disconnectCall(String callId);
 
     void holdCall(String callId);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 71aaa6e..71411d5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3758,26 +3758,26 @@
         sDefaults.putIntArray(KEY_5G_NR_SSRSRP_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-140 dB, -44 dB]
                 new int[] {
-                    -125, /* SIGNAL_STRENGTH_POOR */
-                    -115, /* SIGNAL_STRENGTH_MODERATE */
-                    -105, /* SIGNAL_STRENGTH_GOOD */
-                    -95,  /* SIGNAL_STRENGTH_GREAT */
+                    -110, /* SIGNAL_STRENGTH_POOR */
+                    -90, /* SIGNAL_STRENGTH_MODERATE */
+                    -80, /* SIGNAL_STRENGTH_GOOD */
+                    -65,  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putIntArray(KEY_5G_NR_SSRSRQ_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-20 dB, -3 dB]
                 new int[] {
-                    -14, /* SIGNAL_STRENGTH_POOR */
-                    -12, /* SIGNAL_STRENGTH_MODERATE */
-                    -10, /* SIGNAL_STRENGTH_GOOD */
-                    -8  /* SIGNAL_STRENGTH_GREAT */
+                    -16, /* SIGNAL_STRENGTH_POOR */
+                    -11, /* SIGNAL_STRENGTH_MODERATE */
+                    -9, /* SIGNAL_STRENGTH_GOOD */
+                    -7  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putIntArray(KEY_5G_NR_SSSINR_THRESHOLDS_INT_ARRAY,
                 // Boundaries: [-23 dB, 40 dB]
                 new int[] {
-                    -8, /* SIGNAL_STRENGTH_POOR */
-                    0, /* SIGNAL_STRENGTH_MODERATE */
-                    8, /* SIGNAL_STRENGTH_GOOD */
-                    16  /* SIGNAL_STRENGTH_GREAT */
+                    -5, /* SIGNAL_STRENGTH_POOR */
+                    5, /* SIGNAL_STRENGTH_MODERATE */
+                    15, /* SIGNAL_STRENGTH_GOOD */
+                    30  /* SIGNAL_STRENGTH_GREAT */
                 });
         sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
                 CellSignalStrengthNr.USE_SSRSRP);
diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java
index 4d67bcf..f4c13ff 100644
--- a/telephony/java/android/telephony/CellSignalStrengthNr.java
+++ b/telephony/java/android/telephony/CellSignalStrengthNr.java
@@ -45,28 +45,28 @@
     // Lifted from Default carrier configs and max range of SSRSRP
     // Boundaries: [-140 dB, -44 dB]
     private int[] mSsRsrpThresholds = new int[] {
-            -125, /* SIGNAL_STRENGTH_POOR */
-            -115, /* SIGNAL_STRENGTH_MODERATE */
-            -105, /* SIGNAL_STRENGTH_GOOD */
-            -95,  /* SIGNAL_STRENGTH_GREAT */
+            -110, /* SIGNAL_STRENGTH_POOR */
+            -90, /* SIGNAL_STRENGTH_MODERATE */
+            -80, /* SIGNAL_STRENGTH_GOOD */
+            -65,  /* SIGNAL_STRENGTH_GREAT */
     };
 
     // Lifted from Default carrier configs and max range of SSRSRQ
     // Boundaries: [-20 dB, -3 dB]
     private int[] mSsRsrqThresholds = new int[] {
-            -14, /* SIGNAL_STRENGTH_POOR */
-            -12, /* SIGNAL_STRENGTH_MODERATE */
-            -10, /* SIGNAL_STRENGTH_GOOD */
-            -8  /* SIGNAL_STRENGTH_GREAT */
+            -16, /* SIGNAL_STRENGTH_POOR */
+            -11, /* SIGNAL_STRENGTH_MODERATE */
+            -9, /* SIGNAL_STRENGTH_GOOD */
+            -7  /* SIGNAL_STRENGTH_GREAT */
     };
 
     // Lifted from Default carrier configs and max range of SSSINR
     // Boundaries: [-23 dB, 40 dB]
     private int[] mSsSinrThresholds = new int[] {
-            -8, /* SIGNAL_STRENGTH_POOR */
-            0, /* SIGNAL_STRENGTH_MODERATE */
-            8, /* SIGNAL_STRENGTH_GOOD */
-            16  /* SIGNAL_STRENGTH_GREAT */
+            -5, /* SIGNAL_STRENGTH_POOR */
+            5, /* SIGNAL_STRENGTH_MODERATE */
+            15, /* SIGNAL_STRENGTH_GOOD */
+            30  /* SIGNAL_STRENGTH_GREAT */
     };
 
     /**
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index 9b4292f..704e5aa 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -27,11 +27,7 @@
 
 /**
  * Provides access to information about Telephony IMS services on the device.
- *
- * @hide
  */
-@SystemApi
-@TestApi
 @SystemService(Context.TELEPHONY_IMS_SERVICE)
 public class ImsManager {
 
@@ -45,7 +41,10 @@
      * <p class="note">
      * Carrier applications may listen to this broadcast to be notified of possible IMS provisioning
      * issues.
+     * @hide
      */
+    @SystemApi
+    @TestApi
     // Moved from TelephonyIntents, need to keep backwards compatibility with OEM apps that have
     // this value hard-coded in BroadcastReceiver.
     @SuppressLint("ActionValue")
@@ -104,7 +103,10 @@
      * @param subscriptionId The ID of the subscription that this ImsRcsManager will use.
      * @throws IllegalArgumentException if the subscription is invalid.
      * @return a ImsRcsManager instance with the specific subscription ID.
+     * @hide
      */
+    @SystemApi
+    @TestApi
     @NonNull
     public ImsRcsManager getImsRcsManager(int subscriptionId) {
         if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index aee7cca..bd2375f 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -199,10 +199,10 @@
     }
 
     /**
+     * Indicate if the ModemActivityInfo is invalid due to modem's invalid reporting.
+     *
      * @return {@code true} if this {@link ModemActivityInfo} record is valid,
      * {@code false} otherwise.
-     *
-     * @hide
      */
     public boolean isValid() {
         for (TransmitPower powerInfo : getTransmitPowerInfo()) {
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 31434c1..0cfb8c5 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -20,6 +20,9 @@
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.LinkProperties;
 import android.os.Build;
@@ -31,8 +34,6 @@
 import android.telephony.Annotation.NetworkType;
 import android.telephony.data.ApnSetting;
 
-import dalvik.system.VMRuntime;
-
 import java.util.Objects;
 
 
@@ -134,6 +135,13 @@
     }
 
     /**
+     * To check the SDK version for {@link PreciseDataConnectionState#getDataConnectionState}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long GET_DATA_CONNECTION_STATE_CODE_CHANGE = 147600208L;
+
+    /**
      * Returns the state of data connection that supported the apn types returned by
      * {@link #getDataConnectionApnTypeBitMask()}
      *
@@ -144,7 +152,7 @@
     @SystemApi
     public @DataState int getDataConnectionState() {
         if (mState == TelephonyManager.DATA_DISCONNECTING
-                && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+                && !Compatibility.isChangeEnabled(GET_DATA_CONNECTION_STATE_CODE_CHANGE)) {
             return TelephonyManager.DATA_CONNECTED;
         }
 
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 0ba36b1..e7b2613 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -25,11 +25,12 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
-import android.app.ActivityThread;
 import android.app.PendingIntent;
+import android.compat.Compatibility;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.database.CursorWindow;
 import android.net.Uri;
 import android.os.Build;
@@ -388,7 +389,7 @@
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
         sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
-                true /* persistMessage*/, ActivityThread.currentPackageName());
+                true /* persistMessage*/, null);
     }
 
     /**
@@ -598,7 +599,7 @@
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
         sendTextMessageInternal(destinationAddress, scAddress, text, sentIntent, deliveryIntent,
-                false /* persistMessage */, ActivityThread.currentPackageName());
+                false /* persistMessage */, null);
     }
 
     private void sendTextMessageInternal(
@@ -641,7 +642,7 @@
                         ISms iSms = getISmsServiceOrThrow();
                         if (iSms != null) {
                             iSms.sendTextForSubscriberWithOptions(subId,
-                                    ActivityThread.currentPackageName(), destinationAddress,
+                                    null, destinationAddress,
                                     scAddress,
                                     text, sentIntent, deliveryIntent, persistMessage, finalPriority,
                                     expectMore, finalValidity);
@@ -663,7 +664,7 @@
                 ISms iSms = getISmsServiceOrThrow();
                 if (iSms != null) {
                     iSms.sendTextForSubscriberWithOptions(getSubscriptionId(),
-                            ActivityThread.currentPackageName(), destinationAddress,
+                            null, destinationAddress,
                             scAddress,
                             text, sentIntent, deliveryIntent, persistMessage, finalPriority,
                             expectMore, finalValidity);
@@ -881,7 +882,7 @@
             String destinationAddress, String scAddress, ArrayList<String> parts,
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
-                deliveryIntents, true /* persistMessage*/, ActivityThread.currentPackageName());
+                deliveryIntents, true /* persistMessage*/, null);
     }
 
     /**
@@ -898,8 +899,9 @@
      * subscription.
      * </p>
      *
-     * @param packageName serves as the default package name if
-     * {@link ActivityThread#currentPackageName()} is null.
+     * @param packageName serves as the default package name if the package name that is
+     *        associated with the user id is null.
+     *
      * @hide
      */
     @SystemApi
@@ -909,9 +911,7 @@
             @NonNull List<String> parts, @Nullable List<PendingIntent> sentIntents,
             @Nullable List<PendingIntent> deliveryIntents, @NonNull String packageName) {
         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
-                deliveryIntents, true /* persistMessage*/,
-                ActivityThread.currentPackageName() == null
-                        ? packageName : ActivityThread.currentPackageName());
+                deliveryIntents, true /* persistMessage*/, packageName);
     }
 
     private void sendMultipartTextMessageInternal(
@@ -1012,7 +1012,7 @@
             String destinationAddress, String scAddress, List<String> parts,
             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
-                deliveryIntents, false /* persistMessage*/, ActivityThread.currentPackageName());
+                deliveryIntents, false /* persistMessage*/, null);
     }
 
     /**
@@ -1174,7 +1174,7 @@
                             ISms iSms = getISmsServiceOrThrow();
                             if (iSms != null) {
                                 iSms.sendMultipartTextForSubscriberWithOptions(subId,
-                                        ActivityThread.currentPackageName(), destinationAddress,
+                                        null, destinationAddress,
                                         scAddress, parts, sentIntents, deliveryIntents,
                                         persistMessage, finalPriority, expectMore, finalValidity);
                             }
@@ -1196,7 +1196,7 @@
                     ISms iSms = getISmsServiceOrThrow();
                     if (iSms != null) {
                         iSms.sendMultipartTextForSubscriberWithOptions(getSubscriptionId(),
-                                ActivityThread.currentPackageName(), destinationAddress,
+                                null, destinationAddress,
                                 scAddress, parts, sentIntents, deliveryIntents,
                                 persistMessage, finalPriority, expectMore, finalValidity);
                     }
@@ -1327,7 +1327,7 @@
             public void onSuccess(int subId) {
                 try {
                     ISms iSms = getISmsServiceOrThrow();
-                    iSms.sendDataForSubscriber(subId, ActivityThread.currentPackageName(),
+                    iSms.sendDataForSubscriber(subId, null,
                             destinationAddress, scAddress, destinationPort & 0xFFFF, data,
                             sentIntent, deliveryIntent);
                 } catch (RemoteException e) {
@@ -1453,7 +1453,6 @@
     private void resolveSubscriptionForOperation(SubscriptionResolverResult resolverResult) {
         int subId = getSubscriptionId();
         boolean isSmsSimPickActivityNeeded = false;
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
         try {
             ISms iSms = getISmsService();
             if (iSms != null) {
@@ -1475,14 +1474,14 @@
             return;
         }
         // We need to ask the user pick an appropriate subid for the operation.
-        Log.d(TAG, "resolveSubscriptionForOperation isSmsSimPickActivityNeeded is true for package "
-                + context.getPackageName());
+        Log.d(TAG, "resolveSubscriptionForOperation isSmsSimPickActivityNeeded is true for calling"
+                + " package. ");
         try {
             // Create the SMS pick activity and call back once the activity is complete. Can't do
             // it here because we do not have access to the activity context that is performing this
             // operation.
             // Requires that the calling process has the SEND_SMS permission.
-            getITelephony().enqueueSmsPickResult(context.getOpPackageName(),
+            getITelephony().enqueueSmsPickResult(null,
                     new IIntegerConsumer.Stub() {
                         @Override
                         public void accept(int subId) {
@@ -1500,6 +1499,13 @@
         }
     }
 
+    /**
+     * To check the SDK version for SmsManager.sendResolverResult method.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
+    private static final long GET_TARGET_SDK_VERSION_CODE_CHANGE = 145147528L;
+
     private void sendResolverResult(SubscriptionResolverResult resolverResult, int subId,
             boolean pickActivityShown) {
         if (SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -1507,7 +1513,8 @@
             return;
         }
 
-        if (getTargetSdkVersion() <= Build.VERSION_CODES.P && !pickActivityShown) {
+        if (!Compatibility.isChangeEnabled(GET_TARGET_SDK_VERSION_CODE_CHANGE)
+                && !pickActivityShown) {
             // Do not fail, return a success with an INVALID subid for apps targeting P or below
             // that tried to perform an operation and the SMS disambiguation dialog was never shown,
             // as these applications may not have been written to handle the failure case properly.
@@ -1520,19 +1527,6 @@
         }
     }
 
-    private static int getTargetSdkVersion() {
-        final Context context = ActivityThread.currentApplication().getApplicationContext();
-        int targetSdk;
-        try {
-            targetSdk = context.getPackageManager().getApplicationInfo(
-                    context.getOpPackageName(), 0).targetSdkVersion;
-        } catch (PackageManager.NameNotFoundException e) {
-            // Default to old behavior if we can not find this.
-            targetSdk = -1;
-        }
-        return targetSdk;
-    }
-
     private static ITelephony getITelephony() {
         ITelephony binder = ITelephony.Stub.asInterface(
                 ServiceManager.getService(Context.TELEPHONY_SERVICE));
@@ -1616,7 +1610,7 @@
             ISms iSms = getISmsService();
             if (iSms != null) {
                 success = iSms.copyMessageToIccEfForSubscriber(getSubscriptionId(),
-                        ActivityThread.currentPackageName(),
+                        null,
                         status, pdu, smsc);
             }
         } catch (RemoteException ex) {
@@ -1657,7 +1651,7 @@
             ISms iSms = getISmsService();
             if (iSms != null) {
                 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
-                        ActivityThread.currentPackageName(),
+                        null,
                         messageIndex, STATUS_ON_ICC_FREE, null /* pdu */);
             }
         } catch (RemoteException ex) {
@@ -1700,7 +1694,7 @@
             ISms iSms = getISmsService();
             if (iSms != null) {
                 success = iSms.updateMessageOnIccEfForSubscriber(getSubscriptionId(),
-                        ActivityThread.currentPackageName(),
+                        null,
                         messageIndex, newStatus, pdu);
             }
         } catch (RemoteException ex) {
@@ -1752,7 +1746,7 @@
             if (iSms != null) {
                 records = iSms.getAllMessagesFromIccEfForSubscriber(
                         getSubscriptionId(),
-                        ActivityThread.currentPackageName());
+                        null);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -2495,7 +2489,7 @@
         try {
             ISms iccSms = getISmsServiceOrThrow();
             return iccSms.createAppSpecificSmsToken(getSubscriptionId(),
-                    ActivityThread.currentPackageName(), intent);
+                    null, intent);
 
         } catch (RemoteException ex) {
             ex.rethrowFromSystemServer();
@@ -2615,7 +2609,7 @@
         try {
             ISms iccSms = getISmsServiceOrThrow();
             return iccSms.createAppSpecificSmsTokenWithPackageInfo(getSubscriptionId(),
-                    ActivityThread.currentPackageName(), prefixes, intent);
+                    null, prefixes, intent);
 
         } catch (RemoteException ex) {
             ex.rethrowFromSystemServer();
@@ -2706,7 +2700,7 @@
             ISms iccISms = getISmsServiceOrThrow();
             if (iccISms != null) {
                 return iccISms.checkSmsShortCodeDestination(getSubscriptionId(),
-                        ActivityThread.currentPackageName(), null, destAddress, countryIso);
+                        null, null, destAddress, countryIso);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "checkSmsShortCodeDestination() RemoteException", e);
@@ -2742,7 +2736,7 @@
             ISms iSms = getISmsService();
             if (iSms != null) {
                 smsc = iSms.getSmscAddressFromIccEfForSubscriber(
-                        getSubscriptionId(), ActivityThread.currentPackageName());
+                        getSubscriptionId(), null);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -2776,7 +2770,7 @@
             ISms iSms = getISmsService();
             if (iSms != null) {
                 return iSms.setSmscAddressOnIccEfForSubscriber(
-                        smsc, getSubscriptionId(), ActivityThread.currentPackageName());
+                        smsc, getSubscriptionId(), null);
             }
         } catch (RemoteException ex) {
             // ignore it
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d4ab04cc..ea95aac 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -266,7 +266,7 @@
      * <P>Type: TEXT (String)</P>
      */
     /** @hide */
-    public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id";
+    public static final String UNIQUE_KEY_SUBSCRIPTION_ID = SimInfo.UNIQUE_KEY_SUBSCRIPTION_ID;
 
     /**
      * TelephonyProvider column name for a unique identifier for the subscription within the
@@ -275,18 +275,18 @@
      * <P>Type: TEXT (String)</P>
      */
     /** @hide */
-    public static final String ICC_ID = "icc_id";
+    public static final String ICC_ID = SimInfo.ICC_ID;
 
     /**
      * TelephonyProvider column name for user SIM_SlOT_INDEX
      * <P>Type: INTEGER (int)</P>
      */
     /** @hide */
-    public static final String SIM_SLOT_INDEX = "sim_id";
+    public static final String SIM_SLOT_INDEX = SimInfo.SIM_SLOT_INDEX;
 
     /** SIM is not inserted */
     /** @hide */
-    public static final int SIM_NOT_INSERTED = -1;
+    public static final int SIM_NOT_INSERTED = SimInfo.SIM_NOT_INSERTED;
 
     /**
      * The slot-index for Bluetooth Remote-SIM subscriptions
@@ -301,23 +301,7 @@
      * Default value is 0.
      */
     /** @hide */
-    public static final String SUBSCRIPTION_TYPE = "subscription_type";
-
-    /**
-     * TelephonyProvider column name white_listed_apn_data.
-     * It's a bitmask of APN types that will be allowed on this subscription even if it's metered
-     * and mobile data is turned off by the user.
-     * <P>Type: INTEGER (int)</P> For example, if TYPE_MMS is is true, Telephony will allow MMS
-     * data connection to setup even if MMS is metered and mobile_data is turned off on that
-     * subscription.
-     *
-     * Default value is 0.
-     *
-     * @deprecated Replaced by {@link #DATA_ENABLED_OVERRIDE_RULES}
-     * @hide
-     */
-    @Deprecated
-    public static final String WHITE_LISTED_APN_DATA = "white_listed_apn_data";
+    public static final String SUBSCRIPTION_TYPE = SimInfo.SUBSCRIPTION_TYPE;
 
     /**
      * TelephonyProvider column name data_enabled_override_rules.
@@ -330,7 +314,15 @@
      *
      * @hide
      */
-    public static final String DATA_ENABLED_OVERRIDE_RULES = "data_enabled_override_rules";
+    public static final String DATA_ENABLED_OVERRIDE_RULES = SimInfo.DATA_ENABLED_OVERRIDE_RULES;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SUBSCRIPTION_TYPE_"},
+        value = {
+            SUBSCRIPTION_TYPE_LOCAL_SIM,
+            SUBSCRIPTION_TYPE_REMOTE_SIM})
+    public @interface SubscriptionType {}
 
     /**
      * This constant is to designate a subscription as a Local-SIM Subscription.
@@ -338,7 +330,7 @@
      * device.
      * </p>
      */
-    public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0;
+    public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM;
 
     /**
      * This constant is to designate a subscription as a Remote-SIM Subscription.
@@ -364,29 +356,21 @@
      * was never seen before.
      * </p>
      */
-    public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1;
-
-    /** @hide */
-    @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = {"SUBSCRIPTION_TYPE_"},
-        value = {
-            SUBSCRIPTION_TYPE_LOCAL_SIM,
-            SUBSCRIPTION_TYPE_REMOTE_SIM})
-    public @interface SubscriptionType {}
+    public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = SimInfo.SUBSCRIPTION_TYPE_REMOTE_SIM;
 
     /**
      * TelephonyProvider column name for user displayed name.
      * <P>Type: TEXT (String)</P>
      */
     /** @hide */
-    public static final String DISPLAY_NAME = "display_name";
+    public static final String DISPLAY_NAME = SimInfo.DISPLAY_NAME;
 
     /**
      * TelephonyProvider column name for the service provider name for the SIM.
      * <P>Type: TEXT (String)</P>
      */
     /** @hide */
-    public static final String CARRIER_NAME = "carrier_name";
+    public static final String CARRIER_NAME = SimInfo.CARRIER_NAME;
 
     /**
      * Default name resource
@@ -400,44 +384,44 @@
      *
      * @hide
      */
-    public static final String NAME_SOURCE = "name_source";
+    public static final String NAME_SOURCE = SimInfo.NAME_SOURCE;
 
     /**
      * The name_source is the default, which is from the carrier id.
      * @hide
      */
-    public static final int NAME_SOURCE_DEFAULT_SOURCE = 0;
+    public static final int NAME_SOURCE_DEFAULT = SimInfo.NAME_SOURCE_DEFAULT;
 
     /**
      * The name_source is from SIM EF_SPN.
      * @hide
      */
-    public static final int NAME_SOURCE_SIM_SPN = 1;
+    public static final int NAME_SOURCE_SIM_SPN = SimInfo.NAME_SOURCE_SIM_SPN;
 
     /**
      * The name_source is from user input
      * @hide
      */
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
-    public static final int NAME_SOURCE_USER_INPUT = 2;
+    public static final int NAME_SOURCE_USER_INPUT = SimInfo.NAME_SOURCE_USER_INPUT;
 
     /**
      * The name_source is carrier (carrier app, carrier config, etc.)
      * @hide
      */
-    public static final int NAME_SOURCE_CARRIER = 3;
+    public static final int NAME_SOURCE_CARRIER = SimInfo.NAME_SOURCE_CARRIER;
 
     /**
      * The name_source is from SIM EF_PNN.
      * @hide
      */
-    public static final int NAME_SOURCE_SIM_PNN = 4;
+    public static final int NAME_SOURCE_SIM_PNN = SimInfo.NAME_SOURCE_SIM_PNN;
 
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = {"NAME_SOURCE_"},
             value = {
-                    NAME_SOURCE_DEFAULT_SOURCE,
+                    NAME_SOURCE_DEFAULT,
                     NAME_SOURCE_SIM_SPN,
                     NAME_SOURCE_USER_INPUT,
                     NAME_SOURCE_CARRIER,
@@ -450,67 +434,30 @@
      * <P>Type: INTEGER (int)</P>
      */
     /** @hide */
-    public static final String COLOR = "color";
-
-    /** @hide */
-    public static final int COLOR_1 = 0;
-
-    /** @hide */
-    public static final int COLOR_2 = 1;
-
-    /** @hide */
-    public static final int COLOR_3 = 2;
-
-    /** @hide */
-    public static final int COLOR_4 = 3;
-
-    /** @hide */
-    public static final int COLOR_DEFAULT = COLOR_1;
+    public static final String COLOR = SimInfo.COLOR;
 
     /**
      * TelephonyProvider column name for the phone number of a SIM.
      * <P>Type: TEXT (String)</P>
      */
     /** @hide */
-    public static final String NUMBER = "number";
+    public static final String NUMBER = SimInfo.NUMBER;
 
     /**
-     * TelephonyProvider column name for the number display format of a SIM.
+     * TelephonyProvider column name for whether data roaming is enabled.
      * <P>Type: INTEGER (int)</P>
      */
     /** @hide */
-    public static final String DISPLAY_NUMBER_FORMAT = "display_number_format";
-
-    /** @hide */
-    public static final int DISPLAY_NUMBER_NONE = 0;
-
-    /** @hide */
-    public static final int DISPLAY_NUMBER_FIRST = 1;
-
-    /** @hide */
-    public static final int DISPLAY_NUMBER_LAST = 2;
-
-    /** @hide */
-    public static final int DISPLAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;
-
-    /**
-     * TelephonyProvider column name for permission for data roaming of a SIM.
-     * <P>Type: INTEGER (int)</P>
-     */
-    /** @hide */
-    public static final String DATA_ROAMING = "data_roaming";
+    public static final String DATA_ROAMING = SimInfo.DATA_ROAMING;
 
     /** Indicates that data roaming is enabled for a subscription */
-    public static final int DATA_ROAMING_ENABLE = 1;
+    public static final int DATA_ROAMING_ENABLE = SimInfo.DATA_ROAMING_ENABLE;
 
     /** Indicates that data roaming is disabled for a subscription */
-    public static final int DATA_ROAMING_DISABLE = 0;
+    public static final int DATA_ROAMING_DISABLE = SimInfo.DATA_ROAMING_DISABLE;
 
     /** @hide */
-    public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;
-
-    /** @hide */
-    public static final int SIM_PROVISIONED = 0;
+    public static final int DATA_ROAMING_DEFAULT = SimInfo.DATA_ROAMING_DEFAULT;
 
     /**
      * TelephonyProvider column name for subscription carrier id.
@@ -518,61 +465,61 @@
      * <p>Type: INTEGER (int) </p>
      * @hide
      */
-    public static final String CARRIER_ID = "carrier_id";
+    public static final String CARRIER_ID = SimInfo.CARRIER_ID;
 
     /**
      * @hide A comma-separated list of EHPLMNs associated with the subscription
      * <P>Type: TEXT (String)</P>
      */
-    public static final String EHPLMNS = "ehplmns";
+    public static final String EHPLMNS = SimInfo.EHPLMNS;
 
     /**
      * @hide A comma-separated list of HPLMNs associated with the subscription
      * <P>Type: TEXT (String)</P>
      */
-    public static final String HPLMNS = "hplmns";
+    public static final String HPLMNS = SimInfo.HPLMNS;
 
     /**
      * TelephonyProvider column name for the MCC associated with a SIM, stored as a string.
      * <P>Type: TEXT (String)</P>
      * @hide
      */
-    public static final String MCC_STRING = "mcc_string";
+    public static final String MCC_STRING = SimInfo.MCC_STRING;
 
     /**
      * TelephonyProvider column name for the MNC associated with a SIM, stored as a string.
      * <P>Type: TEXT (String)</P>
      * @hide
      */
-    public static final String MNC_STRING = "mnc_string";
+    public static final String MNC_STRING = SimInfo.MNC_STRING;
 
     /**
      * TelephonyProvider column name for the MCC associated with a SIM.
      * <P>Type: INTEGER (int)</P>
      * @hide
      */
-    public static final String MCC = "mcc";
+    public static final String MCC = SimInfo.MCC;
 
     /**
      * TelephonyProvider column name for the MNC associated with a SIM.
      * <P>Type: INTEGER (int)</P>
      * @hide
      */
-    public static final String MNC = "mnc";
+    public static final String MNC = SimInfo.MNC;
 
     /**
      * TelephonyProvider column name for the iso country code associated with a SIM.
      * <P>Type: TEXT (String)</P>
      * @hide
      */
-    public static final String ISO_COUNTRY_CODE = "iso_country_code";
+    public static final String ISO_COUNTRY_CODE = SimInfo.ISO_COUNTRY_CODE;
 
     /**
      * TelephonyProvider column name for the sim provisioning status associated with a SIM.
      * <P>Type: INTEGER (int)</P>
      * @hide
      */
-    public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status";
+    public static final String SIM_PROVISIONING_STATUS = SimInfo.SIM_PROVISIONING_STATUS;
 
     /**
      * TelephonyProvider column name for whether a subscription is embedded (that is, present on an
@@ -580,7 +527,7 @@
      * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded.
      * @hide
      */
-    public static final String IS_EMBEDDED = "is_embedded";
+    public static final String IS_EMBEDDED = SimInfo.IS_EMBEDDED;
 
     /**
      * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of the
@@ -588,7 +535,7 @@
      * <P>Type: TEXT (String)</P>
      * @hide
      */
-    public static final String CARD_ID = "card_id";
+    public static final String CARD_ID = SimInfo.CARD_ID;
 
     /**
      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
@@ -596,7 +543,7 @@
      * <p>TYPE: BLOB
      * @hide
      */
-    public static final String ACCESS_RULES = "access_rules";
+    public static final String ACCESS_RULES = SimInfo.ACCESS_RULES;
 
     /**
      * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from
@@ -606,7 +553,7 @@
      * @hide
      */
     public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS =
-            "access_rules_from_carrier_configs";
+            SimInfo.ACCESS_RULES_FROM_CARRIER_CONFIGS;
 
     /**
      * TelephonyProvider column name identifying whether an embedded subscription is on a removable
@@ -616,79 +563,79 @@
      * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable.
      * @hide
      */
-    public static final String IS_REMOVABLE = "is_removable";
+    public static final String IS_REMOVABLE = SimInfo.IS_REMOVABLE;
 
     /**
      *  TelephonyProvider column name for extreme threat in CB settings
      * @hide
      */
-    public static final String CB_EXTREME_THREAT_ALERT = "enable_cmas_extreme_threat_alerts";
+    public static final String CB_EXTREME_THREAT_ALERT = SimInfo.CB_EXTREME_THREAT_ALERT;
 
     /**
      * TelephonyProvider column name for severe threat in CB settings
      *@hide
      */
-    public static final String CB_SEVERE_THREAT_ALERT = "enable_cmas_severe_threat_alerts";
+    public static final String CB_SEVERE_THREAT_ALERT = SimInfo.CB_SEVERE_THREAT_ALERT;
 
     /**
      * TelephonyProvider column name for amber alert in CB settings
      *@hide
      */
-    public static final String CB_AMBER_ALERT = "enable_cmas_amber_alerts";
+    public static final String CB_AMBER_ALERT = SimInfo.CB_AMBER_ALERT;
 
     /**
      * TelephonyProvider column name for emergency alert in CB settings
      *@hide
      */
-    public static final String CB_EMERGENCY_ALERT = "enable_emergency_alerts";
+    public static final String CB_EMERGENCY_ALERT = SimInfo.CB_EMERGENCY_ALERT;
 
     /**
      * TelephonyProvider column name for alert sound duration in CB settings
      *@hide
      */
-    public static final String CB_ALERT_SOUND_DURATION = "alert_sound_duration";
+    public static final String CB_ALERT_SOUND_DURATION = SimInfo.CB_ALERT_SOUND_DURATION;
 
     /**
      * TelephonyProvider column name for alert reminder interval in CB settings
      *@hide
      */
-    public static final String CB_ALERT_REMINDER_INTERVAL = "alert_reminder_interval";
+    public static final String CB_ALERT_REMINDER_INTERVAL = SimInfo.CB_ALERT_REMINDER_INTERVAL;
 
     /**
      * TelephonyProvider column name for enabling vibrate in CB settings
      *@hide
      */
-    public static final String CB_ALERT_VIBRATE = "enable_alert_vibrate";
+    public static final String CB_ALERT_VIBRATE = SimInfo.CB_ALERT_VIBRATE;
 
     /**
      * TelephonyProvider column name for enabling alert speech in CB settings
      *@hide
      */
-    public static final String CB_ALERT_SPEECH = "enable_alert_speech";
+    public static final String CB_ALERT_SPEECH = SimInfo.CB_ALERT_SPEECH;
 
     /**
      * TelephonyProvider column name for ETWS test alert in CB settings
      *@hide
      */
-    public static final String CB_ETWS_TEST_ALERT = "enable_etws_test_alerts";
+    public static final String CB_ETWS_TEST_ALERT = SimInfo.CB_ETWS_TEST_ALERT;
 
     /**
      * TelephonyProvider column name for enable channel50 alert in CB settings
      *@hide
      */
-    public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts";
+    public static final String CB_CHANNEL_50_ALERT = SimInfo.CB_CHANNEL_50_ALERT;
 
     /**
      * TelephonyProvider column name for CMAS test alert in CB settings
      *@hide
      */
-    public static final String CB_CMAS_TEST_ALERT= "enable_cmas_test_alerts";
+    public static final String CB_CMAS_TEST_ALERT = SimInfo.CB_CMAS_TEST_ALERT;
 
     /**
      * TelephonyProvider column name for Opt out dialog in CB settings
      *@hide
      */
-    public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog";
+    public static final String CB_OPT_OUT_DIALOG = SimInfo.CB_OPT_OUT_DIALOG;
 
     /**
      * TelephonyProvider column name for enable Volte.
@@ -697,37 +644,44 @@
      * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}.
      *@hide
      */
-    public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled";
+    public static final String ENHANCED_4G_MODE_ENABLED = SimInfo.ENHANCED_4G_MODE_ENABLED;
 
     /**
      * TelephonyProvider column name for enable VT (Video Telephony over IMS)
      *@hide
      */
-    public static final String VT_IMS_ENABLED = "vt_ims_enabled";
+    public static final String VT_IMS_ENABLED = SimInfo.VT_IMS_ENABLED;
 
     /**
      * TelephonyProvider column name for enable Wifi calling
      *@hide
      */
-    public static final String WFC_IMS_ENABLED = "wfc_ims_enabled";
+    public static final String WFC_IMS_ENABLED = SimInfo.WFC_IMS_ENABLED;
 
     /**
      * TelephonyProvider column name for Wifi calling mode
      *@hide
      */
-    public static final String WFC_IMS_MODE = "wfc_ims_mode";
+    public static final String WFC_IMS_MODE = SimInfo.WFC_IMS_MODE;
 
     /**
      * TelephonyProvider column name for Wifi calling mode in roaming
      *@hide
      */
-    public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode";
+    public static final String WFC_IMS_ROAMING_MODE = SimInfo.WFC_IMS_ROAMING_MODE;
 
     /**
      * TelephonyProvider column name for enable Wifi calling in roaming
      *@hide
      */
-    public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled";
+    public static final String WFC_IMS_ROAMING_ENABLED = SimInfo.WFC_IMS_ROAMING_ENABLED;
+
+    /**
+     * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this
+     * subscription.
+     * @hide
+     */
+    public static final String IMS_RCS_UCE_ENABLED = SimInfo.IMS_RCS_UCE_ENABLED;
 
     /**
      * TelephonyProvider column name for whether a subscription is opportunistic, that is,
@@ -736,7 +690,7 @@
      * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic.
      * @hide
      */
-    public static final String IS_OPPORTUNISTIC = "is_opportunistic";
+    public static final String IS_OPPORTUNISTIC = SimInfo.IS_OPPORTUNISTIC;
 
     /**
      * TelephonyProvider column name for group ID. Subscriptions with same group ID
@@ -745,7 +699,7 @@
      *
      * @hide
      */
-    public static final String GROUP_UUID = "group_uuid";
+    public static final String GROUP_UUID = SimInfo.GROUP_UUID;
 
     /**
      * TelephonyProvider column name for group owner. It's the package name who created
@@ -753,14 +707,7 @@
      *
      * @hide
      */
-    public static final String GROUP_OWNER = "group_owner";
-
-    /**
-     * TelephonyProvider column name for whether a subscription is metered or not, that is, whether
-     * the network it connects to charges for subscription or not. For example, paid CBRS or unpaid.
-     * @hide
-     */
-    public static final String IS_METERED = "is_metered";
+    public static final String GROUP_OWNER = SimInfo.GROUP_OWNER;
 
     /**
      * TelephonyProvider column name for the profile class of a subscription
@@ -768,7 +715,7 @@
      * <P>Type: INTEGER (int)</P>
      * @hide
      */
-    public static final String PROFILE_CLASS = "profile_class";
+    public static final String PROFILE_CLASS = SimInfo.PROFILE_CLASS;
 
     /**
      * Profile class of the subscription
@@ -776,11 +723,11 @@
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "PROFILE_CLASS_" }, value = {
-            PROFILE_CLASS_TESTING,
-            PROFILE_CLASS_PROVISIONING,
-            PROFILE_CLASS_OPERATIONAL,
-            PROFILE_CLASS_UNSET,
-            PROFILE_CLASS_DEFAULT
+            SimInfo.PROFILE_CLASS_TESTING,
+            SimInfo.PROFILE_CLASS_PROVISIONING,
+            SimInfo.PROFILE_CLASS_OPERATIONAL,
+            SimInfo.PROFILE_CLASS_UNSET,
+            SimInfo.PROFILE_CLASS_DEFAULT
     })
     public @interface ProfileClass {}
 
@@ -792,7 +739,7 @@
      * @hide
      */
     @SystemApi
-    public static final int PROFILE_CLASS_TESTING = 0;
+    public static final int PROFILE_CLASS_TESTING = SimInfo.PROFILE_CLASS_TESTING;
 
     /**
      * A provisioning profile is pre-loaded onto the eUICC and
@@ -801,7 +748,7 @@
      * @hide
      */
     @SystemApi
-    public static final int PROFILE_CLASS_PROVISIONING = 1;
+    public static final int PROFILE_CLASS_PROVISIONING = SimInfo.PROFILE_CLASS_PROVISIONING;
 
     /**
      * An operational profile can be pre-loaded or downloaded
@@ -810,7 +757,7 @@
      * @hide
      */
     @SystemApi
-    public static final int PROFILE_CLASS_OPERATIONAL = 2;
+    public static final int PROFILE_CLASS_OPERATIONAL = SimInfo.PROFILE_CLASS_OPERATIONAL;
 
     /**
      * The profile class is unset. This occurs when profile class
@@ -819,14 +766,14 @@
      * @hide
      */
     @SystemApi
-    public static final int PROFILE_CLASS_UNSET = -1;
+    public static final int PROFILE_CLASS_UNSET = SimInfo.PROFILE_CLASS_UNSET;
 
     /**
      * Default profile class
      * @hide
      */
     @SystemApi
-    public static final int PROFILE_CLASS_DEFAULT = PROFILE_CLASS_UNSET;
+    public static final int PROFILE_CLASS_DEFAULT = SimInfo.PROFILE_CLASS_DEFAULT;
 
     /**
      * IMSI (International Mobile Subscriber Identity).
@@ -834,13 +781,19 @@
      * @hide
      */
     //TODO: add @SystemApi
-    public static final String IMSI = "imsi";
+    public static final String IMSI = SimInfo.IMSI;
 
     /**
      * Whether uicc applications is set to be enabled or disabled. By default it's enabled.
      * @hide
      */
-    public static final String UICC_APPLICATIONS_ENABLED = "uicc_applications_enabled";
+    public static final String UICC_APPLICATIONS_ENABLED = SimInfo.UICC_APPLICATIONS_ENABLED;
+
+    /**
+     * Indicate which network type is allowed. By default it's enabled.
+     * @hide
+     */
+    public static final String ALLOWED_NETWORK_TYPES = SimInfo.ALLOWED_NETWORK_TYPES;
 
     /**
      * Broadcast Action: The user has changed one of the default subs related to
@@ -2353,7 +2306,28 @@
             try {
                 return Integer.parseInt(result);
             } catch (NumberFormatException err) {
-                logd("getBooleanSubscriptionProperty NumberFormat exception");
+                logd("getIntegerSubscriptionProperty NumberFormat exception");
+            }
+        }
+        return defValue;
+    }
+
+    /**
+     * Returns long value corresponding to query result.
+     * @param subId Subscription Id of Subscription
+     * @param propKey Column name in SubscriptionInfo database
+     * @param defValue Default long value to be returned
+     * @return long result value to be returned
+     * @hide
+     */
+    public static long getLongSubscriptionProperty(int subId, String propKey, long defValue,
+                                                     Context context) {
+        String result = getSubscriptionProperty(subId, propKey, context);
+        if (result != null) {
+            try {
+                return Long.parseLong(result);
+            } catch (NumberFormatException err) {
+                logd("getLongSubscriptionProperty NumberFormat exception");
             }
         }
         return defValue;
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 839889f..3dff079 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -37,7 +37,6 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.WorkerThread;
-import android.app.ActivityThread;
 import android.app.PendingIntent;
 import android.compat.Compatibility;
 import android.compat.annotation.ChangeId;
@@ -109,8 +108,6 @@
 import com.android.internal.telephony.SmsApplication;
 import com.android.telephony.Rlog;
 
-import dalvik.system.VMRuntime;
-
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -374,8 +371,17 @@
         // effort and get the context from the current activity thread.
         if (mContext != null) {
             return mContext.getOpPackageName();
+        } else {
+            ITelephony telephony = getITelephony();
+            if (telephony == null) return null;
+            try {
+                return telephony.getCurrentPackageName();
+            } catch (RemoteException ex) {
+                return null;
+            } catch (NullPointerException ex) {
+                return null;
+            }
         }
-        return ActivityThread.currentOpPackageName();
     }
 
     private String getFeatureId() {
@@ -1222,6 +1228,80 @@
     public static final String EXTRA_SUBSCRIPTION_ID = "android.telephony.extra.SUBSCRIPTION_ID";
 
     /**
+     * Broadcast Action: The Service Provider string(s) have been updated. Activities or
+     * services that use these strings should update their display.
+     *
+     * <p>The intent will have the following extra values:
+     * <dl>
+     *   <dt>{@link #EXTRA_SHOW_PLMN}</dt>
+     *   <dd>Boolean that indicates whether the PLMN should be shown.</dd>
+     *   <dt>{@link #EXTRA_PLMN}</dt>
+     *   <dd>The operator name of the registered network, as a string.</dd>
+     *   <dt>{@link #EXTRA_SHOW_SPN}</dt>
+     *   <dd>Boolean that indicates whether the SPN should be shown.</dd>
+     *   <dt>{@link #EXTRA_SPN}</dt>
+     *   <dd>The service provider name, as a string.</dd>
+     *   <dt>{@link #EXTRA_DATA_SPN}</dt>
+     *   <dd>The service provider name for data service, as a string.</dd>
+     * </dl>
+     *
+     * Note that {@link #EXTRA_SHOW_PLMN} may indicate that {@link #EXTRA_PLMN} should be displayed,
+     * even though the value for {@link #EXTRA_PLMN} is null. This can happen, for example, if the
+     * phone has not registered to a network yet. In this case the receiver may substitute an
+     * appropriate placeholder string (eg, "No service").
+     *
+     * It is recommended to display {@link #EXTRA_PLMN} before / above {@link #EXTRA_SPN} if
+     * both are displayed.
+     *
+     * <p>Note: this is a protected intent that can only be sent by the system.
+     * @hide
+     */
+    @SystemApi
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SERVICE_PROVIDERS_UPDATED =
+            "android.telephony.action.SERVICE_PROVIDERS_UPDATED";
+
+    /**
+     * String intent extra to be used with {@link ACTION_SERVICE_PROVIDERS_UPDATED} to indicate
+     * whether the PLMN should be shown.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SHOW_PLMN = "android.telephony.extra.SHOW_PLMN";
+
+    /**
+     * String intent extra to be used with {@link ACTION_SERVICE_PROVIDERS_UPDATED} to indicate
+     * the operator name of the registered network.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_PLMN = "android.telephony.extra.PLMN";
+
+    /**
+     * String intent extra to be used with {@link ACTION_SERVICE_PROVIDERS_UPDATED} to indicate
+     * whether the PLMN should be shown.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SHOW_SPN = "android.telephony.extra.SHOW_SPN";
+
+    /**
+     * String intent extra to be used with {@link ACTION_SERVICE_PROVIDERS_UPDATED} to indicate
+     * the service provider name.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_SPN = "android.telephony.extra.SPN";
+
+    /**
+     * String intent extra to be used with {@link ACTION_SERVICE_PROVIDERS_UPDATED} to indicate
+     * the service provider name for data service.
+     * @hide
+     */
+    @SystemApi
+    public static final String EXTRA_DATA_SPN = "android.telephony.extra.DATA_SPN";
+
+    /**
      * Broadcast intent action indicating that when data stall recovery is attempted by Telephony,
      * intended for report every data stall recovery step attempted.
      *
@@ -5109,6 +5189,13 @@
     public static final int DATA_DISCONNECTING = 4;
 
     /**
+     * To check the SDK version for {@link TelephonyManager#getDataState}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
+    private static final long GET_DATA_STATE_CODE_CHANGE = 147600208L;
+
+    /**
      * Returns a constant indicating the current data connection state
      * (cellular).
      *
@@ -5126,7 +5213,7 @@
             int state = telephony.getDataStateForSubId(
                     getSubId(SubscriptionManager.getActiveDataSubscriptionId()));
             if (state == TelephonyManager.DATA_DISCONNECTING
-                    && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) {
+                    && !Compatibility.isChangeEnabled(GET_DATA_STATE_CODE_CHANGE)) {
                 return TelephonyManager.DATA_CONNECTED;
             }
 
@@ -5179,6 +5266,13 @@
     //
 
     /**
+     * To check the SDK version for {@link TelephonyManager#listen}.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.P)
+    private static final long LISTEN_CODE_CHANGE = 147600208L;
+
+    /**
      * Registers a listener object to receive notification of changes
      * in specified telephony states.
      * <p>
@@ -5217,7 +5311,7 @@
                 // subId from PhoneStateListener is deprecated Q on forward, use the subId from
                 // TelephonyManager instance. keep using subId from PhoneStateListener for pre-Q.
                 int subId = mSubId;
-                if (VMRuntime.getRuntime().getTargetSdkVersion() >= Build.VERSION_CODES.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.
                     //  TODO: remove this once we completely get rid of mSubId in PhoneStateListener
@@ -6878,6 +6972,30 @@
         }
     }
 
+
+    /**
+     * Resets the {@link android.telephony.ims.ImsService} associated with the specified sim slot.
+     * Used by diagnostic apps to force the IMS stack to be disabled and re-enabled in an effort to
+     * recover from scenarios where the {@link android.telephony.ims.ImsService} gets in to a bad
+     * state.
+     *
+     * @param slotIndex the sim slot to reset the IMS stack on.
+     * @hide */
+    @SystemApi
+    @WorkerThread
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void resetIms(int slotIndex) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.resetIms(slotIndex);
+            }
+        } catch (RemoteException e) {
+            Rlog.e(TAG, "toggleImsOnOff, RemoteException: "
+                    + e.getMessage());
+        }
+    }
+
     /**
      * Enables IMS for the framework. This will trigger IMS registration and ImsFeature capability
      * status updates, if not already enabled.
@@ -7286,7 +7404,9 @@
      *
      * @return the preferred network type.
      * @hide
+     * @deprecated Use {@link #getPreferredNetworkTypeBitmask} instead.
      */
+    @Deprecated
     @RequiresPermission((android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE))
     @UnsupportedAppUsage
     public @PrefNetworkMode int getPreferredNetworkType(int subId) {
@@ -7331,6 +7451,30 @@
     }
 
     /**
+     * Get the allowed network types.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @return the allowed network type bitmask
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @SystemApi
+    public @NetworkTypeBitMask long getAllowedNetworkTypes() {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.getAllowedNetworkTypes(getSubId());
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "getAllowedNetworkTypes RemoteException", ex);
+        }
+        return -1;
+    }
+
+    /**
      * Sets the network selection mode to automatic.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
@@ -7585,7 +7729,9 @@
      * @param networkType the preferred network type
      * @return true on success; false on any failure.
      * @hide
+     * @deprecated Use {@link #setPreferredNetworkTypeBitmask} instead.
      */
+    @Deprecated
     @UnsupportedAppUsage
     public boolean setPreferredNetworkType(int subId, @PrefNetworkMode int networkType) {
         try {
@@ -7600,7 +7746,8 @@
     }
 
     /**
-     * Set the preferred network type bitmask.
+     * Set the preferred network type bitmask but if {@link #setAllowedNetworkTypes} has been set,
+     * only the allowed network type will set to the modem.
      *
      * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the
      * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
@@ -7630,6 +7777,29 @@
     }
 
     /**
+     * Set the allowed network types of the device. This is for carrier or privileged apps to
+     * enable/disable certain network types on the device. The user preferred network types should
+     * be set through {@link #setPreferredNetworkTypeBitmask}.
+     *
+     * @param allowedNetworkTypes The bitmask of allowed network types.
+     * @return true on success; false on any failure.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    @SystemApi
+    public boolean setAllowedNetworkTypes(@NetworkTypeBitMask long allowedNetworkTypes) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                return telephony.setAllowedNetworkTypes(getSubId(), allowedNetworkTypes);
+            }
+        } catch (RemoteException ex) {
+            Rlog.e(TAG, "setAllowedNetworkTypes RemoteException", ex);
+        }
+        return false;
+    }
+
+    /**
      * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
      *
      * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
@@ -10501,6 +10671,27 @@
     }
 
     /**
+     * Enable or disable signal strength changes from radio will always be reported in any
+     * condition (e.g. screen is off). This is only allowed for System caller.
+     *
+     * @param isEnabled {@code true} for enabling; {@code false} for disabling.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setAlwaysReportSignalStrength(boolean isEnabled) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                telephony.setAlwaysReportSignalStrength(getSubId(), isEnabled);
+            }
+        } catch (RemoteException ex) {
+            Log.e(TAG, "setAlwaysReportSignalStrength RemoteException", ex);
+            ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Get the most recently available signal strength information.
      *
      * Get the most recent SignalStrength information reported by the modem. Due
diff --git a/telephony/java/android/telephony/ims/ImsException.java b/telephony/java/android/telephony/ims/ImsException.java
index cb3f0f9..643f452 100644
--- a/telephony/java/android/telephony/ims/ImsException.java
+++ b/telephony/java/android/telephony/ims/ImsException.java
@@ -61,7 +61,6 @@
      * This is a configuration error and there should be no retry. The subscription used for this
      * operation is either invalid or has become inactive. The active subscriptions can be queried
      * with {@link SubscriptionManager#getActiveSubscriptionInfoList()}.
-     * @hide
      */
     public static final int CODE_ERROR_INVALID_SUBSCRIPTION = 3;
 
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index c66672f..ba8e90f 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -57,7 +57,8 @@
  * registration and MmTel capability status callbacks, as well as query/modify user settings for the
  * associated subscription.
  *
- * @see #createForSubscriptionId(int)
+ * Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an instance of this
+ * manager.
  */
 public class ImsMmTelManager implements RegistrationManager {
 
@@ -225,8 +226,13 @@
      * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
      *
      * @throws IllegalArgumentException if the subscription is invalid.
-     *
+     * @deprecated Use {@link android.telephony.ims.ImsManager#getImsMmTelManager(int)} to get an
+     * instance of this class.
+     * @hide
      */
+    @SystemApi
+    @TestApi
+    @Deprecated
     @SuppressAutoDoc // No support for device / profile owner or carrier privileges (b/72967236).
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
@@ -242,7 +248,7 @@
     }
 
     /**
-     * Only visible for testing, use {@link #createForSubscriptionId(int)} instead.
+     * Only visible for testing, use {@link ImsManager#getImsMmTelManager(int)} instead.
      * @hide
      */
     @VisibleForTesting
@@ -252,7 +258,7 @@
 
     /**
      * Registers a {@link RegistrationCallback} with the system, which will provide registration
-     * updates for the subscription specified in {@link #createForSubscriptionId(int)}. Use
+     * updates for the subscription specified in {@link ImsManager#getImsMmTelManager(int)}. Use
      * {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to Subscription changed
      * events and call {@link #unregisterImsRegistrationCallback(RegistrationCallback)} to clean up.
      *
@@ -450,7 +456,7 @@
     /**
      * Registers a {@link CapabilityCallback} with the system, which will provide MmTel service
      * availability updates for the subscription specified in
-     * {@link #createForSubscriptionId(int)}. The method {@see #isAvailable(int, int)}
+     * {@link ImsManager#getImsMmTelManager(int)}. The method {@see #isAvailable(int, int)}
      * can also be used to query this information at any time.
      *
      * Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 62bc2ae..2b3072e 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -60,9 +60,10 @@
  * The telephony framework will then bind to the ImsService you have defined in your manifest
  * if you are either:
  * 1) Defined as the default ImsService for the device in the device overlay using
- *    "config_ims_package".
+ *    "config_ims_mmtel_package" or "config_ims_rcs_package".
  * 2) Defined as a Carrier Provided ImsService in the Carrier Configuration using
- *    {@link CarrierConfigManager#KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING}.
+ *    {@link CarrierConfigManager#KEY_CONFIG_IMS_MMTEL_PACKAGE_OVERRIDE_STRING} or
+ *    {@link CarrierConfigManager#KEY_CONFIG_IMS_RCS_PACKAGE_OVERRIDE_STRING}.
  *
  * There are two ways to define to the platform which {@link ImsFeature}s this {@link ImsService}
  * supports, dynamic or static definitions.
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index 3e2903f..57b9b7a 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -16,10 +16,11 @@
 
 package android.telephony.ims;
 
-import android.annotation.IntDef;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -37,6 +38,7 @@
  * @hide
  */
 @SystemApi
+@TestApi
 public final class RcsContactUceCapability implements Parcelable {
 
     /** Supports 1-to-1 chat */
@@ -99,11 +101,16 @@
     public static final int CAPABILITY_CHAT_BOT_ROLE = (1 << 27);
     /** Supports the unidirectional plug-ins framework. */
     public static final int CAPABILITY_PLUG_IN = (1 << 28);
+    /** Supports standalone Chatbot communication. */
+    public static final int CAPABILITY_STANDALONE_CHAT_BOT = (1 << 29);
+    /** Supports MMTEL based call composer. */
+    public static final int CAPABILITY_MMTEL_CALL_COMPOSER = (1 << 30);
+
 
 
     /** @hide*/
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef(prefix = "CAPABILITY_", flag = true, value = {
+    @LongDef(prefix = "CAPABILITY_", flag = true, value = {
             CAPABILITY_CHAT_STANDALONE,
             CAPABILITY_CHAT_SESSION,
             CAPABILITY_CHAT_SESSION_STORE_FORWARD,
@@ -132,7 +139,9 @@
             CAPABILITY_SHARED_SKETCH,
             CAPABILITY_CHAT_BOT,
             CAPABILITY_CHAT_BOT_ROLE,
-            CAPABILITY_PLUG_IN
+            CAPABILITY_PLUG_IN,
+            CAPABILITY_STANDALONE_CHAT_BOT,
+            CAPABILITY_MMTEL_CALL_COMPOSER
     })
     public @interface CapabilityFlag {}
 
@@ -159,11 +168,11 @@
          * @param type The capability to map to a service URI that is different from the contact's
          *         URI.
          */
-        public @NonNull Builder add(@CapabilityFlag int type, @NonNull Uri serviceUri) {
+        public @NonNull Builder add(@CapabilityFlag long type, @NonNull Uri serviceUri) {
             mCapabilities.mCapabilities |= type;
             // Put each of these capabilities into the map separately.
-            for (int shift = 0; shift < Integer.SIZE; shift++) {
-                int cap = type & (1 << shift);
+            for (long shift = 0; shift < Integer.SIZE; shift++) {
+                long cap = type & (1 << shift);
                 if (cap != 0) {
                     mCapabilities.mServiceMap.put(cap, serviceUri);
                     // remove that capability from the field.
@@ -181,7 +190,7 @@
          * Add a UCE capability flag that this contact supports.
          * @param type the capability that the contact supports.
          */
-        public @NonNull Builder add(@CapabilityFlag int type) {
+        public @NonNull Builder add(@CapabilityFlag long type) {
             mCapabilities.mCapabilities |= type;
             return this;
         }
@@ -207,7 +216,7 @@
     private final Uri mContactUri;
     private long mCapabilities;
     private List<String> mExtensionTags = new ArrayList<>();
-    private Map<Integer, Uri> mServiceMap = new HashMap<>();
+    private Map<Long, Uri> mServiceMap = new HashMap<>();
 
     /**
      * Use {@link Builder} to build an instance of this interface.
@@ -225,7 +234,7 @@
         // read mServiceMap as key,value pair
         int mapSize = in.readInt();
         for (int i = 0; i < mapSize; i++) {
-            mServiceMap.put(in.readInt(), in.readParcelable(Uri.class.getClassLoader()));
+            mServiceMap.put(in.readLong(), in.readParcelable(Uri.class.getClassLoader()));
         }
     }
 
@@ -250,8 +259,8 @@
         // write mServiceMap as key,value pairs
         int mapSize = mServiceMap.keySet().size();
         out.writeInt(mapSize);
-        for (int key : mServiceMap.keySet()) {
-            out.writeInt(key);
+        for (long key : mServiceMap.keySet()) {
+            out.writeLong(key);
             out.writeParcelable(mServiceMap.get(key), 0);
         }
     }
@@ -266,7 +275,7 @@
      * @param type The capability flag to query.
      * @return true if the capability flag specified is set, false otherwise.
      */
-    public boolean isCapable(@CapabilityFlag int type) {
+    public boolean isCapable(@CapabilityFlag long type) {
         return (mCapabilities & type) > 0;
     }
 
@@ -290,13 +299,13 @@
      * <p>
      * This will typically be the contact {@link Uri} available via {@link #getContactUri()} unless
      * a different service {@link Uri} was associated with this capability using
-     * {@link Builder#add(int, Uri)}.
+     * {@link Builder#add(long, Uri)}.
      *
      * @return a String containing the {@link Uri} associated with the service tag or
      * {@code null} if this capability is not set as capable.
-     * @see #isCapable(int)
+     * @see #isCapable(long)
      */
-    public @Nullable Uri getServiceUri(@CapabilityFlag int type) {
+    public @Nullable Uri getServiceUri(@CapabilityFlag long type) {
         Uri result = mServiceMap.getOrDefault(type, null);
         // If the capability is capable, but does not have a service URI associated, use the default
         // contact URI.
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index b47bcb9..d3f393a 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -21,6 +21,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.net.Uri;
 import android.os.Binder;
@@ -29,6 +31,7 @@
 import android.os.ServiceManager;
 import android.telephony.ims.aidl.IImsRcsController;
 import android.telephony.ims.aidl.IRcsUceControllerCallback;
+import android.telephony.ims.feature.RcsFeature;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
@@ -42,6 +45,8 @@
  * @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class.
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsUceAdapter {
     private static final String TAG = "RcsUceAdapter";
 
@@ -197,6 +202,7 @@
     /**
      * Not to be instantiated directly, use
      * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
+     * @hide
      */
     RcsUceAdapter(int subId) {
         mSubId = subId;
@@ -222,7 +228,7 @@
      * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
      */
     @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public void requestCapabilities(@CallbackExecutor Executor executor,
+    public void requestCapabilities(@NonNull @CallbackExecutor Executor executor,
             @NonNull List<Uri> contactNumbers,
             @NonNull CapabilitiesCallback c) throws ImsException {
         if (c == null) {
@@ -299,7 +305,7 @@
      * for the associated subscription.
      *
      * @return true if the user’s setting for UCE is enabled, false otherwise. If false,
-     * {@link ImsRcsManager#isCapable(int)} will return false for
+     * {@link ImsRcsManager#isCapable(int, int)} will return false for
      * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} and
      * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE}
      * @see #setUceSettingEnabled(boolean)
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index f3aea49..a3ce1b5 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -513,7 +513,7 @@
      * @param callProfile The {@link ImsCallProfile} IMS call profile with details.
      *        This can be null if no call information is available for the rejected call.
      * @param reason The {@link ImsReasonInfo} call rejection reason.
-     * * @hide
+     * @hide
      */
     @SystemApi @TestApi
     public final void notifyRejectedCall(@NonNull ImsCallProfile callProfile,
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 501e0e8..e4efc2043 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -349,9 +349,8 @@
      *
      * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if
      * it is supported by the device.
-     * @hide
      */
-    public RcsSipOptionsImplBase getOptionsExchangeImpl() {
+    public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() {
         // Base Implementation, override to implement functionality
         return new RcsSipOptionsImplBase();
     }
@@ -365,9 +364,8 @@
      *
      * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence
      * exchange if it is supported by the device.
-     * @hide
      */
-    public RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
+    public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
         // Base Implementation, override to implement functionality.
         return new RcsPresenceExchangeImplBase();
     }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index f4367da..e8f69ea 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -410,6 +410,13 @@
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
+     *               The {@link android.telecom.InCallService} (dialer app) can use the
+     *               {@link android.telecom.Call#reject(int)} API to reject a call while specifying
+     *               a user-indicated reason for rejecting the call.
+     *               Normal call declines ({@link android.telecom.Call#REJECT_REASON_DECLINED}) will
+     *               map to {@link ImsReasonInfo#CODE_USER_DECLINE}.
+     *               Unwanted calls ({@link android.telecom.Call#REJECT_REASON_UNWANTED}) will map
+     *               to {@link ImsReasonInfo#CODE_SIP_USER_MARKED_UNWANTED}.
      * {@link ImsCallSession.Listener#callSessionStartFailed}
      */
     public void reject(int reason) {
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
index fda295a..a24af2f 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
@@ -17,6 +17,8 @@
 package android.telephony.ims.stub;
 
 import android.annotation.IntDef;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.aidl.IRcsFeatureListener;
@@ -32,6 +34,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsCapabilityExchange {
 
     /**  Service is unknown. */
diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
index bb03448..f200ea2 100644
--- a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
@@ -18,6 +18,8 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
@@ -37,6 +39,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsPresenceExchangeImplBase extends RcsCapabilityExchange {
 
     private static final String LOG_TAG = "RcsPresenceExchangeIB";
diff --git a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
index 1c68fc0..355c4dd 100644
--- a/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsSipOptionsImplBase.java
@@ -19,6 +19,8 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.telephony.ims.ImsException;
@@ -35,6 +37,8 @@
  *
  * @hide
  */
+@SystemApi
+@TestApi
 public class RcsSipOptionsImplBase extends RcsCapabilityExchange {
 
     private static final String LOG_TAG = "RcsSipOptionsImplBase";
@@ -69,6 +73,11 @@
      */
     public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4;
 
+    /**
+     * Indicates that the remote user responded with a 400 BAD REQUEST response.
+     */
+    public static final int RESPONSE_BAD_REQUEST = 5;
+
     /** @hide*/
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "RESPONSE_", value = {
@@ -77,7 +86,8 @@
             RESPONSE_TEMPORARILY_UNAVAILABLE,
             RESPONSE_REQUEST_TIMEOUT,
             RESPONSE_NOT_FOUND,
-            RESPONSE_DOES_NOT_EXIST_ANYWHERE
+            RESPONSE_DOES_NOT_EXIST_ANYWHERE,
+            RESPONSE_BAD_REQUEST
     })
     public @interface SipResponseCode {}
 
@@ -188,7 +198,6 @@
      * @param reason A non-null String containing the reason associated with the SIP code.
      * @param operationToken The token provided by the framework when
      *         {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
-     *
      */
     public void respondToCapabilityRequestWithError(@NonNull Uri contactUri,
             @SipResponseCode int code, @NonNull String reason, int operationToken) {
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 1f84451..f3b467b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -828,6 +828,11 @@
     void disableIms(int slotId);
 
     /**
+    * Toggle framework IMS disables and enables.
+    */
+    void resetIms(int slotIndex);
+
+    /**
      *  Get IImsMmTelFeature binder from ImsResolver that corresponds to the subId and MMTel feature
      *  as well as registering the MmTelFeature for callbacks using the IImsServiceFeatureCallback
      *  interface.
@@ -922,6 +927,23 @@
             int subId, in OperatorInfo operatorInfo, boolean persisSelection);
 
     /**
+     * Get the allowed network types that store in the telephony provider.
+     *
+     * @param subId the id of the subscription.
+     * @return allowedNetworkTypes the allowed network types.
+     */
+    long getAllowedNetworkTypes(int subId);
+
+    /**
+     * Set the allowed network types.
+     *
+     * @param subId the id of the subscription.
+     * @param allowedNetworkTypes the allowed network types.
+     * @return true on success; false on any failure.
+     */
+    boolean setAllowedNetworkTypes(int subId, long allowedNetworkTypes);
+
+    /**
      * Set the preferred network type.
      * Used for device configuration by some CDMA operators.
      *
@@ -973,6 +995,11 @@
      boolean isManualNetworkSelectionAllowed(int subId);
 
     /**
+     * Enable or disable always reporting signal strength changes from radio.
+     */
+     void setAlwaysReportSignalStrength(int subId, boolean isEnable);
+
+    /**
      * Get P-CSCF address from PCO after data connection is established or modified.
      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
      * @param callingPackage The package making the call.
@@ -2087,6 +2114,11 @@
     int getRadioHalVersion();
 
     /**
+     * Get the current calling package name.
+     */
+    String getCurrentPackageName();
+
+    /**
      * Returns true if the specified type of application (e.g. {@link #APPTYPE_CSIM} is present
      * on the UICC card.
      * @hide
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index 284544b..0e0a22ee 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -477,6 +477,7 @@
     int RIL_REQUEST_STOP_KEEPALIVE = 145;
     int RIL_REQUEST_ENABLE_MODEM = 146;
     int RIL_REQUEST_GET_MODEM_STATUS = 147;
+    int RIL_REQUEST_CDMA_SEND_SMS_EXPECT_MORE = 148;
 
     /* The following requests are not defined in RIL.h */
     int RIL_REQUEST_HAL_NON_RIL_BASE = 200;
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
index ae55a75..8559cb9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/SeamlessAppRotationTest.java
@@ -30,10 +30,12 @@
 import android.view.Surface;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.LargeTest;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.MethodSorters;
@@ -50,6 +52,8 @@
 @LargeTest
 @RunWith(Parameterized.class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
+@FlakyTest(bugId = 147659548)
+@Ignore("Waiting bug feedback")
 public class SeamlessAppRotationTest extends FlickerTestBase {
     private int mBeginRotation;
     private int mEndRotation;
diff --git a/tests/PlatformCompatGating/Android.bp b/tests/PlatformCompatGating/Android.bp
index 5e9ef8e..609896e 100644
--- a/tests/PlatformCompatGating/Android.bp
+++ b/tests/PlatformCompatGating/Android.bp
@@ -18,7 +18,6 @@
     name: "PlatformCompatGating",
     // Only compile source java files in this apk.
     srcs: ["src/**/*.java"],
-    certificate: "platform",
     libs: [
         "android.test.runner",
         "android.test.base",
diff --git a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
index 932ec64..c00aa2a 100644
--- a/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
+++ b/tests/PlatformCompatGating/test-rules/src/android/compat/testing/PlatformCompatChangeRule.java
@@ -16,7 +16,9 @@
 
 package android.compat.testing;
 
+import android.Manifest;
 import android.app.Instrumentation;
+import android.app.UiAutomation;
 import android.compat.Compatibility;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
@@ -83,12 +85,16 @@
         @Override
         public void evaluate() throws Throwable {
             Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+            UiAutomation uiAutomation = instrumentation.getUiAutomation();
             String packageName = instrumentation.getTargetContext().getPackageName();
             IPlatformCompat platformCompat = IPlatformCompat.Stub
                     .asInterface(ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
             if (platformCompat == null) {
                 throw new IllegalStateException("Could not get IPlatformCompat service!");
             }
+            uiAutomation.adoptShellPermissionIdentity(
+                    Manifest.permission.READ_COMPAT_CHANGE_CONFIG,
+                    Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG);
             Compatibility.setOverrides(mConfig);
             try {
                 platformCompat.setOverridesForTest(new CompatibilityChangeConfig(mConfig),
@@ -101,6 +107,7 @@
             } catch (RemoteException e) {
                 throw new RuntimeException("Could not call IPlatformCompat binder method!", e);
             } finally {
+                uiAutomation.dropShellPermissionIdentity();
                 Compatibility.clearOverrides();
             }
         }
diff --git a/tests/net/common/java/android/net/LinkAddressTest.java b/tests/net/common/java/android/net/LinkAddressTest.java
index b2e573b..06c6301 100644
--- a/tests/net/common/java/android/net/LinkAddressTest.java
+++ b/tests/net/common/java/android/net/LinkAddressTest.java
@@ -38,6 +38,8 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import android.os.SystemClock;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -316,9 +318,76 @@
 
         l = new LinkAddress(V6_ADDRESS, 64, 123, 456);
         assertParcelingIsLossless(l);
+        l = new LinkAddress(V6_ADDRESS, 64, 123, 456,
+                1L, 3600000L);
+        assertParcelingIsLossless(l);
 
         l = new LinkAddress(V4 + "/28", IFA_F_PERMANENT, RT_SCOPE_LINK);
-        assertParcelSane(l, 4);
+        assertParcelSane(l, 6);
+    }
+
+    @Test
+    public void testDeprecationTime() {
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    LinkAddress.LIFETIME_UNKNOWN, 100000L);
+            fail("Only one time provided should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    200000L, 100000L);
+            fail("deprecation time later than expiration time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    -2, 100000L);
+            fail("negative deprecation time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void testExpirationTime() {
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    200000L, LinkAddress.LIFETIME_UNKNOWN);
+            fail("Only one time provided should cause exception");
+        } catch (IllegalArgumentException expected) { }
+
+        try {
+            new LinkAddress(V6_ADDRESS, 64, 0, 456,
+                    100000L, -2);
+            fail("negative expiration time should cause exception");
+        } catch (IllegalArgumentException expected) { }
+    }
+
+    @Test
+    public void testGetFlags() {
+        LinkAddress l = new LinkAddress(V6_ADDRESS, 64, 123, RT_SCOPE_HOST);
+        assertEquals(123, l.getFlags());
+
+        // Test if deprecated bit was added/remove automatically based on the provided deprecation
+        // time
+        l = new LinkAddress(V6_ADDRESS, 64, 0, RT_SCOPE_HOST,
+                1L, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the flag is added automatically.
+        assertTrue((l.getFlags() & IFA_F_DEPRECATED) != 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
+                SystemClock.elapsedRealtime() + 100000L, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the flag is removed automatically.
+        assertTrue((l.getFlags() & IFA_F_DEPRECATED) == 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED, RT_SCOPE_HOST,
+                LinkAddress.LIFETIME_PERMANENT, LinkAddress.LIFETIME_PERMANENT);
+        // Check if the permanent flag is added.
+        assertTrue((l.getFlags() & IFA_F_PERMANENT) != 0);
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_PERMANENT, RT_SCOPE_HOST,
+                1000L, SystemClock.elapsedRealtime() + 100000L);
+        // Check if the permanent flag is removed
+        assertTrue((l.getFlags() & IFA_F_PERMANENT) == 0);
     }
 
     private void assertGlobalPreferred(LinkAddress l, String msg) {
@@ -389,5 +458,12 @@
                             (IFA_F_TEMPORARY|IFA_F_TENTATIVE|IFA_F_OPTIMISTIC),
                             RT_SCOPE_UNIVERSE);
         assertGlobalPreferred(l, "v6,global,tempaddr+optimistic");
+
+        l = new LinkAddress(V6_ADDRESS, 64, IFA_F_DEPRECATED,
+                RT_SCOPE_UNIVERSE, SystemClock.elapsedRealtime() + 100000,
+                SystemClock.elapsedRealtime() + 200000);
+        // Although the deprecated bit is set, but the deprecation time is in the future, test
+        // if the flag is removed automatically.
+        assertGlobalPreferred(l, "v6,global,tempaddr+deprecated in the future");
     }
 }
diff --git a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
index 797fd83..3e4f3d8 100644
--- a/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/common/java/android/net/NetworkCapabilitiesTest.java
@@ -269,6 +269,7 @@
             .setUids(uids)
             .addCapability(NET_CAPABILITY_EIMS)
             .addCapability(NET_CAPABILITY_NOT_METERED);
+        netCap.setOwnerUid(123);
         assertParcelingIsLossless(netCap);
         netCap.setSSID(TEST_SSID);
         assertParcelSane(netCap, 13);
diff --git a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
index 065add4..7ab4b56 100644
--- a/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
+++ b/tests/net/java/android/net/ConnectivityDiagnosticsManagerTest.java
@@ -16,6 +16,8 @@
 
 package android.net;
 
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsBinder;
+import static android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
 import static android.net.ConnectivityDiagnosticsManager.ConnectivityReport;
 import static android.net.ConnectivityDiagnosticsManager.DataStallReport;
 
@@ -25,12 +27,19 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
 import android.os.PersistableBundle;
 
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+
+import java.util.concurrent.Executor;
 
 @RunWith(JUnit4.class)
 public class ConnectivityDiagnosticsManagerTest {
@@ -41,6 +50,19 @@
     private static final String BUNDLE_KEY = "key";
     private static final String BUNDLE_VALUE = "value";
 
+    private static final Executor INLINE_EXECUTOR = x -> x.run();
+
+    @Mock private ConnectivityDiagnosticsCallback mCb;
+
+    private ConnectivityDiagnosticsBinder mBinder;
+
+    @Before
+    public void setUp() {
+        mCb = mock(ConnectivityDiagnosticsCallback.class);
+
+        mBinder = new ConnectivityDiagnosticsBinder(mCb, INLINE_EXECUTOR);
+    }
+
     private ConnectivityReport createSampleConnectivityReport() {
         final LinkProperties linkProperties = new LinkProperties();
         linkProperties.setInterfaceName(INTERFACE_NAME);
@@ -193,4 +215,34 @@
     public void testDataStallReportParcelUnparcel() {
         assertParcelSane(createSampleDataStallReport(), 4);
     }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnConnectivityReport() {
+        mBinder.onConnectivityReport(createSampleConnectivityReport());
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onConnectivityReport(eq(createSampleConnectivityReport()));
+    }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnDataStallSuspected() {
+        mBinder.onDataStallSuspected(createSampleDataStallReport());
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onDataStallSuspected(eq(createSampleDataStallReport()));
+    }
+
+    @Test
+    public void testConnectivityDiagnosticsCallbackOnNetworkConnectivityReported() {
+        final Network n = new Network(NET_ID);
+        final boolean connectivity = true;
+
+        mBinder.onNetworkConnectivityReported(n, connectivity);
+
+        // The callback will be invoked synchronously by inline executor. Immediately check the
+        // latch without waiting.
+        verify(mCb).onNetworkConnectivityReported(eq(n), eq(connectivity));
+    }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 783f8d1..e80b7c9 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -6313,12 +6313,24 @@
         assertEquals(wifiLp, mService.getActiveLinkProperties());
     }
 
+    @Test
+    public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
+        int callerUid = Process.myUid();
+        final NetworkCapabilities originalNc = new NetworkCapabilities();
+        originalNc.setOwnerUid(callerUid);
 
-    private TestNetworkAgentWrapper establishVpn(LinkProperties lp, int establishingUid,
-            Set<UidRange> vpnRange) throws Exception {
+        final NetworkCapabilities newNc =
+                mService.networkCapabilitiesRestrictedForCallerPermissions(
+                        originalNc, Process.myPid(), callerUid);
+
+        assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
+    }
+
+    private TestNetworkAgentWrapper establishVpn(
+            LinkProperties lp, int ownerUid, Set<UidRange> vpnRange) throws Exception {
         final TestNetworkAgentWrapper
                 vpnNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_VPN, lp);
-        vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
+        vpnNetworkAgent.getNetworkCapabilities().setOwnerUid(ownerUid);
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
         mMockVpn.connect();
         mMockVpn.setUids(vpnRange);