Merge "Add Nullable annotation to getDecorView"
diff --git a/Android.bp b/Android.bp
index 5622206..85ce41b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -201,6 +201,8 @@
         "core/java/android/net/INetworkScoreService.aidl",
         "core/java/android/net/INetworkStatsService.aidl",
         "core/java/android/net/INetworkStatsSession.aidl",
+        "core/java/android/net/ITestNetworkManager.aidl",
+        "core/java/android/net/ITetheringEventCallback.aidl",
         "core/java/android/net/ITetheringStatsProvider.aidl",
         "core/java/android/net/nsd/INsdManager.aidl",
         "core/java/android/nfc/IAppCallback.aidl",
@@ -551,11 +553,13 @@
         "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
         "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
+        "telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl",
         "telephony/java/com/android/internal/telephony/ISms.aidl",
         "telephony/java/com/android/internal/telephony/ISub.aidl",
         "telephony/java/com/android/internal/telephony/IOns.aidl",
         "telephony/java/com/android/internal/telephony/ITelephony.aidl",
         "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
+        "telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl",
         "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
         "telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl",
         "telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl",
diff --git a/api/current.txt b/api/current.txt
index 724adac..9553bf6 100755
--- a/api/current.txt
+++ b/api/current.txt
@@ -7711,9 +7711,9 @@
     method public boolean isMultipleAdvertisementSupported();
     method public boolean isOffloadedFilteringSupported();
     method public boolean isOffloadedScanBatchingSupported();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingInsecureL2capChannel() throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingInsecureRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothServerSocket listenUsingL2capChannel() throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothServerSocket listenUsingRfcommWithServiceRecord(String, java.util.UUID) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean setName(String);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean startDiscovery();
@@ -8081,9 +8081,9 @@
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int, android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADMIN) public boolean createBond();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createInsecureL2capChannel(int) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH) @NonNull public android.bluetooth.BluetoothSocket createL2capChannel(int) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public int describeContents();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH) public boolean fetchUuidsWithSdp();
@@ -8390,9 +8390,9 @@
   }
 
   public final class BluetoothHearingAid implements android.bluetooth.BluetoothProfile {
-    method public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
-    method public int getConnectionState(android.bluetooth.BluetoothDevice);
-    method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getConnectedDevices();
+    method public int getConnectionState(@NonNull android.bluetooth.BluetoothDevice);
+    method @NonNull public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(@NonNull int[]);
     field public static final String ACTION_CONNECTION_STATE_CHANGED = "android.bluetooth.hearingaid.profile.action.CONNECTION_STATE_CHANGED";
   }
 
@@ -27723,7 +27723,7 @@
     method public abstract boolean isRelative();
     method public android.net.Uri normalizeScheme();
     method public static android.net.Uri parse(String);
-    method public String toSafeString();
+    method @NonNull public String toSafeString();
     method public abstract String toString();
     method public static android.net.Uri withAppendedPath(android.net.Uri, String);
     method public static void writeToParcel(android.os.Parcel, android.net.Uri);
@@ -29194,10 +29194,10 @@
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, String);
     method public boolean registerAidsForService(android.content.ComponentName, String, java.util.List<java.lang.String>);
     method public boolean removeAidsForService(android.content.ComponentName, String);
-    method public boolean setOffHostForService(android.content.ComponentName, String);
+    method public boolean setOffHostForService(@NonNull android.content.ComponentName, @NonNull String);
     method public boolean setPreferredService(android.app.Activity, android.content.ComponentName);
     method public boolean supportsAidPrefixRegistration();
-    method public boolean unsetOffHostForService(android.content.ComponentName);
+    method public boolean unsetOffHostForService(@NonNull android.content.ComponentName);
     method public boolean unsetPreferredService(android.app.Activity);
     field public static final String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
     field public static final String CATEGORY_OTHER = "other";
@@ -37321,13 +37321,13 @@
   }
 
   public static final class Telephony.CarrierId implements android.provider.BaseColumns {
-    method @NonNull public static android.net.Uri getPreciseCarrierIdUriForSubscriptionId(int);
+    method @NonNull public static android.net.Uri getSpecificCarrierIdUriForSubscriptionId(int);
     method public static android.net.Uri getUriForSubscriptionId(int);
     field public static final String CARRIER_ID = "carrier_id";
     field public static final String CARRIER_NAME = "carrier_name";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final String PRECISE_CARRIER_ID = "precise_carrier_id";
-    field public static final String PRECISE_CARRIER_ID_NAME = "precise_carrier_id_name";
+    field public static final String SPECIFIC_CARRIER_ID = "specific_carrier_id";
+    field public static final String SPECIFIC_CARRIER_ID_NAME = "specific_carrier_id_name";
   }
 
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
@@ -39449,7 +39449,7 @@
     method @Nullable public String getImsi();
     method public String getMcc();
     method public String getMnc();
-    method public int getPreciseCarrierId();
+    method public int getSpecificCarrierId();
     method @Nullable public String getSpn();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.service.carrier.CarrierIdentifier> CREATOR;
@@ -42270,6 +42270,7 @@
     field public static final String KEY_SUPPORT_PAUSE_IMS_VIDEO_CALLS_BOOL = "support_pause_ims_video_calls_bool";
     field public static final String KEY_SUPPORT_SWAP_AFTER_MERGE_BOOL = "support_swap_after_merge_bool";
     field public static final String KEY_TREAT_DOWNGRADED_VIDEO_CALLS_AS_VIDEO_CALLS_BOOL = "treat_downgraded_video_calls_as_video_calls_bool";
+    field public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
     field public static final String KEY_USE_HFA_FOR_PROVISIONING_BOOL = "use_hfa_for_provisioning_bool";
     field public static final String KEY_USE_OTASP_FOR_PROVISIONING_BOOL = "use_otasp_for_provisioning_bool";
     field public static final String KEY_USE_RCS_PRESENCE_BOOL = "use_rcs_presence_bool";
@@ -42560,7 +42561,7 @@
   public class MbmsGroupCallSession implements java.lang.AutoCloseable {
     method public void close();
     method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
-    method public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
+    method @Nullable public static android.telephony.MbmsGroupCallSession create(@NonNull android.content.Context, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.MbmsGroupCallSessionCallback);
     method @Nullable public android.telephony.mbms.GroupCall startGroupCall(long, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.List<java.lang.Integer>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.mbms.GroupCallCallback);
   }
 
@@ -42688,6 +42689,7 @@
   public class PhoneStateListener {
     ctor public PhoneStateListener();
     ctor public PhoneStateListener(@NonNull java.util.concurrent.Executor);
+    method public void onActiveDataSubscriptionIdChanged(int);
     method public void onCallForwardingIndicatorChanged(boolean);
     method public void onCallStateChanged(int, String);
     method public void onCellInfoChanged(java.util.List<android.telephony.CellInfo>);
@@ -42700,6 +42702,7 @@
     method @Deprecated public void onSignalStrengthChanged(int);
     method public void onSignalStrengthsChanged(android.telephony.SignalStrength);
     method public void onUserMobileDataStateChanged(boolean);
+    field public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 4194304; // 0x400000
     field public static final int LISTEN_CALL_FORWARDING_INDICATOR = 8; // 0x8
     field public static final int LISTEN_CALL_STATE = 32; // 0x20
     field public static final int LISTEN_CELL_INFO = 1024; // 0x400
@@ -42919,9 +42922,9 @@
     method public String getIccId();
     method public int getIconTint();
     method @Deprecated public int getMcc();
-    method public String getMccString();
+    method @Nullable public String getMccString();
     method @Deprecated public int getMnc();
-    method public String getMncString();
+    method @Nullable public String getMncString();
     method public String getNumber();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
@@ -43066,9 +43069,9 @@
     method public String getSimCountryIso();
     method public String getSimOperator();
     method public String getSimOperatorName();
-    method public int getSimPreciseCarrierId();
-    method @Nullable public CharSequence getSimPreciseCarrierIdName();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getSimSerialNumber();
+    method public int getSimSpecificCarrierId();
+    method @Nullable public CharSequence getSimSpecificCarrierIdName();
     method public int getSimState();
     method public int getSimState(int);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public String getSubscriberId();
@@ -43120,7 +43123,7 @@
     method @Deprecated public void setVoicemailRingtoneUri(android.telecom.PhoneAccountHandle, android.net.Uri);
     method @Deprecated public void setVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void switchMultiSimConfig(int);
-    method public boolean updateAvailableNetworks(java.util.List<android.telephony.AvailableNetworkInfo>);
+    method public void updateAvailableNetworks(@NonNull java.util.List<android.telephony.AvailableNetworkInfo>, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.Consumer<java.lang.Integer>);
     field public static final String ACTION_CONFIGURE_VOICEMAIL = "android.telephony.action.CONFIGURE_VOICEMAIL";
     field public static final String ACTION_NETWORK_COUNTRY_CHANGED = "android.telephony.action.NETWORK_COUNTRY_CHANGED";
     field @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public static final String ACTION_PHONE_STATE_CHANGED = "android.intent.action.PHONE_STATE";
@@ -43128,7 +43131,7 @@
     field public static final String ACTION_SECRET_CODE = "android.telephony.action.SECRET_CODE";
     field public static final String ACTION_SHOW_VOICEMAIL_NOTIFICATION = "android.telephony.action.SHOW_VOICEMAIL_NOTIFICATION";
     field public static final String ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_CARRIER_IDENTITY_CHANGED";
-    field public static final String ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED";
+    field public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED = "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
     field public static final int APPTYPE_CSIM = 4; // 0x4
     field public static final int APPTYPE_ISIM = 5; // 0x5
     field public static final int APPTYPE_RUIM = 3; // 0x3
@@ -43163,8 +43166,8 @@
     field public static final String EXTRA_NETWORK_COUNTRY = "android.telephony.extra.NETWORK_COUNTRY";
     field public static final String EXTRA_NOTIFICATION_COUNT = "android.telephony.extra.NOTIFICATION_COUNT";
     field public static final String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telephony.extra.PHONE_ACCOUNT_HANDLE";
-    field public static final String EXTRA_PRECISE_CARRIER_ID = "android.telephony.extra.PRECISE_CARRIER_ID";
-    field public static final String EXTRA_PRECISE_CARRIER_NAME = "android.telephony.extra.PRECISE_CARRIER_NAME";
+    field public static final String EXTRA_SPECIFIC_CARRIER_ID = "android.telephony.extra.SPECIFIC_CARRIER_ID";
+    field public static final String EXTRA_SPECIFIC_CARRIER_NAME = "android.telephony.extra.SPECIFIC_CARRIER_NAME";
     field public static final String EXTRA_STATE = "state";
     field public static final String EXTRA_STATE_IDLE;
     field public static final String EXTRA_STATE_OFFHOOK;
@@ -43196,6 +43199,9 @@
     field public static final int PHONE_TYPE_GSM = 1; // 0x1
     field public static final int PHONE_TYPE_NONE = 0; // 0x0
     field public static final int PHONE_TYPE_SIP = 3; // 0x3
+    field public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2; // 0x2
+    field public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0; // 0x0
+    field public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1; // 0x1
     field public static final int SIM_STATE_ABSENT = 1; // 0x1
     field public static final int SIM_STATE_CARD_IO_ERROR = 8; // 0x8
     field public static final int SIM_STATE_CARD_RESTRICTED = 9; // 0x9
@@ -43209,6 +43215,11 @@
     field public static final int UNINITIALIZED_CARD_ID = -2; // 0xfffffffe
     field public static final int UNKNOWN_CARRIER_ID = -1; // 0xffffffff
     field public static final int UNSUPPORTED_CARD_ID = -1; // 0xffffffff
+    field public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2; // 0x2
+    field public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3; // 0x3
+    field public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4; // 0x4
+    field public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0; // 0x0
+    field public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1; // 0x1
     field public static final int USSD_ERROR_SERVICE_UNAVAIL = -2; // 0xfffffffe
     field public static final int USSD_RETURN_FAILURE = -1; // 0xffffffff
     field public static final String VVM_TYPE_CVVM = "vvm_type_cvvm";
@@ -43373,26 +43384,26 @@
   public static class ApnSetting.Builder {
     ctor public ApnSetting.Builder();
     method public android.telephony.data.ApnSetting build();
-    method public android.telephony.data.ApnSetting.Builder setApnName(String);
-    method public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
-    method public android.telephony.data.ApnSetting.Builder setAuthType(int);
-    method public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setApnName(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setApnTypeBitmask(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setAuthType(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierEnabled(boolean);
     method @NonNull public android.telephony.data.ApnSetting.Builder setCarrierId(int);
-    method public android.telephony.data.ApnSetting.Builder setEntryName(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setEntryName(String);
     method @Deprecated public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(java.net.InetAddress);
-    method public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String);
-    method public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int);
-    method public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri);
-    method public android.telephony.data.ApnSetting.Builder setMvnoType(int);
-    method public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int);
-    method public android.telephony.data.ApnSetting.Builder setOperatorNumeric(String);
-    method public android.telephony.data.ApnSetting.Builder setPassword(String);
-    method public android.telephony.data.ApnSetting.Builder setProtocol(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyAddress(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsProxyPort(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMmsc(android.net.Uri);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setMvnoType(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setNetworkTypeBitmask(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setOperatorNumeric(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setPassword(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProtocol(int);
     method @Deprecated public android.telephony.data.ApnSetting.Builder setProxyAddress(java.net.InetAddress);
-    method public android.telephony.data.ApnSetting.Builder setProxyAddress(String);
-    method public android.telephony.data.ApnSetting.Builder setProxyPort(int);
-    method public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int);
-    method public android.telephony.data.ApnSetting.Builder setUser(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProxyAddress(String);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setProxyPort(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setRoamingProtocol(int);
+    method @NonNull public android.telephony.data.ApnSetting.Builder setUser(String);
   }
 
 }
@@ -55291,7 +55302,7 @@
   public final class DelegateLastClassLoader extends dalvik.system.PathClassLoader {
     ctor public DelegateLastClassLoader(String, ClassLoader);
     ctor public DelegateLastClassLoader(String, String, ClassLoader);
-    ctor public DelegateLastClassLoader(String, String, ClassLoader, boolean);
+    ctor public DelegateLastClassLoader(@NonNull String, @Nullable String, @Nullable ClassLoader, boolean);
   }
 
   public class DexClassLoader extends dalvik.system.BaseDexClassLoader {
diff --git a/api/system-current.txt b/api/system-current.txt
index bb119cc..568010b 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3100,11 +3100,13 @@
     method @RequiresPermission(android.Manifest.permission.LOCAL_MAC_ADDRESS) 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 @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) public void registerTetheringEventCallback(@NonNull java.util.concurrent.Executor, @NonNull android.net.ConnectivityManager.OnTetheringEventCallback);
     method @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", android.Manifest.permission.NETWORK_SETUP_WIZARD, "android.permission.NETWORK_STACK"}) public void setAirplaneMode(boolean);
     method @RequiresPermission(android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) public void startCaptivePortalApp(android.net.Network, 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 @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
@@ -3122,7 +3124,12 @@
   }
 
   public static interface ConnectivityManager.OnTetheringEntitlementResultListener {
-    method public void onEntitlementResult(int);
+    method public void onTetheringEntitlementResult(int);
+  }
+
+  public abstract static class ConnectivityManager.OnTetheringEventCallback {
+    ctor public ConnectivityManager.OnTetheringEventCallback();
+    method public void onUpstreamChanged(@Nullable android.net.Network);
   }
 
   public final class IpPrefix implements android.os.Parcelable {
@@ -3186,6 +3193,7 @@
     method public int[] getTransportTypes();
     method public boolean satisfiedByNetworkCapabilities(android.net.NetworkCapabilities);
     field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
+    field public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24; // 0x18
   }
 
   public class NetworkKey implements android.os.Parcelable {
@@ -3334,10 +3342,12 @@
     ctor public CaptivePortalProbeResult(int, String, String);
     ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec);
     method public boolean isFailed();
+    method public boolean isPartialConnectivity();
     method public boolean isPortal();
     method public boolean isSuccessful();
     field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
     field public static final int FAILED_CODE = 599; // 0x257
+    field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL;
     field public static final int PORTAL_CODE = 302; // 0x12e
     field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
     field public static final int SUCCESS_CODE = 204; // 0xcc
@@ -3469,6 +3479,7 @@
     field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa
     field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8
     field public static final int NETWORK_LINGER = 5; // 0x5
+    field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd
     field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb
     field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9
     field public static final int NETWORK_UNLINGER = 6; // 0x6
@@ -4001,7 +4012,7 @@
     field public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";
   }
 
-  public class BugreportManager {
+  public final class BugreportManager {
     method @RequiresPermission(android.Manifest.permission.DUMP) public void cancelBugreport();
     method @RequiresPermission(android.Manifest.permission.DUMP) public void startBugreport(@NonNull android.os.ParcelFileDescriptor, @Nullable android.os.ParcelFileDescriptor, @NonNull android.os.BugreportParams, @NonNull java.util.concurrent.Executor, @NonNull android.os.BugreportManager.BugreportCallback);
   }
@@ -4010,7 +4021,7 @@
     ctor public BugreportManager.BugreportCallback();
     method public void onError(int);
     method public void onFinished();
-    method public void onProgress(float);
+    method public void onProgress(@FloatRange(from=0.0f, to=100.0f) float);
     field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
     field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
     field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
@@ -4019,7 +4030,7 @@
   }
 
   public final class BugreportParams {
-    ctor public BugreportParams(@android.os.BugreportParams.BugreportMode int);
+    ctor public BugreportParams(int);
     method public int getMode();
     field public static final int BUGREPORT_MODE_FULL = 0; // 0x0
     field public static final int BUGREPORT_MODE_INTERACTIVE = 1; // 0x1
@@ -4029,9 +4040,6 @@
     field public static final int BUGREPORT_MODE_WIFI = 5; // 0x5
   }
 
-  @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef(prefix={"BUGREPORT_MODE_"}, value={android.os.BugreportParams.BUGREPORT_MODE_FULL, android.os.BugreportParams.BUGREPORT_MODE_INTERACTIVE, android.os.BugreportParams.BUGREPORT_MODE_REMOTE, android.os.BugreportParams.BUGREPORT_MODE_WEAR, android.os.BugreportParams.BUGREPORT_MODE_TELEPHONY, android.os.BugreportParams.BUGREPORT_MODE_WIFI}) public static @interface BugreportParams.BugreportMode {
-  }
-
   public final class ConfigUpdate {
     field public static final String ACTION_UPDATE_CARRIER_ID_DB = "android.os.action.UPDATE_CARRIER_ID_DB";
     field public static final String ACTION_UPDATE_CARRIER_PROVISIONING_URLS = "android.intent.action.UPDATE_CARRIER_PROVISIONING_URLS";
@@ -6306,6 +6314,7 @@
     method public void requestEmbeddedSubscriptionInfoListRefresh(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultDataSubId(int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDefaultSmsSubId(int);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setPreferredDataSubscriptionId(int, boolean, @NonNull java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setSubscriptionEnabled(int, boolean);
     field @NonNull public static final android.net.Uri ADVANCED_CALLING_ENABLED_CONTENT_URI;
     field public static final int PROFILE_CLASS_DEFAULT = -1; // 0xffffffff
@@ -6422,7 +6431,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
     method public void updateServiceLocation();
-    field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT";
+    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_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";
@@ -6430,8 +6439,8 @@
     field public static final int CARRIER_PRIVILEGE_STATUS_HAS_ACCESS = 1; // 0x1
     field public static final int CARRIER_PRIVILEGE_STATUS_NO_ACCESS = 0; // 0x0
     field public static final int CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED = -1; // 0xffffffff
-    field public static final String EXTRA_DEBUG_EVENT_DESCRIPTION = "android.telephony.extra.DEBUG_EVENT_DESCRIPTION";
-    field public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID";
+    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_SIM_STATE = "android.telephony.extra.SIM_STATE";
     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";
@@ -7397,7 +7406,7 @@
   public static class ProvisioningManager.Callback {
     ctor public ProvisioningManager.Callback();
     method public void onProvisioningIntChanged(int, int);
-    method public void onProvisioningStringChanged(int, String);
+    method public void onProvisioningStringChanged(int, @NonNull String);
   }
 
 }
diff --git a/api/test-current.txt b/api/test-current.txt
index 618bde8..d43b1c4 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -703,6 +703,21 @@
     field public static final android.os.Parcelable.Creator<android.net.StaticIpConfiguration> CREATOR;
   }
 
+  public final class TestNetworkInterface implements android.os.Parcelable {
+    ctor public TestNetworkInterface(android.os.ParcelFileDescriptor, String);
+    method public int describeContents();
+    method public android.os.ParcelFileDescriptor getFileDescriptor();
+    method public String getInterfaceName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.net.TestNetworkInterface> CREATOR;
+  }
+
+  public class TestNetworkManager {
+    method public android.net.TestNetworkInterface createTunInterface(@NonNull android.net.LinkAddress[]);
+    method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
+    method public void teardownTestNetwork(@NonNull android.net.Network);
+  }
+
   public class TrafficStats {
     method public static long getLoopbackRxBytes();
     method public static long getLoopbackRxPackets();
@@ -736,10 +751,12 @@
     ctor public CaptivePortalProbeResult(int, String, String);
     ctor public CaptivePortalProbeResult(int, String, String, android.net.captiveportal.CaptivePortalProbeSpec);
     method public boolean isFailed();
+    method public boolean isPartialConnectivity();
     method public boolean isPortal();
     method public boolean isSuccessful();
     field public static final android.net.captiveportal.CaptivePortalProbeResult FAILED;
     field public static final int FAILED_CODE = 599; // 0x257
+    field public static final android.net.captiveportal.CaptivePortalProbeResult PARTIAL;
     field public static final int PORTAL_CODE = 302; // 0x12e
     field public static final android.net.captiveportal.CaptivePortalProbeResult SUCCESS;
     field public static final int SUCCESS_CODE = 204; // 0xcc
@@ -871,6 +888,7 @@
     field public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10; // 0xa
     field public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8; // 0x8
     field public static final int NETWORK_LINGER = 5; // 0x5
+    field public static final int NETWORK_PARTIAL_CONNECTIVITY = 13; // 0xd
     field public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11; // 0xb
     field public static final int NETWORK_REVALIDATION_SUCCESS = 9; // 0x9
     field public static final int NETWORK_UNLINGER = 6; // 0x6
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 3666d6a..469c964 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -2,9 +2,6 @@
     class core animation
     user graphics
     group graphics audio
-    # bootanimation depends on libandroidicu in the Runtime APEX.
-    # TODO(b/124939955): Remove this dependency on libandroidicu
-    updatable
     disabled
     oneshot
     writepid /dev/stune/top-app/tasks
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 8badf97..b02cf48 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -23,18 +23,7 @@
 Landroid/app/admin/IDevicePolicyManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/admin/IDevicePolicyManager;
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_packageHasActiveAdmins:I
 Landroid/app/admin/IDevicePolicyManager$Stub;->TRANSACTION_removeActiveAdmin:I
-Landroid/app/admin/IDevicePolicyManager;->packageHasActiveAdmins(Ljava/lang/String;I)Z
 Landroid/app/backup/IBackupManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/backup/IBackupManager;
-Landroid/app/backup/IBackupManager;->acknowledgeFullBackupOrRestore(IZLjava/lang/String;Ljava/lang/String;Landroid/app/backup/IFullBackupRestoreObserver;)V
-Landroid/app/backup/IBackupManager;->clearBackupData(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/app/backup/IBackupManager;->dataChanged(Ljava/lang/String;)V
-Landroid/app/backup/IBackupManager;->getCurrentTransport()Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->isBackupEnabled()Z
-Landroid/app/backup/IBackupManager;->isBackupServiceActive(I)Z
-Landroid/app/backup/IBackupManager;->listAllTransports()[Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->selectBackupTransport(Ljava/lang/String;)Ljava/lang/String;
-Landroid/app/backup/IBackupManager;->setAutoRestore(Z)V
-Landroid/app/backup/IBackupManager;->setBackupEnabled(Z)V
 Landroid/app/backup/IFullBackupRestoreObserver$Stub;-><init>()V
 Landroid/app/backup/IRestoreObserver$Stub;-><init>()V
 Landroid/app/IActivityController$Stub;-><init>()V
@@ -111,19 +100,12 @@
 Landroid/app/job/IJobCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/job/IJobCallback$Stub;-><init>()V
 Landroid/app/job/IJobCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobCallback;
-Landroid/app/job/IJobCallback;->acknowledgeStartMessage(IZ)V
-Landroid/app/job/IJobCallback;->acknowledgeStopMessage(IZ)V
-Landroid/app/job/IJobCallback;->completeWork(II)Z
-Landroid/app/job/IJobCallback;->dequeueWork(I)Landroid/app/job/JobWorkItem;
-Landroid/app/job/IJobCallback;->jobFinished(IZ)V
 Landroid/app/job/IJobScheduler$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/job/IJobScheduler$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobScheduler;
 Landroid/app/job/IJobService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/job/IJobService$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/app/job/IJobService$Stub;-><init>()V
 Landroid/app/job/IJobService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/job/IJobService;
-Landroid/app/job/IJobService;->startJob(Landroid/app/job/JobParameters;)V
-Landroid/app/job/IJobService;->stopJob(Landroid/app/job/JobParameters;)V
 Landroid/app/PackageDeleteObserver;-><init>()V
 Landroid/app/PackageInstallObserver;-><init>()V
 Landroid/app/ResourcesManager$ActivityResources;-><init>()V
@@ -132,10 +114,6 @@
 Landroid/app/trust/ITrustManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/app/UiAutomationConnection;-><init>()V
 Landroid/app/usage/IUsageStatsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/app/usage/IUsageStatsManager;
-Landroid/app/usage/IUsageStatsManager;->isAppInactive(Ljava/lang/String;I)Z
-Landroid/app/usage/IUsageStatsManager;->queryConfigurationStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
-Landroid/app/usage/IUsageStatsManager;->queryUsageStats(IJJLjava/lang/String;)Landroid/content/pm/ParceledListSlice;
-Landroid/app/usage/IUsageStatsManager;->setAppInactive(Ljava/lang/String;ZI)V
 Landroid/app/UserSwitchObserver;-><init>()V
 Landroid/app/VrStateCallback;-><init>()V
 Landroid/bluetooth/IBluetooth$Stub$Proxy;->getAddress()Ljava/lang/String;
@@ -180,22 +158,14 @@
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelected(Ljava/lang/String;ILjava/lang/String;)V
 Landroid/companion/ICompanionDeviceDiscoveryServiceCallback;->onDeviceSelectionCancel()V
 Landroid/companion/IFindDeviceCallback;->onSuccess(Landroid/app/PendingIntent;)V
-Landroid/content/ContentProviderProxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/IClipboard$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IClipboard$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IClipboard;
 Landroid/content/IContentService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IContentService$Stub;-><init>()V
 Landroid/content/IContentService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IContentService;
-Landroid/content/IContentService;->cancelSync(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)V
-Landroid/content/IContentService;->getIsSyncable(Landroid/accounts/Account;Ljava/lang/String;)I
-Landroid/content/IContentService;->getMasterSyncAutomatically()Z
-Landroid/content/IContentService;->getSyncAdapterTypes()[Landroid/content/SyncAdapterType;
-Landroid/content/IContentService;->isSyncActive(Landroid/accounts/Account;Ljava/lang/String;Landroid/content/ComponentName;)Z
-Landroid/content/IContentService;->setMasterSyncAutomatically(Z)V
 Landroid/content/IIntentReceiver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/IIntentReceiver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/IIntentReceiver$Stub;-><init>()V
-Landroid/content/IIntentReceiver;->performReceive(Landroid/content/Intent;ILjava/lang/String;Landroid/os/Bundle;ZZI)V
 Landroid/content/IOnPrimaryClipChangedListener$Stub;-><init>()V
 Landroid/content/IOnPrimaryClipChangedListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IOnPrimaryClipChangedListener;
 Landroid/content/IRestrictionsManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/IRestrictionsManager;
@@ -203,24 +173,16 @@
 Landroid/content/ISyncAdapter$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncAdapter$Stub;-><init>()V
 Landroid/content/ISyncAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncAdapter;
-Landroid/content/ISyncAdapter;->cancelSync(Landroid/content/ISyncContext;)V
-Landroid/content/ISyncAdapter;->onUnsyncableAccount(Landroid/content/ISyncAdapterUnsyncableAccountCallback;)V
-Landroid/content/ISyncAdapter;->startSync(Landroid/content/ISyncContext;Ljava/lang/String;Landroid/accounts/Account;Landroid/os/Bundle;)V
 Landroid/content/ISyncContext$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/ISyncContext$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncContext$Stub;-><init>()V
 Landroid/content/ISyncContext$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncContext;
 Landroid/content/ISyncServiceAdapter$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncServiceAdapter;
-Landroid/content/ISyncServiceAdapter;->cancelSync(Landroid/content/ISyncContext;)V
-Landroid/content/ISyncServiceAdapter;->startSync(Landroid/content/ISyncContext;Landroid/os/Bundle;)V
 Landroid/content/ISyncStatusObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/ISyncStatusObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/ISyncStatusObserver$Stub;-><init>()V
 Landroid/content/ISyncStatusObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/ISyncStatusObserver;
-Landroid/content/ISyncStatusObserver;->onStatusChanged(I)V
 Landroid/content/om/IOverlayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/om/IOverlayManager;
-Landroid/content/om/IOverlayManager;->getAllOverlays(I)Ljava/util/Map;
-Landroid/content/om/IOverlayManager;->getOverlayInfo(Ljava/lang/String;I)Landroid/content/om/OverlayInfo;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDataObserver$Stub$Proxy;->onRemoveCompleted(Ljava/lang/String;Z)V
@@ -228,7 +190,6 @@
 Landroid/content/pm/IPackageDataObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDataObserver;
 Landroid/content/pm/IPackageDataObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
 Landroid/content/pm/IPackageDataObserver$Stub;->TRANSACTION_onRemoveCompleted:I
-Landroid/content/pm/IPackageDataObserver;->onRemoveCompleted(Ljava/lang/String;Z)V
 Landroid/content/pm/IPackageDeleteObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageDeleteObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver;
@@ -238,17 +199,9 @@
 Landroid/content/pm/IPackageDeleteObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageDeleteObserver2$Stub;-><init>()V
 Landroid/content/pm/IPackageDeleteObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageDeleteObserver2;
-Landroid/content/pm/IPackageDeleteObserver2;->onPackageDeleted(Ljava/lang/String;ILjava/lang/String;)V
-Landroid/content/pm/IPackageDeleteObserver;->packageDeleted(Ljava/lang/String;I)V
-Landroid/content/pm/IPackageInstaller;->uninstall(Landroid/content/pm/VersionedPackage;Ljava/lang/String;ILandroid/content/IntentSender;I)V
 Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageInstallerCallback$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallerCallback$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallerCallback;
-Landroid/content/pm/IPackageInstallerCallback;->onSessionActiveChanged(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionBadgingChanged(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionCreated(I)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionFinished(IZ)V
-Landroid/content/pm/IPackageInstallerCallback;->onSessionProgressChanged(IF)V
 Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageInstallerSession$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallerSession$Stub;-><init>()V
@@ -257,8 +210,6 @@
 Landroid/content/pm/IPackageInstallObserver2$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/content/pm/IPackageInstallObserver2$Stub;-><init>()V
 Landroid/content/pm/IPackageInstallObserver2$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageInstallObserver2;
-Landroid/content/pm/IPackageInstallObserver2;->onPackageInstalled(Ljava/lang/String;ILjava/lang/String;Landroid/os/Bundle;)V
-Landroid/content/pm/IPackageInstallObserver2;->onUserActionRequired(Landroid/content/Intent;)V
 Landroid/content/pm/IPackageManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IPackageManager$Stub$Proxy;->checkUidPermission(Ljava/lang/String;I)I
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
@@ -270,62 +221,6 @@
 Landroid/content/pm/IPackageManager$Stub$Proxy;->getSystemSharedLibraryNames()[Ljava/lang/String;
 Landroid/content/pm/IPackageManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageManager;
 Landroid/content/pm/IPackageManager$Stub;->TRANSACTION_getApplicationInfo:I
-Landroid/content/pm/IPackageManager;->addPermission(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->addPermissionAsync(Landroid/content/pm/PermissionInfo;)Z
-Landroid/content/pm/IPackageManager;->canonicalToCurrentPackageNames([Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->checkPermission(Ljava/lang/String;Ljava/lang/String;I)I
-Landroid/content/pm/IPackageManager;->checkSignatures(Ljava/lang/String;Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->checkUidSignatures(II)I
-Landroid/content/pm/IPackageManager;->clearPackagePreferredActivities(Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->currentToCanonicalPackageNames([Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->deleteApplicationCacheFiles(Ljava/lang/String;Landroid/content/pm/IPackageDataObserver;)V
-Landroid/content/pm/IPackageManager;->getActivityInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getApplicationEnabledSetting(Ljava/lang/String;I)I
-Landroid/content/pm/IPackageManager;->getApplicationInfo(Ljava/lang/String;II)Landroid/content/pm/ApplicationInfo;
-Landroid/content/pm/IPackageManager;->getAppOpPermissionPackages(Ljava/lang/String;)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getBlockUninstallForUser(Ljava/lang/String;I)Z
-Landroid/content/pm/IPackageManager;->getComponentEnabledSetting(Landroid/content/ComponentName;I)I
-Landroid/content/pm/IPackageManager;->getFlagsForUid(I)I
-Landroid/content/pm/IPackageManager;->getHomeActivities(Ljava/util/List;)Landroid/content/ComponentName;
-Landroid/content/pm/IPackageManager;->getInstalledApplications(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->getInstalledPackages(II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->getInstallerPackageName(Ljava/lang/String;)Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getInstallLocation()I
-Landroid/content/pm/IPackageManager;->getInstrumentationInfo(Landroid/content/ComponentName;I)Landroid/content/pm/InstrumentationInfo;
-Landroid/content/pm/IPackageManager;->getLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;I)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager;->getNameForUid(I)Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPackageInfo(Ljava/lang/String;II)Landroid/content/pm/PackageInfo;
-Landroid/content/pm/IPackageManager;->getPackageInstaller()Landroid/content/pm/IPackageInstaller;
-Landroid/content/pm/IPackageManager;->getPackagesForUid(I)[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPackageUid(Ljava/lang/String;II)I
-Landroid/content/pm/IPackageManager;->getPermissionControllerPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getPermissionGroupInfo(Ljava/lang/String;I)Landroid/content/pm/PermissionGroupInfo;
-Landroid/content/pm/IPackageManager;->getPreferredActivities(Ljava/util/List;Ljava/util/List;Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->getProviderInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ProviderInfo;
-Landroid/content/pm/IPackageManager;->getReceiverInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ActivityInfo;
-Landroid/content/pm/IPackageManager;->getServiceInfo(Landroid/content/ComponentName;II)Landroid/content/pm/ServiceInfo;
-Landroid/content/pm/IPackageManager;->getServicesSystemSharedLibraryPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getSharedSystemSharedLibraryPackageName()Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getSystemSharedLibraryNames()[Ljava/lang/String;
-Landroid/content/pm/IPackageManager;->getUidForSharedUser(Ljava/lang/String;)I
-Landroid/content/pm/IPackageManager;->grantRuntimePermission(Ljava/lang/String;Ljava/lang/String;I)V
-Landroid/content/pm/IPackageManager;->hasSystemUidErrors()Z
-Landroid/content/pm/IPackageManager;->isPackageAvailable(Ljava/lang/String;I)Z
-Landroid/content/pm/IPackageManager;->isSafeMode()Z
-Landroid/content/pm/IPackageManager;->isStorageLow()Z
-Landroid/content/pm/IPackageManager;->isUidPrivileged(I)Z
-Landroid/content/pm/IPackageManager;->queryInstrumentation(Ljava/lang/String;I)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->queryIntentActivities(Landroid/content/Intent;Ljava/lang/String;II)Landroid/content/pm/ParceledListSlice;
-Landroid/content/pm/IPackageManager;->querySyncProviders(Ljava/util/List;Ljava/util/List;)V
-Landroid/content/pm/IPackageManager;->removePermission(Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->replacePreferredActivity(Landroid/content/IntentFilter;I[Landroid/content/ComponentName;Landroid/content/ComponentName;I)V
-Landroid/content/pm/IPackageManager;->resolveIntent(Landroid/content/Intent;Ljava/lang/String;II)Landroid/content/pm/ResolveInfo;
-Landroid/content/pm/IPackageManager;->setApplicationEnabledSetting(Ljava/lang/String;IIILjava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setApplicationHiddenSettingAsUser(Ljava/lang/String;ZI)Z
-Landroid/content/pm/IPackageManager;->setComponentEnabledSetting(Landroid/content/ComponentName;III)V
-Landroid/content/pm/IPackageManager;->setInstallerPackageName(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/content/pm/IPackageManager;->setLastChosenActivity(Landroid/content/Intent;Ljava/lang/String;ILandroid/content/IntentFilter;ILandroid/content/ComponentName;)V
-Landroid/content/pm/IPackageManager;->setPackageStoppedState(Ljava/lang/String;ZI)V
 Landroid/content/pm/IPackageMoveObserver$Stub;-><init>()V
 Landroid/content/pm/IPackageMoveObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageMoveObserver;
 Landroid/content/pm/IPackageStatsObserver$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -334,13 +229,11 @@
 Landroid/content/pm/IPackageStatsObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IPackageStatsObserver;
 Landroid/content/pm/IPackageStatsObserver$Stub;->DESCRIPTOR:Ljava/lang/String;
 Landroid/content/pm/IPackageStatsObserver$Stub;->TRANSACTION_onGetStatsCompleted:I
-Landroid/content/pm/IPackageStatsObserver;->onGetStatsCompleted(Landroid/content/pm/PackageStats;Z)V
 Landroid/content/pm/IShortcutService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/content/pm/IShortcutService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/content/pm/IShortcutService;
 Landroid/content/res/ConfigurationBoundResourceCache;-><init>()V
 Landroid/content/res/DrawableCache;-><init>()V
 Landroid/content/UndoManager;-><init>()V
-Landroid/database/BulkCursorProxy;->mRemote:Landroid/os/IBinder;
 Landroid/database/IContentObserver$Stub;-><init>()V
 Landroid/database/IContentObserver$Stub;->asInterface(Landroid/os/IBinder;)Landroid/database/IContentObserver;
 Landroid/database/IContentObserver;->onChange(ZLandroid/net/Uri;I)V
@@ -402,16 +295,13 @@
 Landroid/hardware/camera2/CaptureResult;->TONEMAP_CURVE_RED:Landroid/hardware/camera2/CaptureResult$Key;
 Landroid/hardware/camera2/utils/HashCodeHelpers;->hashCode([I)I
 Landroid/hardware/display/IDisplayManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/display/IDisplayManager;
-Landroid/hardware/display/IDisplayManager;->getDisplayInfo(I)Landroid/view/DisplayInfo;
 Landroid/hardware/fingerprint/IFingerprintService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/fingerprint/IFingerprintService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/fingerprint/IFingerprintService;
 Landroid/hardware/ICameraService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/ICameraService;
 Landroid/hardware/input/IInputManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/input/IInputManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/input/IInputManager;
 Landroid/hardware/input/IInputManager$Stub;->TRANSACTION_injectInputEvent:I
-Landroid/hardware/input/IInputManager;->injectInputEvent(Landroid/view/InputEvent;I)Z
 Landroid/hardware/location/IActivityRecognitionHardwareClient$Stub;-><init>()V
-Landroid/hardware/location/IActivityRecognitionHardwareClient;->onAvailabilityChanged(ZLandroid/hardware/location/IActivityRecognitionHardware;)V
 Landroid/hardware/location/IContextHubService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/location/IContextHubService;
 Landroid/hardware/usb/IUsbManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/hardware/usb/IUsbManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/hardware/usb/IUsbManager;
@@ -421,48 +311,28 @@
 Landroid/location/ICountryListener$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;-><init>()V
 Landroid/location/IGeocodeProvider$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/IGeocodeProvider;
-Landroid/location/IGeocodeProvider;->getFromLocation(DDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
-Landroid/location/IGeocodeProvider;->getFromLocationName(Ljava/lang/String;DDDDILandroid/location/GeocoderParams;Ljava/util/List;)Ljava/lang/String;
 Landroid/location/IGeofenceProvider$Stub;-><init>()V
-Landroid/location/IGeofenceProvider;->setGeofenceHardware(Landroid/hardware/location/IGeofenceHardware;)V
 Landroid/location/ILocationListener$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationListener$Stub$Proxy;->mRemote:Landroid/os/IBinder;
 Landroid/location/ILocationListener$Stub;-><init>()V
 Landroid/location/ILocationListener$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationListener;
-Landroid/location/ILocationListener;->onLocationChanged(Landroid/location/Location;)V
-Landroid/location/ILocationListener;->onProviderDisabled(Ljava/lang/String;)V
-Landroid/location/ILocationListener;->onProviderEnabled(Ljava/lang/String;)V
-Landroid/location/ILocationListener;->onStatusChanged(Ljava/lang/String;ILandroid/os/Bundle;)V
 Landroid/location/ILocationManager$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/location/ILocationManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/location/ILocationManager;
 Landroid/location/ILocationManager$Stub;->TRANSACTION_getAllProviders:I
-Landroid/location/ILocationManager;->getAllProviders()Ljava/util/List;
-Landroid/location/ILocationManager;->getNetworkProviderPackage()Ljava/lang/String;
-Landroid/location/ILocationManager;->reportLocation(Landroid/location/Location;Z)V
 Landroid/location/INetInitiatedListener$Stub;-><init>()V
-Landroid/location/INetInitiatedListener;->sendNiResponse(II)Z
 Landroid/location/LocationManager$ListenerTransport;-><init>(Landroid/location/LocationManager;Landroid/location/LocationListener;Landroid/os/Looper;)V
 Landroid/media/effect/SingleFilterEffect;-><init>(Landroid/media/effect/EffectContext;Ljava/lang/String;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V
-Landroid/media/IAudioFocusDispatcher;->dispatchAudioFocusChange(ILjava/lang/String;)V
 Landroid/media/IAudioRoutesObserver$Stub;-><init>()V
 Landroid/media/IAudioService$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Landroid/media/IAudioService$Stub;-><init>()V
 Landroid/media/IAudioService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IAudioService;
-Landroid/media/IAudioService;->getStreamMaxVolume(I)I
-Landroid/media/IAudioService;->getStreamVolume(I)I
-Landroid/media/IAudioService;->setStreamVolume(IIILjava/lang/String;)V
-Landroid/media/IAudioService;->startWatchingRoutes(Landroid/media/IAudioRoutesObserver;)Landroid/media/AudioRoutesInfo;
 Landroid/media/IMediaRouterService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaRouterService;
 Landroid/media/IMediaScannerListener$Stub;-><init>()V
 Landroid/media/IMediaScannerService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IMediaScannerService;
-Landroid/media/IMediaScannerService;->requestScanFile(Ljava/lang/String;Ljava/lang/String;Landroid/media/IMediaScannerListener;)V
-Landroid/media/IMediaScannerService;->scanFile(Ljava/lang/String;Ljava/lang/String;)V
-Landroid/media/IRemoteDisplayCallback;->onStateChanged(Landroid/media/RemoteDisplayState;)V
 Landroid/media/IRingtonePlayer;->play(Landroid/os/IBinder;Landroid/net/Uri;Landroid/media/AudioAttributes;FZ)V
 Landroid/media/IVolumeController$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/IVolumeController;
 Landroid/media/MediaFile;-><init>()V
 Landroid/media/MediaScanner$MyMediaScannerClient;-><init>(Landroid/media/MediaScanner;)V
-Landroid/media/projection/IMediaProjectionManager;->hasProjectionPermission(ILjava/lang/String;)Z
 Landroid/media/session/ISessionManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/media/session/ISessionManager;
 Landroid/media/tv/ITvRemoteProvider$Stub;-><init>()V
 Landroid/media/tv/ITvRemoteServiceInput;->clearInputBridge(Landroid/os/IBinder;)V
@@ -1549,7 +1419,7 @@
 Lcom/android/internal/os/BatterySipper$DrainType;->values()[Lcom/android/internal/os/BatterySipper$DrainType;
 Lcom/android/internal/os/BinderInternal;->getContextObject()Landroid/os/IBinder;
 Lcom/android/internal/os/BinderInternal;->handleGc()V
-Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;
+Lcom/android/internal/os/ClassLoaderFactory;->createClassloaderNamespace(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;
 Lcom/android/internal/os/IDropBoxManagerService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/os/IDropBoxManagerService;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->name:Ljava/lang/String;
 Lcom/android/internal/os/ProcessCpuTracker$Stats;->rel_stime:I
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4b4611e..5f99d6a 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -131,6 +131,8 @@
 import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.policy.PhoneWindow;
 
+import dalvik.system.VMRuntime;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -2052,6 +2054,7 @@
             mDoReportFullyDrawn = false;
             try {
                 ActivityManager.getService().reportActivityFullyDrawn(mToken, mRestoredFromBundle);
+                VMRuntime.getRuntime().notifyStartupCompleted();
             } catch (RemoteException e) {
             }
         }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 0046302..0e95e639 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -122,6 +122,7 @@
     void setActiveAdmin(in ComponentName policyReceiver, boolean refreshing, int userHandle);
     boolean isAdminActive(in ComponentName policyReceiver, int userHandle);
     List<ComponentName> getActiveAdmins(int userHandle);
+    @UnsupportedAppUsage
     boolean packageHasActiveAdmins(String packageName, int userHandle);
     void getRemoveWarning(in ComponentName policyReceiver, in RemoteCallback result, int userHandle);
     void removeActiveAdmin(in ComponentName policyReceiver, int userHandle);
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index f3ca746..34191f1 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -44,6 +44,7 @@
      * only callers who hold the android.permission.BACKUP permission
      * may invoke it for arbitrary packages.
      */
+    @UnsupportedAppUsage
     void dataChanged(String packageName);
 
     /**
@@ -54,6 +55,7 @@
      * only callers who hold the android.permission.BACKUP permission
      * may invoke it for arbitrary packages.
      */
+    @UnsupportedAppUsage
     void clearBackupData(String transportName, String packageName);
 
     /**
@@ -92,6 +94,7 @@
      *
      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
      */
+    @UnsupportedAppUsage
     void setBackupEnabled(boolean isEnabled);
 
     /**
@@ -107,6 +110,7 @@
      * @param doAutoRestore When true, enables the automatic app-data restore facility.  When
      *   false, this facility will be disabled.
      */
+    @UnsupportedAppUsage
     void setAutoRestore(boolean doAutoRestore);
 
     /**
@@ -121,6 +125,7 @@
      *
      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
      */
+    @UnsupportedAppUsage
     boolean isBackupEnabled();
 
     /**
@@ -217,6 +222,7 @@
      *
      * <p>Callers must hold the android.permission.BACKUP permission to use this method.
      */
+    @UnsupportedAppUsage
     void acknowledgeFullBackupOrRestore(int token, boolean allow,
             in String curPassword, in String encryptionPassword,
             IFullBackupRestoreObserver observer);
@@ -255,12 +261,14 @@
      * Identify the currently selected transport.  Callers must hold the
      * android.permission.BACKUP permission to use this method.
      */
+    @UnsupportedAppUsage
     String getCurrentTransport();
 
     /**
      * Request a list of all available backup transports' names.  Callers must
      * hold the android.permission.BACKUP permission to use this method.
      */
+    @UnsupportedAppUsage
     String[] listAllTransports();
 
     ComponentName[] listAllTransportComponents();
@@ -283,6 +291,7 @@
      *   name is not one of the currently available transports, no change is made to
      *   the current transport setting and the method returns null.
      */
+    @UnsupportedAppUsage
     String selectBackupTransport(String transport);
 
     /**
@@ -385,6 +394,7 @@
      * @param whichUser User handle of the defined user whose backup active state
      *     is being queried.
      */
+    @UnsupportedAppUsage
     boolean isBackupServiceActive(int whichUser);
 
     /**
diff --git a/core/java/android/app/job/IJobCallback.aidl b/core/java/android/app/job/IJobCallback.aidl
index e7695e2..d281da0 100644
--- a/core/java/android/app/job/IJobCallback.aidl
+++ b/core/java/android/app/job/IJobCallback.aidl
@@ -36,6 +36,7 @@
      * @param ongoing True to indicate that the client is processing the job. False if the job is
      * complete
      */
+    @UnsupportedAppUsage
     void acknowledgeStartMessage(int jobId, boolean ongoing);
     /**
      * Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
@@ -43,14 +44,17 @@
      * @param jobId Unique integer used to identify this job.
      * @param reschedule Whether or not to reschedule this job.
      */
+    @UnsupportedAppUsage
     void acknowledgeStopMessage(int jobId, boolean reschedule);
     /*
      * Called to deqeue next work item for the job.
      */
+    @UnsupportedAppUsage
     JobWorkItem dequeueWork(int jobId);
     /*
      * Called to report that job has completed processing a work item.
      */
+    @UnsupportedAppUsage
     boolean completeWork(int jobId, int workId);
     /*
      * Tell the job manager that the client is done with its execution, so that it can go on to
@@ -59,5 +63,6 @@
      * @param jobId Unique integer used to identify this job.
      * @param reschedule Whether or not to reschedule this job.
      */
+    @UnsupportedAppUsage
     void jobFinished(int jobId, boolean reschedule);
 }
diff --git a/core/java/android/app/job/IJobService.aidl b/core/java/android/app/job/IJobService.aidl
index 7f55d29..22ad252 100644
--- a/core/java/android/app/job/IJobService.aidl
+++ b/core/java/android/app/job/IJobService.aidl
@@ -26,7 +26,9 @@
  */
 oneway interface IJobService {
     /** Begin execution of application's job. */
+    @UnsupportedAppUsage
     void startJob(in JobParameters jobParams);
     /** Stop execution of application's job. */
+    @UnsupportedAppUsage
     void stopJob(in JobParameters jobParams);
 }
diff --git a/core/java/android/app/usage/IUsageStatsManager.aidl b/core/java/android/app/usage/IUsageStatsManager.aidl
index 9713527..763af9e 100644
--- a/core/java/android/app/usage/IUsageStatsManager.aidl
+++ b/core/java/android/app/usage/IUsageStatsManager.aidl
@@ -28,8 +28,10 @@
  * {@hide}
  */
 interface IUsageStatsManager {
+    @UnsupportedAppUsage
     ParceledListSlice queryUsageStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
+    @UnsupportedAppUsage
     ParceledListSlice queryConfigurationStats(int bucketType, long beginTime, long endTime,
             String callingPackage);
     ParceledListSlice queryEventStats(int bucketType, long beginTime, long endTime,
@@ -38,7 +40,9 @@
     UsageEvents queryEventsForPackage(long beginTime, long endTime, String callingPackage);
     UsageEvents queryEventsForUser(long beginTime, long endTime, int userId, String callingPackage);
     UsageEvents queryEventsForPackageForUser(long beginTime, long endTime, int userId, String pkg, String callingPackage);
+    @UnsupportedAppUsage
     void setAppInactive(String packageName, boolean inactive, int userId);
+    @UnsupportedAppUsage
     boolean isAppInactive(String packageName, int userId);
     void whitelistAppTemporarily(String packageName, long duration, int userId);
     void onCarrierPrivilegedAppsChanged();
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ab8c196..b8a741a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -19,6 +19,7 @@
 
 import android.Manifest;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -3057,7 +3058,7 @@
      * permissions, or unable to start this CoC
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingL2capChannel()
+    public @NonNull BluetoothServerSocket listenUsingL2capChannel()
             throws IOException {
         BluetoothServerSocket socket =
                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, true, true,
@@ -3115,7 +3116,7 @@
      * permissions, or unable to start this CoC
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothServerSocket listenUsingInsecureL2capChannel()
+    public @NonNull BluetoothServerSocket listenUsingInsecureL2capChannel()
             throws IOException {
         BluetoothServerSocket socket =
                             new BluetoothServerSocket(BluetoothSocket.TYPE_L2CAP_LE, false, false,
diff --git a/core/java/android/bluetooth/BluetoothCodecStatus.java b/core/java/android/bluetooth/BluetoothCodecStatus.java
index 78560d2..32bb681 100644
--- a/core/java/android/bluetooth/BluetoothCodecStatus.java
+++ b/core/java/android/bluetooth/BluetoothCodecStatus.java
@@ -74,8 +74,8 @@
      * @param c2 the second array of capabilities to compare
      * @return true if both arrays contain same capabilities
      */
-    private static boolean sameCapabilities(BluetoothCodecConfig[] c1,
-                                            BluetoothCodecConfig[] c2) {
+    public static boolean sameCapabilities(BluetoothCodecConfig[] c1,
+                                           BluetoothCodecConfig[] c2) {
         if (c1 == null) {
             return (c2 == null);
         }
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 4d8dc35..c4c14d1 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -2182,7 +2183,7 @@
      * permissions
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createL2capChannel(int psm) throws IOException {
+    public @NonNull BluetoothSocket createL2capChannel(int psm) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "createL2capChannel: Bluetooth is not enabled");
             throw new IOException();
@@ -2221,7 +2222,7 @@
      * permissions
      */
     @RequiresPermission(Manifest.permission.BLUETOOTH)
-    public BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
+    public @NonNull BluetoothSocket createInsecureL2capChannel(int psm) throws IOException {
         if (!isBluetoothEnabled()) {
             Log.e(TAG, "createInsecureL2capChannel: Bluetooth is not enabled");
             throw new IOException();
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 23a8159..c5a0bbd 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
@@ -302,7 +303,7 @@
      * {@inheritDoc}
      */
     @Override
-    public List<BluetoothDevice> getConnectedDevices() {
+    public @NonNull List<BluetoothDevice> getConnectedDevices() {
         if (VDBG) log("getConnectedDevices()");
         try {
             mServiceLock.readLock().lock();
@@ -322,8 +323,8 @@
     /**
      * {@inheritDoc}
      */
-    @Override
-    public List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) {
+    @Override public @NonNull List<BluetoothDevice> getDevicesMatchingConnectionStates(
+    @NonNull int[] states) {
         if (VDBG) log("getDevicesMatchingStates()");
         try {
             mServiceLock.readLock().lock();
@@ -344,7 +345,7 @@
      * {@inheritDoc}
      */
     @Override
-    public int getConnectionState(BluetoothDevice device) {
+    public int getConnectionState(@NonNull BluetoothDevice device) {
         if (VDBG) log("getState(" + device + ")");
         try {
             mServiceLock.readLock().lock();
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 6bede13..fccb5eb 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -795,5 +795,6 @@
         }
     }
 
+    @UnsupportedAppUsage
     private IBinder mRemote;
 }
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index dc17666..44bfd3c 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -61,6 +61,7 @@
      */
     void sync(in SyncRequest request);
     void syncAsUser(in SyncRequest request, int userId);
+    @UnsupportedAppUsage
     void cancelSync(in Account account, String authority, in ComponentName cname);
     void cancelSyncAsUser(in Account account, String authority, in ComponentName cname, int userId);
 
@@ -118,6 +119,7 @@
      * Check if this account/provider is syncable.
      * @return >0 if it is syncable, 0 if not, and <0 if the state isn't known yet.
      */
+    @UnsupportedAppUsage
     int getIsSyncable(in Account account, String providerName);
     int getIsSyncableAsUser(in Account account, String providerName, int userId);
 
@@ -127,9 +129,11 @@
      */
     void setIsSyncable(in Account account, String providerName, int syncable);
 
+    @UnsupportedAppUsage
     void setMasterSyncAutomatically(boolean flag);
     void setMasterSyncAutomaticallyAsUser(boolean flag, int userId);
 
+    @UnsupportedAppUsage
     boolean getMasterSyncAutomatically();
     boolean getMasterSyncAutomaticallyAsUser(int userId);
 
@@ -140,6 +144,7 @@
      * Returns the types of the SyncAdapters that are registered with the system.
      * @return Returns the types of the SyncAdapters that are registered with the system.
      */
+    @UnsupportedAppUsage
     SyncAdapterType[] getSyncAdapterTypes();
     SyncAdapterType[] getSyncAdapterTypesAsUser(int userId);
 
@@ -153,6 +158,7 @@
      * @param cname component to identify sync service, must be null if account/providerName are
      * non-null.
      */
+    @UnsupportedAppUsage
     boolean isSyncActive(in Account account, String authority, in ComponentName cname);
 
     /**
diff --git a/core/java/android/content/IIntentReceiver.aidl b/core/java/android/content/IIntentReceiver.aidl
index 3d92723..2b45021 100644
--- a/core/java/android/content/IIntentReceiver.aidl
+++ b/core/java/android/content/IIntentReceiver.aidl
@@ -27,6 +27,7 @@
  * {@hide}
  */
 oneway interface IIntentReceiver {
+    @UnsupportedAppUsage
     void performReceive(in Intent intent, int resultCode, String data,
             in Bundle extras, boolean ordered, boolean sticky, int sendingUser);
 }
diff --git a/core/java/android/content/ISyncAdapter.aidl b/core/java/android/content/ISyncAdapter.aidl
index 0eb581e..9242d02 100644
--- a/core/java/android/content/ISyncAdapter.aidl
+++ b/core/java/android/content/ISyncAdapter.aidl
@@ -32,6 +32,7 @@
      *
      * @param cb If called back with {@code false} accounts are not synced.
      */
+    @UnsupportedAppUsage
     void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb);
 
     /**
@@ -44,6 +45,7 @@
      * @param account the account that should be synced
      * @param extras SyncAdapter-specific parameters
      */
+    @UnsupportedAppUsage
     void startSync(ISyncContext syncContext, String authority,
       in Account account, in Bundle extras);
 
@@ -52,5 +54,6 @@
      * after the ISyncContext.onFinished() for that sync was called.
      * @param syncContext the ISyncContext that was passed to {@link #startSync}
      */
+    @UnsupportedAppUsage
     void cancelSync(ISyncContext syncContext);
 }
diff --git a/core/java/android/content/ISyncServiceAdapter.aidl b/core/java/android/content/ISyncServiceAdapter.aidl
index d419307..29f3a40 100644
--- a/core/java/android/content/ISyncServiceAdapter.aidl
+++ b/core/java/android/content/ISyncServiceAdapter.aidl
@@ -35,11 +35,13 @@
      * @param extras SyncAdapter-specific parameters.
      *
      */
+    @UnsupportedAppUsage
     void startSync(ISyncContext syncContext, in Bundle extras);
 
     /**
      * Cancel the currently ongoing sync.
      */
+    @UnsupportedAppUsage
     void cancelSync(ISyncContext syncContext);
 
 }
diff --git a/core/java/android/content/ISyncStatusObserver.aidl b/core/java/android/content/ISyncStatusObserver.aidl
index eb26845..64bf3bd 100644
--- a/core/java/android/content/ISyncStatusObserver.aidl
+++ b/core/java/android/content/ISyncStatusObserver.aidl
@@ -20,5 +20,6 @@
  * @hide
  */
 oneway interface ISyncStatusObserver {
+    @UnsupportedAppUsage
     void onStatusChanged(int which);
 }
diff --git a/core/java/android/content/om/IOverlayManager.aidl b/core/java/android/content/om/IOverlayManager.aidl
index 5b3c9dd..722c128 100644
--- a/core/java/android/content/om/IOverlayManager.aidl
+++ b/core/java/android/content/om/IOverlayManager.aidl
@@ -37,6 +37,7 @@
      *         mapped to lists of overlays; if no overlays exist for the
      *         requested user, an empty map is returned.
      */
+    @UnsupportedAppUsage
     Map getAllOverlays(in int userId);
 
     /**
@@ -60,6 +61,7 @@
      * @return The OverlayInfo for the overlay package; or null if no such
      *         overlay package exists.
      */
+    @UnsupportedAppUsage
     OverlayInfo getOverlayInfo(in String packageName, in int userId);
 
     /**
diff --git a/core/java/android/content/pm/IPackageDataObserver.aidl b/core/java/android/content/pm/IPackageDataObserver.aidl
index d010ee4..926ecda 100644
--- a/core/java/android/content/pm/IPackageDataObserver.aidl
+++ b/core/java/android/content/pm/IPackageDataObserver.aidl
@@ -24,5 +24,6 @@
  * {@hide}
  */
 oneway interface IPackageDataObserver {
+    @UnsupportedAppUsage
     void onRemoveCompleted(in String packageName, boolean succeeded);
 }
diff --git a/core/java/android/content/pm/IPackageDeleteObserver.aidl b/core/java/android/content/pm/IPackageDeleteObserver.aidl
index 2e2d16e..faae81e 100644
--- a/core/java/android/content/pm/IPackageDeleteObserver.aidl
+++ b/core/java/android/content/pm/IPackageDeleteObserver.aidl
@@ -23,6 +23,7 @@
  * {@hide}
  */
 oneway interface IPackageDeleteObserver {
+    @UnsupportedAppUsage
     void packageDeleted(in String packageName, in int returnCode);
 }
 
diff --git a/core/java/android/content/pm/IPackageDeleteObserver2.aidl b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
index bff3baa..ea80967 100644
--- a/core/java/android/content/pm/IPackageDeleteObserver2.aidl
+++ b/core/java/android/content/pm/IPackageDeleteObserver2.aidl
@@ -21,5 +21,6 @@
 /** {@hide} */
 oneway interface IPackageDeleteObserver2 {
     void onUserActionRequired(in Intent intent);
+    @UnsupportedAppUsage
     void onPackageDeleted(String packageName, int returnCode, String msg);
 }
diff --git a/core/java/android/content/pm/IPackageInstallObserver2.aidl b/core/java/android/content/pm/IPackageInstallObserver2.aidl
index bb5f22a..ed2eb7d 100644
--- a/core/java/android/content/pm/IPackageInstallObserver2.aidl
+++ b/core/java/android/content/pm/IPackageInstallObserver2.aidl
@@ -25,6 +25,7 @@
  * @hide
  */
 oneway interface IPackageInstallObserver2 {
+    @UnsupportedAppUsage
     void onUserActionRequired(in Intent intent);
 
     /**
@@ -42,5 +43,6 @@
      * </tr>
      * </table>
      */
+    @UnsupportedAppUsage
     void onPackageInstalled(String basePackageName, int returnCode, String msg, in Bundle extras);
 }
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index ecc8cd6..fa23933 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -45,6 +45,7 @@
     void registerCallback(IPackageInstallerCallback callback, int userId);
     void unregisterCallback(IPackageInstallerCallback callback);
 
+    @UnsupportedAppUsage
     void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags,
             in IntentSender statusReceiver, int userId);
 
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index 974eb1e..ee26500 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -18,9 +18,14 @@
 
 /** {@hide} */
 oneway interface IPackageInstallerCallback {
+    @UnsupportedAppUsage
     void onSessionCreated(int sessionId);
+    @UnsupportedAppUsage
     void onSessionBadgingChanged(int sessionId);
+    @UnsupportedAppUsage
     void onSessionActiveChanged(int sessionId, boolean active);
+    @UnsupportedAppUsage
     void onSessionProgressChanged(int sessionId, float progress);
+    @UnsupportedAppUsage
     void onSessionFinished(int sessionId, boolean success);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index da7d664..48165dc 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -62,45 +62,60 @@
  */
 interface IPackageManager {
     void checkPackageStartable(String packageName, int userId);
+    @UnsupportedAppUsage
     boolean isPackageAvailable(String packageName, int userId);
+    @UnsupportedAppUsage
     PackageInfo getPackageInfo(String packageName, int flags, int userId);
     PackageInfo getPackageInfoVersioned(in VersionedPackage versionedPackage,
             int flags, int userId);
+    @UnsupportedAppUsage
     int getPackageUid(String packageName, int flags, int userId);
     int[] getPackageGids(String packageName, int flags, int userId);
 
+    @UnsupportedAppUsage
     String[] currentToCanonicalPackageNames(in String[] names);
+    @UnsupportedAppUsage
     String[] canonicalToCurrentPackageNames(in String[] names);
 
     PermissionInfo getPermissionInfo(String name, String packageName, int flags);
 
     ParceledListSlice queryPermissionsByGroup(String group, int flags);
 
+    @UnsupportedAppUsage
     PermissionGroupInfo getPermissionGroupInfo(String name, int flags);
 
     ParceledListSlice getAllPermissionGroups(int flags);
 
+    @UnsupportedAppUsage
     ApplicationInfo getApplicationInfo(String packageName, int flags ,int userId);
 
+    @UnsupportedAppUsage
     ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
 
     boolean activitySupportsIntent(in ComponentName className, in Intent intent,
             String resolvedType);
 
+    @UnsupportedAppUsage
     ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     ProviderInfo getProviderInfo(in ComponentName className, int flags, int userId);
 
+    @UnsupportedAppUsage
     int checkPermission(String permName, String pkgName, int userId);
 
     int checkUidPermission(String permName, int uid);
 
+    @UnsupportedAppUsage
     boolean addPermission(in PermissionInfo info);
 
+    @UnsupportedAppUsage
     void removePermission(String name);
 
+    @UnsupportedAppUsage
     void grantRuntimePermission(String packageName, String permissionName, int userId);
 
     void revokeRuntimePermission(String packageName, String permissionName, int userId);
@@ -119,33 +134,43 @@
 
     boolean isProtectedBroadcast(String actionName);
 
+    @UnsupportedAppUsage
     int checkSignatures(String pkg1, String pkg2);
 
+    @UnsupportedAppUsage
     int checkUidSignatures(int uid1, int uid2);
 
     List<String> getAllPackages();
 
+    @UnsupportedAppUsage
     String[] getPackagesForUid(int uid);
 
+    @UnsupportedAppUsage
     String getNameForUid(int uid);
     String[] getNamesForUids(in int[] uids);
 
+    @UnsupportedAppUsage
     int getUidForSharedUser(String sharedUserName);
 
+    @UnsupportedAppUsage
     int getFlagsForUid(int uid);
 
     int getPrivateFlagsForUid(int uid);
 
+    @UnsupportedAppUsage
     boolean isUidPrivileged(int uid);
 
+    @UnsupportedAppUsage
     String[] getAppOpPermissionPackages(String permissionName);
 
+    @UnsupportedAppUsage
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
     ResolveInfo findPersistentPreferredActivity(in Intent intent, int userId);
 
     boolean canForwardTo(in Intent intent, String resolvedType, int sourceUserId, int targetUserId);
 
+    @UnsupportedAppUsage
     ParceledListSlice queryIntentActivities(in Intent intent,
             String resolvedType, int flags, int userId);
 
@@ -172,6 +197,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
+    @UnsupportedAppUsage
     ParceledListSlice getInstalledPackages(int flags, in int userId);
 
     /**
@@ -189,6 +215,7 @@
      * limit that kicks in when flags are included that bloat up the data
      * returned.
      */
+    @UnsupportedAppUsage
     ParceledListSlice getInstalledApplications(int flags, int userId);
 
     /**
@@ -209,20 +236,24 @@
      * @param outInfo Filled in with a list of the ProviderInfo for each
      *                name in 'outNames'.
      */
+    @UnsupportedAppUsage
     void querySyncProviders(inout List<String> outNames,
             inout List<ProviderInfo> outInfo);
 
     ParceledListSlice queryContentProviders(
             String processName, int uid, int flags, String metaDataKey);
 
+    @UnsupportedAppUsage
     InstrumentationInfo getInstrumentationInfo(
             in ComponentName className, int flags);
 
+    @UnsupportedAppUsage
     ParceledListSlice queryInstrumentation(
             String targetPackage, int flags);
 
     void finishPackageInstall(int token, boolean didLaunch);
 
+    @UnsupportedAppUsage
     void setInstallerPackageName(in String targetPackage, in String installerPackageName);
 
     void setApplicationCategoryHint(String packageName, int categoryHint, String callerPackageName);
@@ -242,24 +273,30 @@
     void deletePackageVersioned(in VersionedPackage versionedPackage,
             IPackageDeleteObserver2 observer, int userId, int flags);
 
+    @UnsupportedAppUsage
     String getInstallerPackageName(in String packageName);
 
     void resetApplicationPreferences(int userId);
 
+    @UnsupportedAppUsage
     ResolveInfo getLastChosenActivity(in Intent intent,
             String resolvedType, int flags);
 
+    @UnsupportedAppUsage
     void setLastChosenActivity(in Intent intent, String resolvedType, int flags,
             in IntentFilter filter, int match, in ComponentName activity);
 
     void addPreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity, int userId);
 
+    @UnsupportedAppUsage
     void replacePreferredActivity(in IntentFilter filter, int match,
             in ComponentName[] set, in ComponentName activity, int userId);
 
+    @UnsupportedAppUsage
     void clearPackagePreferredActivities(String packageName);
 
+    @UnsupportedAppUsage
     int getPreferredActivities(out List<IntentFilter> outFilters,
             out List<ComponentName> outActivities, String packageName);
 
@@ -296,6 +333,7 @@
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
      */
+     @UnsupportedAppUsage
      ComponentName getHomeActivities(out List<ResolveInfo> outHomeCandidates);
 
     void setHomeActivity(in ComponentName className, int userId);
@@ -303,23 +341,27 @@
     /**
      * As per {@link android.content.pm.PackageManager#setComponentEnabledSetting}.
      */
+    @UnsupportedAppUsage
     void setComponentEnabledSetting(in ComponentName componentName,
             in int newState, in int flags, int userId);
 
     /**
      * As per {@link android.content.pm.PackageManager#getComponentEnabledSetting}.
      */
+    @UnsupportedAppUsage
     int getComponentEnabledSetting(in ComponentName componentName, int userId);
 
     /**
      * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}.
      */
+    @UnsupportedAppUsage
     void setApplicationEnabledSetting(in String packageName, in int newState, int flags,
             int userId, String callingPackage);
 
     /**
      * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}.
      */
+    @UnsupportedAppUsage
     int getApplicationEnabledSetting(in String packageName, int userId);
 
     /**
@@ -337,6 +379,7 @@
      * Set whether the given package should be considered stopped, making
      * it not visible to implicit intents that filter out stopped packages.
      */
+    @UnsupportedAppUsage
     void setPackageStoppedState(String packageName, boolean stopped, int userId);
 
     /**
@@ -392,6 +435,7 @@
      * files need to be deleted
      * @param observer a callback used to notify when the deletion is finished.
      */
+    @UnsupportedAppUsage
     void deleteApplicationCacheFiles(in String packageName, IPackageDataObserver observer);
 
     /**
@@ -432,6 +476,7 @@
      * Get a list of shared libraries that are available on the
      * system.
      */
+    @UnsupportedAppUsage
     String[] getSystemSharedLibraryNames();
 
     /**
@@ -443,8 +488,10 @@
     boolean hasSystemFeature(String name, int version);
 
     void enterSafeMode();
+    @UnsupportedAppUsage
     boolean isSafeMode();
     void systemReady();
+    @UnsupportedAppUsage
     boolean hasSystemUidErrors();
 
     /**
@@ -563,9 +610,11 @@
     int movePackage(in String packageName, in String volumeUuid);
     int movePrimaryStorage(in String volumeUuid);
 
+    @UnsupportedAppUsage
     boolean addPermissionAsync(in PermissionInfo info);
 
     boolean setInstallLocation(int loc);
+    @UnsupportedAppUsage
     int getInstallLocation();
 
     int installExistingPackageAsUser(String packageName, int userId, int installFlags,
@@ -593,17 +642,21 @@
     boolean isPermissionEnforced(String permission);
 
     /** Reflects current DeviceStorageMonitorService state */
+    @UnsupportedAppUsage
     boolean isStorageLow();
 
+    @UnsupportedAppUsage
     boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden, int userId);
     boolean getApplicationHiddenSettingAsUser(String packageName, int userId);
 
     void setSystemAppHiddenUntilInstalled(String packageName, boolean hidden);
     boolean setSystemAppInstallState(String packageName, boolean installed, int userId);
 
+    @UnsupportedAppUsage
     IPackageInstaller getPackageInstaller();
 
     boolean setBlockUninstallForUser(String packageName, boolean blockUninstall, int userId);
+    @UnsupportedAppUsage
     boolean getBlockUninstallForUser(String packageName, int userId);
 
     KeySet getKeySetByAlias(String packageName, String alias);
@@ -624,6 +677,7 @@
 
     boolean isPermissionRevokedByPolicy(String permission, String packageName, int userId);
 
+    @UnsupportedAppUsage
     String getPermissionControllerPackageName();
 
     ParceledListSlice getInstantApps(int userId);
@@ -640,7 +694,9 @@
      */
     void setUpdateAvailable(String packageName, boolean updateAvaialble);
 
+    @UnsupportedAppUsage
     String getServicesSystemSharedLibraryPackageName();
+    @UnsupportedAppUsage
     String getSharedSystemSharedLibraryPackageName();
 
     ChangedPackages getChangedPackages(int sequenceNumber, int userId);
diff --git a/core/java/android/content/pm/IPackageStatsObserver.aidl b/core/java/android/content/pm/IPackageStatsObserver.aidl
index ede4d1d..559a035 100644
--- a/core/java/android/content/pm/IPackageStatsObserver.aidl
+++ b/core/java/android/content/pm/IPackageStatsObserver.aidl
@@ -26,5 +26,6 @@
  */
 oneway interface IPackageStatsObserver {
     
+    @UnsupportedAppUsage
     void onGetStatsCompleted(in PackageStats pStats, boolean succeeded);
 }
diff --git a/core/java/android/database/BulkCursorNative.java b/core/java/android/database/BulkCursorNative.java
index d3c11e7..77a13cf 100644
--- a/core/java/android/database/BulkCursorNative.java
+++ b/core/java/android/database/BulkCursorNative.java
@@ -16,6 +16,7 @@
 
 package android.database;
 
+import android.annotation.UnsupportedAppUsage;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -138,6 +139,7 @@
 
 
 final class BulkCursorProxy implements IBulkCursor {
+    @UnsupportedAppUsage
     private IBinder mRemote;
     private Bundle mExtras;
 
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index ac863b2..81abdea0 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1174,6 +1174,7 @@
     {
         private final Camera mCamera;
 
+        @UnsupportedAppUsage
         public EventHandler(Camera c, Looper looper) {
             super(looper);
             mCamera = c;
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b575997..37d93e7 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -30,6 +30,7 @@
 
 /** @hide */
 interface IDisplayManager {
+    @UnsupportedAppUsage
     DisplayInfo getDisplayInfo(int displayId);
     int[] getDisplayIds();
 
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 97868fa..cd17a3e 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -46,6 +46,7 @@
 
     // Injects an input event into the system.  To inject into windows owned by other
     // applications, the caller must have the INJECT_EVENTS permission.
+    @UnsupportedAppUsage
     boolean injectInputEvent(in InputEvent ev, int mode);
 
     // Calibrate input device position
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
index 3fe645c..2dfaf60 100644
--- a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
@@ -32,5 +32,6 @@
      * @param isSupported whether the platform has hardware support for the feature
      * @param instance the available instance to provide access to the feature
      */
+    @UnsupportedAppUsage
     void onAvailabilityChanged(in boolean isSupported, in IActivityRecognitionHardware instance);
 }
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 524077b..2a357ff 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -56,6 +56,7 @@
 import android.util.Log;
 import android.util.SparseIntArray;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.util.Preconditions;
@@ -426,6 +427,16 @@
             "android.net.conn.PROMPT_LOST_VALIDATION";
 
     /**
+     * Action used to display a dialog that asks the user whether to stay connected to a network
+     * that has not validated. This intent is used to start the dialog in settings via
+     * startActivity.
+     *
+     * @hide
+     */
+    public static final String ACTION_PROMPT_PARTIAL_CONNECTIVITY =
+            "android.net.conn.PROMPT_PARTIAL_CONNECTIVITY";
+
+    /**
      * Invalid tethering type.
      * @see #startTethering(int, boolean, OnStartTetheringCallback)
      * @hide
@@ -2542,6 +2553,94 @@
     }
 
     /**
+     * Callback for use with {@link registerTetheringEventCallback} to find out tethering
+     * upstream status.
+     *
+     *@hide
+     */
+    @SystemApi
+    public abstract static class OnTetheringEventCallback {
+
+        /**
+         * Called when tethering upstream changed. This can be called multiple times and can be
+         * called any time.
+         *
+         * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
+         * have any upstream.
+         */
+        public void onUpstreamChanged(@Nullable Network network) {}
+    }
+
+    @GuardedBy("mTetheringEventCallbacks")
+    private final ArrayMap<OnTetheringEventCallback, ITetheringEventCallback>
+            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 loses its upstream or
+     * disabled, {@link OnTetheringEventCallback#onUpstreamChanged} will immediately be called
+     * with a null argument. 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.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void registerTetheringEventCallback(
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull final OnTetheringEventCallback callback) {
+        Preconditions.checkNotNull(callback, "OnTetheringEventCallback cannot be null.");
+
+        synchronized (mTetheringEventCallbacks) {
+            Preconditions.checkArgument(!mTetheringEventCallbacks.containsKey(callback),
+                    "callback was already registered.");
+            ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
+                @Override
+                public void onUpstreamChanged(Network network) throws RemoteException {
+                    Binder.withCleanCallingIdentity(() ->
+                            executor.execute(() -> {
+                                callback.onUpstreamChanged(network);
+                            }));
+                }
+            };
+            try {
+                String pkgName = mContext.getOpPackageName();
+                Log.i(TAG, "registerTetheringUpstreamCallback:" + pkgName);
+                mService.registerTetheringEventCallback(remoteCallback, pkgName);
+                mTetheringEventCallbacks.put(callback, remoteCallback);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+    /**
+     * Remove tethering event callback previously registered with
+     * {@link #registerTetheringEventCallback}.
+     *
+     * @param callback previously registered callback.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
+    public void unregisterTetheringEventCallback(
+            @NonNull final OnTetheringEventCallback callback) {
+        synchronized (mTetheringEventCallbacks) {
+            ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
+            Preconditions.checkNotNull(remoteCallback, "callback was not registered.");
+            try {
+                String pkgName = mContext.getOpPackageName();
+                Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
+                mService.unregisterTetheringEventCallback(remoteCallback, pkgName);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+    }
+
+
+    /**
      * Get the list of regular expressions that define any tetherable
      * USB network interfaces.  If USB tethering is not supported by the
      * device, this list should be empty.
@@ -2706,7 +2805,7 @@
          *         {@link #TETHER_ERROR_PROVISION_FAILED}, or
          *         {@link #TETHER_ERROR_ENTITLEMENT_UNKONWN}.
          */
-        void onEntitlementResult(@EntitlementResultCode int resultCode);
+        void onTetheringEntitlementResult(@EntitlementResultCode int resultCode);
     }
 
     /**
@@ -2756,7 +2855,7 @@
             protected void onReceiveResult(int resultCode, Bundle resultData) {
                 Binder.withCleanCallingIdentity(() ->
                             executor.execute(() -> {
-                                listener.onEntitlementResult(resultCode);
+                                listener.onTetheringEntitlementResult(resultCode);
                             }));
             }
         };
@@ -3059,11 +3158,11 @@
         }
     }
 
-    /** {@hide} */
+    /** {@hide} - returns the factory serial number */
     @UnsupportedAppUsage
-    public void registerNetworkFactory(Messenger messenger, String name) {
+    public int registerNetworkFactory(Messenger messenger, String name) {
         try {
-            mService.registerNetworkFactory(messenger, name);
+            return mService.registerNetworkFactory(messenger, name);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3079,6 +3178,10 @@
         }
     }
 
+    // TODO : remove this method. It is a stopgap measure to help sheperding a number
+    // of dependent changes that would conflict throughout the automerger graph. Having this
+    // temporarily helps with the process of going through with all these dependent changes across
+    // the entire tree.
     /**
      * @hide
      * Register a NetworkAgent with ConnectivityService.
@@ -3086,8 +3189,20 @@
      */
     public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
             NetworkCapabilities nc, int score, NetworkMisc misc) {
+        return registerNetworkAgent(messenger, ni, lp, nc, score, misc,
+                NetworkFactory.SerialNumber.NONE);
+    }
+
+    /**
+     * @hide
+     * Register a NetworkAgent with ConnectivityService.
+     * @return NetID corresponding to NetworkAgent.
+     */
+    public int registerNetworkAgent(Messenger messenger, NetworkInfo ni, LinkProperties lp,
+            NetworkCapabilities nc, int score, NetworkMisc misc, int factorySerialNumber) {
         try {
-            return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc);
+            return mService.registerNetworkAgent(messenger, ni, lp, nc, score, misc,
+                    factorySerialNumber);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3187,9 +3302,9 @@
 
         /**
          * Called if no network is found in the timeout time specified in
-         * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call. This callback is not
-         * called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
-         * without timeout. When this callback is invoked the associated
+         * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the
+         * requested network request cannot be fulfilled (whether or not a timeout was
+         * specified). When this callback is invoked the associated
          * {@link NetworkRequest} will have already been removed and released, as if
          * {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
          */
@@ -3929,7 +4044,7 @@
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
         try {
             mService.setAcceptUnvalidated(network, accept, always);
@@ -3939,6 +4054,29 @@
     }
 
     /**
+     * Informs the system whether it should consider the network as validated even if it only has
+     * partial connectivity. If {@code accept} is true, then the network will be considered as
+     * validated even if connectivity is only partial. If {@code always} is true, then the choice
+     * is remembered, so that the next time the user connects to this network, the system will
+     * switch to it.
+     *
+     * @param network The network to accept.
+     * @param accept Whether to consider the network as validated even if it has partial
+     *               connectivity.
+     * @param always Whether to remember this choice in the future.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
+    public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
+        try {
+            mService.setAcceptPartialConnectivity(network, accept, always);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Informs the system to penalize {@code network}'s score when it becomes unvalidated. This is
      * only meaningful if the system is configured not to penalize such networks, e.g., if the
      * {@code config_networkAvoidBadWifi} configuration variable is set to 0 and the {@code
@@ -3948,7 +4086,7 @@
      *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL)
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public void setAvoidUnvalidated(Network network) {
         try {
             mService.setAvoidUnvalidated(network);
diff --git a/core/java/android/net/DnsPacket.java b/core/java/android/net/DnsPacket.java
index 458fb34..0ac02b1 100644
--- a/core/java/android/net/DnsPacket.java
+++ b/core/java/android/net/DnsPacket.java
@@ -28,7 +28,6 @@
 import java.text.FieldPosition;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.StringJoiner;
 
 /**
  * Defines basic data for DNS protocol based on RFC 1035.
@@ -42,7 +41,7 @@
         public final int id;
         public final int flags;
         public final int rcode;
-        private final int[] mSectionCount;
+        private final int[] mRecordCount;
 
         /**
          * Create a new DnsHeader from a positioned ByteBuffer.
@@ -52,27 +51,32 @@
          * When this constructor returns, the reading position of the ByteBuffer has been
          * advanced to the end of the DNS header record.
          * This is meant to chain with other methods reading a DNS response in sequence.
-         *
          */
         DnsHeader(@NonNull ByteBuffer buf) throws BufferUnderflowException {
             id = BitUtils.uint16(buf.getShort());
             flags = BitUtils.uint16(buf.getShort());
             rcode = flags & 0xF;
-            mSectionCount = new int[NUM_SECTIONS];
+            mRecordCount = new int[NUM_SECTIONS];
             for (int i = 0; i < NUM_SECTIONS; ++i) {
-                mSectionCount[i] = BitUtils.uint16(buf.getShort());
+                mRecordCount[i] = BitUtils.uint16(buf.getShort());
             }
         }
 
         /**
-         * Get section count by section type.
+         * Get record count by type.
          */
-        public int getSectionCount(int sectionType) {
-            return mSectionCount[sectionType];
+        public int getRecordCount(int type) {
+            return mRecordCount[type];
         }
     }
 
-    public class DnsSection {
+    /**
+     * It's used both for DNS questions and DNS resource records.
+     *
+     * DNS questions (No TTL/RDATA)
+     * DNS resource records (With TTL/RDATA)
+     */
+    public class DnsRecord {
         private static final int MAXNAMESIZE = 255;
         private static final int MAXLABELSIZE = 63;
         private static final int MAXLABELCOUNT = 128;
@@ -81,57 +85,57 @@
         private final DecimalFormat byteFormat = new DecimalFormat();
         private final FieldPosition pos = new FieldPosition(0);
 
-        private static final String TAG = "DnsSection";
+        private static final String TAG = "DnsRecord";
 
         public final String dName;
         public final int nsType;
         public final int nsClass;
         public final long ttl;
-        private final byte[] mRR;
+        private final byte[] mRdata;
 
         /**
-         * Create a new DnsSection from a positioned ByteBuffer.
+         * Create a new DnsRecord from a positioned ByteBuffer.
          *
-         * The ByteBuffer must be in network byte order (which is the default).
-         * Reads the passed ByteBuffer from its current position and decodes a DNS section.
+         * @param ByteBuffer input of record, must be in network byte order
+         *         (which is the default).
+         * Reads the passed ByteBuffer from its current position and decodes a DNS record.
          * When this constructor returns, the reading position of the ByteBuffer has been
          * advanced to the end of the DNS header record.
          * This is meant to chain with other methods reading a DNS response in sequence.
-         *
          */
-        DnsSection(int sectionType, @NonNull ByteBuffer buf)
+        DnsRecord(int recordType, @NonNull ByteBuffer buf)
                 throws BufferUnderflowException, ParseException {
             dName = parseName(buf, 0 /* Parse depth */);
             if (dName.length() > MAXNAMESIZE) {
-                throw new ParseException("Parse name fail, name size is too long");
+                throw new ParseException(
+                        "Parse name fail, name size is too long: " + dName.length());
             }
             nsType = BitUtils.uint16(buf.getShort());
             nsClass = BitUtils.uint16(buf.getShort());
 
-            if (sectionType != QDSECTION) {
+            if (recordType != QDSECTION) {
                 ttl = BitUtils.uint32(buf.getInt());
                 final int length = BitUtils.uint16(buf.getShort());
-                mRR = new byte[length];
-                buf.get(mRR);
+                mRdata = new byte[length];
+                buf.get(mRdata);
             } else {
                 ttl = 0;
-                mRR = null;
+                mRdata = null;
             }
         }
 
         /**
-         * Get a copy of rr.
+         * Get a copy of rdata.
          */
-        @Nullable public byte[] getRR() {
-            return (mRR == null) ? null : mRR.clone();
+        @Nullable
+        public byte[] getRR() {
+            return (mRdata == null) ? null : mRdata.clone();
         }
 
         /**
          * Convert label from {@code byte[]} to {@code String}
          *
-         * It follows the same converting rule as native layer.
-         * (See ns_name.c in libc)
-         *
+         * Follows the same conversion rules of the native code (ns_name.c in libc)
          */
         private String labelToString(@NonNull byte[] label) {
             final StringBuffer sb = new StringBuffer();
@@ -139,13 +143,16 @@
                 int b = BitUtils.uint8(label[i]);
                 // Control characters and non-ASCII characters.
                 if (b <= 0x20 || b >= 0x7f) {
+                    // Append the byte as an escaped decimal number, e.g., "\19" for 0x13.
                     sb.append('\\');
                     byteFormat.format(b, sb, pos);
                 } else if (b == '"' || b == '.' || b == ';' || b == '\\'
                         || b == '(' || b == ')' || b == '@' || b == '$') {
+                    // Append the byte as an escaped character, e.g., "\:" for 0x3a.
                     sb.append('\\');
                     sb.append((char) b);
                 } else {
+                    // Append the byte as a character, e.g., "a" for 0x61.
                     sb.append((char) b);
                 }
             }
@@ -154,7 +161,9 @@
 
         private String parseName(@NonNull ByteBuffer buf, int depth) throws
                 BufferUnderflowException, ParseException {
-            if (depth > MAXLABELCOUNT) throw new ParseException("Parse name fails, too many labels");
+            if (depth > MAXLABELCOUNT) {
+                throw new ParseException("Failed to parse name, too many labels");
+            }
             final int len = BitUtils.uint8(buf.get());
             final int mask = len & NAME_COMPRESSION;
             if (0 == len) {
@@ -194,7 +203,7 @@
     private static final String TAG = DnsPacket.class.getSimpleName();
 
     protected final DnsHeader mHeader;
-    protected final List<DnsSection>[] mSections;
+    protected final List<DnsRecord>[] mRecords;
 
     public static class ParseException extends Exception {
         public ParseException(String msg) {
@@ -216,18 +225,18 @@
             throw new ParseException("Parse Header fail, bad input data", e);
         }
 
-        mSections = new ArrayList[NUM_SECTIONS];
+        mRecords = new ArrayList[NUM_SECTIONS];
 
         for (int i = 0; i < NUM_SECTIONS; ++i) {
-            final int count = mHeader.getSectionCount(i);
+            final int count = mHeader.getRecordCount(i);
             if (count > 0) {
-                mSections[i] = new ArrayList(count);
+                mRecords[i] = new ArrayList(count);
             }
             for (int j = 0; j < count; ++j) {
                 try {
-                    mSections[i].add(new DnsSection(i, buffer));
+                    mRecords[i].add(new DnsRecord(i, buffer));
                 } catch (BufferUnderflowException e) {
-                    throw new ParseException("Parse section fail", e);
+                    throw new ParseException("Parse record fail", e);
                 }
             }
         }
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 6d54264..d3bc3e6 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -43,6 +43,9 @@
 /**
  * Dns resolver class for asynchronous dns querying
  *
+ * Note that if a client sends a query with more than 1 record in the question section but
+ * the remote dns server does not support this, it may not respond at all, leading to a timeout.
+ *
  */
 public final class DnsResolver {
     private static final String TAG = "DnsResolver";
@@ -226,19 +229,19 @@
             if (mHeader.rcode != 0) {
                 throw new ParseException("Response error, rcode:" + mHeader.rcode);
             }
-            if (mHeader.getSectionCount(ANSECTION) == 0) {
+            if (mHeader.getRecordCount(ANSECTION) == 0) {
                 throw new ParseException("No available answer");
             }
-            if (mHeader.getSectionCount(QDSECTION) == 0) {
+            if (mHeader.getRecordCount(QDSECTION) == 0) {
                 throw new ParseException("No question found");
             }
-            // Assume only one question per answer packet. (RFC1035)
-            mQueryType = mSections[QDSECTION].get(0).nsType;
+            // Expect only one question in question section.
+            mQueryType = mRecords[QDSECTION].get(0).nsType;
         }
 
         public @NonNull List<InetAddress> getAddresses() {
             final List<InetAddress> results = new ArrayList<InetAddress>();
-            for (final DnsSection ansSec : mSections[ANSECTION]) {
+            for (final DnsRecord ansSec : mRecords[ANSECTION]) {
                 // Only support A and AAAA, also ignore answers if query type != answer type.
                 int nsType = ansSec.nsType;
                 if (nsType != mQueryType || (nsType != TYPE_A && nsType != TYPE_AAAA)) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index ad903d9..403b44d 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -19,6 +19,7 @@
 import android.app.PendingIntent;
 import android.net.ConnectionInfo;
 import android.net.LinkProperties;
+import android.net.ITetheringEventCallback;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo;
@@ -149,14 +150,14 @@
 
     void setAirplaneMode(boolean enable);
 
-    void registerNetworkFactory(in Messenger messenger, in String name);
+    int registerNetworkFactory(in Messenger messenger, in String name);
 
     boolean requestBandwidthUpdate(in Network network);
 
     void unregisterNetworkFactory(in Messenger messenger);
 
     int registerNetworkAgent(in Messenger messenger, in NetworkInfo ni, in LinkProperties lp,
-            in NetworkCapabilities nc, int score, in NetworkMisc misc);
+            in NetworkCapabilities nc, int score, in NetworkMisc misc, in int factorySerialNumber);
 
     NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
             in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);
@@ -175,6 +176,7 @@
     void releaseNetworkRequest(in NetworkRequest networkRequest);
 
     void setAcceptUnvalidated(in Network network, boolean accept, boolean always);
+    void setAcceptPartialConnectivity(in Network network, boolean accept, boolean always);
     void setAvoidUnvalidated(in Network network);
     void startCaptivePortalApp(in Network network);
     void startCaptivePortalAppInternal(in Network network, in Bundle appExtras);
@@ -214,4 +216,7 @@
 
     void getLatestTetheringEntitlementResult(int type, in ResultReceiver receiver,
             boolean showEntitlementUi, String callerPkg);
+
+    void registerTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
+    void unregisterTetheringEventCallback(ITetheringEventCallback callback, String callerPkg);
 }
diff --git a/core/java/android/net/INetworkMonitor.aidl b/core/java/android/net/INetworkMonitor.aidl
index c94cdde..5d1ab98 100644
--- a/core/java/android/net/INetworkMonitor.aidl
+++ b/core/java/android/net/INetworkMonitor.aidl
@@ -32,9 +32,16 @@
     // 3. a broken network (e.g. DNS failed, connect failed, HTTP request failed).
     const int NETWORK_TEST_RESULT_INVALID = 1;
 
+    // After a network has been tested, this result can be sent with EVENT_NETWORK_TESTED.
+    // The network may be used as a default internet connection, but it was found to be a partial
+    // connectivity network which can get the pass result for http probe but get the failed result
+    // for https probe.
+    const int NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY = 2;
+
     void start();
     void launchCaptivePortalApp();
     void notifyCaptivePortalAppFinished(int response);
+    void notifyAcceptPartialConnectivity();
     void forceReevaluation(int uid);
     void notifyPrivateDnsChanged(in PrivateDnsConfigParcel config);
     void notifyDnsResponse(int returnCode);
diff --git a/core/java/android/net/ITestNetworkManager.aidl b/core/java/android/net/ITestNetworkManager.aidl
new file mode 100644
index 0000000..119a30c
--- /dev/null
+++ b/core/java/android/net/ITestNetworkManager.aidl
@@ -0,0 +1,36 @@
+/**
+ * Copyright (c) 2018, 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;
+import android.net.TestNetworkInterface;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Interface that allows for creation and management of test-only networks.
+ *
+ * @hide
+ */
+interface ITestNetworkManager
+{
+    TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs);
+
+    void setupTestNetwork(in String iface, in IBinder binder);
+
+    void teardownTestNetwork(int netId);
+}
diff --git a/core/java/android/net/ITetheringEventCallback.aidl b/core/java/android/net/ITetheringEventCallback.aidl
new file mode 100644
index 0000000..d502088
--- /dev/null
+++ b/core/java/android/net/ITetheringEventCallback.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.Network;
+
+/**
+ * Callback class for receiving tethering changed events
+ * @hide
+ */
+oneway interface ITetheringEventCallback
+{
+    void onUpstreamChanged(in Network network);
+}
diff --git a/core/java/android/net/IpMemoryStore.java b/core/java/android/net/IpMemoryStore.java
index b35f097..2f4d9bc 100644
--- a/core/java/android/net/IpMemoryStore.java
+++ b/core/java/android/net/IpMemoryStore.java
@@ -171,4 +171,9 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /** Gets an instance of the memory store */
+    public static IpMemoryStore getMemoryStore(final Context context) {
+        return (IpMemoryStore) context.getSystemService(Context.IP_MEMORY_STORE_SERVICE);
+    }
 }
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 7bef690..b55f6ba 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -57,6 +57,7 @@
     private static final long BW_REFRESH_MIN_WIN_MS = 500;
     private boolean mPollLceScheduled = false;
     private AtomicBoolean mPollLcePending = new AtomicBoolean(false);
+    public final int mFactorySerialNumber;
 
     private static final int BASE = Protocol.BASE_NETWORK_AGENT;
 
@@ -212,16 +213,31 @@
      */
     public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
 
+    // TODO : remove these two constructors. They are a stopgap measure to help sheperding a number
+    // of dependent changes that would conflict throughout the automerger graph. Having these
+    // temporarily helps with the process of going through with all these dependent changes across
+    // the entire tree.
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
             NetworkCapabilities nc, LinkProperties lp, int score) {
-        this(looper, context, logTag, ni, nc, lp, score, null);
+        this(looper, context, logTag, ni, nc, lp, score, null, NetworkFactory.SerialNumber.NONE);
+    }
+    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
+            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
+        this(looper, context, logTag, ni, nc, lp, score, misc, NetworkFactory.SerialNumber.NONE);
     }
 
     public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
-            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc) {
+            NetworkCapabilities nc, LinkProperties lp, int score, int factorySerialNumber) {
+        this(looper, context, logTag, ni, nc, lp, score, null, factorySerialNumber);
+    }
+
+    public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
+            NetworkCapabilities nc, LinkProperties lp, int score, NetworkMisc misc,
+            int factorySerialNumber) {
         super(looper);
         LOG_TAG = logTag;
         mContext = context;
+        mFactorySerialNumber = factorySerialNumber;
         if (ni == null || nc == null || lp == null) {
             throw new IllegalArgumentException();
         }
@@ -230,7 +246,8 @@
         ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
                 Context.CONNECTIVITY_SERVICE);
         netId = cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
-                new LinkProperties(lp), new NetworkCapabilities(nc), score, misc);
+                new LinkProperties(lp), new NetworkCapabilities(nc), score, misc,
+                factorySerialNumber);
     }
 
     @Override
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 0a63e75..e1cfe99 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -143,7 +143,8 @@
             NET_CAPABILITY_NOT_CONGESTED,
             NET_CAPABILITY_NOT_SUSPENDED,
             NET_CAPABILITY_OEM_PAID,
-            NET_CAPABILITY_MCX
+            NET_CAPABILITY_MCX,
+            NET_CAPABILITY_PARTIAL_CONNECTIVITY,
     })
     public @interface NetCapability { }
 
@@ -304,8 +305,15 @@
      */
     public static final int NET_CAPABILITY_MCX = 23;
 
+    /**
+     * Indicates that this network was tested to only provide partial connectivity.
+     * @hide
+     */
+    @SystemApi
+    public static final int NET_CAPABILITY_PARTIAL_CONNECTIVITY = 24;
+
     private static final int MIN_NET_CAPABILITY = NET_CAPABILITY_MMS;
-    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_MCX;
+    private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 
     /**
      * Network capabilities that are expected to be mutable, i.e., can change while a particular
@@ -320,7 +328,8 @@
             | (1 << NET_CAPABILITY_NOT_ROAMING)
             | (1 << NET_CAPABILITY_FOREGROUND)
             | (1 << NET_CAPABILITY_NOT_CONGESTED)
-            | (1 << NET_CAPABILITY_NOT_SUSPENDED);
+            | (1 << NET_CAPABILITY_NOT_SUSPENDED)
+            | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY);
 
     /**
      * Network capabilities that are not allowed in NetworkRequests. This exists because the
@@ -375,6 +384,15 @@
             (1 << NET_CAPABILITY_WIFI_P2P);
 
     /**
+     * Capabilities that are managed by ConnectivityService.
+     */
+    private static final long CONNECTIVITY_MANAGED_CAPABILITIES =
+            (1 << NET_CAPABILITY_VALIDATED)
+            | (1 << NET_CAPABILITY_CAPTIVE_PORTAL)
+            | (1 << NET_CAPABILITY_FOREGROUND)
+            | (1 << NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+
+    /**
      * Adds the given capability to this {@code NetworkCapability} instance.
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
@@ -507,6 +525,14 @@
                 && ((mUnwantedNetworkCapabilities & (1 << capability)) != 0);
     }
 
+    /**
+     * Check if this NetworkCapabilities has system managed capabilities or not.
+     * @hide
+     */
+    public boolean hasConnectivityManagedCapability() {
+        return ((mNetworkCapabilities & CONNECTIVITY_MANAGED_CAPABILITIES) != 0);
+    }
+
     /** Note this method may result in having the same capability in wanted and unwanted lists. */
     private void combineNetCapabilities(NetworkCapabilities nc) {
         this.mNetworkCapabilities |= nc.mNetworkCapabilities;
@@ -1599,31 +1625,32 @@
      */
     public static String capabilityNameOf(@NetCapability int capability) {
         switch (capability) {
-            case NET_CAPABILITY_MMS:            return "MMS";
-            case NET_CAPABILITY_SUPL:           return "SUPL";
-            case NET_CAPABILITY_DUN:            return "DUN";
-            case NET_CAPABILITY_FOTA:           return "FOTA";
-            case NET_CAPABILITY_IMS:            return "IMS";
-            case NET_CAPABILITY_CBS:            return "CBS";
-            case NET_CAPABILITY_WIFI_P2P:       return "WIFI_P2P";
-            case NET_CAPABILITY_IA:             return "IA";
-            case NET_CAPABILITY_RCS:            return "RCS";
-            case NET_CAPABILITY_XCAP:           return "XCAP";
-            case NET_CAPABILITY_EIMS:           return "EIMS";
-            case NET_CAPABILITY_NOT_METERED:    return "NOT_METERED";
-            case NET_CAPABILITY_INTERNET:       return "INTERNET";
-            case NET_CAPABILITY_NOT_RESTRICTED: return "NOT_RESTRICTED";
-            case NET_CAPABILITY_TRUSTED:        return "TRUSTED";
-            case NET_CAPABILITY_NOT_VPN:        return "NOT_VPN";
-            case NET_CAPABILITY_VALIDATED:      return "VALIDATED";
-            case NET_CAPABILITY_CAPTIVE_PORTAL: return "CAPTIVE_PORTAL";
-            case NET_CAPABILITY_NOT_ROAMING:    return "NOT_ROAMING";
-            case NET_CAPABILITY_FOREGROUND:     return "FOREGROUND";
-            case NET_CAPABILITY_NOT_CONGESTED:  return "NOT_CONGESTED";
-            case NET_CAPABILITY_NOT_SUSPENDED:  return "NOT_SUSPENDED";
-            case NET_CAPABILITY_OEM_PAID:       return "OEM_PAID";
-            case NET_CAPABILITY_MCX:            return "MCX";
-            default:                            return Integer.toString(capability);
+            case NET_CAPABILITY_MMS:                  return "MMS";
+            case NET_CAPABILITY_SUPL:                 return "SUPL";
+            case NET_CAPABILITY_DUN:                  return "DUN";
+            case NET_CAPABILITY_FOTA:                 return "FOTA";
+            case NET_CAPABILITY_IMS:                  return "IMS";
+            case NET_CAPABILITY_CBS:                  return "CBS";
+            case NET_CAPABILITY_WIFI_P2P:             return "WIFI_P2P";
+            case NET_CAPABILITY_IA:                   return "IA";
+            case NET_CAPABILITY_RCS:                  return "RCS";
+            case NET_CAPABILITY_XCAP:                 return "XCAP";
+            case NET_CAPABILITY_EIMS:                 return "EIMS";
+            case NET_CAPABILITY_NOT_METERED:          return "NOT_METERED";
+            case NET_CAPABILITY_INTERNET:             return "INTERNET";
+            case NET_CAPABILITY_NOT_RESTRICTED:       return "NOT_RESTRICTED";
+            case NET_CAPABILITY_TRUSTED:              return "TRUSTED";
+            case NET_CAPABILITY_NOT_VPN:              return "NOT_VPN";
+            case NET_CAPABILITY_VALIDATED:            return "VALIDATED";
+            case NET_CAPABILITY_CAPTIVE_PORTAL:       return "CAPTIVE_PORTAL";
+            case NET_CAPABILITY_NOT_ROAMING:          return "NOT_ROAMING";
+            case NET_CAPABILITY_FOREGROUND:           return "FOREGROUND";
+            case NET_CAPABILITY_NOT_CONGESTED:        return "NOT_CONGESTED";
+            case NET_CAPABILITY_NOT_SUSPENDED:        return "NOT_SUSPENDED";
+            case NET_CAPABILITY_OEM_PAID:             return "OEM_PAID";
+            case NET_CAPABILITY_MCX:                  return "MCX";
+            case NET_CAPABILITY_PARTIAL_CONNECTIVITY: return "PARTIAL_CONNECTIVITY";
+            default:                                  return Integer.toString(capability);
         }
     }
 
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 181cab4..5b1d12c 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -27,11 +27,14 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.Protocol;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * A NetworkFactory is an entity that creates NetworkAgent objects.
@@ -49,6 +52,20 @@
  * @hide
  **/
 public class NetworkFactory extends Handler {
+    /** @hide */
+    public static class SerialNumber {
+        // Guard used by no network factory.
+        public static final int NONE = -1;
+        // A hardcoded serial number for NetworkAgents representing VPNs. These agents are
+        // not created by any factory, so they use this constant for clarity instead of NONE.
+        public static final int VPN = -2;
+        private static final AtomicInteger sNetworkFactorySerialNumber = new AtomicInteger(1);
+        /** Returns a unique serial number for a factory. */
+        public static final int nextSerialNumber() {
+            return sNetworkFactorySerialNumber.getAndIncrement();
+        }
+    }
+
     private static final boolean DBG = true;
     private static final boolean VDBG = false;
 
@@ -64,7 +81,7 @@
      * disregard any that it will never be able to service, for example
      * those requiring a different bearer.
      * msg.obj = NetworkRequest
-     * msg.arg1 = score - the score of the any network currently satisfying this
+     * msg.arg1 = score - the score of the network currently satisfying this
      *            request.  If this bearer knows in advance it cannot
      *            exceed this score it should not try to connect, holding the request
      *            for the future.
@@ -74,6 +91,8 @@
      *            with the same NetworkRequest but an updated score.
      *            Also, network conditions may change for this bearer
      *            allowing for a better score in the future.
+     * msg.arg2 = the serial number of the factory currently responsible for the
+     *            NetworkAgent handling this request, or SerialNumber.NONE if none.
      */
     public static final int CMD_REQUEST_NETWORK = BASE;
 
@@ -96,7 +115,16 @@
      */
     private static final int CMD_SET_FILTER = BASE + 3;
 
+    /**
+     * Sent by NetworkFactory to ConnectivityService to indicate that a request is
+     * unfulfillable.
+     * @see #releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest).
+     */
+    public static final int EVENT_UNFULFILLABLE_REQUEST = BASE + 4;
+
     private final Context mContext;
+    private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
+    private AsyncChannel mAsyncChannel;
     private final String LOG_TAG;
 
     private final SparseArray<NetworkRequestInfo> mNetworkRequests =
@@ -107,6 +135,7 @@
 
     private int mRefCount = 0;
     private Messenger mMessenger = null;
+    private int mSerialNumber;
 
     @UnsupportedAppUsage
     public NetworkFactory(Looper looper, Context context, String logTag,
@@ -121,7 +150,8 @@
         if (DBG) log("Registering NetworkFactory");
         if (mMessenger == null) {
             mMessenger = new Messenger(this);
-            ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
+            mSerialNumber = ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger,
+                    LOG_TAG);
         }
     }
 
@@ -136,8 +166,38 @@
     @Override
     public void handleMessage(Message msg) {
         switch (msg.what) {
+            case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+                if (mAsyncChannel != null) {
+                    log("Received new connection while already connected!");
+                    break;
+                }
+                if (VDBG) log("NetworkFactory fully connected");
+                AsyncChannel ac = new AsyncChannel();
+                ac.connected(null, this, msg.replyTo);
+                ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+                        AsyncChannel.STATUS_SUCCESSFUL);
+                mAsyncChannel = ac;
+                for (Message m : mPreConnectedQueue) {
+                    ac.sendMessage(m);
+                }
+                mPreConnectedQueue.clear();
+                break;
+            }
+            case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+                if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+                if (mAsyncChannel != null) {
+                    mAsyncChannel.disconnect();
+                    mAsyncChannel = null;
+                }
+                break;
+            }
+            case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+                if (DBG) log("NetworkFactory channel lost");
+                mAsyncChannel = null;
+                break;
+            }
             case CMD_REQUEST_NETWORK: {
-                handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
+                handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
                 break;
             }
             case CMD_CANCEL_REQUEST: {
@@ -159,11 +219,13 @@
         public final NetworkRequest request;
         public int score;
         public boolean requested; // do we have a request outstanding, limited by score
+        public int factorySerialNumber;
 
-        public NetworkRequestInfo(NetworkRequest request, int score) {
+        NetworkRequestInfo(NetworkRequest request, int score, int factorySerialNumber) {
             this.request = request;
             this.score = score;
             this.requested = false;
+            this.factorySerialNumber = factorySerialNumber;
         }
 
         @Override
@@ -172,16 +234,51 @@
         }
     }
 
+    /**
+     * Add a NetworkRequest that the bearer may want to attempt to satisfy.
+     * @see #CMD_REQUEST_NETWORK
+     *
+     * @param request the request to handle.
+     * @param score the score of the NetworkAgent currently satisfying this request.
+     * @param servingFactorySerialNumber the serial number of the NetworkFactory that
+     *         created the NetworkAgent currently satisfying this request.
+     */
+    // TODO : remove this method. It is a stopgap measure to help sheperding a number
+    // of dependent changes that would conflict throughout the automerger graph. Having this
+    // temporarily helps with the process of going through with all these dependent changes across
+    // the entire tree.
     @VisibleForTesting
     protected void handleAddRequest(NetworkRequest request, int score) {
+        handleAddRequest(request, score, SerialNumber.NONE);
+    }
+
+    /**
+     * Add a NetworkRequest that the bearer may want to attempt to satisfy.
+     * @see #CMD_REQUEST_NETWORK
+     *
+     * @param request the request to handle.
+     * @param score the score of the NetworkAgent currently satisfying this request.
+     * @param servingFactorySerialNumber the serial number of the NetworkFactory that
+     *         created the NetworkAgent currently satisfying this request.
+     */
+    @VisibleForTesting
+    protected void handleAddRequest(NetworkRequest request, int score,
+            int servingFactorySerialNumber) {
         NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
         if (n == null) {
-            if (DBG) log("got request " + request + " with score " + score);
-            n = new NetworkRequestInfo(request, score);
+            if (DBG) {
+                log("got request " + request + " with score " + score
+                        + " and serial " + servingFactorySerialNumber);
+            }
+            n = new NetworkRequestInfo(request, score, servingFactorySerialNumber);
             mNetworkRequests.put(n.request.requestId, n);
         } else {
-            if (VDBG) log("new score " + score + " for exisiting request " + request);
+            if (VDBG) {
+                log("new score " + score + " for exisiting request " + request
+                        + " with serial " + servingFactorySerialNumber);
+            }
             n.score = score;
+            n.factorySerialNumber = servingFactorySerialNumber;
         }
         if (VDBG) log("  my score=" + mScore + ", my filter=" + mCapabilityFilter);
 
@@ -231,16 +328,19 @@
     }
 
     private void evalRequest(NetworkRequestInfo n) {
-        if (VDBG) log("evalRequest");
-        if (n.requested == false && n.score < mScore &&
-                n.request.networkCapabilities.satisfiedByNetworkCapabilities(
-                mCapabilityFilter) && acceptRequest(n.request, n.score)) {
+        if (VDBG) {
+            log("evalRequest");
+            log(" n.requests = " + n.requested);
+            log(" n.score = " + n.score);
+            log(" mScore = " + mScore);
+            log(" n.factorySerialNumber = " + n.factorySerialNumber);
+            log(" mSerialNumber = " + mSerialNumber);
+        }
+        if (shouldNeedNetworkFor(n)) {
             if (VDBG) log("  needNetworkFor");
             needNetworkFor(n.request, n.score);
             n.requested = true;
-        } else if (n.requested == true &&
-                (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
-                mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
+        } else if (shouldReleaseNetworkFor(n)) {
             if (VDBG) log("  releaseNetworkFor");
             releaseNetworkFor(n.request);
             n.requested = false;
@@ -249,10 +349,39 @@
         }
     }
 
+    private boolean shouldNeedNetworkFor(NetworkRequestInfo n) {
+        // If this request is already tracked, it doesn't qualify for need
+        return !n.requested
+            // If the score of this request is higher or equal to that of this factory and some
+            // other factory is responsible for it, then this factory should not track the request
+            // because it has no hope of satisfying it.
+            && (n.score < mScore || n.factorySerialNumber == mSerialNumber)
+            // If this factory can't satisfy the capability needs of this request, then it
+            // should not be tracked.
+            && n.request.networkCapabilities.satisfiedByNetworkCapabilities(mCapabilityFilter)
+            // Finally if the concrete implementation of the factory rejects the request, then
+            // don't track it.
+            && acceptRequest(n.request, n.score);
+    }
+
+    private boolean shouldReleaseNetworkFor(NetworkRequestInfo n) {
+        // Don't release a request that's not tracked.
+        return n.requested
+            // The request should be released if it can't be satisfied by this factory. That
+            // means either of the following conditions are met :
+            // - Its score is too high to be satisfied by this factory and it's not already
+            //   assigned to the factory
+            // - This factory can't satisfy the capability needs of the request
+            // - The concrete implementation of the factory rejects the request
+            && ((n.score > mScore && n.factorySerialNumber != mSerialNumber)
+                    || !n.request.networkCapabilities.satisfiedByNetworkCapabilities(
+                            mCapabilityFilter)
+                    || !acceptRequest(n.request, n.score));
+    }
+
     private void evalRequests() {
         for (int i = 0; i < mNetworkRequests.size(); i++) {
             NetworkRequestInfo n = mNetworkRequests.valueAt(i);
-
             evalRequest(n);
         }
     }
@@ -267,6 +396,27 @@
         });
     }
 
+    /**
+     * Can be called by a factory to release a request as unfulfillable: the request will be
+     * removed, and the caller will get a
+     * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
+     * returns.
+     *
+     * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
+     * is able to fulfill this request!
+     */
+    protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
+        post(() -> {
+            if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
+            Message msg = obtainMessage(EVENT_UNFULFILLABLE_REQUEST, r);
+            if (mAsyncChannel != null) {
+                mAsyncChannel.sendMessage(msg);
+            } else {
+                mPreConnectedQueue.add(msg);
+            }
+        });
+    }
+
     // override to do simple mode (request independent)
     protected void startNetwork() { }
     protected void stopNetwork() { }
@@ -280,16 +430,6 @@
         if (--mRefCount == 0) stopNetwork();
     }
 
-
-    public void addNetworkRequest(NetworkRequest networkRequest, int score) {
-        sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
-                new NetworkRequestInfo(networkRequest, score)));
-    }
-
-    public void removeNetworkRequest(NetworkRequest networkRequest) {
-        sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
-    }
-
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     public void setScoreFilter(int score) {
         sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
@@ -304,6 +444,10 @@
         return mNetworkRequests.size();
     }
 
+    public int getSerialNumber() {
+        return mSerialNumber;
+    }
+
     protected void log(String s) {
         Log.d(LOG_TAG, s);
     }
@@ -321,10 +465,11 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - ScoreFilter=").
-                append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=").
-                append(mNetworkRequests.size()).append(", refCount=").append(mRefCount).
-                append("}");
+        StringBuilder sb = new StringBuilder("{").append(LOG_TAG).append(" - mSerialNumber=")
+                .append(mSerialNumber).append(", ScoreFilter=")
+                .append(mScore).append(", Filter=").append(mCapabilityFilter).append(", requests=")
+                .append(mNetworkRequests.size()).append(", refCount=").append(mRefCount)
+                .append("}");
         return sb.toString();
     }
 }
diff --git a/core/java/android/net/NetworkMisc.java b/core/java/android/net/NetworkMisc.java
index c0487b5..6fb2390 100644
--- a/core/java/android/net/NetworkMisc.java
+++ b/core/java/android/net/NetworkMisc.java
@@ -52,6 +52,12 @@
     public boolean acceptUnvalidated;
 
     /**
+     * Whether the user explicitly set that this network should be validated even if presence of
+     * only partial internet connectivity.
+     */
+    public boolean acceptPartialConnectivity;
+
+    /**
      * Set to avoid surfacing the "Sign in to network" notification.
      * if carrier receivers/apps are registered to handle the carrier-specific provisioning
      * procedure, a carrier specific provisioning notification will be placed.
diff --git a/core/java/android/net/OWNERS b/core/java/android/net/OWNERS
index 15f4913..a1c7fce 100644
--- a/core/java/android/net/OWNERS
+++ b/core/java/android/net/OWNERS
@@ -1,12 +1,11 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
-jsharkey@android.com
 jchalard@google.com
+jsharkey@android.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
-silberst@google.com
 
 per-file SSL*, Uri*, Url* = flooey@google.com, narayan@google.com, tobiast@google.com
diff --git a/core/java/android/net/ParseException.java b/core/java/android/net/ParseException.java
index 68b209b..2380e86 100644
--- a/core/java/android/net/ParseException.java
+++ b/core/java/android/net/ParseException.java
@@ -24,6 +24,7 @@
     public String response;
 
     ParseException(String response) {
+        super(response);
         this.response = response;
     }
 }
diff --git a/core/java/android/net/SSLCertificateSocketFactory.java b/core/java/android/net/SSLCertificateSocketFactory.java
index 45860b3..95d66bb 100644
--- a/core/java/android/net/SSLCertificateSocketFactory.java
+++ b/core/java/android/net/SSLCertificateSocketFactory.java
@@ -62,7 +62,7 @@
  *
  * The handshake timeout does not apply to actual TCP socket connection.
  * If you want a connection timeout as well, use {@link #createSocket()}
- * and {@link Socket#connect(SocketAddress, int)}, after which you
+ * and {@link Socket#connect(java.net.SocketAddress, int)}, after which you
  * must verify the identity of the server you are connected to.
  *
  * <p class="caution"><b>Most {@link SSLSocketFactory} implementations do not
@@ -211,14 +211,14 @@
     }
 
     /**
-     * Verify the hostname of the certificate used by the other end of a
-     * connected socket.  You MUST call this if you did not supply a hostname
-     * to {@link #createSocket()}.  It is harmless to call this method
-     * redundantly if the hostname has already been verified.
+     * Verify the hostname of the certificate used by the other end of a connected socket using the
+     * {@link HostnameVerifier} obtained from {@code
+     * HttpsURLConnection.getDefaultHostnameVerifier()}. You MUST call this if you did not supply a
+     * hostname to {@link #createSocket()}.  It is harmless to call this method redundantly if the
+     * hostname has already been verified.
      *
-     * <p>Wildcard certificates are allowed to verify any matching hostname,
-     * so "foo.bar.example.com" is verified if the peer has a certificate
-     * for "*.example.com".
+     * <p>Wildcard certificates are allowed to verify any matching hostname, so
+     * "foo.bar.example.com" is verified if the peer has a certificate for "*.example.com".
      *
      * @param socket An SSL socket which has been connected to a server
      * @param hostname The expected hostname of the remote server
@@ -483,7 +483,8 @@
      * {@inheritDoc}
      *
      * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
-     * certificate hostname after connecting; if this instance was created with
+     * certificate hostname after connecting using the {@link HostnameVerifier} obtained from
+     * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with
      * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
      * instead.
      */
@@ -562,7 +563,8 @@
      * {@inheritDoc}
      *
      * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
-     * certificate hostname after connecting; if this instance was created with
+     * certificate hostname after connecting using the {@link HostnameVerifier} obtained from
+     * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with
      * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
      * instead.
      */
@@ -585,7 +587,8 @@
      * {@inheritDoc}
      *
      * <p>By default, this method returns a <i>connected</i> socket and verifies the peer's
-     * certificate hostname after connecting; if this instance was created with
+     * certificate hostname after connecting using the {@link HostnameVerifier} obtained from
+     * {@code HttpsURLConnection.getDefaultHostnameVerifier()}; if this instance was created with
      * {@link #getInsecure(int, SSLSessionCache)}, it returns a socket that is <i>not connected</i>
      * instead.
      */
diff --git a/core/java/android/net/TcpSocketKeepalive.java b/core/java/android/net/TcpSocketKeepalive.java
index 8f6ee7b..f691a0d 100644
--- a/core/java/android/net/TcpSocketKeepalive.java
+++ b/core/java/android/net/TcpSocketKeepalive.java
@@ -45,13 +45,14 @@
      * - The application must not write to or read from the socket after calling this method, until
      *   onDataReceived, onStopped, or onError are called. If it does, the keepalive will fail
      *   with {@link #ERROR_SOCKET_NOT_IDLE}, or {@code #ERROR_INVALID_SOCKET} if the socket
-     *   experienced an error (as in poll(2) returned POLLERR); if this happens, the data received
-     *   from the socket may be invalid, and the socket can't be recovered.
+     *   experienced an error (as in poll(2) returned POLLERR or POLLHUP); if this happens, the data
+     *   received from the socket may be invalid, and the socket can't be recovered.
      * - If the socket has data in the send or receive buffer, then this call will fail with
      *   {@link #ERROR_SOCKET_NOT_IDLE} and can be retried after the data has been processed.
-     *   An app could ensure this by using an application-layer protocol where it can receive
-     *   acknowledgement that it will go into keepalive mode. It could then go into keepalive
-     *   mode after having read the acknowledgement, draining the socket.
+     *   An app could ensure this by using an application-layer protocol to receive acknowledgement
+     *   that indicates all data has been delivered to server, e.g. HTTP 200 OK.
+     *   Then the app could go into keepalive mode after reading all remaining data within the
+     *   acknowledgement.
      */
     @Override
     void startImpl(int intervalSec) {
diff --git a/core/java/android/net/TestNetworkInterface.aidl b/core/java/android/net/TestNetworkInterface.aidl
new file mode 100644
index 0000000..e1f4f9f
--- /dev/null
+++ b/core/java/android/net/TestNetworkInterface.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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;
+
+/** @hide */
+parcelable TestNetworkInterface;
diff --git a/core/java/android/net/TestNetworkInterface.java b/core/java/android/net/TestNetworkInterface.java
new file mode 100644
index 0000000..30e68f5
--- /dev/null
+++ b/core/java/android/net/TestNetworkInterface.java
@@ -0,0 +1,74 @@
+/*
+ * 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.annotation.TestApi;
+import android.os.Parcel;
+import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
+
+/**
+ * This class is used to return the interface name and fd of the test interface
+ *
+ * @hide
+ */
+@TestApi
+public final class TestNetworkInterface implements Parcelable {
+    private static final String TAG = "TestNetworkInterface";
+
+    private final ParcelFileDescriptor mFileDescriptor;
+    private final String mInterfaceName;
+
+    @Override
+    public int describeContents() {
+        return (mFileDescriptor != null) ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeParcelable(mFileDescriptor, PARCELABLE_WRITE_RETURN_VALUE);
+        out.writeString(mInterfaceName);
+    }
+
+    public TestNetworkInterface(ParcelFileDescriptor pfd, String intf) {
+        mFileDescriptor = pfd;
+        mInterfaceName = intf;
+    }
+
+    private TestNetworkInterface(Parcel in) {
+        mFileDescriptor = in.readParcelable(ParcelFileDescriptor.class.getClassLoader());
+        mInterfaceName = in.readString();
+    }
+
+    public ParcelFileDescriptor getFileDescriptor() {
+        return mFileDescriptor;
+    }
+
+    public String getInterfaceName() {
+        return mInterfaceName;
+    }
+
+    public static final Parcelable.Creator<TestNetworkInterface> CREATOR =
+            new Parcelable.Creator<TestNetworkInterface>() {
+                public TestNetworkInterface createFromParcel(Parcel in) {
+                    return new TestNetworkInterface(in);
+                }
+
+                public TestNetworkInterface[] newArray(int size) {
+                    return new TestNetworkInterface[size];
+                }
+            };
+}
diff --git a/core/java/android/net/TestNetworkManager.java b/core/java/android/net/TestNetworkManager.java
new file mode 100644
index 0000000..cd58e66
--- /dev/null
+++ b/core/java/android/net/TestNetworkManager.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2018 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.TestApi;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Class that allows creation and management of per-app, test-only networks
+ *
+ * @hide
+ */
+@TestApi
+public class TestNetworkManager {
+    @NonNull private static final String TAG = TestNetworkManager.class.getSimpleName();
+
+    @NonNull private final ITestNetworkManager mService;
+    @NonNull private final Context mContext;
+
+    /** @hide */
+    public TestNetworkManager(@NonNull Context context, @NonNull ITestNetworkManager service) {
+        mContext = Preconditions.checkNotNull(context, "missing Context");
+        mService = Preconditions.checkNotNull(service, "missing ITestNetworkManager");
+    }
+
+    /**
+     * Teardown the capability-limited, testing-only network for a given interface
+     *
+     * @param network The test network that should be torn down
+     * @hide
+     */
+    @TestApi
+    public void teardownTestNetwork(@NonNull Network network) {
+        try {
+            mService.teardownTestNetwork(network.netId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Sets up a capability-limited, testing-only network for a given interface
+     *
+     * @param iface the name of the interface to be used for the Network LinkProperties.
+     * @param binder A binder object guarding the lifecycle of this test network.
+     * @hide
+     */
+    @TestApi
+    public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+        try {
+            mService.setupTestNetwork(iface, binder);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Create a tun interface for testing purposes
+     *
+     * @param linkAddrs an array of LinkAddresses to assign to the TUN interface
+     * @return A ParcelFileDescriptor of the underlying TUN interface. Close this to tear down the
+     *     TUN interface.
+     * @hide
+     */
+    @TestApi
+    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+        try {
+            return mService.createTunInterface(linkAddrs);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 28b2707..9125cfb 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.Intent;
@@ -380,6 +381,7 @@
      * returned as {@code http://example.com/...}.
      * @return the common forms PII redacted string of this URI
      */
+    @NonNull
     public String toSafeString() {
         String scheme = getScheme();
         String ssp = getSchemeSpecificPart();
diff --git a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
index 7432687..3930344 100644
--- a/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
+++ b/core/java/android/net/captiveportal/CaptivePortalProbeResult.java
@@ -30,10 +30,20 @@
     public static final int SUCCESS_CODE = 204;
     public static final int FAILED_CODE = 599;
     public static final int PORTAL_CODE = 302;
+    // Set partial connectivity http response code to -1 to prevent conflict with the other http
+    // response codes. Besides the default http response code of probe result is set as 599 in
+    // NetworkMonitor#sendParallelHttpProbes(), so response code will be set as -1 only when
+    // NetworkMonitor detects partial connectivity.
+    /**
+     * @hide
+     */
+    public static final int PARTIAL_CODE = -1;
 
     public static final CaptivePortalProbeResult FAILED = new CaptivePortalProbeResult(FAILED_CODE);
     public static final CaptivePortalProbeResult SUCCESS =
             new CaptivePortalProbeResult(SUCCESS_CODE);
+    public static final CaptivePortalProbeResult PARTIAL =
+            new CaptivePortalProbeResult(PARTIAL_CODE);
 
     private final int mHttpResponseCode;  // HTTP response code returned from Internet probe.
     public final String redirectUrl;      // Redirect destination returned from Internet probe.
@@ -69,4 +79,8 @@
     public boolean isFailed() {
         return !isSuccessful() && !isPortal();
     }
+
+    public boolean isPartialConnectivity() {
+        return mHttpResponseCode == PARTIAL_CODE;
+    }
 }
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index f5b2ff1..5128115 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -50,6 +50,8 @@
 
     public static final int NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND = 12;
 
+    public static final int NETWORK_PARTIAL_CONNECTIVITY = 13;
+
     /** @hide */
     @IntDef(value = {
             NETWORK_CONNECTED,
@@ -64,6 +66,7 @@
             NETWORK_FIRST_VALIDATION_PORTAL_FOUND,
             NETWORK_REVALIDATION_PORTAL_FOUND,
             NETWORK_CONSECUTIVE_DNS_TIMEOUT_FOUND,
+            NETWORK_PARTIAL_CONNECTIVITY,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 01932ab..f23dc2d 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -16,6 +16,7 @@
 
 package android.nfc.cardemulation;
 
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Activity;
@@ -359,7 +360,7 @@
      * @param service The component name of the service
      * @return whether the registration was successful.
      */
-    public boolean unsetOffHostForService(ComponentName service) {
+    public boolean unsetOffHostForService(@NonNull ComponentName service) {
         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
         if (adapter == null) {
             return false;
@@ -405,7 +406,8 @@
      * @param offHostSecureElement Secure Element to register the AID to
      * @return whether the registration was successful.
      */
-    public boolean setOffHostForService(ComponentName service, String offHostSecureElement) {
+    public boolean setOffHostForService(@NonNull ComponentName service,
+            @NonNull String offHostSecureElement) {
         boolean validSecureElement = false;
 
         NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 684369a..672624c 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.CallbackExecutor;
+import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -39,7 +40,7 @@
  */
 @SystemApi
 @SystemService(Context.BUGREPORT_SERVICE)
-public class BugreportManager {
+public final class BugreportManager {
     private final Context mContext;
     private final IDumpstate mBinder;
 
@@ -90,7 +91,7 @@
          * Called when there is a progress update.
          * @param progress the progress in [0.0, 100.0]
          */
-        public void onProgress(float progress) {}
+        public void onProgress(@FloatRange(from = 0f, to = 100f) float progress) {}
 
         /**
          * Called when taking bugreport resulted in an error.
diff --git a/core/java/android/os/BugreportParams.java b/core/java/android/os/BugreportParams.java
index 3871375..279ccae 100644
--- a/core/java/android/os/BugreportParams.java
+++ b/core/java/android/os/BugreportParams.java
@@ -41,6 +41,7 @@
 
     /**
      * Defines acceptable types of bugreports.
+     * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "BUGREPORT_MODE_" }, value = {
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
index 70054fc..000b8f3 100644
--- a/core/java/android/security/keystore/recovery/RecoveryController.java
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -29,6 +29,7 @@
 import android.os.ServiceSpecificException;
 import android.security.KeyStore;
 import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
 
 import com.android.internal.widget.ILockSettings;
 
@@ -635,7 +636,7 @@
             return getKeyFromGrant(grantAlias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
-        } catch (UnrecoverableKeyException e) {
+        } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) {
             throw new InternalRecoveryServiceException("Failed to get key from keystore", e);
         } catch (ServiceSpecificException e) {
             if (e.errorCode == ERROR_INSECURE_USER) {
@@ -666,7 +667,7 @@
             return getKeyFromGrant(grantAlias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
-        } catch (UnrecoverableKeyException e) {
+        } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) {
             throw new InternalRecoveryServiceException("Failed to get key from keystore", e);
         } catch (ServiceSpecificException e) {
             if (e.errorCode == ERROR_INSECURE_USER) {
@@ -696,6 +697,8 @@
             return getKeyFromGrant(grantAlias);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) {
+            throw new UnrecoverableKeyException("Failed to get key from keystore");
         } catch (ServiceSpecificException e) {
             throw wrapUnexpectedServiceSpecificException(e);
         }
@@ -704,7 +707,8 @@
     /**
      * Returns the key with the given {@code grantAlias}.
      */
-    @NonNull Key getKeyFromGrant(@NonNull String grantAlias) throws UnrecoverableKeyException {
+    @NonNull Key getKeyFromGrant(@NonNull String grantAlias)
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(
                 mKeyStore,
                 grantAlias,
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
index 3bb6421..6622712 100644
--- a/core/java/android/security/keystore/recovery/RecoverySession.java
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -22,6 +22,7 @@
 import android.annotation.SystemApi;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.util.ArrayMap;
 import android.util.Log;
 
@@ -218,7 +219,7 @@
             Key key;
             try {
                 key = mRecoveryController.getKeyFromGrant(grantAlias);
-            } catch (UnrecoverableKeyException e) {
+            } catch (KeyPermanentlyInvalidatedException | UnrecoverableKeyException e) {
                 throw new InternalRecoveryServiceException(
                         String.format(
                                 Locale.US,
diff --git a/core/java/android/service/carrier/CarrierIdentifier.java b/core/java/android/service/carrier/CarrierIdentifier.java
index 8c73a87..3b71aa7 100644
--- a/core/java/android/service/carrier/CarrierIdentifier.java
+++ b/core/java/android/service/carrier/CarrierIdentifier.java
@@ -55,7 +55,7 @@
     private @Nullable String mGid1;
     private @Nullable String mGid2;
     private int mCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
-    private int mPreciseCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+    private int mSpecificCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
 
     public CarrierIdentifier(String mcc, String mnc, @Nullable String spn, @Nullable String imsi,
             @Nullable String gid1, @Nullable String gid2) {
@@ -72,12 +72,12 @@
      * @param gid2 group id level 2
      * @param carrierid carrier unique identifier {@link TelephonyManager#getSimCarrierId()}, used
      *                  to uniquely identify the carrier and look up the carrier configurations.
-     * @param preciseCarrierId precise carrier identifier
-     * {@link TelephonyManager#getSimPreciseCarrierId()}
+     * @param specificCarrierId specific carrier identifier
+     * {@link TelephonyManager#getSimSpecificCarrierId()}
      */
     public CarrierIdentifier(@NonNull String mcc, @NonNull String mnc, @Nullable String spn,
                              @Nullable String imsi, @Nullable String gid1, @Nullable String gid2,
-                             int carrierid, int preciseCarrierId) {
+                             int carrierid, int specificCarrierId) {
         mMcc = mcc;
         mMnc = mnc;
         mSpn = spn;
@@ -85,7 +85,7 @@
         mGid1 = gid1;
         mGid2 = gid2;
         mCarrierId = carrierid;
-        mPreciseCarrierId = preciseCarrierId;
+        mSpecificCarrierId = specificCarrierId;
     }
 
     /**
@@ -162,11 +162,17 @@
     }
 
     /**
-     * Returns the precise carrier id.
-     * @see TelephonyManager#getSimPreciseCarrierId()
+     * A specific carrier ID returns the fine-grained carrier ID of the current subscription.
+     * It can represent the fact that a carrier may be in effect an aggregation of other carriers
+     * (ie in an MVNO type scenario) where each of these specific carriers which are used to make
+     * up the actual carrier service may have different carrier configurations.
+     * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+     * different carrier configuration for different service offering such as a prepaid plan.
+     *
+     * @see TelephonyManager#getSimSpecificCarrierId()
      */
-    public int getPreciseCarrierId() {
-        return mPreciseCarrierId;
+    public int getSpecificCarrierId() {
+        return mSpecificCarrierId;
     }
 
     @Override
@@ -186,12 +192,12 @@
                 && Objects.equals(mGid1, that.mGid1)
                 && Objects.equals(mGid2, that.mGid2)
                 && Objects.equals(mCarrierId, that.mCarrierId)
-                && Objects.equals(mPreciseCarrierId, that.mPreciseCarrierId);
+                && Objects.equals(mSpecificCarrierId, that.mSpecificCarrierId);
     }
 
     @Override
     public int hashCode(){
-        return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mPreciseCarrierId);
+        return Objects.hash(mMcc, mMnc, mSpn, mImsi, mGid1, mGid2, mCarrierId, mSpecificCarrierId);
     }
 
     @Override
@@ -208,7 +214,7 @@
         out.writeString(mGid1);
         out.writeString(mGid2);
         out.writeInt(mCarrierId);
-        out.writeInt(mPreciseCarrierId);
+        out.writeInt(mSpecificCarrierId);
     }
 
     @Override
@@ -221,7 +227,7 @@
               + ",gid1=" + mGid1
               + ",gid2=" + mGid2
               + ",carrierid=" + mCarrierId
-              + ",mPreciseCarrierId=" + mPreciseCarrierId
+              + ",specificCarrierId=" + mSpecificCarrierId
               + "}";
     }
 
@@ -234,7 +240,7 @@
         mGid1 = in.readString();
         mGid2 = in.readString();
         mCarrierId = in.readInt();
-        mPreciseCarrierId = in.readInt();
+        mSpecificCarrierId = in.readInt();
     }
 
     /** @hide */
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index 9c8148d..6a91191 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -30,6 +30,7 @@
 import android.text.method.LinkMovementMethod;
 import android.text.method.MovementMethod;
 import android.text.style.URLSpan;
+import android.util.Log;
 import android.util.Patterns;
 import android.view.textclassifier.TextClassifier;
 import android.view.textclassifier.TextLinks;
@@ -78,6 +79,9 @@
  */
 
 public class Linkify {
+
+    private static final String LOG_TAG = "Linkify";
+
     /**
      *  Bit field indicating that web URLs should be matched in methods that
      *  take an options mask
@@ -247,6 +251,11 @@
 
     private static boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
             @Nullable Context context) {
+        if (text != null && containsUnsupportedCharacters(text.toString())) {
+            android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
+            return false;
+        }
+
         if (mask == 0) {
             return false;
         }
@@ -293,6 +302,29 @@
     }
 
     /**
+     * Returns true if the specified text contains at least one unsupported character for applying
+     * links. Also logs the error.
+     *
+     * @param text the text to apply links to
+     * @hide
+     */
+    public static boolean containsUnsupportedCharacters(String text) {
+        if (text.contains("\u202C")) {
+            Log.e(LOG_TAG, "Unsupported character for applying links: u202C");
+            return true;
+        }
+        if (text.contains("\u202D")) {
+            Log.e(LOG_TAG, "Unsupported character for applying links: u202D");
+            return true;
+        }
+        if (text.contains("\u202E")) {
+            Log.e(LOG_TAG, "Unsupported character for applying links: u202E");
+            return true;
+        }
+        return false;
+    }
+
+    /**
      *  Scans the text of the provided TextView and turns all occurrences of
      *  the link types indicated in the mask into clickable links.  If matches
      *  are found the movement method for the TextView is set to
@@ -462,6 +494,11 @@
     public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
             @Nullable  String defaultScheme, @Nullable String[] schemes,
             @Nullable MatchFilter matchFilter, @Nullable TransformFilter transformFilter) {
+        if (spannable != null && containsUnsupportedCharacters(spannable.toString())) {
+            android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
+            return false;
+        }
+
         final String[] schemesCopy;
         if (defaultScheme == null) defaultScheme = "";
         if (schemes == null || schemes.length < 1) {
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 9511a9e..49ca969 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -104,7 +104,7 @@
     /**
      * @hide
      */
-    static final TextClassification EMPTY = new TextClassification.Builder().build();
+    public static final TextClassification EMPTY = new TextClassification.Builder().build();
 
     private static final String LOG_TAG = "TextClassification";
     // TODO(toki): investigate a way to derive this based on device properties.
diff --git a/core/java/android/view/textclassifier/TextLinksParams.java b/core/java/android/view/textclassifier/TextLinksParams.java
index be4c3bc..c21206c 100644
--- a/core/java/android/view/textclassifier/TextLinksParams.java
+++ b/core/java/android/view/textclassifier/TextLinksParams.java
@@ -107,6 +107,13 @@
         Preconditions.checkNotNull(textLinks);
 
         final String textString = text.toString();
+
+        if (Linkify.containsUnsupportedCharacters(textString)) {
+            // Do not apply links to text containing unsupported characters.
+            android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
+            return TextLinks.STATUS_NO_LINKS_APPLIED;
+        }
+
         if (!textString.startsWith(textLinks.getText())) {
             return TextLinks.STATUS_DIFFERENT_TEXT;
         }
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 0f56aba..a18c385 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -7700,6 +7700,11 @@
                 mLastSeenPos = firstPos;
 
                 final int childCount = getChildCount();
+
+                if (childCount <= 0) {
+                    return;
+                }
+
                 final int position = mTargetPos;
                 final int lastPos = firstPos + childCount - 1;
 
diff --git a/core/java/android/widget/SelectionActionModeHelper.java b/core/java/android/widget/SelectionActionModeHelper.java
index 6cb0eaa..0d88e69 100644
--- a/core/java/android/widget/SelectionActionModeHelper.java
+++ b/core/java/android/widget/SelectionActionModeHelper.java
@@ -31,6 +31,7 @@
 import android.text.Selection;
 import android.text.Spannable;
 import android.text.TextUtils;
+import android.text.util.Linkify;
 import android.util.Log;
 import android.view.ActionMode;
 import android.view.textclassifier.SelectionEvent;
@@ -1045,7 +1046,12 @@
 
                 trimText();
                 final TextClassification classification;
-                if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) {
+                if (Linkify.containsUnsupportedCharacters(mText)) {
+                    // Do not show smart actions for text containing unsupported characters.
+                    android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
+                    classification = TextClassification.EMPTY;
+                } else if (mContext.getApplicationInfo().targetSdkVersion
+                        >= Build.VERSION_CODES.P) {
                     final TextClassification.Request request =
                             new TextClassification.Request.Builder(
                                     mTrimmedText, mRelativeStart, mRelativeEnd)
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index ec02432..940cc36 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -18,6 +18,8 @@
 
 import android.annotation.UnsupportedAppUsage;
 import android.os.Build;
+import android.net.ProxyInfo;
+import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
@@ -46,6 +48,10 @@
     public static final int TYPE_IPSEC_HYBRID_RSA = 5;
     public static final int TYPE_MAX = 5;
 
+    // Match these constants with R.array.vpn_proxy_settings.
+    public static final int PROXY_NONE = 0;
+    public static final int PROXY_MANUAL = 1;
+
     // Entity fields.
     @UnsupportedAppUsage
     public final String key;           // -1
@@ -68,6 +74,7 @@
     public String ipsecUserCert = "";  // 12
     public String ipsecCaCert = "";    // 13
     public String ipsecServerCert = "";// 14
+    public ProxyInfo proxy = null;     // 15~18
 
     // Helper fields.
     @UnsupportedAppUsage
@@ -96,6 +103,7 @@
         ipsecCaCert = in.readString();
         ipsecServerCert = in.readString();
         saveLogin = in.readInt() != 0;
+        proxy = in.readParcelable(null);
     }
 
     @Override
@@ -117,6 +125,7 @@
         out.writeString(ipsecCaCert);
         out.writeString(ipsecServerCert);
         out.writeInt(saveLogin ? 1 : 0);
+        out.writeParcelable(proxy, flags);
     }
 
     @UnsupportedAppUsage
@@ -127,8 +136,8 @@
             }
 
             String[] values = new String(value, StandardCharsets.UTF_8).split("\0", -1);
-            // There can be 14 or 15 values in ICS MR1.
-            if (values.length < 14 || values.length > 15) {
+            // There can be 14 - 19 Bytes in values.length.
+            if (values.length < 14 || values.length > 19) {
                 return null;
             }
 
@@ -151,7 +160,18 @@
             profile.ipsecUserCert = values[12];
             profile.ipsecCaCert = values[13];
             profile.ipsecServerCert = (values.length > 14) ? values[14] : "";
-
+            if (values.length > 15) {
+                String host = (values.length > 15) ? values[15] : "";
+                String port = (values.length > 16) ? values[16] : "";
+                String exclList = (values.length > 17) ? values[17] : "";
+                String pacFileUrl = (values.length > 18) ? values[18] : "";
+                if (pacFileUrl.isEmpty()) {
+                    profile.proxy = new ProxyInfo(host, port.isEmpty() ?
+                            0 : Integer.parseInt(port), exclList);
+                } else {
+                    profile.proxy = new ProxyInfo(pacFileUrl);
+                }
+            } // else profle.proxy = null
             profile.saveLogin = !profile.username.isEmpty() || !profile.password.isEmpty();
             return profile;
         } catch (Exception e) {
@@ -176,6 +196,13 @@
         builder.append('\0').append(ipsecUserCert);
         builder.append('\0').append(ipsecCaCert);
         builder.append('\0').append(ipsecServerCert);
+        if (proxy != null) {
+            builder.append('\0').append(proxy.getHost() != null ? proxy.getHost() : "");
+            builder.append('\0').append(proxy.getPort());
+            builder.append('\0').append(proxy.getExclusionListAsString() != null ?
+                    proxy.getExclusionListAsString() : "");
+            builder.append('\0').append(proxy.getPacFileUrl().toString());
+        }
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
 
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index c5bc45a..99a1a19 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -115,20 +115,13 @@
         final ClassLoader classLoader = createClassLoader(dexPath, librarySearchPath, parent,
                 classLoaderName, sharedLibraries);
 
-        boolean isForVendor = false;
-        for (String path : dexPath.split(":")) {
-            if (path.startsWith("/vendor/")) {
-                isForVendor = true;
-                break;
-            }
-        }
         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "createClassloaderNamespace");
         String errorMessage = createClassloaderNamespace(classLoader,
                                                          targetSdkVersion,
                                                          librarySearchPath,
                                                          libraryPermittedPath,
                                                          isNamespaceShared,
-                                                         isForVendor);
+                                                         dexPath);
         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 
         if (errorMessage != null) {
@@ -144,5 +137,5 @@
                                                             String librarySearchPath,
                                                             String libraryPermittedPath,
                                                             boolean isNamespaceShared,
-                                                            boolean isForVendor);
+                                                            String dexPath);
 }
diff --git a/core/java/com/android/internal/os/KernelWakelockReader.java b/core/java/com/android/internal/os/KernelWakelockReader.java
index 46667d1..86b2a90 100644
--- a/core/java/com/android/internal/os/KernelWakelockReader.java
+++ b/core/java/com/android/internal/os/KernelWakelockReader.java
@@ -66,7 +66,7 @@
      */
     public final KernelWakelockStats readKernelWakelockStats(KernelWakelockStats staleStats) {
         byte[] buffer = new byte[32*1024];
-        int len;
+        int len = 0;
         boolean wakeup_sources;
         final long startTime = SystemClock.uptimeMillis();
 
@@ -87,7 +87,11 @@
                 }
             }
 
-            len = is.read(buffer);
+            int cnt;
+            while ((cnt = is.read(buffer, len, buffer.length - len)) > 0) {
+                len += cnt;
+            }
+
             is.close();
         } catch (java.io.IOException e) {
             Slog.wtf(TAG, "failed to read kernel wakelocks", e);
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index 209933a..8b3f47a 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -44,17 +44,19 @@
             SystemProperties.getBoolean("ro.fw.system_user_split", false);
 
     // ------ ro.crypto.* -------- //
-    public static final String CRYPTO_STATE = SystemProperties.get("ro.crypto.state");
-    public static final String CRYPTO_TYPE = CryptoProperties.type().orElse("none");
+    public static final CryptoProperties.state_values CRYPTO_STATE =
+            CryptoProperties.state().orElse(CryptoProperties.state_values.UNSUPPORTED);
+    public static final CryptoProperties.type_values CRYPTO_TYPE =
+            CryptoProperties.type().orElse(CryptoProperties.type_values.NONE);
     // These are pseudo-properties
     public static final boolean CRYPTO_ENCRYPTABLE =
-            !CRYPTO_STATE.isEmpty() && !"unsupported".equals(CRYPTO_STATE);
+            CRYPTO_STATE != CryptoProperties.state_values.UNSUPPORTED;
     public static final boolean CRYPTO_ENCRYPTED =
-            "encrypted".equalsIgnoreCase(CRYPTO_STATE);
+            CRYPTO_STATE == CryptoProperties.state_values.ENCRYPTED;
     public static final boolean CRYPTO_FILE_ENCRYPTED =
-            "file".equalsIgnoreCase(CRYPTO_TYPE);
+            CRYPTO_TYPE == CryptoProperties.type_values.FILE;
     public static final boolean CRYPTO_BLOCK_ENCRYPTED =
-            "block".equalsIgnoreCase(CRYPTO_TYPE);
+            CRYPTO_TYPE == CryptoProperties.type_values.BLOCK;
 
     public static final boolean CONTROL_PRIVAPP_PERMISSIONS_LOG =
             "log".equalsIgnoreCase(CONTROL_PRIVAPP_PERMISSIONS);
diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS
index 7311eee..d3836d4 100644
--- a/core/java/com/android/server/net/OWNERS
+++ b/core/java/com/android/server/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
index 9ce3289..f8d41e4 100644
--- a/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
+++ b/core/jni/com_android_internal_os_ClassLoaderFactory.cpp
@@ -28,16 +28,16 @@
                                               jstring librarySearchPath,
                                               jstring libraryPermittedPath,
                                               jboolean isShared,
-                                              jboolean isForVendor) {
+                                              jstring dexPath) {
     return android::CreateClassLoaderNamespace(env, targetSdkVersion,
                                                classLoader, isShared == JNI_TRUE,
-                                               isForVendor == JNI_TRUE,
+                                               dexPath,
                                                librarySearchPath, libraryPermittedPath);
 }
 
 static const JNINativeMethod g_methods[] = {
     { "createClassloaderNamespace",
-      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZZ)Ljava/lang/String;",
+      "(Ljava/lang/ClassLoader;ILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;)Ljava/lang/String;",
       reinterpret_cast<void*>(createClassloaderNamespace_native) },
 };
 
diff --git a/core/proto/android/server/connectivity/data_stall_event.proto b/core/proto/android/server/connectivity/data_stall_event.proto
index 21717d8..a82326f 100644
--- a/core/proto/android/server/connectivity/data_stall_event.proto
+++ b/core/proto/android/server/connectivity/data_stall_event.proto
@@ -25,6 +25,7 @@
     VALID = 1;
     INVALID = 2;
     PORTAL = 3;
+    PARTIAL = 4;
 }
 
 enum ApBand {
@@ -86,4 +87,4 @@
     repeated int32 dns_return_code = 1;
     // Indicate the timestamp of the dns event.
     repeated int64 dns_time = 2;
-}
\ No newline at end of file
+}
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b412f0f..75aa60f 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -280,9 +280,9 @@
     <!-- WFC, summary for Disabled -->
     <string name="wifi_calling_off_summary">Off</string>
     <!-- WFC, summary for Wi-Fi Preferred -->
-    <string name="wfc_mode_wifi_preferred_summary">Wi-Fi preferred</string>
+    <string name="wfc_mode_wifi_preferred_summary">Call over Wi-Fi</string>
     <!-- WFC, summary for Mobile data Preferred -->
-    <string name="wfc_mode_cellular_preferred_summary">Mobile preferred</string>
+    <string name="wfc_mode_cellular_preferred_summary">Call over mobile network</string>
     <!-- WFC, summary for Wi-Fi Only -->
     <string name="wfc_mode_wifi_only_summary">Wi-Fi only</string>
 
@@ -3197,13 +3197,18 @@
     <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
 
     <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's title. -->
-    <string name="wifi_no_internet">Wi-Fi has no internet access</string>
+    <string name="wifi_no_internet"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has no internet access</string>
 
     <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. -->
     <string name="wifi_no_internet_detailed">Tap for options</string>
 
     <!-- A notification is shown after the user logs in to a captive portal network, to indicate that the network should now have internet connectivity. This is the message of notification. [CHAR LIMIT=50] -->
     <string name="captive_portal_logged_in_detailed">Connected</string>
+    <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's title. [CHAR LIMIT=50] -->
+    <string name="network_partial_connectivity"><xliff:g id="network_ssid" example="GoogleGuest">%1$s</xliff:g> has limited connectivity</string>
+
+    <!-- A notification is shown when the user connects to a network that doesn't have access to some services (e.g. Push notifications may not work). This is the notification's message. [CHAR LIMIT=50] -->
+    <string name="network_partial_connectivity_detailed">Tap to connect anyway</string>
 
     <!-- A notification is shown when the user's softap config has been changed due to underlying
          hardware restrictions. This is the notifications's title.
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4689caa..a95fa54 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1211,6 +1211,8 @@
   <java-symbol type="string" name="mediasize_japanese_kahu" />
   <java-symbol type="string" name="mediasize_japanese_kaku2" />
   <java-symbol type="string" name="mediasize_japanese_you4" />
+  <java-symbol type="string" name="network_partial_connectivity" />
+  <java-symbol type="string" name="network_partial_connectivity_detailed" />
   <java-symbol type="string" name="reason_service_unavailable" />
   <java-symbol type="string" name="reason_unknown" />
   <java-symbol type="string" name="restr_pin_enter_admin_pin" />
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
index c8a53cc..9015e92 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationManagerTest.java
@@ -39,6 +39,8 @@
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
+import android.text.Spannable;
+import android.text.SpannableString;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
@@ -307,6 +309,16 @@
     }
 
     @Test
+    public void testApplyLinks_unsupportedCharacter() {
+        if (isTextClassifierDisabled()) return;
+        Spannable url = new SpannableString("\u202Emoc.diordna.com");
+        TextLinks.Request request = new TextLinks.Request.Builder(url).build();
+        assertEquals(
+                TextLinks.STATUS_NO_LINKS_APPLIED,
+                mClassifier.generateLinks(request).apply(url, 0, null));
+    }
+
+    @Test
     public void testSetTextClassifier() {
         TextClassifier classifier = mock(TextClassifier.class);
         mTcm.setTextClassifier(classifier);
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 70dc618..90758ba 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -983,6 +983,19 @@
     }
 
     @Test
+    public void testNoAssistItemForTextFieldWithUnsupportedCharacters() throws Throwable {
+        useSystemDefaultTextClassifier();
+        final String text = "\u202Emoc.diordna.com";
+        final TextView textView = mActivity.findViewById(R.id.textview);
+        mActivityRule.runOnUiThread(() -> textView.setText(text));
+        mInstrumentation.waitForIdleSync();
+
+        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('.')));
+        sleepForFloatingToolbarPopup();
+        assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist);
+    }
+
+    @Test
     public void testSelectionMetricsLogger_noAbandonAfterCopy() throws Throwable {
         final List<SelectionEvent> selectionEvents = new ArrayList<>();
         final TextClassifier classifier = new TextClassifier() {
diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java
index 030fa60..6155ae4 100644
--- a/keystore/java/android/security/KeyChain.java
+++ b/keystore/java/android/security/KeyChain.java
@@ -36,6 +36,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.security.keystore.AndroidKeyStoreProvider;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 
 import java.io.ByteArrayInputStream;
@@ -538,7 +539,7 @@
             try {
                 return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore(
                         KeyStore.getInstance(), keyId, KeyStore.UID_SELF);
-            } catch (RuntimeException | UnrecoverableKeyException e) {
+            } catch (RuntimeException | UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
                 throw new KeyChainException(e);
             }
         }
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 25a6cdc..6dfe1fd 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -97,6 +97,9 @@
      */
     public static final int OP_AUTH_NEEDED = 15;
 
+    // Used when a user changes their pin, invalidating old auth bound keys.
+    public static final int KEY_PERMANENTLY_INVALIDATED = 17;
+
     // Used for UID field to indicate the calling UID.
     public static final int UID_SELF = -1;
 
@@ -219,6 +222,15 @@
     }
 
     public byte[] get(String key, int uid) {
+        return get(key, uid, false);
+    }
+
+    @UnsupportedAppUsage
+    public byte[] get(String key) {
+        return get(key, UID_SELF);
+    }
+
+    public byte[] get(String key, int uid, boolean suppressKeyNotFoundWarning) {
         try {
             key = key != null ? key : "";
             return mBinder.get(key, uid);
@@ -226,16 +238,18 @@
             Log.w(TAG, "Cannot connect to keystore", e);
             return null;
         } catch (android.os.ServiceSpecificException e) {
-            Log.w(TAG, "KeyStore exception", e);
+            if (!suppressKeyNotFoundWarning || e.errorCode != KEY_NOT_FOUND) {
+                Log.w(TAG, "KeyStore exception", e);
+            }
             return null;
         }
     }
 
-    @UnsupportedAppUsage
-    public byte[] get(String key) {
-        return get(key, UID_SELF);
+    public byte[] get(String key, boolean suppressKeyNotFoundWarning) {
+        return get(key, UID_SELF, suppressKeyNotFoundWarning);
     }
 
+
     public boolean put(String key, byte[] value, int uid, int flags) {
         return insert(key, value, uid, flags) == NO_ERROR;
     }
@@ -1188,6 +1202,8 @@
                     return new KeyStoreException(errorCode, "Key blob corrupted");
                 case OP_AUTH_NEEDED:
                     return new KeyStoreException(errorCode, "Operation requires authorization");
+                case KEY_PERMANENTLY_INVALIDATED:
+                    return new KeyStoreException(errorCode, "Key permanently invalidated");
                 default:
                     return new KeyStoreException(errorCode, String.valueOf(errorCode));
             }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index d44c894..91aac83 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -526,7 +526,7 @@
                                 + result.getPrivate().getAlgorithm() + " vs " + mJcaKeyAlgorithm);
             }
             return result;
-        } catch (UnrecoverableKeyException e) {
+        } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) {
             throw new ProviderException("Failed to load generated key pair from keystore", e);
         }
     }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index c7c9ee4..234615d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -228,10 +228,16 @@
     @NonNull
     private static KeyCharacteristics getKeyCharacteristics(@NonNull KeyStore keyStore,
             @NonNull String alias, int uid)
-            throws UnrecoverableKeyException {
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
         int errorCode = keyStore.getKeyCharacteristics(
                 alias, null, null, uid, keyCharacteristics);
+        if (errorCode == KeyStore.KEY_PERMANENTLY_INVALIDATED) {
+            throw (KeyPermanentlyInvalidatedException)
+                new KeyPermanentlyInvalidatedException(
+                            "User changed or deleted their auth credentials",
+                            KeyStore.getKeyStoreException(errorCode));
+        }
         if (errorCode != KeyStore.NO_ERROR) {
             throw (UnrecoverableKeyException)
                     new UnrecoverableKeyException("Failed to obtain information about key")
@@ -276,7 +282,7 @@
     @NonNull
     public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(
             @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException {
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         return loadAndroidKeyStorePublicKeyFromKeystore(keyStore, privateKeyAlias, uid,
                 getKeyCharacteristics(keyStore, privateKeyAlias, uid));
     }
@@ -297,7 +303,7 @@
     @NonNull
     public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore(
             @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException {
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         return loadAndroidKeyStoreKeyPairFromKeystore(keyStore, privateKeyAlias, uid,
                 getKeyCharacteristics(keyStore, privateKeyAlias, uid));
     }
@@ -315,7 +321,7 @@
     @NonNull
     public static AndroidKeyStorePrivateKey loadAndroidKeyStorePrivateKeyFromKeystore(
             @NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid)
-            throws UnrecoverableKeyException {
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException {
         return loadAndroidKeyStorePrivateKeyFromKeystore(keyStore, privateKeyAlias, uid,
                 getKeyCharacteristics(keyStore, privateKeyAlias, uid));
     }
@@ -354,7 +360,7 @@
     @NonNull
     public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore(
             @NonNull KeyStore keyStore, @NonNull String userKeyAlias, int uid)
-            throws UnrecoverableKeyException  {
+            throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException  {
         KeyCharacteristics keyCharacteristics = getKeyCharacteristics(keyStore, userKeyAlias, uid);
 
         Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 4c007cb..105af6e 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -24,6 +24,7 @@
 import android.security.keymaster.KeyCharacteristics;
 import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterDefs;
+import android.security.keystore.KeyPermanentlyInvalidatedException;
 import android.security.keystore.KeyProperties;
 import android.security.keystore.KeyProtection;
 import android.security.keystore.SecureKeyImportUnavailableException;
@@ -93,13 +94,20 @@
     public Key engineGetKey(String alias, char[] password) throws NoSuchAlgorithmException,
             UnrecoverableKeyException {
         String userKeyAlias = Credentials.USER_PRIVATE_KEY + alias;
+        AndroidKeyStoreKey key;
         if (!mKeyStore.contains(userKeyAlias, mUid)) {
             // try legacy prefix for backward compatibility
             userKeyAlias = Credentials.USER_SECRET_KEY + alias;
             if (!mKeyStore.contains(userKeyAlias, mUid)) return null;
         }
-        return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore, userKeyAlias,
-                mUid);
+        try {
+            key = AndroidKeyStoreProvider.loadAndroidKeyStoreKeyFromKeystore(mKeyStore,
+                                                                             userKeyAlias,
+                                                                             mUid);
+        } catch (KeyPermanentlyInvalidatedException e) {
+            throw new UnrecoverableKeyException(e.getMessage());
+        }
+        return key;
     }
 
     @Override
diff --git a/location/java/android/location/IGeocodeProvider.aidl b/location/java/android/location/IGeocodeProvider.aidl
index aaa70c7..7eaf7b8 100644
--- a/location/java/android/location/IGeocodeProvider.aidl
+++ b/location/java/android/location/IGeocodeProvider.aidl
@@ -26,9 +26,11 @@
  */
 interface IGeocodeProvider {
 
+    @UnsupportedAppUsage
     String getFromLocation(double latitude, double longitude, int maxResults,
         in GeocoderParams params, out List<Address> addrs);
 
+    @UnsupportedAppUsage
     String getFromLocationName(String locationName,
         double lowerLeftLatitude, double lowerLeftLongitude,
         double upperRightLatitude, double upperRightLongitude, int maxResults,
diff --git a/location/java/android/location/IGeofenceProvider.aidl b/location/java/android/location/IGeofenceProvider.aidl
index d4ff0dd..426ebef 100644
--- a/location/java/android/location/IGeofenceProvider.aidl
+++ b/location/java/android/location/IGeofenceProvider.aidl
@@ -24,5 +24,6 @@
  * {@hide}
  */
 oneway interface IGeofenceProvider {
+    @UnsupportedAppUsage
     void setGeofenceHardware(in IGeofenceHardware proxy);
 }
diff --git a/location/java/android/location/ILocationListener.aidl b/location/java/android/location/ILocationListener.aidl
index 7627cf6..e40b408 100644
--- a/location/java/android/location/ILocationListener.aidl
+++ b/location/java/android/location/ILocationListener.aidl
@@ -25,8 +25,12 @@
  */
 oneway interface ILocationListener
 {
+    @UnsupportedAppUsage
     void onLocationChanged(in Location location);
+    @UnsupportedAppUsage
     void onStatusChanged(String provider, int status, in Bundle extras);
+    @UnsupportedAppUsage
     void onProviderEnabled(String provider);
+    @UnsupportedAppUsage
     void onProviderDisabled(String provider);
 }
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 1276881..0ba1700 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -82,11 +82,13 @@
     boolean injectLocation(in Location location);
 
     // --- deprecated ---
+    @UnsupportedAppUsage
     List<String> getAllProviders();
     List<String> getProviders(in Criteria criteria, boolean enabledOnly);
     String getBestProvider(in Criteria criteria, boolean enabledOnly);
     boolean providerMeetsCriteria(String provider, in Criteria criteria);
     ProviderProperties getProviderProperties(String provider);
+    @UnsupportedAppUsage
     String getNetworkProviderPackage();
 
     boolean isProviderEnabledForUser(String provider, int userId);
@@ -110,6 +112,7 @@
     // Used by location providers to tell the location manager when it has a new location.
     // Passive is true if the location is coming from the passive provider, in which case
     // it need not be shared with other providers.
+    @UnsupportedAppUsage
     void reportLocation(in Location location, boolean passive);
 
     // Used when a (initially Gnss) Location batch arrives
diff --git a/location/java/android/location/INetInitiatedListener.aidl b/location/java/android/location/INetInitiatedListener.aidl
index fc64dd6..a9e9136 100644
--- a/location/java/android/location/INetInitiatedListener.aidl
+++ b/location/java/android/location/INetInitiatedListener.aidl
@@ -22,5 +22,6 @@
  */
 interface INetInitiatedListener
 {
+    @UnsupportedAppUsage
     boolean sendNiResponse(int notifId, int userResponse);
 }
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 9bd5994..b531325 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -17,6 +17,7 @@
 package com.android.internal.location;
 
 import java.io.UnsupportedEncodingException;
+import java.util.concurrent.TimeUnit;
 
 import android.app.Notification;
 import android.app.NotificationManager;
@@ -27,19 +28,17 @@
 import android.content.IntentFilter;
 import android.location.LocationManager;
 import android.location.INetInitiatedListener;
+import android.os.SystemClock;
 import android.telephony.TelephonyManager;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.PhoneStateListener;
-import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.SystemProperties;
 import android.util.Log;
 
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.R;
 import com.android.internal.telephony.GsmAlphabet;
-import com.android.internal.telephony.TelephonyProperties;
 
 /**
  * A GPS Network-initiated Handler class used by LocationManager.
@@ -50,8 +49,7 @@
 
     private static final String TAG = "GpsNetInitiatedHandler";
 
-    private static final boolean DEBUG = true;
-    private static final boolean VERBOSE = false;
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     // NI verify activity for bringing up UI (not used yet)
     public static final String ACTION_NI_VERIFY = "android.intent.action.NETWORK_INITIATED_VERIFY";
@@ -94,6 +92,9 @@
     public static final int GPS_ENC_SUPL_UCS2 = 3;
     public static final int GPS_ENC_UNKNOWN = -1;
 
+    // Limit on SUPL NI emergency mode time extension after emergency sessions ends
+    private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300;  // 5 minute maximum
+
     private final Context mContext;
     private final TelephonyManager mTelephonyManager;
     private final PhoneStateListener mPhoneStateListener;
@@ -109,7 +110,7 @@
     private volatile boolean mIsSuplEsEnabled;
 
     // Set to true if the phone is having emergency call.
-    private volatile boolean mIsInEmergency;
+    private volatile boolean mIsInEmergencyCall;
 
     // If Location function is enabled.
     private volatile boolean mIsLocationEnabled = false;
@@ -119,6 +120,10 @@
     // Set to true if string from HAL is encoded as Hex, e.g., "3F0039"
     static private boolean mIsHexInput = true;
 
+    // End time of emergency call, and extension, if set
+    private long mCallEndElapsedRealtimeMillis = 0;
+    private long mEmergencyExtensionMillis = 0;
+
     public static class GpsNiNotification
     {
         public int notificationId;
@@ -146,16 +151,12 @@
             if (action.equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
                 String phoneNumber = intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER);
                 /*
-                   Emergency Mode is when during emergency call or in emergency call back mode.
-                   For checking if it is during emergency call:
-                       mIsInEmergency records if the phone is in emergency call or not. It will
+                   Tracks the emergency call:
+                       mIsInEmergencyCall records if the phone is in emergency call or not. It will
                        be set to true when the phone is having emergency call, and then will
                        be set to false by mPhoneStateListener when the emergency call ends.
-                   For checking if it is in emergency call back mode:
-                       Emergency call back mode will be checked by reading system properties
-                       when necessary: SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)
                 */
-                setInEmergency(PhoneNumberUtils.isEmergencyNumber(phoneNumber));
+                mIsInEmergencyCall = PhoneNumberUtils.isEmergencyNumber(phoneNumber);
                 if (DEBUG) Log.v(TAG, "ACTION_NEW_OUTGOING_CALL - " + getInEmergency());
             } else if (action.equals(LocationManager.MODE_CHANGED_ACTION)) {
                 updateLocationMode();
@@ -195,7 +196,10 @@
                 if (DEBUG) Log.d(TAG, "onCallStateChanged(): state is "+ state);
                 // listening for emergency call ends
                 if (state == TelephonyManager.CALL_STATE_IDLE) {
-                    setInEmergency(false);
+                    if (mIsInEmergencyCall) {
+                        mCallEndElapsedRealtimeMillis = SystemClock.elapsedRealtime();
+                        mIsInEmergencyCall = false;
+                    }
                 }
             }
         };
@@ -229,22 +233,35 @@
         return mIsLocationEnabled;
     }
 
-    // Note: Currently, there are two mechanisms involved to determine if a
-    // phone is in emergency mode:
-    // 1. If the user is making an emergency call, this is provided by activly
-    //    monitoring the outgoing phone number;
-    // 2. If the device is in a emergency callback state, this is provided by
-    //    system properties.
-    // If either one of above exists, the phone is considered in an emergency
-    // mode. Because of this complexity, we need to be careful about how to set
-    // and clear the emergency state.
-    public void setInEmergency(boolean isInEmergency) {
-        mIsInEmergency = isInEmergency;
+    /**
+     * Determines whether device is in user-initiated emergency session based on the following
+     * 1. If the user is making an emergency call, this is provided by actively
+     *    monitoring the outgoing phone number;
+     * 2. If the user has recently ended an emergency call, and the device is in a configured time
+     *    window after the end of that call.
+     * 3. If the device is in a emergency callback state, this is provided by querying
+     *    TelephonyManager.
+     * @return true if is considered in user initiated emergency mode for NI purposes
+     */
+    public boolean getInEmergency() {
+        boolean isInEmergencyExtension =
+                (SystemClock.elapsedRealtime() - mCallEndElapsedRealtimeMillis) <
+                        mEmergencyExtensionMillis;
+        boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
+        return mIsInEmergencyCall || isInEmergencyCallback || isInEmergencyExtension;
     }
 
-    public boolean getInEmergency() {
-        boolean isInEmergencyCallback = mTelephonyManager.getEmergencyCallbackMode();
-        return mIsInEmergency || isInEmergencyCallback;
+    public void setEmergencyExtensionSeconds(int emergencyExtensionSeconds) {
+        if (emergencyExtensionSeconds > MAX_EMERGENCY_MODE_EXTENSION_SECONDS) {
+            Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds
+                    + " too high, reset to " + MAX_EMERGENCY_MODE_EXTENSION_SECONDS);
+            emergencyExtensionSeconds = MAX_EMERGENCY_MODE_EXTENSION_SECONDS;
+        } else if (emergencyExtensionSeconds < 0) {
+            Log.w(TAG, "emergencyExtensionSeconds " + emergencyExtensionSeconds
+                    + " is negative, reset to zero.");
+            emergencyExtensionSeconds = 0;
+        }
+        mEmergencyExtensionMillis = TimeUnit.SECONDS.toMillis(emergencyExtensionSeconds);
     }
 
 
diff --git a/media/java/android/media/IAudioFocusDispatcher.aidl b/media/java/android/media/IAudioFocusDispatcher.aidl
index 3b33c5b..e3512fa 100644
--- a/media/java/android/media/IAudioFocusDispatcher.aidl
+++ b/media/java/android/media/IAudioFocusDispatcher.aidl
@@ -23,6 +23,7 @@
  */
 oneway interface IAudioFocusDispatcher {
 
+    @UnsupportedAppUsage
     void dispatchAudioFocusChange(int focusChange, String clientId);
 
     void dispatchFocusResultFromExtPolicy(int requestResult, String clientId);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index abd6411..1a44a83 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -63,6 +63,7 @@
 
     void adjustStreamVolume(int streamType, int direction, int flags, String callingPackage);
 
+    @UnsupportedAppUsage
     void setStreamVolume(int streamType, int index, int flags, String callingPackage);
 
     boolean isStreamMute(int streamType);
@@ -73,10 +74,12 @@
 
     void setMasterMute(boolean mute, int flags, String callingPackage, int userId);
 
+    @UnsupportedAppUsage
     int getStreamVolume(int streamType);
 
     int getStreamMinVolume(int streamType);
 
+    @UnsupportedAppUsage
     int getStreamMaxVolume(int streamType);
 
     int getLastAudibleStreamVolume(int streamType);
@@ -155,6 +158,7 @@
 
     void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
 
+    @UnsupportedAppUsage
     AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
 
     boolean isCameraSoundForced();
diff --git a/media/java/android/media/IMediaScannerService.aidl b/media/java/android/media/IMediaScannerService.aidl
index c531646..24b5595 100644
--- a/media/java/android/media/IMediaScannerService.aidl
+++ b/media/java/android/media/IMediaScannerService.aidl
@@ -31,6 +31,7 @@
      * @param listener an optional IMediaScannerListener. 
      * If specified, the caller will be notified when scanning is complete via the listener.
      */
+    @UnsupportedAppUsage
     void requestScanFile(String path, String mimeType, in IMediaScannerListener listener);
 
     /**
@@ -40,5 +41,6 @@
      * @param mimeType  an optional mimeType for the file.
      * If mimeType is null, then the mimeType will be inferred from the file extension.
      */
+    @UnsupportedAppUsage
     void scanFile(String path, String mimeType);
 }
diff --git a/media/java/android/media/IRemoteDisplayCallback.aidl b/media/java/android/media/IRemoteDisplayCallback.aidl
index 19cf070..584417d 100644
--- a/media/java/android/media/IRemoteDisplayCallback.aidl
+++ b/media/java/android/media/IRemoteDisplayCallback.aidl
@@ -22,5 +22,6 @@
  * {@hide}
  */
 oneway interface IRemoteDisplayCallback {
+    @UnsupportedAppUsage
     void onStateChanged(in RemoteDisplayState state);
 }
diff --git a/media/java/android/media/projection/IMediaProjectionManager.aidl b/media/java/android/media/projection/IMediaProjectionManager.aidl
index 7e10c51..d190fce 100644
--- a/media/java/android/media/projection/IMediaProjectionManager.aidl
+++ b/media/java/android/media/projection/IMediaProjectionManager.aidl
@@ -24,6 +24,7 @@
 
 /** {@hide} */
 interface IMediaProjectionManager {
+    @UnsupportedAppUsage
     boolean hasProjectionPermission(int uid, String packageName);
     IMediaProjection createProjection(int uid, String packageName, int type,
             boolean permanentGrant);
diff --git a/native/android/OWNERS b/native/android/OWNERS
index b3f50aa..266764a 100644
--- a/native/android/OWNERS
+++ b/native/android/OWNERS
@@ -1,4 +1,4 @@
 set noparent
 
-per-file libandroid_net.map.txt, net.c = codewiz@google.com, ek@google.com, jchalard@google.com
+per-file libandroid_net.map.txt, net.c = codewiz@google.com, jchalard@google.com, junyulai@google.com
 per-file libandroid_net.map.txt, net.c = lorenzo@google.com, reminv@google.com, satk@google.com
diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS
index 7311eee..d3836d4 100644
--- a/packages/CaptivePortalLogin/OWNERS
+++ b/packages/CaptivePortalLogin/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index f210840..190247a 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -14,12 +14,11 @@
 // limitations under the License.
 //
 
-// Library including the network stack, used to compile the network stack app, or linked into the
-// system server on devices that run the stack there
-java_library {
-    name: "NetworkStackLib",
+// Library including the network stack, used to compile both variants of the network stack
+android_library {
+    name: "NetworkStackBase",
     sdk_version: "system_current",
-    installable: true,
+    min_sdk_version: "28",
     srcs: [
         "src/**/*.java",
         ":framework-networkstack-shared-srcs",
@@ -29,7 +28,24 @@
         "netd_aidl_interface-java",
         "networkstack-aidl-interfaces-java",
         "datastallprotosnano",
-    ]
+    ],
+    manifest: "AndroidManifestBase.xml",
+}
+
+// Non-updatable in-process network stack for devices not using the module
+android_app {
+    name: "InProcessNetworkStack",
+    sdk_version: "system_current",
+    min_sdk_version: "28",
+    certificate: "platform",
+    privileged: true,
+    static_libs: [
+        "NetworkStackBase",
+    ],
+    jarjar_rules: "jarjar-rules-shared.txt",
+    // The permission configuration *must* be included to ensure security of the device
+    required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest_InProcess.xml",
 }
 
 // Updatable network stack packaged as an application
@@ -40,9 +56,10 @@
     certificate: "networkstack",
     privileged: true,
     static_libs: [
-        "NetworkStackLib"
+        "NetworkStackBase"
     ],
     jarjar_rules: "jarjar-rules-shared.txt",
-    manifest: "AndroidManifest.xml",
+    // The permission configuration *must* be included to ensure security of the device
     required: ["NetworkStackPermissionStub"],
+    manifest: "AndroidManifest.xml",
 }
diff --git a/packages/NetworkStack/AndroidManifest.xml b/packages/NetworkStack/AndroidManifest.xml
index 003f1e5..a90db11 100644
--- a/packages/NetworkStack/AndroidManifest.xml
+++ b/packages/NetworkStack/AndroidManifest.xml
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 /*
- * Copyright (C) 2014 The Android Open Source Project
+ * 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.
@@ -18,30 +18,14 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
           package="com.android.networkstack"
-          android:sharedUserId="android.uid.networkstack"
-          android:versionCode="11"
-          android:versionName="Q-initial">
-    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
-    <uses-permission android:name="android.permission.INTERNET" />
-    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
-    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
-    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+          android:sharedUserId="android.uid.networkstack">
     <!-- Signature permission defined in NetworkStackStub -->
     <uses-permission android:name="android.permission.MAINLINE_NETWORK_STACK" />
-    <!-- Send latency broadcast as current user -->
-    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
-    <uses-permission android:name="android.permission.WAKE_LOCK" />
-    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
-    <application
-        android:label="NetworkStack"
-        android:defaultToDeviceProtectedStorage="true"
-        android:directBootAware="true"
-        android:usesCleartextTraffic="true">
+    <application>
         <service android:name="com.android.server.NetworkStackService">
             <intent-filter>
                 <action android:name="android.net.INetworkStackConnector"/>
             </intent-filter>
         </service>
     </application>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/AndroidManifestBase.xml b/packages/NetworkStack/AndroidManifestBase.xml
new file mode 100644
index 0000000..621d30c
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifestBase.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack"
+          android:versionCode="11"
+          android:versionName="Q-initial">
+    <uses-sdk android:minSdkVersion="28" android:targetSdkVersion="28" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CONNECTIVITY_INTERNAL" />
+    <!-- Send latency broadcast as current user -->
+    <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
+    <application
+        android:label="NetworkStack"
+        android:defaultToDeviceProtectedStorage="true"
+        android:directBootAware="true"
+        android:usesCleartextTraffic="true">
+    </application>
+</manifest>
diff --git a/packages/NetworkStack/AndroidManifest_InProcess.xml b/packages/NetworkStack/AndroidManifest_InProcess.xml
new file mode 100644
index 0000000..48fcecd
--- /dev/null
+++ b/packages/NetworkStack/AndroidManifest_InProcess.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.networkstack.inprocess"
+          android:sharedUserId="android.uid.system"
+          android:process="system">
+    <application>
+        <service android:name="com.android.server.NetworkStackService" android:process="system">
+            <intent-filter>
+                <action android:name="android.net.INetworkStackConnector.InProcess"/>
+            </intent-filter>
+        </service>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/packages/NetworkStack/OWNERS b/packages/NetworkStack/OWNERS
index a395465..0e1e65d 100644
--- a/packages/NetworkStack/OWNERS
+++ b/packages/NetworkStack/OWNERS
@@ -1,5 +1,6 @@
 codewiz@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/packages/NetworkStack/TEST_MAPPING b/packages/NetworkStack/TEST_MAPPING
index 55ba591..fe9731fe 100644
--- a/packages/NetworkStack/TEST_MAPPING
+++ b/packages/NetworkStack/TEST_MAPPING
@@ -1,5 +1,5 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "NetworkStackTests"
     }
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
index 17a36ad..c96411e 100644
--- a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
@@ -46,6 +46,8 @@
             return DataStallEventProto.VALID;
         } else if (result.isPortal()) {
             return DataStallEventProto.PORTAL;
+        } else if (result.isPartialConnectivity()) {
+            return DataStallEventProto.PARTIAL;
         } else {
             return DataStallEventProto.INVALID;
         }
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 90db207..72955bb 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -253,6 +253,12 @@
         }
 
         @Override
+        public void notifyAcceptPartialConnectivity() {
+            checkNetworkStackCallingPermission();
+            mNm.notifyAcceptPartialConnectivity();
+        }
+
+        @Override
         public void forceReevaluation(int uid) {
             checkNetworkStackCallingPermission();
             mNm.forceReevaluation(uid);
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index c3447fd..fc56da7 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -24,6 +24,7 @@
 import static android.net.ConnectivityManager.TYPE_MOBILE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
+import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
@@ -227,6 +228,12 @@
      */
     public static final int EVENT_DNS_NOTIFICATION = 17;
 
+    /**
+     * ConnectivityService notifies NetworkMonitor that the user accepts partial connectivity and
+     * NetworkMonitor should ignore the https probe.
+     */
+    public static final int EVENT_ACCEPT_PARTIAL_CONNECTIVITY = 18;
+
     // Start mReevaluateDelayMs at this value and double.
     private static final int INITIAL_REEVALUATE_DELAY_MS = 1000;
     private static final int MAX_REEVALUATE_DELAY_MS = 10 * 60 * 1000;
@@ -379,6 +386,14 @@
     }
 
     /**
+     * ConnectivityService notifies NetworkMonitor that the user accepts partial connectivity and
+     * NetworkMonitor should ignore the https probe.
+     */
+    public void notifyAcceptPartialConnectivity() {
+        sendMessage(EVENT_ACCEPT_PARTIAL_CONNECTIVITY);
+    }
+
+    /**
      * Request the NetworkMonitor to reevaluate the network.
      */
     public void forceReevaluation(int responsibleUid) {
@@ -636,6 +651,10 @@
                 case EVENT_DNS_NOTIFICATION:
                     mDnsStallDetector.accumulateConsecutiveDnsTimeoutCount(message.arg1);
                     break;
+                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
+                    mUseHttps = false;
+                    transitionTo(mEvaluatingPrivateDnsState);
+                    break;
                 default:
                     break;
             }
@@ -1058,6 +1077,11 @@
                         notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
                         mLastPortalProbeResult = probeResult;
                         transitionTo(mCaptivePortalState);
+                    } else if (probeResult.isPartialConnectivity()) {
+                        logNetworkEvent(NetworkEvent.NETWORK_PARTIAL_CONNECTIVITY);
+                        notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY,
+                                probeResult.redirectUrl);
+                        transitionTo(mWaitingForNextProbeState);
                     } else {
                         logNetworkEvent(NetworkEvent.NETWORK_VALIDATION_FAILED);
                         notifyNetworkTested(NETWORK_TEST_RESULT_INVALID, probeResult.redirectUrl);
@@ -1065,7 +1089,8 @@
                     }
                     return HANDLED;
                 case EVENT_DNS_NOTIFICATION:
-                    // Leave the event to DefaultState to record correct dns timestamp.
+                case EVENT_ACCEPT_PARTIAL_CONNECTIVITY:
+                    // Leave the event to DefaultState.
                     return NOT_HANDLED;
                 default:
                     // Wait for probe result and defer events to next state by default.
@@ -1504,10 +1529,11 @@
         // If we have new-style probe specs, use those. Otherwise, use the fallback URLs.
         final CaptivePortalProbeSpec probeSpec = nextFallbackSpec();
         final URL fallbackUrl = (probeSpec != null) ? probeSpec.getUrl() : nextFallbackUrl();
+        CaptivePortalProbeResult fallbackProbeResult = null;
         if (fallbackUrl != null) {
-            CaptivePortalProbeResult result = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
-            if (result.isPortal()) {
-                return result;
+            fallbackProbeResult = sendHttpProbe(fallbackUrl, PROBE_FALLBACK, probeSpec);
+            if (fallbackProbeResult.isPortal()) {
+                return fallbackProbeResult;
             }
         }
         // Otherwise wait until http and https probes completes and use their results.
@@ -1517,6 +1543,12 @@
                 return httpProbe.result();
             }
             httpsProbe.join();
+            final boolean isHttpSuccessful =
+                    (httpProbe.result().isSuccessful()
+                    || (fallbackProbeResult != null && fallbackProbeResult.isSuccessful()));
+            if (httpsProbe.result().isFailed() && isHttpSuccessful) {
+                return CaptivePortalProbeResult.PARTIAL;
+            }
             return httpsProbe.result();
         } catch (InterruptedException e) {
             validationLog("Error: http or https probe wait interrupted!");
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index f6eb900..6fbeead 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -33,7 +33,9 @@
     public static void checkNetworkStackCallingPermission() {
         // TODO: check that the calling PID is the system server.
         final int caller = getCallingUid();
-        if (caller != Process.SYSTEM_UID && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
+        if (caller != Process.SYSTEM_UID
+                && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID
+                && UserHandle.getAppId(caller) != Process.PHONE_UID) {
             throw new SecurityException("Invalid caller: " + caller);
         }
     }
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index f22b647..aadf99e 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -22,9 +22,8 @@
     resource_dirs: ["res"],
     static_libs: [
         "androidx.test.rules",
-        "frameworks-base-testutils",
         "mockito-target-extended-minus-junit4",
-        "NetworkStackLib",
+        "NetworkStackBase",
         "testables",
     ],
     libs: [
diff --git a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
index 1990229..bd488ea 100644
--- a/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
+++ b/packages/NetworkStack/tests/src/android/net/ip/IpClientTest.java
@@ -34,6 +34,7 @@
 import static org.mockito.Mockito.when;
 
 import android.app.AlarmManager;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
@@ -46,14 +47,11 @@
 import android.net.shared.InitialConfiguration;
 import android.net.shared.ProvisioningConfiguration;
 import android.net.util.InterfaceParams;
-import android.provider.Settings;
-import android.test.mock.MockContentResolver;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.R;
-import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.NetworkObserver;
 import com.android.server.NetworkObserverRegistry;
 
@@ -94,7 +92,7 @@
     @Mock private IIpClientCallbacks mCb;
     @Mock private AlarmManager mAlarm;
     @Mock private IpClient.Dependencies mDependencies;
-    private MockContentResolver mContentResolver;
+    @Mock private ContentResolver mContentResolver;
 
     private NetworkObserver mObserver;
     private InterfaceParams mIfParams;
@@ -109,9 +107,6 @@
         when(mDependencies.getNetd(any())).thenReturn(mNetd);
         when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
                 .thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
-
-        mContentResolver = new MockContentResolver();
-        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
 
         mIfParams = null;
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index ee2baf2..d93aef2 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
+import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.provider.Settings.Global.DATA_STALL_EVALUATION_TYPE_DNS;
@@ -525,7 +526,7 @@
         wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
         makeDnsTimeoutEvent(wrappedMonitor, 5);
         assertTrue(wrappedMonitor.isDataStall());
-        verify(mDataStallStatsUtils, times(1)).write(any(), any());
+        verify(mDataStallStatsUtils, times(1)).write(makeEmptyDataStallDetectionStats(), any());
     }
 
     @Test
@@ -534,7 +535,7 @@
         wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
         makeDnsTimeoutEvent(wrappedMonitor, 3);
         assertFalse(wrappedMonitor.isDataStall());
-        verify(mDataStallStatsUtils, never()).write(any(), any());
+        verify(mDataStallStatsUtils, never()).write(makeEmptyDataStallDetectionStats(), any());
     }
 
     @Test
@@ -572,6 +573,34 @@
                 stats.build());
     }
 
+    @Test
+    public void testIgnoreHttpsProbe() throws Exception {
+        setSslException(mHttpsConnection);
+        setStatus(mHttpConnection, 204);
+
+        final NetworkMonitor nm = makeMonitor();
+        nm.notifyNetworkConnected();
+        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+                .notifyNetworkTested(NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY, null);
+
+        nm.notifyAcceptPartialConnectivity();
+        verify(mCallbacks, timeout(HANDLER_TIMEOUT_MS).times(1))
+                .notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
+    }
+
+    @Test
+    public void testIsPartialConnectivity() throws IOException {
+        setStatus(mHttpsConnection, 500);
+        setStatus(mHttpConnection, 204);
+        setStatus(mFallbackConnection, 500);
+        assertPartialConnectivity(makeMonitor().isCaptivePortal());
+
+        setStatus(mHttpsConnection, 500);
+        setStatus(mHttpConnection, 500);
+        setStatus(mFallbackConnection, 204);
+        assertPartialConnectivity(makeMonitor().isCaptivePortal());
+    }
+
     private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
         for (int i = 0; i < count; i++) {
             wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
@@ -586,6 +615,10 @@
         }
     }
 
+    private DataStallDetectionStats makeEmptyDataStallDetectionStats() {
+        return new DataStallDetectionStats.Builder().build();
+    }
+
     private void setDataStallEvaluationType(int type) {
         when(mDependencies.getSetting(any(),
             eq(Settings.Global.DATA_STALL_EVALUATION_TYPE), anyInt())).thenReturn(type);
@@ -645,6 +678,10 @@
         assertFalse(result.isSuccessful());
     }
 
+    private void assertPartialConnectivity(CaptivePortalProbeResult result) {
+        assertTrue(result.isPartialConnectivity());
+    }
+
     private void setSslException(HttpURLConnection connection) throws IOException {
         doThrow(new SSLHandshakeException("Invalid cert")).when(connection).getResponseCode();
     }
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 8ee55e1..b94600b 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -233,6 +233,8 @@
     NOTE_NETWORK_SWITCH = 743;
     // Device logged-in captive portal network successfully
     NOTE_NETWORK_LOGGED_IN = 744;
+    // A partial connectivity network was detected during network validation
+    NOTE_NETWORK_PARTIAL_CONNECTIVITY = 745;
 
     // Notify the user that their work profile has been deleted
     // Package: android
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 4293157..85c82bc 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -16,12 +16,6 @@
 
 package android.renderscript;
 
-import java.io.File;
-import java.lang.reflect.Method;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
 import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.AssetManager;
@@ -32,6 +26,12 @@
 import android.util.Log;
 import android.view.Surface;
 
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
 // TODO: Clean up the whitespace that separates methods in this class.
 
 /**
@@ -114,8 +114,9 @@
                 Class<?> vm_runtime = Class.forName("dalvik.system.VMRuntime");
                 Method get_runtime = vm_runtime.getDeclaredMethod("getRuntime");
                 sRuntime = get_runtime.invoke(null);
-                registerNativeAllocation = vm_runtime.getDeclaredMethod("registerNativeAllocation", Integer.TYPE);
-                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Integer.TYPE);
+                registerNativeAllocation =
+                        vm_runtime.getDeclaredMethod("registerNativeAllocation", Long.TYPE);
+                registerNativeFree = vm_runtime.getDeclaredMethod("registerNativeFree", Long.TYPE);
             } catch (Exception e) {
                 Log.e(LOG_TAG, "Error loading GC methods: " + e);
                 throw new RSRuntimeException("Error loading GC methods: " + e);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 8390263..524d5c6 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -25,6 +25,7 @@
 import static android.net.ConnectivityManager.TYPE_VPN;
 import static android.net.ConnectivityManager.getNetworkTypeName;
 import static android.net.ConnectivityManager.isNetworkTypeValid;
+import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
@@ -34,6 +35,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.NetworkPolicyManager.RULE_NONE;
@@ -71,6 +73,7 @@
 import android.net.INetworkPolicyListener;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.InetAddresses;
 import android.net.IpPrefix;
 import android.net.LinkProperties;
@@ -81,6 +84,7 @@
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
 import android.net.NetworkConfig;
+import android.net.NetworkFactory;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
@@ -488,6 +492,15 @@
     public static final int EVENT_TIMEOUT_NOTIFICATION = 44;
 
     /**
+     * Used to specify whether a network should be used even if connectivity is partial.
+     * arg1 = whether to accept the network if its connectivity is partial (1 for true or 0 for
+     * false)
+     * arg2 = whether to remember this choice in the future (1 for true or 0 for false)
+     * obj  = network
+     */
+    private static final int EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY = 45;
+
+    /**
      * Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
      * should be shown.
      */
@@ -1061,7 +1074,8 @@
             handleRegisterNetworkRequest(new NetworkRequestInfo(
                     null, networkRequest, new Binder()));
         } else {
-            handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID);
+            handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
+                    /* callOnUnavailable */ false);
         }
     }
 
@@ -2486,9 +2500,7 @@
             switch (msg.what) {
                 case NetworkAgent.EVENT_NETWORK_CAPABILITIES_CHANGED: {
                     final NetworkCapabilities networkCapabilities = (NetworkCapabilities) msg.obj;
-                    if (networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL) ||
-                            networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED) ||
-                            networkCapabilities.hasCapability(NET_CAPABILITY_FOREGROUND)) {
+                    if (networkCapabilities.hasConnectivityManagedCapability()) {
                         Slog.wtf(TAG, "BUG: " + nai + " has CS-managed capability.");
                     }
                     updateCapabilities(nai.getCurrentScore(), nai, networkCapabilities);
@@ -2513,6 +2525,14 @@
                     }
                     nai.networkMisc.explicitlySelected = true;
                     nai.networkMisc.acceptUnvalidated = msg.arg1 == 1;
+                    // Mark the network as temporarily accepting partial connectivity so that it
+                    // will be validated (and possibly become default) even if it only provides
+                    // partial internet access. Note that if user connects to partial connectivity
+                    // and choose "don't ask again", then wifi disconnected by some reasons(maybe
+                    // out of wifi coverage) and if the same wifi is available again, the device
+                    // will auto connect to this wifi even though the wifi has "no internet".
+                    // TODO: Evaluate using a separate setting in IpMemoryStore.
+                    nai.networkMisc.acceptPartialConnectivity = msg.arg1 == 1;
                     break;
                 }
                 case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
@@ -2530,6 +2550,23 @@
                     final NetworkAgentInfo nai = getNetworkAgentInfoForNetId(msg.arg2);
                     if (nai == null) break;
 
+                    final boolean partialConnectivity =
+                            (msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
+                                    // If user accepts partial connectivity network, NetworkMonitor
+                                    // will skip https probing. It will make partial connectivity
+                                    // network becomes valid. But user still need to know this
+                                    // network is limited. So, it's needed to refer to
+                                    // acceptPartialConnectivity to add
+                                    // NET_CAPABILITY_PARTIAL_CONNECTIVITY into NetworkCapabilities
+                                    // of this network. So that user can see "Limited connection"
+                                    // in the settings.
+                                    || (nai.networkMisc.acceptPartialConnectivity
+                                            && nai.partialConnectivity);
+                    // Once a network is determined to have partial connectivity, it cannot
+                    // go back to full connectivity without a disconnect.
+                    final boolean partialConnectivityChange =
+                            (partialConnectivity && !nai.partialConnectivity);
+
                     final boolean valid = (msg.arg1 == NETWORK_TEST_RESULT_VALID);
                     final boolean wasValidated = nai.lastValidated;
                     final boolean wasDefault = isDefaultNetwork(nai);
@@ -2538,6 +2575,17 @@
                         nai.captivePortalLoginNotified = true;
                         showNetworkNotification(nai, NotificationType.LOGGED_IN);
                     }
+                    // If this network has just connected and partial connectivity has just been
+                    // detected, tell NetworkMonitor if the user accepted partial connectivity on a
+                    // previous connect.
+                    if ((msg.arg1 == NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY)
+                            && nai.networkMisc.acceptPartialConnectivity) {
+                        try {
+                            nai.networkMonitor().notifyAcceptPartialConnectivity();
+                        } catch (RemoteException e) {
+                            e.rethrowFromSystemServer();
+                        }
+                    }
 
                     final String redirectUrl = (msg.obj instanceof String) ? (String) msg.obj : "";
 
@@ -2567,6 +2615,9 @@
                             mNotifier.clearNotification(nai.network.netId,
                                     NotificationType.LOST_INTERNET);
                         }
+                    } else if (partialConnectivityChange) {
+                        nai.partialConnectivity = partialConnectivity;
+                        updateCapabilities(nai.getCurrentScore(), nai, nai.networkCapabilities);
                     }
                     updateInetCondition(nai);
                     // Let the NetworkAgent know the state of its network
@@ -2605,7 +2656,7 @@
                     }
                     if (!visible) {
                         // Only clear SIGN_IN and NETWORK_SWITCH notifications here, or else other
-                        // notifications belong to the same network may be cleared unexpected.
+                        // notifications belong to the same network may be cleared unexpectedly.
                         mNotifier.clearNotification(netId, NotificationType.SIGN_IN);
                         mNotifier.clearNotification(netId, NotificationType.NETWORK_SWITCH);
                     } else {
@@ -2652,11 +2703,25 @@
             return true;
         }
 
+        private boolean maybeHandleNetworkFactoryMessage(Message msg) {
+            switch (msg.what) {
+                default:
+                    return false;
+                case android.net.NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
+                    handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
+                            /* callOnUnavailable */ true);
+                    break;
+                }
+            }
+            return true;
+        }
+
         @Override
         public void handleMessage(Message msg) {
-            if (!maybeHandleAsyncChannelMessage(msg) &&
-                    !maybeHandleNetworkMonitorMessage(msg) &&
-                    !maybeHandleNetworkAgentInfoMessage(msg)) {
+            if (!maybeHandleAsyncChannelMessage(msg)
+                    && !maybeHandleNetworkMonitorMessage(msg)
+                    && !maybeHandleNetworkAgentInfoMessage(msg)
+                    && !maybeHandleNetworkFactoryMessage(msg)) {
                 maybeHandleNetworkAgentMessage(msg);
             }
         }
@@ -2821,12 +2886,24 @@
         if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
             if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
                 if (VDBG) log("NetworkFactory connected");
+                // Finish setting up the full connection
+                mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
+                        AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
                 // A network factory has connected.  Send it all current NetworkRequests.
                 for (NetworkRequestInfo nri : mNetworkRequests.values()) {
                     if (nri.request.isListen()) continue;
                     NetworkAgentInfo nai = getNetworkForRequest(nri.request.requestId);
-                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
-                            (nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
+                    final int score;
+                    final int serial;
+                    if (nai != null) {
+                        score = nai.getCurrentScore();
+                        serial = nai.factorySerialNumber;
+                    } else {
+                        score = 0;
+                        serial = NetworkFactory.SerialNumber.NONE;
+                    }
+                    ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, serial,
+                            nri.request);
                 }
             } else {
                 loge("Error connecting NetworkFactory");
@@ -2924,7 +3001,7 @@
             NetworkAgentInfo currentNetwork = getNetworkForRequest(request.requestId);
             if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
                 clearNetworkForRequest(request.requestId);
-                sendUpdatedScoreToFactories(request, 0);
+                sendUpdatedScoreToFactories(request, null);
             }
         }
         nai.clearLingerState();
@@ -2982,7 +3059,8 @@
         if (existingRequest != null) { // remove the existing request.
             if (DBG) log("Replacing " + existingRequest.request + " with "
                     + nri.request + " because their intents matched.");
-            handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
+            handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
+                    /* callOnUnavailable */ false);
         }
         handleRegisterNetworkRequest(nri);
     }
@@ -3000,7 +3078,7 @@
         }
         rematchAllNetworksAndRequests(null, 0);
         if (nri.request.isRequest() && getNetworkForRequest(nri.request.requestId) == null) {
-            sendUpdatedScoreToFactories(nri.request, 0);
+            sendUpdatedScoreToFactories(nri.request, null);
         }
     }
 
@@ -3008,7 +3086,7 @@
             int callingUid) {
         NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
         if (nri != null) {
-            handleReleaseNetworkRequest(nri.request, callingUid);
+            handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
         }
     }
 
@@ -3091,7 +3169,8 @@
         callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
     }
 
-    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
+    private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
+            boolean callOnUnavailable) {
         final NetworkRequestInfo nri =
                 getNriForAppRequest(request, callingUid, "release NetworkRequest");
         if (nri == null) {
@@ -3101,6 +3180,9 @@
             log("releasing " + nri.request + " (release request)");
         }
         handleRemoveNetworkRequest(nri);
+        if (callOnUnavailable) {
+            callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
+        }
     }
 
     private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
@@ -3191,14 +3273,21 @@
 
     @Override
     public void setAcceptUnvalidated(Network network, boolean accept, boolean always) {
-        enforceConnectivityInternalPermission();
+        enforceNetworkStackSettingsOrSetup();
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_UNVALIDATED,
                 encodeBool(accept), encodeBool(always), network));
     }
 
     @Override
+    public void setAcceptPartialConnectivity(Network network, boolean accept, boolean always) {
+        enforceNetworkStackSettingsOrSetup();
+        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY,
+                encodeBool(accept), encodeBool(always), network));
+    }
+
+    @Override
     public void setAvoidUnvalidated(Network network) {
-        enforceConnectivityInternalPermission();
+        enforceNetworkStackSettingsOrSetup();
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_AVOID_UNVALIDATED, network));
     }
 
@@ -3224,6 +3313,10 @@
         if (accept != nai.networkMisc.acceptUnvalidated) {
             int oldScore = nai.getCurrentScore();
             nai.networkMisc.acceptUnvalidated = accept;
+            // If network becomes partial connectivity and user already accepted to use this
+            // network, we should respect the user's option and don't need to popup the
+            // PARTIAL_CONNECTIVITY notification to user again.
+            nai.networkMisc.acceptPartialConnectivity = accept;
             rematchAllNetworksAndRequests(nai, oldScore);
             sendUpdatedScoreToFactories(nai);
         }
@@ -3242,6 +3335,48 @@
 
     }
 
+    private void handleSetAcceptPartialConnectivity(Network network, boolean accept,
+            boolean always) {
+        if (DBG) {
+            log("handleSetAcceptPartialConnectivity network=" + network + " accept=" + accept
+                    + " always=" + always);
+        }
+
+        final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
+        if (nai == null) {
+            // Nothing to do.
+            return;
+        }
+
+        if (nai.lastValidated) {
+            // The network validated while the dialog box was up. Take no action.
+            return;
+        }
+
+        if (accept != nai.networkMisc.acceptPartialConnectivity) {
+            nai.networkMisc.acceptPartialConnectivity = accept;
+        }
+
+        // TODO: Use the current design or save the user choice into IpMemoryStore.
+        if (always) {
+            nai.asyncChannel.sendMessage(
+                    NetworkAgent.CMD_SAVE_ACCEPT_UNVALIDATED, encodeBool(accept));
+        }
+
+        if (!accept) {
+            // Tell the NetworkAgent to not automatically reconnect to the network.
+            nai.asyncChannel.sendMessage(NetworkAgent.CMD_PREVENT_AUTOMATIC_RECONNECT);
+            // Tear down the network.
+            teardownUnneededNetwork(nai);
+        } else {
+            try {
+                nai.networkMonitor().notifyAcceptPartialConnectivity();
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+    }
+
     private void handleSetAvoidUnvalidated(Network network) {
         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
         if (nai == null || nai.lastValidated) {
@@ -3412,6 +3547,9 @@
             case LOST_INTERNET:
                 action = ConnectivityManager.ACTION_PROMPT_LOST_VALIDATION;
                 break;
+            case PARTIAL_CONNECTIVITY:
+                action = ConnectivityManager.ACTION_PROMPT_PARTIAL_CONNECTIVITY;
+                break;
             default:
                 Slog.wtf(TAG, "Unknown notification type " + type);
                 return;
@@ -3434,22 +3572,36 @@
         if (VDBG || DDBG) log("handlePromptUnvalidated " + network);
         NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
 
-        // Only prompt if the network is unvalidated and was explicitly selected by the user, and if
-        // we haven't already been told to switch to it regardless of whether it validated or not.
-        // Also don't prompt on captive portals because we're already prompting the user to sign in.
-        if (nai == null || nai.everValidated || nai.everCaptivePortalDetected ||
-                !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated) {
+        // Only prompt if the network is unvalidated or network has partial internet connectivity
+        // and was explicitly selected by the user, and if we haven't already been told to switch
+        // to it regardless of whether it validated or not. Also don't prompt on captive portals
+        // because we're already prompting the user to sign in.
+        if (nai == null || nai.everValidated || nai.everCaptivePortalDetected
+                || !nai.networkMisc.explicitlySelected || nai.networkMisc.acceptUnvalidated
+                || nai.networkMisc.acceptPartialConnectivity) {
             return;
         }
-        showNetworkNotification(nai, NotificationType.NO_INTERNET);
+        // TODO: Evaluate if it's needed to wait 8 seconds for triggering notification when
+        // NetworkMonitor detects the network is partial connectivity. Need to change the design to
+        // popup the notification immediately when the network is partial connectivity.
+        if (nai.partialConnectivity) {
+            // Treat PARTIAL_CONNECTIVITY as NO_INTERNET temporary until Settings has been updated.
+            // TODO: Need to change back to PARTIAL_CONNECTIVITY when Settings part is merged.
+            showNetworkNotification(nai, NotificationType.NO_INTERNET);
+        } else {
+            showNetworkNotification(nai, NotificationType.NO_INTERNET);
+        }
     }
 
     private void handleNetworkUnvalidated(NetworkAgentInfo nai) {
         NetworkCapabilities nc = nai.networkCapabilities;
         if (DBG) log("handleNetworkUnvalidated " + nai.name() + " cap=" + nc);
 
-        if (nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
-            mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
+        if (!nc.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
+            return;
+        }
+
+        if (mMultinetworkPolicyTracker.shouldNotifyWifiUnvalidated()) {
             showNetworkNotification(nai, NotificationType.LOST_INTERNET);
         }
     }
@@ -3532,7 +3684,8 @@
                     break;
                 }
                 case EVENT_RELEASE_NETWORK_REQUEST: {
-                    handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
+                    handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
+                            /* callOnUnavailable */ false);
                     break;
                 }
                 case EVENT_SET_ACCEPT_UNVALIDATED: {
@@ -3540,6 +3693,12 @@
                     handleSetAcceptUnvalidated(network, toBool(msg.arg1), toBool(msg.arg2));
                     break;
                 }
+                case EVENT_SET_ACCEPT_PARTIAL_CONNECTIVITY: {
+                    Network network = (Network) msg.obj;
+                    handleSetAcceptPartialConnectivity(network, toBool(msg.arg1),
+                            toBool(msg.arg2));
+                    break;
+                }
                 case EVENT_SET_AVOID_UNVALIDATED: {
                     handleSetAvoidUnvalidated((Network) msg.obj);
                     break;
@@ -3764,6 +3923,22 @@
         mTethering.getLatestTetheringEntitlementResult(type, receiver, showEntitlementUi);
     }
 
+    /** Register tethering event callback. */
+    @Override
+    public void registerTetheringEventCallback(ITetheringEventCallback callback,
+            String callerPkg) {
+        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+        mTethering.registerTetheringEventCallback(callback);
+    }
+
+    /** Unregister tethering event callback. */
+    @Override
+    public void unregisterTetheringEventCallback(ITetheringEventCallback callback,
+            String callerPkg) {
+        ConnectivityManager.enforceTetherChangePermission(mContext, callerPkg);
+        mTethering.unregisterTetheringEventCallback(callback);
+    }
+
     // Called when we lose the default network and have no replacement yet.
     // This will automatically be cleared after X seconds or a new default network
     // becomes CONNECTED, whichever happens first.  The timer is started by the
@@ -4678,11 +4853,14 @@
         public final String name;
         public final Messenger messenger;
         public final AsyncChannel asyncChannel;
+        public final int factorySerialNumber;
 
-        public NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel) {
+        NetworkFactoryInfo(String name, Messenger messenger, AsyncChannel asyncChannel,
+                int factorySerialNumber) {
             this.name = name;
             this.messenger = messenger;
             this.asyncChannel = asyncChannel;
+            this.factorySerialNumber = factorySerialNumber;
         }
     }
 
@@ -5043,10 +5221,12 @@
     }
 
     @Override
-    public void registerNetworkFactory(Messenger messenger, String name) {
+    public int registerNetworkFactory(Messenger messenger, String name) {
         enforceConnectivityInternalPermission();
-        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel());
+        NetworkFactoryInfo nfi = new NetworkFactoryInfo(name, messenger, new AsyncChannel(),
+                NetworkFactory.SerialNumber.nextSerialNumber());
         mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_FACTORY, nfi));
+        return nfi.factorySerialNumber;
     }
 
     private void handleRegisterNetworkFactory(NetworkFactoryInfo nfi) {
@@ -5151,9 +5331,35 @@
         return nri.request.requestId == mDefaultRequest.requestId;
     }
 
+    // TODO : remove this method. It's a stopgap measure to help sheperding a number of dependent
+    // changes that would conflict throughout the automerger graph. Having this method temporarily
+    // helps with the process of going through with all these dependent changes across the entire
+    // tree.
     public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
             LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
             int currentScore, NetworkMisc networkMisc) {
+        return registerNetworkAgent(messenger, networkInfo, linkProperties, networkCapabilities,
+                currentScore, networkMisc, NetworkFactory.SerialNumber.NONE);
+    }
+
+    /**
+     * Register a new agent with ConnectivityService to handle a network.
+     *
+     * @param messenger a messenger for ConnectivityService to contact the agent asynchronously.
+     * @param networkInfo the initial info associated with this network. It can be updated later :
+     *         see {@link #updateNetworkInfo}.
+     * @param linkProperties the initial link properties of this network. They can be updated
+     *         later : see {@link #updateLinkProperties}.
+     * @param networkCapabilities the initial capabilites of this network. They can be updated
+     *         later : see {@link #updateNetworkCapabilities}.
+     * @param currentScore the initial score of the network. See
+     *         {@link NetworkAgentInfo#getCurrentScore}.
+     * @param networkMisc metadata about the network. This is never updated.
+     * @param factorySerialNumber the serial number of the factory owning this NetworkAgent.
+     */
+    public int registerNetworkAgent(Messenger messenger, NetworkInfo networkInfo,
+            LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
+            int currentScore, NetworkMisc networkMisc, int factorySerialNumber) {
         enforceConnectivityInternalPermission();
 
         LinkProperties lp = new LinkProperties(linkProperties);
@@ -5163,7 +5369,8 @@
         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
         final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
                 new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
-                mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS);
+                mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS,
+                factorySerialNumber);
         // Make sure the network capabilities reflect what the agent info says.
         nai.networkCapabilities = mixInCapabilities(nai, nc);
         final String extraInfo = networkInfo.getExtraInfo();
@@ -5448,6 +5655,11 @@
         } else {
             newNc.addCapability(NET_CAPABILITY_NOT_SUSPENDED);
         }
+        if (nai.partialConnectivity) {
+            newNc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        } else {
+            newNc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        }
 
         return newNc;
     }
@@ -5585,17 +5797,23 @@
             NetworkRequest nr = nai.requestAt(i);
             // Don't send listening requests to factories. b/17393458
             if (nr.isListen()) continue;
-            sendUpdatedScoreToFactories(nr, nai.getCurrentScore());
+            sendUpdatedScoreToFactories(nr, nai);
         }
     }
 
-    private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
+    private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, NetworkAgentInfo nai) {
+        int score = 0;
+        int serial = 0;
+        if (nai != null) {
+            score = nai.getCurrentScore();
+            serial = nai.factorySerialNumber;
+        }
         if (VDBG || DDBG){
             log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
         }
         for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
-            nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
-                    networkRequest);
+            nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+                    serial, networkRequest);
         }
     }
 
@@ -5873,7 +6091,7 @@
                     // TODO - this could get expensive if we have a lot of requests for this
                     // network.  Think about if there is a way to reduce this.  Push
                     // netid->request mapping to each factory?
-                    sendUpdatedScoreToFactories(nri.request, score);
+                    sendUpdatedScoreToFactories(nri.request, newNetwork);
                     if (isDefaultRequest(nri)) {
                         isNewDefault = true;
                         oldDefaultNetwork = currentNetwork;
@@ -5897,7 +6115,7 @@
                 newNetwork.removeRequest(nri.request.requestId);
                 if (currentNetwork == newNetwork) {
                     clearNetworkForRequest(nri.request.requestId);
-                    sendUpdatedScoreToFactories(nri.request, 0);
+                    sendUpdatedScoreToFactories(nri.request, null);
                 } else {
                     Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
                             newNetwork.name() +
diff --git a/services/core/java/com/android/server/DynamicAndroidService.java b/services/core/java/com/android/server/DynamicAndroidService.java
index 12a3f02..8488941 100644
--- a/services/core/java/com/android/server/DynamicAndroidService.java
+++ b/services/core/java/com/android/server/DynamicAndroidService.java
@@ -118,7 +118,9 @@
         if (gsiService.isGsiRunning()) {
             return gsiService.disableGsiInstall();
         } else {
-            return gsiService.setGsiBootable() == 0;
+            final int status = gsiService.getGsiBootStatus();
+            final boolean singleBoot = (status == IGsiService.BOOT_STATUS_SINGLE_BOOT);
+            return gsiService.setGsiBootable(singleBoot) == 0;
         }
     }
 
@@ -129,6 +131,6 @@
 
     @Override
     public boolean commit() throws RemoteException {
-        return getGsiService().setGsiBootable() == 0;
+        return getGsiService().setGsiBootable(true) == 0;
     }
 }
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index a4fda8e..a9645c4 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -2506,6 +2506,10 @@
                 modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID, route);
             }
         }
+
+        // IPv6 link local should be activated always.
+        modifyRoute(MODIFY_OPERATION_ADD, INetd.LOCAL_NET_ID,
+                new RouteInfo(new IpPrefix("fe80::/64"), null, iface));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 84d6154..e78ae55 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -238,6 +238,8 @@
 
     private PhoneCapability mPhoneCapability = null;
 
+    private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+
     @TelephonyManager.RadioPowerState
     private int mRadioPowerState = TelephonyManager.RADIO_POWER_UNAVAILABLE;
 
@@ -258,7 +260,8 @@
     static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR
                         | PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR
-                        | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST;
+                        | PhoneStateListener.LISTEN_EMERGENCY_NUMBER_LIST
+                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
@@ -818,9 +821,10 @@
                             remove(r.binder);
                         }
                     }
-                    if ((events & PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE) != 0) {
+                    if ((events & PhoneStateListener
+                            .LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE) != 0) {
                         try {
-                            r.callback.onPreferredDataSubIdChanged(mPreferredDataSubId);
+                            r.callback.onActiveDataSubIdChanged(mActiveDataSubId);
                         } catch (RemoteException ex) {
                             remove(r.binder);
                         }
@@ -1740,23 +1744,23 @@
         }
     }
 
-    public void notifyPreferredDataSubIdChanged(int preferredSubId) {
-        if (!checkNotifyPermission("notifyPreferredDataSubIdChanged()")) {
+    public void notifyActiveDataSubIdChanged(int activeDataSubId) {
+        if (!checkNotifyPermission("notifyActiveDataSubIdChanged()")) {
             return;
         }
 
         if (VDBG) {
-            log("notifyPreferredDataSubIdChanged: preferredSubId=" + preferredSubId);
+            log("notifyActiveDataSubIdChanged: activeDataSubId=" + activeDataSubId);
         }
 
         synchronized (mRecords) {
-            mPreferredDataSubId = preferredSubId;
+            mActiveDataSubId = activeDataSubId;
 
             for (Record r : mRecords) {
                 if (r.matchPhoneStateListenerEvent(
-                        PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE)) {
+                        PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE)) {
                     try {
-                        r.callback.onPreferredDataSubIdChanged(preferredSubId);
+                        r.callback.onActiveDataSubIdChanged(activeDataSubId);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
                     }
@@ -1893,7 +1897,7 @@
             pw.println("mBackgroundCallState=" + mBackgroundCallState);
             pw.println("mSrvccState=" + mSrvccState);
             pw.println("mPhoneCapability=" + mPhoneCapability);
-            pw.println("mPreferredDataSubId=" + mPreferredDataSubId);
+            pw.println("mActiveDataSubId=" + mActiveDataSubId);
             pw.println("mRadioPowerState=" + mRadioPowerState);
             pw.println("mEmergencyNumberList=" + mEmergencyNumberList);
             pw.println("mCallQuality=" + mCallQuality);
@@ -2165,14 +2169,6 @@
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, null);
         }
 
-        if ((events & PhoneStateListener.LISTEN_PREFERRED_DATA_SUBID_CHANGE) != 0) {
-            // It can have either READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE.
-            TelephonyPermissions.checkReadPhoneState(mContext,
-                    SubscriptionManager.INVALID_SUBSCRIPTION_ID, Binder.getCallingPid(),
-                    Binder.getCallingUid(), callingPackage, "listen to "
-                            + "LISTEN_PREFERRED_DATA_SUBID_CHANGE");
-        }
-
         if ((events & PhoneStateListener.LISTEN_CALL_DISCONNECT_CAUSES) != 0) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);
diff --git a/services/core/java/com/android/server/TestNetworkService.java b/services/core/java/com/android/server/TestNetworkService.java
new file mode 100644
index 0000000..e64ab78
--- /dev/null
+++ b/services/core/java/com/android/server/TestNetworkService.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import static com.android.internal.util.Preconditions.checkNotNull;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.INetd;
+import android.net.ITestNetworkManager;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
+import android.net.NetworkInfo;
+import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
+import android.net.StringNetworkSpecifier;
+import android.net.TestNetworkInterface;
+import android.net.util.NetdService;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.INetworkManagementService;
+import android.os.Looper;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.UncheckedIOException;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InterfaceAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/** @hide */
+class TestNetworkService extends ITestNetworkManager.Stub {
+    @NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
+    @NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
+    @NonNull private static final String TEST_TUN_PREFIX = "testtun";
+    @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
+
+    @NonNull private final Context mContext;
+    @NonNull private final INetworkManagementService mNMS;
+    @NonNull private final INetd mNetd;
+
+    @NonNull private final HandlerThread mHandlerThread;
+    @NonNull private final Handler mHandler;
+
+    // Native method stubs
+    private static native int jniCreateTun(@NonNull String iface);
+
+    @VisibleForTesting
+    protected TestNetworkService(
+            @NonNull Context context, @NonNull INetworkManagementService netManager) {
+        mHandlerThread = new HandlerThread("TestNetworkServiceThread");
+        mHandlerThread.start();
+        mHandler = new Handler(mHandlerThread.getLooper());
+
+        mContext = checkNotNull(context, "missing Context");
+        mNMS = checkNotNull(netManager, "missing INetworkManagementService");
+        mNetd = checkNotNull(NetdService.getInstance(), "could not get netd instance");
+    }
+
+    /**
+     * Create a TUN interface with the given interface name and link addresses
+     *
+     * <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
+     * TUN interface.
+     */
+    @Override
+    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
+        enforceTestNetworkPermissions(mContext);
+
+        checkNotNull(linkAddrs, "missing linkAddrs");
+
+        String iface = TEST_TUN_PREFIX + sTestTunIndex.getAndIncrement();
+        return Binder.withCleanCallingIdentity(
+                () -> {
+                    try {
+                        ParcelFileDescriptor tunIntf =
+                                ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
+                        for (LinkAddress addr : linkAddrs) {
+                            mNetd.interfaceAddAddress(
+                                    iface,
+                                    addr.getAddress().getHostAddress(),
+                                    addr.getPrefixLength());
+                        }
+
+                        return new TestNetworkInterface(tunIntf, iface);
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                });
+    }
+
+    // Tracker for TestNetworkAgents
+    @GuardedBy("mTestNetworkTracker")
+    @NonNull
+    private final SparseArray<TestNetworkAgent> mTestNetworkTracker = new SparseArray<>();
+
+    public class TestNetworkAgent extends NetworkAgent implements IBinder.DeathRecipient {
+        private static final int NETWORK_SCORE = 1; // Use a low, non-zero score.
+
+        private final int mUid;
+        @NonNull private final NetworkInfo mNi;
+        @NonNull private final NetworkCapabilities mNc;
+        @NonNull private final LinkProperties mLp;
+
+        @GuardedBy("mBinderLock")
+        @NonNull
+        private IBinder mBinder;
+
+        @NonNull private final Object mBinderLock = new Object();
+
+        private TestNetworkAgent(
+                @NonNull Looper looper,
+                @NonNull Context context,
+                @NonNull NetworkInfo ni,
+                @NonNull NetworkCapabilities nc,
+                @NonNull LinkProperties lp,
+                int uid,
+                @NonNull IBinder binder)
+                throws RemoteException {
+            super(looper, context, TEST_NETWORK_TYPE, ni, nc, lp, NETWORK_SCORE);
+
+            mUid = uid;
+            mNi = ni;
+            mNc = nc;
+            mLp = lp;
+
+            synchronized (mBinderLock) {
+                mBinder = binder; // Binder null-checks in create()
+
+                try {
+                    mBinder.linkToDeath(this, 0);
+                } catch (RemoteException e) {
+                    binderDied();
+                    throw e; // Abort, signal failure up the stack.
+                }
+            }
+        }
+
+        /**
+         * If the Binder object dies, this function is called to free the resources of this
+         * TestNetworkAgent
+         */
+        @Override
+        public void binderDied() {
+            teardown();
+        }
+
+        @Override
+        protected void unwanted() {
+            teardown();
+        }
+
+        private void teardown() {
+            mNi.setDetailedState(DetailedState.DISCONNECTED, null, null);
+            mNi.setIsAvailable(false);
+            sendNetworkInfo(mNi);
+
+            // Synchronize on mBinderLock to ensure that unlinkToDeath is never called more than
+            // once (otherwise it could throw an exception)
+            synchronized (mBinderLock) {
+                // If mBinder is null, this Test Network has already been cleaned up.
+                if (mBinder == null) return;
+                mBinder.unlinkToDeath(this, 0);
+                mBinder = null;
+            }
+
+            // Has to be in TestNetworkAgent to ensure all teardown codepaths properly clean up
+            // resources, even for binder death or unwanted calls.
+            synchronized (mTestNetworkTracker) {
+                mTestNetworkTracker.remove(netId);
+            }
+        }
+    }
+
+    private TestNetworkAgent registerTestNetworkAgent(
+            @NonNull Looper looper,
+            @NonNull Context context,
+            @NonNull String iface,
+            int callingUid,
+            @NonNull IBinder binder)
+            throws RemoteException, SocketException {
+        checkNotNull(looper, "missing Looper");
+        checkNotNull(context, "missing Context");
+        // iface and binder validity checked by caller
+
+        // Build network info with special testing type
+        NetworkInfo ni = new NetworkInfo(ConnectivityManager.TYPE_TEST, 0, TEST_NETWORK_TYPE, "");
+        ni.setDetailedState(DetailedState.CONNECTED, null, null);
+        ni.setIsAvailable(true);
+
+        // Build narrow set of NetworkCapabilities, useful only for testing
+        NetworkCapabilities nc = new NetworkCapabilities();
+        nc.clearAll(); // Remove default capabilities.
+        nc.addTransportType(NetworkCapabilities.TRANSPORT_TEST);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED);
+        nc.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+        nc.setNetworkSpecifier(new StringNetworkSpecifier(iface));
+
+        // Build LinkProperties
+        LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(iface);
+
+        // Find the currently assigned addresses, and add them to LinkProperties
+        boolean allowIPv4 = false, allowIPv6 = false;
+        NetworkInterface netIntf = NetworkInterface.getByName(iface);
+        checkNotNull(netIntf, "No such network interface found: " + netIntf);
+
+        for (InterfaceAddress intfAddr : netIntf.getInterfaceAddresses()) {
+            lp.addLinkAddress(
+                    new LinkAddress(intfAddr.getAddress(), intfAddr.getNetworkPrefixLength()));
+
+            if (intfAddr.getAddress() instanceof Inet6Address) {
+                allowIPv6 |= !intfAddr.getAddress().isLinkLocalAddress();
+            } else if (intfAddr.getAddress() instanceof Inet4Address) {
+                allowIPv4 = true;
+            }
+        }
+
+        // Add global routes (but as non-default, non-internet providing network)
+        if (allowIPv4) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null, iface));
+        }
+        if (allowIPv6) {
+            lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null, iface));
+        }
+
+        return new TestNetworkAgent(looper, context, ni, nc, lp, callingUid, binder);
+    }
+
+    /**
+     * Sets up a Network with extremely limited privileges, guarded by the MANAGE_TEST_NETWORKS
+     * permission.
+     *
+     * <p>This method provides a Network that is useful only for testing.
+     */
+    @Override
+    public void setupTestNetwork(@NonNull String iface, @NonNull IBinder binder) {
+        enforceTestNetworkPermissions(mContext);
+
+        checkNotNull(iface, "missing Iface");
+        checkNotNull(binder, "missing IBinder");
+
+        if (!(iface.startsWith(INetd.IPSEC_INTERFACE_PREFIX)
+                || iface.startsWith(TEST_TUN_PREFIX))) {
+            throw new IllegalArgumentException(
+                    "Cannot create network for non ipsec, non-testtun interface");
+        }
+
+        // Setup needs to be done with NETWORK_STACK privileges.
+        int callingUid = Binder.getCallingUid();
+        Binder.withCleanCallingIdentity(
+                () -> {
+                    try {
+                        mNMS.setInterfaceUp(iface);
+
+                        // Synchronize all accesses to mTestNetworkTracker to prevent the case
+                        // where:
+                        // 1. TestNetworkAgent successfully binds to death of binder
+                        // 2. Before it is added to the mTestNetworkTracker, binder dies,
+                        // binderDied() is called (on a different thread)
+                        // 3. This thread is pre-empted, put() is called after remove()
+                        synchronized (mTestNetworkTracker) {
+                            TestNetworkAgent agent =
+                                    registerTestNetworkAgent(
+                                            mHandler.getLooper(),
+                                            mContext,
+                                            iface,
+                                            callingUid,
+                                            binder);
+
+                            mTestNetworkTracker.put(agent.netId, agent);
+                        }
+                    } catch (SocketException e) {
+                        throw new UncheckedIOException(e);
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                });
+    }
+
+    /** Teardown a test network */
+    @Override
+    public void teardownTestNetwork(int netId) {
+        enforceTestNetworkPermissions(mContext);
+
+        TestNetworkAgent agent;
+        synchronized (mTestNetworkTracker) {
+            agent = mTestNetworkTracker.get(netId);
+        }
+
+        if (agent == null) {
+            return; // Already torn down
+        } else if (agent.mUid != Binder.getCallingUid()) {
+            throw new SecurityException("Attempted to modify other user's test networks");
+        }
+
+        // Safe to be called multiple times.
+        agent.teardown();
+    }
+
+    // STOPSHIP: Change this back to android.Manifest.permission.MANAGE_TEST_NETWORKS
+    private static final String PERMISSION_NAME = "dummy";
+
+    public static void enforceTestNetworkPermissions(@NonNull Context context) {
+        // STOPSHIP: Re-enable these checks. Disabled until adoptShellPermissionIdentity() can be
+        //           called from CTS test code.
+        if (false) {
+            context.enforceCallingOrSelfPermission(PERMISSION_NAME, "TestNetworkService");
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
index 6cff57d..cc4c173 100644
--- a/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
+++ b/services/core/java/com/android/server/connectivity/KeepaliveTracker.java
@@ -239,7 +239,12 @@
                                 .sendMessage(CMD_START_SOCKET_KEEPALIVE, slot, mInterval, mPacket);
                         break;
                     case TYPE_TCP:
-                        mTcpController.startSocketMonitor(mFd, this, mSlot);
+                        try {
+                            mTcpController.startSocketMonitor(mFd, this, mSlot);
+                        } catch (InvalidSocketException e) {
+                            handleStopKeepalive(mNai, mSlot, ERROR_INVALID_SOCKET);
+                            return;
+                        }
                         mNai.asyncChannel
                                 .sendMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0 /* Unused */,
                                         mPacket);
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index f11a0de..8f2825c 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -156,6 +156,9 @@
     // last detected.
     public boolean captivePortalLoginNotified;
 
+    // Set to true when partial connectivity was detected.
+    public boolean partialConnectivity;
+
     // Networks are lingered when they become unneeded as a result of their NetworkRequests being
     // satisfied by a higher-scoring network. so as to allow communication to wrap up before the
     // network is taken down.  This usually only happens to the default network. Lingering ends with
@@ -235,6 +238,8 @@
     public final Messenger messenger;
     public final AsyncChannel asyncChannel;
 
+    public final int factorySerialNumber;
+
     // Used by ConnectivityService to keep track of 464xlat.
     public final Nat464Xlat clatd;
 
@@ -250,7 +255,7 @@
     public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
             LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
             NetworkMisc misc, ConnectivityService connService, INetd netd,
-            INetworkManagementService nms) {
+            INetworkManagementService nms, int factorySerialNumber) {
         this.messenger = messenger;
         asyncChannel = ac;
         network = net;
@@ -263,6 +268,7 @@
         mContext = context;
         mHandler = handler;
         networkMisc = misc;
+        this.factorySerialNumber = factorySerialNumber;
     }
 
     /**
@@ -592,6 +598,8 @@
         for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
     }
 
+    // TODO: Print shorter members first and only print the boolean variable which value is true
+    // to improve readability.
     public String toString() {
         return "NetworkAgentInfo{ ni{" + networkInfo + "}  "
                 + "network{" + network + "}  nethandle{" + network.getNetworkHandle() + "}  "
@@ -604,6 +612,8 @@
                 + "everCaptivePortalDetected{" + everCaptivePortalDetected + "} "
                 + "lastCaptivePortalDetected{" + lastCaptivePortalDetected + "} "
                 + "captivePortalLoginNotified{" + captivePortalLoginNotified + "} "
+                + "partialConnectivity{" + partialConnectivity + "} "
+                + "acceptPartialConnectivity{" + networkMisc.acceptPartialConnectivity + "} "
                 + "clat{" + clatd + "} "
                 + "}";
     }
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index b50477b..053da0d 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -47,8 +47,9 @@
         LOST_INTERNET(SystemMessage.NOTE_NETWORK_LOST_INTERNET),
         NETWORK_SWITCH(SystemMessage.NOTE_NETWORK_SWITCH),
         NO_INTERNET(SystemMessage.NOTE_NETWORK_NO_INTERNET),
-        SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN),
-        LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN);
+        LOGGED_IN(SystemMessage.NOTE_NETWORK_LOGGED_IN),
+        PARTIAL_CONNECTIVITY(SystemMessage.NOTE_NETWORK_PARTIAL_CONNECTIVITY),
+        SIGN_IN(SystemMessage.NOTE_NETWORK_SIGN_IN);
 
         public final int eventId;
 
@@ -169,11 +170,18 @@
         CharSequence details;
         int icon = getIcon(transportType);
         if (notifyType == NotificationType.NO_INTERNET && transportType == TRANSPORT_WIFI) {
-            title = r.getString(R.string.wifi_no_internet, 0);
+            title = r.getString(R.string.wifi_no_internet,
+                    WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
             details = r.getString(R.string.wifi_no_internet_detailed);
+        } else if (notifyType == NotificationType.PARTIAL_CONNECTIVITY
+                && transportType == TRANSPORT_WIFI) {
+            title = r.getString(R.string.network_partial_connectivity,
+                    WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
+            details = r.getString(R.string.network_partial_connectivity_detailed);
         } else if (notifyType == NotificationType.LOST_INTERNET &&
                 transportType == TRANSPORT_WIFI) {
-            title = r.getString(R.string.wifi_no_internet, 0);
+            title = r.getString(R.string.wifi_no_internet,
+                    WifiInfo.removeDoubleQuotes(nai.networkCapabilities.getSSID()));
             details = r.getString(R.string.wifi_no_internet_detailed);
         } else if (notifyType == NotificationType.SIGN_IN) {
             switch (transportType) {
@@ -316,6 +324,8 @@
         }
         switch (t) {
             case SIGN_IN:
+                return 5;
+            case PARTIAL_CONNECTIVITY:
                 return 4;
             case NO_INTERNET:
                 return 3;
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 9789688..1ac09ad 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -70,9 +70,8 @@
     private static final long MAX_PAC_SIZE = 20 * 1000 * 1000;
 
     // Return values for #setCurrentProxyScriptUrl
-    enum ToSendOrNotToSendBroadcast {
-        DONT_SEND_BROADCAST, DO_SEND_BROADCAST
-    }
+    public static final boolean DONT_SEND_BROADCAST = false;
+    public static final boolean DO_SEND_BROADCAST = true;
 
     private String mCurrentPac;
     @GuardedBy("mProxyLock")
@@ -176,11 +175,11 @@
      * @param proxy Proxy information that is about to be broadcast.
      * @return Returns whether the broadcast should be sent : either DO_ or DONT_SEND_BROADCAST
      */
-    synchronized ToSendOrNotToSendBroadcast setCurrentProxyScriptUrl(ProxyInfo proxy) {
+    synchronized boolean setCurrentProxyScriptUrl(ProxyInfo proxy) {
         if (!Uri.EMPTY.equals(proxy.getPacFileUrl())) {
             if (proxy.getPacFileUrl().equals(mPacUrl) && (proxy.getPort() > 0)) {
                 // Allow to send broadcast, nothing to do.
-                return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+                return DO_SEND_BROADCAST;
             }
             mPacUrl = proxy.getPacFileUrl();
             mCurrentDelay = DELAY_1;
@@ -188,7 +187,7 @@
             mHasDownloaded = false;
             getAlarmManager().cancel(mPacRefreshIntent);
             bind();
-            return ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST;
+            return DONT_SEND_BROADCAST;
         } else {
             getAlarmManager().cancel(mPacRefreshIntent);
             synchronized (mProxyLock) {
@@ -204,7 +203,7 @@
                     }
                 }
             }
-            return ToSendOrNotToSendBroadcast.DO_SEND_BROADCAST;
+            return DO_SEND_BROADCAST;
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index a671287..e715890 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -208,8 +208,7 @@
     public void sendProxyBroadcast() {
         final ProxyInfo defaultProxy = getDefaultProxy();
         final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
-        if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)
-                == PacManager.ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST) {
+        if (mPacManager.setCurrentProxyScriptUrl(proxyInfo) == PacManager.DONT_SEND_BROADCAST) {
             return;
         }
         if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
diff --git a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
index 65de83b..3e21b5b 100644
--- a/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
+++ b/services/core/java/com/android/server/connectivity/TcpKeepaliveController.java
@@ -215,18 +215,20 @@
      * Start monitoring incoming packets.
      *
      * @param fd socket fd to monitor.
-     * @param messenger a callback to notify socket status.
+     * @param ki a {@link KeepaliveInfo} that tracks information about a socket keepalive.
      * @param slot keepalive slot.
      */
     public void startSocketMonitor(@NonNull final FileDescriptor fd,
-            @NonNull final KeepaliveInfo ki, final int slot) {
+            @NonNull final KeepaliveInfo ki, final int slot)
+            throws IllegalArgumentException, InvalidSocketException {
         synchronized (mListeners) {
             if (null != mListeners.get(slot)) {
                 throw new IllegalArgumentException("This slot is already taken");
             }
             for (int i = 0; i < mListeners.size(); ++i) {
                 if (fd.equals(mListeners.valueAt(i))) {
-                    throw new IllegalArgumentException("This fd is already registered");
+                    Log.e(TAG, "This fd is already registered.");
+                    throw new InvalidSocketException(ERROR_INVALID_SOCKET);
                 }
             }
             mFdHandlerQueue.addOnFileDescriptorEventListener(fd, FD_EVENTS, (readyFd, events) -> {
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 3b4b6f8..35704d40 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -62,6 +62,7 @@
 import android.hardware.usb.UsbManager;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -82,6 +83,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
@@ -184,6 +186,9 @@
     private final VersionedBroadcastListener mDefaultSubscriptionChange;
     private final TetheringDependencies mDeps;
     private final EntitlementManager mEntitlementMgr;
+    private final Handler mHandler;
+    private final RemoteCallbackList<ITetheringEventCallback> mTetheringEventCallbacks =
+            new RemoteCallbackList<>();
 
     private volatile TetheringConfiguration mConfig;
     private InterfaceSet mCurrentUpstreamIfaceSet;
@@ -193,6 +198,7 @@
     private boolean mRndisEnabled;       // track the RNDIS function enabled state
     // True iff. WiFi tethering should be started when soft AP is ready.
     private boolean mWifiTetherRequested;
+    private Network mTetherUpstream;
 
     public Tethering(Context context, INetworkManagementService nmService,
             INetworkStatsService statsService, INetworkPolicyManager policyManager,
@@ -213,9 +219,9 @@
         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper, deps);
         mTetherMasterSM.start();
 
-        final Handler smHandler = mTetherMasterSM.getHandler();
-        mOffloadController = new OffloadController(smHandler,
-                mDeps.getOffloadHardwareInterface(smHandler, mLog),
+        mHandler = mTetherMasterSM.getHandler();
+        mOffloadController = new OffloadController(mHandler,
+                mDeps.getOffloadHardwareInterface(mHandler, mLog),
                 mContext.getContentResolver(), mNMService,
                 mLog);
         mUpstreamNetworkMonitor = deps.getUpstreamNetworkMonitor(mContext, mTetherMasterSM, mLog,
@@ -227,7 +233,7 @@
         mEntitlementMgr = mDeps.getEntitlementManager(mContext, mTetherMasterSM,
                 mLog, systemProperties);
         mCarrierConfigChange = new VersionedBroadcastListener(
-                "CarrierConfigChangeListener", mContext, smHandler, filter,
+                "CarrierConfigChangeListener", mContext, mHandler, filter,
                 (Intent ignored) -> {
                     mLog.log("OBSERVED carrier config change");
                     updateConfiguration();
@@ -237,7 +243,7 @@
         filter = new IntentFilter();
         filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         mDefaultSubscriptionChange = new VersionedBroadcastListener(
-                "DefaultSubscriptionChangeListener", mContext, smHandler, filter,
+                "DefaultSubscriptionChangeListener", mContext, mHandler, filter,
                 (Intent ignored) -> {
                     mLog.log("OBSERVED default data subscription change");
                     updateConfiguration();
@@ -248,14 +254,13 @@
         // Load tethering configuration.
         updateConfiguration();
 
-        startStateMachineUpdaters();
+        startStateMachineUpdaters(mHandler);
     }
 
-    private void startStateMachineUpdaters() {
+    private void startStateMachineUpdaters(Handler handler) {
         mCarrierConfigChange.startListening();
         mDefaultSubscriptionChange.startListening();
 
-        final Handler handler = mTetherMasterSM.getHandler();
         IntentFilter filter = new IntentFilter();
         filter.addAction(UsbManager.ACTION_USB_STATE);
         filter.addAction(CONNECTIVITY_ACTION);
@@ -1229,8 +1234,13 @@
                     sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
                 }
             }
-            mUpstreamNetworkMonitor.setCurrentUpstream((ns != null) ? ns.network : null);
             setUpstreamNetwork(ns);
+            final Network newUpstream = (ns != null) ? ns.network : null;
+            if (mTetherUpstream != newUpstream) {
+                mTetherUpstream = newUpstream;
+                mUpstreamNetworkMonitor.setCurrentUpstream(mTetherUpstream);
+                reportUpstreamChanged(mTetherUpstream);
+            }
         }
 
         protected void setUpstreamNetwork(NetworkState ns) {
@@ -1413,6 +1423,10 @@
                 mUpstreamNetworkMonitor.stop();
                 notifyDownstreamsOfNewUpstreamIface(null);
                 handleNewUpstreamNetworkState(null);
+                if (mTetherUpstream != null) {
+                    mTetherUpstream = null;
+                    reportUpstreamChanged(null);
+                }
             }
 
             private boolean updateUpstreamWanted() {
@@ -1684,6 +1698,40 @@
         }
     }
 
+    /** Register tethering event callback */
+    public void registerTetheringEventCallback(ITetheringEventCallback callback) {
+        mHandler.post(() -> {
+            try {
+                callback.onUpstreamChanged(mTetherUpstream);
+            } catch (RemoteException e) {
+                // Not really very much to do here.
+            }
+            mTetheringEventCallbacks.register(callback);
+        });
+    }
+
+    /** Unregister tethering event callback */
+    public void unregisterTetheringEventCallback(ITetheringEventCallback callback) {
+        mHandler.post(() -> {
+            mTetheringEventCallbacks.unregister(callback);
+        });
+    }
+
+    private void reportUpstreamChanged(Network network) {
+        final int length = mTetheringEventCallbacks.beginBroadcast();
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mTetheringEventCallbacks.getBroadcastItem(i).onUpstreamChanged(network);
+                } catch (RemoteException e) {
+                    // Not really very much to do here.
+                }
+            }
+        } finally {
+            mTetheringEventCallbacks.finishBroadcast();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
         // Binder.java closes the resource for us.
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 205fc77..8005dda 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -54,6 +54,7 @@
 import android.net.Network;
 import android.net.NetworkAgent;
 import android.net.NetworkCapabilities;
+import android.net.NetworkFactory;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
@@ -989,7 +990,8 @@
         try {
             mNetworkAgent = new NetworkAgent(mLooper, mContext, NETWORKTYPE /* logtag */,
                     mNetworkInfo, mNetworkCapabilities, lp,
-                    ConnectivityConstants.VPN_DEFAULT_SCORE, networkMisc) {
+                    ConnectivityConstants.VPN_DEFAULT_SCORE, networkMisc,
+                    NetworkFactory.SerialNumber.VPN) {
                             @Override
                             public void unwanted() {
                                 // We are user controlled, not driven by NetworkRequest.
@@ -1840,6 +1842,7 @@
         config.interfaze = iface;
         config.session = profile.name;
         config.isMetered = false;
+        config.proxyInfo = profile.proxy;
 
         config.addLegacyRoutes(profile.routes);
         if (!profile.dnsServers.isEmpty()) {
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 0ec1f9c..809a48f 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -723,6 +723,17 @@
                 Log.e(TAG, "unable to parse SUPL_ES: " + suplESProperty);
             }
         }
+
+        String emergencyExtensionSecondsString
+                = properties.getProperty("ES_EXTENSION_SEC", "0");
+        try {
+            int emergencyExtensionSeconds =
+                    Integer.parseInt(emergencyExtensionSecondsString);
+            mNIHandler.setEmergencyExtensionSeconds(emergencyExtensionSeconds);
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "unable to parse ES_EXTENSION_SEC: "
+                    + emergencyExtensionSecondsString);
+        }
     }
 
     private void loadPropertiesFromResource(Context context,
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index 2e91f99..28ae6a4 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,12 +1,11 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
 jsharkey@android.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
-silberst@google.com
 sudheersai@google.com
 yamasani@google.com
diff --git a/services/core/java/com/android/server/pm/OWNERS b/services/core/java/com/android/server/pm/OWNERS
index 3c1ee3e..cd0cbd6 100644
--- a/services/core/java/com/android/server/pm/OWNERS
+++ b/services/core/java/com/android/server/pm/OWNERS
@@ -10,76 +10,48 @@
 toddke@google.com
 
 # apex support
-per-file ApexManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
-per-file StagingManager.java = dariofreni@google.com, narayan@google.com, toddke@android.com, toddke@google.com
+per-file ApexManager.java = dariofreni@google.com
+per-file StagingManager.java = dariofreni@google.com
 
 # dex
-per-file AbstractStatsBase.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file AbstractStatsBase.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file AbstractStatsBase.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file BackgroundDexOptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file CompilerStats.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file DynamicCodeLoggingService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file InstructionSets.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptService.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file OtaDexoptShellCommand.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageDexOptimizer.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageManagerServiceCompilerMapping.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = agampe@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = calin@google.com, toddke@google.com, svetoslavganov@google.com
-per-file PackageUsage.java = ngeoffray@google.com, toddke@google.com, svetoslavganov@google.com
+per-file AbstractStatsBase.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file BackgroundDexOptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file CompilerStats.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file DynamicCodeLoggingService.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file InstructionSets.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file OtaDexoptService.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file OtaDexoptShellCommand.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageDexOptimizer.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageManagerServiceCompilerMapping.java = agampe@google.com, calin@google.com, ngeoffray@google.com
+per-file PackageUsage.java = agampe@google.com, calin@google.com, ngeoffray@google.com
 
 # multi user / cross profile
-per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileAppsServiceImpl.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileAppsService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileIntentFilter.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file CrossProfileIntentResolver.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserManagerService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file UserManagerService.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = yamasani@google.com, omakoto@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = rubinxu@google.com, yamasani@google.com, hackbod@google.com
-per-file UserRestrictionsUtils.java = sandness@google.com, yamasani@google.com, hackbod@google.com
+per-file CrossProfileAppsServiceImpl.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileAppsService.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileIntentFilter.java = omakoto@google.com, yamasani@google.com
+per-file CrossProfileIntentResolver.java = omakoto@google.com, yamasani@google.com
+per-file UserManagerService.java = omakoto@google.com, yamasani@google.com
+per-file UserRestrictionsUtils.java = omakoto@google.com, rubinxu@google.com, sandness@google.com, yamasani@google.com
 
 # security
-per-file KeySetHandle.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file KeySetManagerService.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file PackageKeySetData.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file PackageSignatures.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
-per-file SELinuxMMAC.java = cbrubaker@google.com, svetoslavganov@google.com, hackbod@google.com
+per-file KeySetHandle.java = cbrubaker@google.com
+per-file KeySetManagerService.java = cbrubaker@google.com
+per-file PackageKeySetData.java = cbrubaker@google.com
+per-file PackageSignatures.java = cbrubaker@google.com
+per-file SELinuxMMAC.java = cbrubaker@google.com
 
 # shortcuts
-per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutService.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
-per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com, hackbod@google.com
+per-file LauncherAppsService.java = omakoto@google.com, yamasani@google.com
+per-file ShareTargetInfo.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutBitmapSaver.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutDumpFiles.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutLauncher.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutNonPersistentUser.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackage.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackageInfo.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutPackageItem.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutParser.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutRequestPinProcessor.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutService.java = omakoto@google.com, yamasani@google.com
+per-file ShortcutUser.java = omakoto@google.com, yamasani@google.com
 
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 6735ab4..07a6c70 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -38,6 +38,7 @@
         "com_android_server_SerialService.cpp",
         "com_android_server_storage_AppFuseBridge.cpp",
         "com_android_server_SystemServer.cpp",
+        "com_android_server_TestNetworkService.cpp",
         "com_android_server_tv_TvUinputBridge.cpp",
         "com_android_server_tv_TvInputHal.cpp",
         "com_android_server_vr_VrManagerService.cpp",
diff --git a/services/core/jni/com_android_server_TestNetworkService.cpp b/services/core/jni/com_android_server_TestNetworkService.cpp
new file mode 100644
index 0000000..b90ff23
--- /dev/null
+++ b/services/core/jni/com_android_server_TestNetworkService.cpp
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#define LOG_NDEBUG 0
+
+#define LOG_TAG "TestNetworkServiceJni"
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <linux/ipv6_route.h>
+#include <linux/route.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <log/log.h>
+
+#include "netutils/ifc.h"
+
+#include "jni.h"
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
+
+namespace android {
+
+//------------------------------------------------------------------------------
+
+static void throwException(JNIEnv* env, int error, const char* action, const char* iface) {
+    const std::string& msg =
+        android::base::StringPrintf("Error %s %s: %s", action, iface, strerror(error));
+
+    jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
+}
+
+static int createTunInterface(JNIEnv* env, const char* iface) {
+    base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
+    ifreq ifr{};
+
+    // Allocate interface.
+    ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+    strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
+    if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
+        throwException(env, errno, "allocating", ifr.ifr_name);
+        return -1;
+    }
+
+    // Activate interface using an unconnected datagram socket.
+    base::unique_fd inet6CtrlSock(socket(AF_INET6, SOCK_DGRAM, 0));
+    ifr.ifr_flags = IFF_UP;
+
+    if (ioctl(inet6CtrlSock.get(), SIOCSIFFLAGS, &ifr)) {
+        throwException(env, errno, "activating", ifr.ifr_name);
+        return -1;
+    }
+
+    return tun.release();
+}
+
+//------------------------------------------------------------------------------
+
+static jint create(JNIEnv* env, jobject /* thiz */, jstring jIface) {
+    ScopedUtfChars iface(env, jIface);
+    if (!iface.c_str()) {
+        jniThrowNullPointerException(env, "iface");
+        return -1;
+    }
+
+    int tun = createTunInterface(env, iface.c_str());
+
+    // Any exceptions will be thrown from the createTunInterface call
+    return tun;
+}
+
+//------------------------------------------------------------------------------
+
+static const JNINativeMethod gMethods[] = {
+    {"jniCreateTun", "(Ljava/lang/String;)I", (void*)create},
+};
+
+int register_android_server_TestNetworkService(JNIEnv* env) {
+    return jniRegisterNativeMethods(env, "com/android/server/TestNetworkService", gMethods,
+                                    NELEM(gMethods));
+}
+
+}; // namespace android
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index bb6e684..83347bb 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -43,6 +43,7 @@
 int register_android_server_location_GnssLocationProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
 int register_android_server_connectivity_tethering_OffloadHardwareInterface(JNIEnv*);
+int register_android_server_TestNetworkService(JNIEnv* env);
 int register_android_server_devicepolicy_CryptoTestHelper(JNIEnv*);
 int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
 int register_android_server_tv_TvUinputBridge(JNIEnv* env);
@@ -88,6 +89,7 @@
     register_android_server_location_GnssLocationProvider(env);
     register_android_server_connectivity_Vpn(env);
     register_android_server_connectivity_tethering_OffloadHardwareInterface(env);
+    register_android_server_TestNetworkService(env);
     register_android_server_devicepolicy_CryptoTestHelper(env);
     register_android_server_ConsumerIrService(env);
     register_android_server_BatteryStatsService(env);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 31e1e35..9c6b52f 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4793,26 +4793,22 @@
     private boolean resetPasswordInternal(String password, long tokenHandle, byte[] token,
             int flags, int callingUid, int userHandle) {
         int quality;
-        final int realQuality;
         synchronized (getLockObject()) {
             quality = getPasswordQuality(null, userHandle, /* parent */ false);
             if (quality == DevicePolicyManager.PASSWORD_QUALITY_MANAGED) {
                 quality = PASSWORD_QUALITY_UNSPECIFIED;
             }
             final PasswordMetrics metrics = PasswordMetrics.computeForPassword(password);
-            realQuality = metrics.quality;
-            if (quality != PASSWORD_QUALITY_UNSPECIFIED) {
-
-                if (realQuality < quality
-                        && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
-                    Slog.w(LOG_TAG, "resetPassword: password quality 0x"
-                            + Integer.toHexString(realQuality)
-                            + " does not meet required quality 0x"
-                            + Integer.toHexString(quality));
-                    return false;
-                }
-                quality = Math.max(realQuality, quality);
+            final int realQuality = metrics.quality;
+            if (realQuality < quality
+                    && quality != DevicePolicyManager.PASSWORD_QUALITY_COMPLEX) {
+                Slog.w(LOG_TAG, "resetPassword: password quality 0x"
+                        + Integer.toHexString(realQuality)
+                        + " does not meet required quality 0x"
+                        + Integer.toHexString(quality));
+                return false;
             }
+            quality = Math.max(realQuality, quality);
             int length = getPasswordMinimumLength(null, userHandle, /* parent */ false);
             if (password.length() < length) {
                 Slog.w(LOG_TAG, "resetPassword: password length " + password.length()
@@ -4889,7 +4885,7 @@
         try {
             if (token == null) {
                 if (!TextUtils.isEmpty(password)) {
-                    mLockPatternUtils.saveLockPassword(password, null, realQuality, userHandle);
+                    mLockPatternUtils.saveLockPassword(password, null, quality, userHandle);
                 } else {
                     mLockPatternUtils.clearLock(null, userHandle);
                 }
@@ -4898,7 +4894,7 @@
                 result = mLockPatternUtils.setLockCredentialWithToken(password,
                         TextUtils.isEmpty(password) ? LockPatternUtils.CREDENTIAL_TYPE_NONE
                                 : LockPatternUtils.CREDENTIAL_TYPE_PASSWORD,
-                        realQuality, tokenHandle, token, userHandle);
+                        quality, tokenHandle, token, userHandle);
             }
             boolean requireEntry = (flags & DevicePolicyManager.RESET_PASSWORD_REQUIRE_ENTRY) != 0;
             if (requireEntry) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index d288910..d33d7f5 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1241,14 +1241,6 @@
             }
             traceEnd();
 
-            traceBeginAndSlog("StartNetworkStack");
-            try {
-                NetworkStackClient.getInstance().start(context);
-            } catch (Throwable e) {
-                reportWtf("starting Network Stack", e);
-            }
-            traceEnd();
-
             traceBeginAndSlog("StartNsdService");
             try {
                 serviceDiscovery = NsdService.create(context);
@@ -1931,6 +1923,14 @@
                     SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
             traceEnd();
 
+            traceBeginAndSlog("StartNetworkStack");
+            try {
+                NetworkStackClient.getInstance().start(context);
+            } catch (Throwable e) {
+                reportWtf("starting Network Stack", e);
+            }
+            traceEnd();
+
             traceBeginAndSlog("MakeLocationServiceReady");
             try {
                 if (locationF != null) locationF.systemRunning();
diff --git a/services/net/OWNERS b/services/net/OWNERS
index 7311eee..d3836d4 100644
--- a/services/net/OWNERS
+++ b/services/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 830dbbe..a8f4a77 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -42,7 +42,6 @@
 import com.android.internal.annotations.GuardedBy;
 
 import java.io.PrintWriter;
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 
 /**
@@ -53,6 +52,7 @@
     private static final String TAG = NetworkStackClient.class.getSimpleName();
 
     private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
+    private static final String IN_PROCESS_SUFFIX = ".InProcess";
 
     private static NetworkStackClient sInstance;
 
@@ -175,42 +175,50 @@
     public void start(Context context) {
         log("Starting network stack");
         mNetworkStackStartRequested = true;
-        // Try to bind in-process if the library is available
-        IBinder connector = null;
-        try {
-            final Class service = Class.forName(
-                    "com.android.server.NetworkStackService",
-                    true /* initialize */,
-                    context.getClassLoader());
-            connector = (IBinder) service.getMethod("makeConnector", Context.class)
-                    .invoke(null, context);
-        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
-            logWtf("Could not create network stack connector from NetworkStackService", e);
-            // TODO: crash/reboot system here ?
-            return;
-        } catch (ClassNotFoundException e) {
-            // Normal behavior if stack is provided by the app: fall through
+
+        final PackageManager pm = context.getPackageManager();
+
+        // Try to bind in-process if the device was shipped with an in-process version
+        Intent intent = getNetworkStackIntent(pm, true /* inSystemProcess */);
+
+        // Otherwise use the updatable module version
+        if (intent == null) {
+            intent = getNetworkStackIntent(pm, false /* inSystemProcess */);
+            log("Starting network stack process");
+        } else {
+            log("Starting network stack in-process");
         }
 
-        // In-process network stack. Add the service to the service manager here.
-        if (connector != null) {
-            log("Registering in-process network stack connector");
-            registerNetworkStackService(connector);
-            return;
-        }
-        // Start the network stack process. The service will be added to the service manager in
-        // NetworkStackConnection.onServiceConnected().
-        log("Starting network stack process");
-        final Intent intent = new Intent(INetworkStackConnector.class.getName());
-        final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
-        intent.setComponent(comp);
-
-        if (comp == null) {
-            logWtf("Could not resolve the network stack with " + intent, null);
+        if (intent == null) {
+            logWtf("Could not resolve the network stack", null);
             // TODO: crash/reboot system server ?
             return;
         }
-        final PackageManager pm = context.getPackageManager();
+
+        // Start the network stack. The service will be added to the service manager in
+        // NetworkStackConnection.onServiceConnected().
+        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+            logWtf("Could not bind to network stack with " + intent, null);
+            return;
+            // TODO: crash/reboot system server if no network stack after a timeout ?
+        }
+
+        log("Network stack service start requested");
+    }
+
+    @Nullable
+    private Intent getNetworkStackIntent(@NonNull PackageManager pm, boolean inSystemProcess) {
+        final String baseAction = INetworkStackConnector.class.getName();
+        final Intent intent =
+                new Intent(inSystemProcess ? baseAction + IN_PROCESS_SUFFIX : baseAction);
+        final ComponentName comp = intent.resolveSystemService(pm, 0);
+
+        if (comp == null) {
+            return null;
+        }
+        intent.setComponent(comp);
+
         int uid = -1;
         try {
             uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
@@ -218,25 +226,27 @@
             logWtf("Network stack package not found", e);
             // Fall through
         }
-        if (uid != Process.NETWORK_STACK_UID) {
+
+        final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+        if (uid != expectedUid) {
             throw new SecurityException("Invalid network stack UID: " + uid);
         }
 
+        if (!inSystemProcess) {
+            checkNetworkStackPermission(pm, comp);
+        }
+
+        return intent;
+    }
+
+    private void checkNetworkStackPermission(
+            @NonNull PackageManager pm, @NonNull ComponentName comp) {
         final int hasPermission =
                 pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
         if (hasPermission != PERMISSION_GRANTED) {
             throw new SecurityException(
                     "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
         }
-
-        if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
-                Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
-            logWtf("Could not bind to network stack in-process, or in app with " + intent, null);
-            return;
-            // TODO: crash/reboot system server if no network stack after a timeout ?
-        }
-
-        log("Network stack service start requested");
     }
 
     private void log(@NonNull String message) {
@@ -289,7 +299,8 @@
     private void requestConnector(@NonNull NetworkStackCallback request) {
         // TODO: PID check.
         final int caller = Binder.getCallingUid();
-        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+        if (caller != Process.SYSTEM_UID && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
+                && !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
             // Don't even attempt to obtain the connector and give a nice error message
             throw new SecurityException(
                     "Only the system server should try to bind to the network stack.");
diff --git a/services/net/java/android/net/ip/IpServer.java b/services/net/java/android/net/ip/IpServer.java
index 34fc735..0e44f88 100644
--- a/services/net/java/android/net/ip/IpServer.java
+++ b/services/net/java/android/net/ip/IpServer.java
@@ -87,7 +87,6 @@
         return "UNKNOWN: " + state;
     }
 
-    private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
     private static final byte DOUG_ADAMS = (byte) 42;
 
     private static final String USB_NEAR_IFACE_ADDR = "192.168.42.129";
@@ -557,16 +556,6 @@
                 addedPrefixes.removeAll(mLastRaParams.prefixes);
             }
 
-            if (mLastRaParams == null || mLastRaParams.prefixes.isEmpty()) {
-                // We need to be able to send unicast RAs, and clients might
-                // like to ping the default router's link-local address.  Note
-                // that we never remove the link-local route from the network
-                // until Tethering disables tethering on the interface. We
-                // only need to add the link-local prefix once, but in the
-                // event we add it more than once netd silently ignores EEXIST.
-                addedPrefixes.add(LINK_LOCAL_PREFIX);
-            }
-
             if (!addedPrefixes.isEmpty()) {
                 final ArrayList<RouteInfo> toBeAdded =
                         getLocalRoutesFor(mIfaceName, addedPrefixes);
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index d148ea1..9097430 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -28,6 +28,7 @@
         "services.usage",
         "guava",
         "androidx.test.rules",
+        "hamcrest-library",
         "mockito-target-minus-junit4",
         "platform-test-annotations",
         "ShortcutManagerTestUtils",
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 84b2238..558d8d4 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1589,7 +1589,7 @@
                                 Build.VERSION_CODES.O_MR1) {
                     Log.e("TAG", "addNewIncomingCall failed. Use public api " +
                             "acceptHandover for API > O-MR1");
-                    // TODO add "return" after DUO team adds support for new handover API
+                    return;
                 }
                 getTelecomService().addNewIncomingCall(
                         phoneAccount, extras == null ? new Bundle() : extras);
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 4939157..983d134 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -4309,24 +4309,24 @@
         }
 
         /**
-         * Generates a content {@link Uri} used to receive updates on precise carrier identity
+         * Generates a content {@link Uri} used to receive updates on specific carrier identity
          * change on the given subscriptionId returned by
-         * {@link TelephonyManager#getSimPreciseCarrierId()}.
-         * @see TelephonyManager#ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED
+         * {@link TelephonyManager#getSimSpecificCarrierId()}.
+         * @see TelephonyManager#ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-         * precise carrier identity {@link TelephonyManager#getSimPreciseCarrierId()}
+         * specific carrier identity {@link TelephonyManager#getSimSpecificCarrierId()}
          * while your app is running. You can also use a {@link JobService} to ensure your app
          * is notified of changes to the {@link Uri} even when it is not running.
          * Note, however, that using a {@link JobService} does not guarantee timely delivery of
          * updates to the {@link Uri}.
          *
          * @param subscriptionId the subscriptionId to receive updates on
-         * @return the Uri used to observe precise carrier identity changes
+         * @return the Uri used to observe specific carrier identity changes
          */
         @NonNull
-        public static Uri getPreciseCarrierIdUriForSubscriptionId(int subscriptionId) {
-            return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "precise"),
+        public static Uri getSpecificCarrierIdUriForSubscriptionId(int subscriptionId) {
+            return Uri.withAppendedPath(Uri.withAppendedPath(CONTENT_URI, "specific"),
                     String.valueOf(subscriptionId));
         }
 
@@ -4346,26 +4346,30 @@
 
         /**
          * A fine-grained carrier id.
-         * @see TelephonyManager#getSimPreciseCarrierId()
+         * The specific carrier ID would be used for configuration purposes, but apps wishing to
+         * know about the carrier itself should use the regular carrier ID returned by
+         * {@link TelephonyManager#getSimCarrierId()}.
+         *
+         * @see TelephonyManager#getSimSpecificCarrierId()
          * This is not a database column, only used to notify content observers for
-         * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+         * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
          */
-        public static final String PRECISE_CARRIER_ID = "precise_carrier_id";
+        public static final String SPECIFIC_CARRIER_ID = "specific_carrier_id";
 
         /**
-         * A user facing carrier name for precise carrier id {@link #PRECISE_CARRIER_ID}.
-         * @see TelephonyManager#getSimPreciseCarrierIdName()
+         * A user facing carrier name for specific carrier id {@link #SPECIFIC_CARRIER_ID}.
+         * @see TelephonyManager#getSimSpecificCarrierIdName()
          * This is not a database column, only used to notify content observers for
-         * {@link #getPreciseCarrierIdUriForSubscriptionId(int)}
+         * {@link #getSpecificCarrierIdUriForSubscriptionId(int)}
          */
-        public static final String PRECISE_CARRIER_ID_NAME = "precise_carrier_id_name";
+        public static final String SPECIFIC_CARRIER_ID_NAME = "specific_carrier_id_name";
 
         /**
          * A unique parent carrier id. The parent-child
          * relationship can be used to further differentiate a single carrier by different networks,
-         * by prepaid v.s. postpaid or even by 4G v.s. 3G plan. It's an optional field.
-         * A carrier id with a valid parent_carrier_id is considered fine-grained carrier id, will
-         * not be returned as {@link #CARRIER_ID} but {@link #PRECISE_CARRIER_ID}.
+         * by prepaid v.s. postpaid. It's an optional field.
+         * A carrier id with a valid parent_carrier_id is considered fine-grained specific carrier
+         * ID, will not be returned as {@link #CARRIER_ID} but {@link #SPECIFIC_CARRIER_ID}.
          * <P>Type: INTEGER </P>
          * @hide
          */
diff --git a/telephony/java/android/telephony/DebugEventReporter.java b/telephony/java/android/telephony/AnomalyReporter.java
similarity index 82%
rename from telephony/java/android/telephony/DebugEventReporter.java
rename to telephony/java/android/telephony/AnomalyReporter.java
index 14b7dd6..9753d8b 100644
--- a/telephony/java/android/telephony/DebugEventReporter.java
+++ b/telephony/java/android/telephony/AnomalyReporter.java
@@ -29,7 +29,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.List;
-import java.util.List;
 import java.util.Map;
 import java.util.UUID;
 import java.util.concurrent.ConcurrentHashMap;
@@ -37,7 +36,7 @@
 /**
  * A Simple Surface for Telephony to notify a loosely-coupled debugger of particular issues.
  *
- * DebugEventReporter allows an optional external logging component to receive events detected by
+ * AnomalyReporter allows an optional external logging component to receive events detected by
  * the framework and take action. This log surface is designed to provide maximium flexibility
  * to the receiver of these events. Envisioned use cases of this include notifying a vendor
  * component of: an event that necessitates (timely) log collection on non-AOSP components;
@@ -49,8 +48,8 @@
  *
  * @hide
  */
-public final class DebugEventReporter {
-    private static final String TAG = "DebugEventReporter";
+public final class AnomalyReporter {
+    private static final String TAG = "AnomalyReporter";
 
     private static Context sContext = null;
 
@@ -63,12 +62,12 @@
      */
     private static String sDebugPackageName = null;
 
-    private DebugEventReporter() {};
+    private AnomalyReporter() {};
 
     /**
      * If enabled, build and send an intent to a Debug Service for logging.
      *
-     * This method sends the {@link TelephonyManager#DEBUG_EVENT DEBUG_EVENT} broadcast, which is
+     * This method sends the {@link TelephonyManager#ACTION_ANOMALY_REPORTED} broadcast, which is
      * system protected. Invoking this method unless you are the system will result in an error.
      *
      * @param eventId a fixed event ID that will be sent for each instance of the same event. This
@@ -77,9 +76,9 @@
      *        identification and discussion of this event. This description should ideally be
      *        static and must not contain any sensitive information (especially PII).
      */
-    public static void sendEvent(@NonNull UUID eventId, String description) {
+    public static void reportAnomaly(@NonNull UUID eventId, String description) {
         if (sContext == null) {
-            Rlog.w(TAG, "DebugEventReporter not yet initialized, dropping event=" + eventId);
+            Rlog.w(TAG, "AnomalyReporter not yet initialized, dropping event=" + eventId);
             return;
         }
 
@@ -94,28 +93,28 @@
         // so drop these events silently.
         if (sDebugPackageName == null) return;
 
-        Intent dbgIntent = new Intent(TelephonyManager.ACTION_DEBUG_EVENT);
-        dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_ID, new ParcelUuid(eventId));
+        Intent dbgIntent = new Intent(TelephonyManager.ACTION_ANOMALY_REPORTED);
+        dbgIntent.putExtra(TelephonyManager.EXTRA_ANOMALY_ID, new ParcelUuid(eventId));
         if (description != null) {
-            dbgIntent.putExtra(TelephonyManager.EXTRA_DEBUG_EVENT_DESCRIPTION, description);
+            dbgIntent.putExtra(TelephonyManager.EXTRA_ANOMALY_DESCRIPTION, description);
         }
         dbgIntent.setPackage(sDebugPackageName);
         sContext.sendBroadcast(dbgIntent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
     }
 
     /**
-     * Initialize the DebugEventReporter with the current context.
+     * Initialize the AnomalyReporter with the current context.
      *
-     * This method must be invoked before any calls to sendEvent() will succeed. This method should
-     * only be invoked at most once.
+     * This method must be invoked before any calls to reportAnomaly() will succeed. This method
+     * should only be invoked at most once.
      *
-     * @param context a Context object used to initialize this singleton DebugEventReporter in
+     * @param context a Context object used to initialize this singleton AnomalyReporter in
      *        the current process.
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public static void initialize(@NonNull Context context) {
         if (context == null) {
-            throw new IllegalArgumentException("DebugEventReporter needs a non-null context.");
+            throw new IllegalArgumentException("AnomalyReporter needs a non-null context.");
         }
 
         // Ensure that this context has sufficient permissions to send debug events.
@@ -129,13 +128,13 @@
         PackageManager pm = sContext.getPackageManager();
         if (pm == null) return;
         List<ResolveInfo> packages = pm.queryBroadcastReceivers(
-                new Intent(TelephonyManager.ACTION_DEBUG_EVENT),
+                new Intent(TelephonyManager.ACTION_ANOMALY_REPORTED),
                 PackageManager.MATCH_SYSTEM_ONLY
                         | PackageManager.MATCH_DIRECT_BOOT_AWARE
                         | PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
         if (packages == null || packages.isEmpty()) return;
         if (packages.size() > 1) {
-            Rlog.e(TAG, "Multiple DebugEvent Receivers installed.");
+            Rlog.e(TAG, "Multiple Anomaly Receivers installed.");
         }
 
         for (ResolveInfo r : packages) {
@@ -156,14 +155,14 @@
         // Initialization may only be performed once.
     }
 
-    /** Dump the contents of the DebugEventReporter */
+    /** Dump the contents of the AnomalyReporter */
     public static void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
         if (sContext == null) return;
         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
         sContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP");
         pw.println("Initialized=" + (sContext != null ? "Yes" : "No"));
         pw.println("Debug Package=" + sDebugPackageName);
-        pw.println("Event Counts:");
+        pw.println("Anomaly Counts:");
         pw.increaseIndent();
         for (UUID event : sEvents.keySet()) {
             pw.println(event + ": " + sEvents.get(event));
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
old mode 100644
new mode 100755
index ee69dad..3454c1c
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -31,6 +31,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.service.carrier.CarrierService;
+import android.telecom.TelecomManager;
 import android.telephony.ims.ImsReasonInfo;
 
 import com.android.internal.telephony.ICarrierConfigLoader;
@@ -71,10 +72,10 @@
      * one is available for the slot index. An optional int extra
      * {@link TelephonyManager#EXTRA_CARRIER_ID} is included to indicate the carrier id for the
      * changed carrier configuration. An optional int extra
-     * {@link TelephonyManager#EXTRA_PRECISE_CARRIER_ID} is included to indicate the precise
+     * {@link TelephonyManager#EXTRA_SPECIFIC_CARRIER_ID} is included to indicate the precise
      * carrier id for the changed carrier configuration.
      * @see TelephonyManager#getSimCarrierId()
-     * @see TelephonyManager#getSimPreciseCarrierId()
+     * @see TelephonyManager#getSimSpecificCarrierId()
      */
     public static final String
             ACTION_CARRIER_CONFIG_CHANGED = "android.telephony.action.CARRIER_CONFIG_CHANGED";
@@ -1812,17 +1813,32 @@
 
     /**
      * Determine whether user can change Wi-Fi Calling preference in roaming.
-     * {@code false} - roaming preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT} is
-     *                 the same as home preference {@link KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT}
-     *                 and cannot be changed.
-     * {@code true}  - roaming preference can be changed by user independently.
-     *
+     * {@code false} - roaming preference cannot be changed by user independently. If
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false,
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_ROAMING_MODE_INT} is used as the default
+     *                 value. If {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is
+     *                 true, roaming preference is the same as home preference and
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
+     * {@code true}  - roaming preference can be changed by user independently if
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is false. If
+     *                 {@link #KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL} is true, this
+     *                 configuration is ignored and roaming preference cannot be changed.
      * @hide
      */
     public static final String KEY_EDITABLE_WFC_ROAMING_MODE_BOOL =
             "editable_wfc_roaming_mode_bool";
 
     /**
+     * Flag specifying whether the carrier will use the WFC home network mode in roaming network.
+     * {@code false} - roaming preference can be selected separately from the home preference.
+     * {@code true}  - roaming preference is the same as home preference and
+     *                 {@link #KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT} is used as the default value.
+     * @hide
+     */
+    public static final String KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL =
+            "use_wfc_home_network_mode_in_roaming_network_bool";
+
+    /**
      * Determine whether current lpp_mode used for E-911 needs to be kept persistently.
      * {@code false} - not keeping the lpp_mode means using default configuration of gps.conf
      *                 when sim is not presented.
@@ -2110,6 +2126,18 @@
     public static final String KEY_RTT_SUPPORTED_BOOL = "rtt_supported_bool";
 
     /**
+     * Boolean flag indicating whether the carrier supports TTY.
+     * <p>
+     * Note that {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} controls availability of TTY over
+     * VoLTE; if {@link #KEY_TTY_SUPPORTED_BOOL} is disabled, then
+     * {@link #KEY_CARRIER_VOLTE_TTY_SUPPORTED_BOOL} is also implicitly disabled.
+     * <p>
+     * {@link TelecomManager#isTtySupported()} should be used to determine if a device supports TTY,
+     * and this carrier config key should be used to see if the current carrier supports it.
+     */
+    public static final String KEY_TTY_SUPPORTED_BOOL = "tty_supported_bool";
+
+    /**
      * Indicates if the carrier supports auto-upgrading a call to RTT when receiving a call from a
      * RTT-supported device.
      * @hide
@@ -2426,6 +2454,17 @@
      */
     public static final String KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG =
             "opportunistic_network_data_switch_hysteresis_time_long";
+    /**
+     * Determines whether the carrier wants to cancel the cs reject notification automatically
+     * when the voice registration state changes.
+     * If true, the notification will be automatically removed
+     *          when the voice registration state changes.
+     * If false, the notification will persist until the user dismisses it,
+     *           the SIM is removed, or the device is rebooted.
+     * @hide
+     */
+    public static final String KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION =
+            "carrier_auto_cancel_cs_notification";
 
    /**
     * An int array containing CDMA enhanced roaming indicator values for Home (non-roaming) network.
@@ -2759,6 +2798,7 @@
         sDefaults.putBoolean(KEY_NOTIFY_VT_HANDOVER_TO_WIFI_FAILURE_BOOL, false);
         sDefaults.putStringArray(KEY_FILTERED_CNAP_NAMES_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
+        sDefaults.putBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL, false);
         sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
         sDefaults.putBoolean(KEY_PERSIST_LPP_MODE_BOOL, true);
         sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
@@ -2785,6 +2825,7 @@
         sDefaults.putStringArray(KEY_ROAMING_OPERATOR_STRING_ARRAY, null);
         sDefaults.putBoolean(KEY_SHOW_IMS_REGISTRATION_STATUS_BOOL, false);
         sDefaults.putBoolean(KEY_RTT_SUPPORTED_BOOL, false);
+        sDefaults.putBoolean(KEY_TTY_SUPPORTED_BOOL, true);
         sDefaults.putBoolean(KEY_DISABLE_CHARGE_INDICATION_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true);
         sDefaults.putStringArray(KEY_FEATURE_ACCESS_CODES_STRING_ARRAY, null);
@@ -2845,6 +2886,7 @@
                 });
         sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
                 "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
+        sDefaults.putBoolean(KEY_AUTO_CANCEL_CS_REJECT_NOTIFICATION, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index 7655834..bda8812 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -86,7 +86,7 @@
         }
 
         if ((mMccStr != null && mMncStr == null) || (mMccStr == null && mMncStr != null)) {
-            DebugEventReporter.sendEvent(
+            AnomalyReporter.reportAnomaly(
                     UUID.fromString("a3ab0b9d-f2aa-4baf-911d-7096c0d4645a"),
                     "CellIdentity Missing Half of PLMN ID");
         }
diff --git a/telephony/java/android/telephony/CellInfo.java b/telephony/java/android/telephony/CellInfo.java
index c7853f1..cdaf6ed 100644
--- a/telephony/java/android/telephony/CellInfo.java
+++ b/telephony/java/android/telephony/CellInfo.java
@@ -22,7 +22,6 @@
 import android.hardware.radio.V1_4.CellInfo.Info;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -325,9 +324,9 @@
     }
 
     /** @hide */
-    protected CellInfo(android.hardware.radio.V1_4.CellInfo ci) {
+    protected CellInfo(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
         this.mRegistered = ci.isRegistered;
-        this.mTimeStamp = SystemClock.elapsedRealtimeNanos();
+        this.mTimeStamp = timeStamp;
         this.mCellConnectionStatus = ci.connectionStatus;
     }
 
@@ -358,14 +357,14 @@
     }
 
     /** @hide */
-    public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci) {
+    public static CellInfo create(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
         if (ci == null) return null;
         switch (ci.info.getDiscriminator()) {
-            case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci);
-            case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci);
-            case Info.hidl_discriminator.lte: return new CellInfoLte(ci);
-            case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci);
-            case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci);
+            case Info.hidl_discriminator.gsm: return new CellInfoGsm(ci, timeStamp);
+            case Info.hidl_discriminator.cdma: return new CellInfoCdma(ci, timeStamp);
+            case Info.hidl_discriminator.lte: return new CellInfoLte(ci, timeStamp);
+            case Info.hidl_discriminator.wcdma: return new CellInfoWcdma(ci, timeStamp);
+            case Info.hidl_discriminator.tdscdma: return new CellInfoTdscdma(ci, timeStamp);
             default: return null;
         }
     }
diff --git a/telephony/java/android/telephony/CellInfoCdma.java b/telephony/java/android/telephony/CellInfoCdma.java
index 4440108..359c8be 100644
--- a/telephony/java/android/telephony/CellInfoCdma.java
+++ b/telephony/java/android/telephony/CellInfoCdma.java
@@ -68,8 +68,8 @@
     }
 
     /** @hide */
-    public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoCdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoCdma cic = ci.info.cdma();
         mCellIdentityCdma = new CellIdentityCdma(cic.cellIdentityCdma);
         mCellSignalStrengthCdma =
diff --git a/telephony/java/android/telephony/CellInfoGsm.java b/telephony/java/android/telephony/CellInfoGsm.java
index 248adfc..dc2779f 100644
--- a/telephony/java/android/telephony/CellInfoGsm.java
+++ b/telephony/java/android/telephony/CellInfoGsm.java
@@ -64,8 +64,8 @@
     }
 
     /** @hide */
-    public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoGsm(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoGsm cig = ci.info.gsm();
         mCellIdentityGsm = new CellIdentityGsm(cig.cellIdentityGsm);
         mCellSignalStrengthGsm = new CellSignalStrengthGsm(cig.signalStrengthGsm);
diff --git a/telephony/java/android/telephony/CellInfoLte.java b/telephony/java/android/telephony/CellInfoLte.java
index 8e8ce8a..0e9623d 100644
--- a/telephony/java/android/telephony/CellInfoLte.java
+++ b/telephony/java/android/telephony/CellInfoLte.java
@@ -71,8 +71,8 @@
     }
 
     /** @hide */
-    public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoLte(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_4.CellInfoLte cil = ci.info.lte();
         mCellIdentityLte = new CellIdentityLte(cil.base.cellIdentityLte);
         mCellSignalStrengthLte = new CellSignalStrengthLte(cil.base.signalStrengthLte);
diff --git a/telephony/java/android/telephony/CellInfoTdscdma.java b/telephony/java/android/telephony/CellInfoTdscdma.java
index 2ab38fb..cb45e95 100644
--- a/telephony/java/android/telephony/CellInfoTdscdma.java
+++ b/telephony/java/android/telephony/CellInfoTdscdma.java
@@ -65,8 +65,8 @@
     }
 
     /** @hide */
-    public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoTdscdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoTdscdma cit = ci.info.tdscdma();
         mCellIdentityTdscdma = new CellIdentityTdscdma(cit.cellIdentityTdscdma);
         mCellSignalStrengthTdscdma = new CellSignalStrengthTdscdma(cit.signalStrengthTdscdma);
diff --git a/telephony/java/android/telephony/CellInfoWcdma.java b/telephony/java/android/telephony/CellInfoWcdma.java
index 65e0470..fe06c78 100644
--- a/telephony/java/android/telephony/CellInfoWcdma.java
+++ b/telephony/java/android/telephony/CellInfoWcdma.java
@@ -64,8 +64,8 @@
     }
 
     /** @hide */
-    public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci) {
-        super(ci);
+    public CellInfoWcdma(android.hardware.radio.V1_4.CellInfo ci, long timeStamp) {
+        super(ci, timeStamp);
         final android.hardware.radio.V1_2.CellInfoWcdma ciw = ci.info.wcdma();
         mCellIdentityWcdma = new CellIdentityWcdma(ciw.cellIdentityWcdma);
         mCellSignalStrengthWcdma = new CellSignalStrengthWcdma(ciw.signalStrengthWcdma);
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index a4207c9..e0f1690 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -151,6 +151,17 @@
     }
 
     /**
+     * Return the Received Signal Strength Indicator
+     *
+     * @return the RSSI in dBm (-113, -51) or
+     *         {@link android.telephony.CellInfo#UNAVAILABLE UNAVAILABLE}.
+     * @hide
+     */
+    public int getRssi() {
+        return mRssi;
+    }
+
+    /**
      * Return the Bit Error Rate
      *
      * @return the bit error rate (0-7, 99) as defined in TS 27.007 8.5 or
diff --git a/telephony/java/android/telephony/MbmsGroupCallSession.java b/telephony/java/android/telephony/MbmsGroupCallSession.java
index 269cda1..f1be31f 100644
--- a/telephony/java/android/telephony/MbmsGroupCallSession.java
+++ b/telephony/java/android/telephony/MbmsGroupCallSession.java
@@ -141,7 +141,7 @@
      * Create a new {@link MbmsGroupCallSession} using the system default data subscription ID.
      * See {@link #create(Context, int, Executor, MbmsGroupCallSessionCallback)}.
      */
-    public static MbmsGroupCallSession create(@NonNull Context context,
+    public static @Nullable MbmsGroupCallSession create(@NonNull Context context,
             @NonNull Executor executor, @NonNull MbmsGroupCallSessionCallback callback) {
         return create(context, SubscriptionManager.getDefaultSubscriptionId(), executor, callback);
     }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 24319a2..918bf60 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -292,14 +292,16 @@
     public static final int LISTEN_PHONE_CAPABILITY_CHANGE                 = 0x00200000;
 
     /**
-     *  Listen for changes to preferred data subId.
-     *  See {@link SubscriptionManager#setPreferredDataSubId(int)}
-     *  for more details.
+     *  Listen for changes to active data subId. Active data subscription is
+     *  the current subscription used to setup Cellular Internet data. For example,
+     *  it could be the current active opportunistic subscription in use, or the
+     *  subscription user selected as default data subscription in DSDS mode.
      *
-     *  @see #onPreferredDataSubIdChanged
-     *  @hide
+     *  Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
+     *  READ_PHONE_STATE}
+     *  @see #onActiveDataSubscriptionIdChanged
      */
-    public static final int LISTEN_PREFERRED_DATA_SUBID_CHANGE              = 0x00400000;
+    public static final int LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE = 0x00400000;
 
     /**
      *  Listen for changes to the radio power state.
@@ -704,14 +706,13 @@
     }
 
     /**
-     * Callback invoked when preferred data subId changes. Requires
-     * the READ_PRIVILEGED_PHONE_STATE permission.
-     * @param subId the new preferred data subId. If it's INVALID_SUBSCRIPTION_ID,
-     *              it means it's unset and defaultDataSub is used to determine which
-     *              modem is preferred.
-     * @hide
+     * Callback invoked when active data subId changes. Requires
+     * the READ_PHONE_STATE permission.
+     * @param subId current subscription used to setup Cellular Internet data.
+     *              For example, it could be the current active opportunistic subscription in use,
+     *              or the subscription user selected as default data subscription in DSDS mode.
      */
-    public void onPreferredDataSubIdChanged(int subId) {
+    public void onActiveDataSubscriptionIdChanged(int subId) {
         // default implementation empty
     }
 
@@ -995,12 +996,12 @@
                     () -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes)));
         }
 
-        public void onPreferredDataSubIdChanged(int subId) {
+        public void onActiveDataSubIdChanged(int subId) {
             PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
             if (psl == null) return;
 
             Binder.withCleanCallingIdentity(
-                    () -> mExecutor.execute(() -> psl.onPreferredDataSubIdChanged(subId)));
+                    () -> mExecutor.execute(() -> psl.onActiveDataSubscriptionIdChanged(subId)));
         }
 
         public void onImsCallDisconnectCauseChanged(ImsReasonInfo disconnectCause) {
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index d777bf1..c39f1f5 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -316,6 +316,7 @@
      *  <code>RESULT_ERROR_GENERIC_FAILURE</code><br>
      *  <code>RESULT_ERROR_RADIO_OFF</code><br>
      *  <code>RESULT_ERROR_NULL_PDU</code><br>
+     *  <code>RESULT_ERROR_NO_SERVICE</code><br>
      *  For <code>RESULT_ERROR_GENERIC_FAILURE</code> the sentIntent may include
      *  the extra "errorCode" containing a radio technology specific value,
      *  generally only useful for troubleshooting.<br>
@@ -365,19 +366,12 @@
         if (DBG) {
             Log.d(TAG, "for subId: " + subId + ", subscription-info: " + info);
         }
-        if (info == null) {
-            // There is no subscription for the given subId. That can only mean one thing:
-            // the caller is using a SmsManager instance with an obsolete subscription id.
-            // That is most probably because caller didn't invalidate SmsManager instance
-            // for an already deleted subscription id.
-            Log.e(TAG, "subId: " + subId + " for this SmsManager instance is obsolete.");
-            sendErrorInPendingIntent(sentIntent, SmsManager.RESULT_ERROR_NO_SERVICE);
-        }
 
         /* If the Subscription associated with this SmsManager instance belongs to a remote-sim,
          * then send the message thru the remote-sim subscription.
          */
-        if (info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
+        if (info != null
+                && info.getSubscriptionType() == SubscriptionManager.SUBSCRIPTION_TYPE_REMOTE_SIM) {
             if (DBG) Log.d(TAG, "sending message thru bluetooth");
             sendTextMessageBluetooth(destinationAddress, scAddress, text, sentIntent,
                     deliveryIntent, info);
@@ -385,8 +379,10 @@
         }
 
         try {
+            // If the subscription is invalid or default, we will use the default phone to send the
+            // SMS and possibly fail later in the SMS sending process.
             ISms iccISms = getISmsServiceOrThrow();
-            iccISms.sendTextForSubscriber(getSubscriptionId(), ActivityThread.currentPackageName(),
+            iccISms.sendTextForSubscriber(subId, ActivityThread.currentPackageName(),
                     destinationAddress,
                     scAddress, text, sentIntent, deliveryIntent,
                     persistMessage);
@@ -459,6 +455,9 @@
     }
 
     private void sendErrorInPendingIntent(PendingIntent intent, int errorCode) {
+        if (intent == null) {
+            return;
+        }
         try {
             intent.send(errorCode);
         } catch (PendingIntent.CanceledException e) {
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 443f908..58f12e2 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -425,14 +425,14 @@
     /**
      * @return The MCC, as a string.
      */
-    public String getMccString() {
+    public @Nullable String getMccString() {
         return this.mMcc;
     }
 
     /**
      * @return The MNC, as a string.
      */
-    public String getMncString() {
+    public @Nullable String getMncString() {
         return this.mMnc;
     }
 
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 635e4fe..1662d6e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -59,6 +59,7 @@
 import android.util.Log;
 
 import com.android.internal.telephony.IOnSubscriptionsChangedListener;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
 import com.android.internal.telephony.ISub;
 import com.android.internal.telephony.ITelephonyRegistry;
 import com.android.internal.telephony.PhoneConstants;
@@ -68,10 +69,13 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -1241,7 +1245,7 @@
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
-        return getActiveSubscriptionInfoList(false);
+        return getActiveSubscriptionInfoList(/* userVisibleonly */true);
     }
 
     /**
@@ -2086,7 +2090,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subId = iSub.getActiveSubIdList();
+                subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -2583,17 +2587,35 @@
      *              {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means
      *              it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *              is used to determine which modem is preferred.
+     * @param needValidation whether validation is needed before switch happens.
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
+     *                 See {@link TelephonyManager.SetOpportunisticSubscriptionResult}
+     *                 for more details. Pass null if don't care about the result.
+     *
      * @hide
      *
      */
+    @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
-    public void setPreferredDataSubscriptionId(int subId) {
+    public void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+            @NonNull @CallbackExecutor Executor executor, Consumer<Integer> callback) {
         if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId);
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
-            if (iSub != null) {
-                iSub.setPreferredDataSubscriptionId(subId);
-            }
+            if (iSub == null) return;
+
+            ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() {
+                @Override
+                public void onComplete(int result) {
+                    Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                        if (callback != null) {
+                            callback.accept(result);
+                        }
+                    }));
+                }
+            };
+            iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub);
         } catch (RemoteException ex) {
             // ignore it
         }
@@ -2681,7 +2703,8 @@
      *  1) Even if it's active, it will be dormant most of the time. The modem will not try
      *     to scan or camp until it knows an available network is nearby to save power.
      *  2) Telephony relies on system app or carrier input to notify nearby available networks.
-     *     See {@link TelephonyManager#updateAvailableNetworks(List)} for more information.
+     *     See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)}
+     *     for more information.
      *  3) In multi-SIM devices, when the network is nearby and camped, system may automatically
      *     switch internet data between it and default data subscription, based on carrier
      *     recommendation and its signal strength and metered-ness, etc.
@@ -2845,15 +2868,30 @@
     /**
      * Whether system UI should hide a subscription. If it's a bundled opportunistic
      * subscription, it shouldn't show up in anywhere in Settings app, dialer app,
-     * or status bar.
+     * or status bar. Exception is if caller is carrier app, in which case they will
+     * want to see their own hidden subscriptions.
      *
      * @param info the subscriptionInfo to check against.
      * @return true if this subscription should be hidden.
      *
      * @hide
      */
-    public static boolean shouldHideSubscription(SubscriptionInfo info) {
-        return (info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic());
+    public boolean shouldHideSubscription(SubscriptionInfo info) {
+        if (info == null) return false;
+
+        // If hasCarrierPrivileges or canManageSubscription returns true, it means caller
+        // has carrier privilege.
+        boolean hasCarrierPrivilegePermission = (info.isEmbedded() && canManageSubscription(info))
+                || TelephonyManager.from(mContext).hasCarrierPrivileges(info.getSubscriptionId());
+
+        return isInvisibleSubscription(info) && !hasCarrierPrivilegePermission;
+    }
+
+    /**
+     * @hide
+     */
+    public static boolean isInvisibleSubscription(SubscriptionInfo info) {
+        return info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic();
     }
 
     /**
@@ -2872,8 +2910,33 @@
         if (availableList == null) {
             return null;
         } else {
-            return availableList.stream().filter(subInfo -> !shouldHideSubscription(subInfo))
-                    .collect(Collectors.toList());
+            // Multiple subscriptions in a group should only have one representative.
+            // It should be the current active primary subscription if any, or any
+            // primary subscription.
+            List<SubscriptionInfo> selectableList = new ArrayList<>();
+            Map<String, SubscriptionInfo> groupMap = new HashMap<>();
+
+            for (SubscriptionInfo info : availableList) {
+                // Opportunistic subscriptions are considered invisible
+                // to users so they should never be returned.
+                if (isInvisibleSubscription(info)) continue;
+
+                String groupUuid = info.getGroupUuid();
+                if (groupUuid == null) {
+                    // Doesn't belong to any group. Add in the list.
+                    selectableList.add(info);
+                } else if (!groupMap.containsKey(groupUuid)
+                        || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX
+                        && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) {
+                    // If it belongs to a group that has never been recorded or it's the current
+                    // active subscription, add it in the list.
+                    selectableList.remove(groupMap.get(groupUuid));
+                    selectableList.add(info);
+                    groupMap.put(groupUuid, info);
+                }
+
+            }
+            return selectableList;
         }
     }
 
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 3db7218..3e7b7e1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -83,6 +83,7 @@
 import com.android.internal.telephony.IPhoneSubInfo;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.ITelephonyRegistry;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 import com.android.internal.telephony.OperatorInfo;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.RILConstants;
@@ -98,6 +99,7 @@
 import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -1246,30 +1248,34 @@
     public static final String EXTRA_CARRIER_NAME = "android.telephony.extra.CARRIER_NAME";
 
     /**
-     * Broadcast Action: The subscription precise carrier identity has changed.
-     * The precise carrier id can be used to further differentiate a carrier by different
-     * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
-     * carrier id returned by {@link #getSimCarrierId()} but could have multiple precise carrier id.
-     * e.g, {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM,
-     * while {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based
-     * on the current subscription IMSI. For carriers without any fine-grained ids, precise carrier
-     * id is same as carrier id.
+     * Broadcast Action: The subscription specific carrier identity has changed.
+     *
+     * A specific carrier ID returns the fine-grained carrier ID of the current subscription.
+     * It can represent the fact that a carrier may be in effect an aggregation of other carriers
+     * (ie in an MVNO type scenario) where each of these specific carriers which are used to make
+     * up the actual carrier service may have different carrier configurations.
+     * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+     * different carrier configuration for different service offering such as a prepaid plan.
+     *
+     * the specific carrier ID would be used for configuration purposes, but apps wishing to know
+     * about the carrier itself should use the regular carrier ID returned by
+     * {@link #getSimCarrierId()}.
      *
      * <p>Similar like {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED}, this intent will be
      * sent on the event of {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} while its also
      * possible to be sent without {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} when
-     * precise carrier id changes with the same carrier id.
+     * specific carrier ID changes while carrier ID remains the same.
      * e.g, the same subscription switches to different IMSI could potentially change its
-     * precise carrier id while carrier id remains the same.
-     * @see #getSimPreciseCarrierId()
+     * specific carrier ID while carrier id remains the same.
+     * @see #getSimSpecificCarrierId()
      * @see #getSimCarrierId()
      *
      * The intent will have the following extra values:
      * <ul>
-     *   <li>{@link #EXTRA_PRECISE_CARRIER_ID} The up-to-date precise carrier id of the
+     *   <li>{@link #EXTRA_SPECIFIC_CARRIER_ID} The up-to-date specific carrier id of the
      *   current subscription.
      *   </li>
-     *   <li>{@link #EXTRA_PRECISE_CARRIER_NAME} The up-to-date name of the precise carrier id.
+     *   <li>{@link #EXTRA_SPECIFIC_CARRIER_NAME} The up-to-date name of the specific carrier id.
      *   </li>
      *   <li>{@link #EXTRA_SUBSCRIPTION_ID} The subscription id associated with the changed carrier
      *   identity.
@@ -1278,30 +1284,30 @@
      * <p class="note">This is a protected intent that can only be sent by the system.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED =
-            "android.telephony.action.SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED";
+    public static final String ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED =
+            "android.telephony.action.SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED";
 
     /**
-     * An int extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
-     * indicates the updated precise carrier id returned by
-     * {@link TelephonyManager#getSimPreciseCarrierId()}. Note, its possible precise carrier id
+     * An int extra used with {@link #ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED} which
+     * indicates the updated specific carrier id returned by
+     * {@link TelephonyManager#getSimSpecificCarrierId()}. Note, its possible specific carrier id
      * changes while {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} remains the same
      * e.g, when subscription switch to different IMSIs.
      * <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
      * the carrier cannot be identified.
      */
-    public static final String EXTRA_PRECISE_CARRIER_ID =
-            "android.telephony.extra.PRECISE_CARRIER_ID";
+    public static final String EXTRA_SPECIFIC_CARRIER_ID =
+            "android.telephony.extra.SPECIFIC_CARRIER_ID";
 
     /**
-     * An string extra used with {@link #ACTION_SUBSCRIPTION_PRECISE_CARRIER_IDENTITY_CHANGED} which
-     * indicates the updated precise carrier name returned by
-     * {@link TelephonyManager#getSimPreciseCarrierIdName()}.
-     * <p>it's a user-facing name of the precise carrier id {@link #EXTRA_PRECISE_CARRIER_ID}, e.g,
-     * Tracfone-AT&T.
+     * An string extra used with {@link #ACTION_SUBSCRIPTION_SPECIFIC_CARRIER_IDENTITY_CHANGED}
+     * which indicates the updated specific carrier name returned by
+     * {@link TelephonyManager#getSimSpecificCarrierIdName()}.
+     * <p>it's a user-facing name of the specific carrier id {@link #EXTRA_SPECIFIC_CARRIER_ID}
+     * e.g, Tracfone-AT&T
      */
-    public static final String EXTRA_PRECISE_CARRIER_NAME =
-            "android.telephony.extra.PRECISE_CARRIER_NAME";
+    public static final String EXTRA_SPECIFIC_CARRIER_NAME =
+            "android.telephony.extra.SPECIFIC_CARRIER_NAME";
 
     /**
      * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} to indicate the
@@ -1364,41 +1370,42 @@
      * in the application manifest. For performance reasons, if no application to receive these
      * events is detected at boot, then these events will not be sent.
      *
-     * <p>Each event will include an {@link EXTRA_DEBUG_EVENT_ID} that will uniquely identify the
+     * <p>Each event will include an {@link EXTRA_ANOMALY_ID} that will uniquely identify the
      * event that has occurred. Each event will be sent to the diagnostic monitor only once per
      * boot cycle (as another optimization).
      *
-     * @see #EXTRA_DEBUG_EVENT_ID
-     * @see #EXTRA_DEBUG_EVENT_DESCRIPTION
+     * @see #EXTRA_ANOMALY_ID
+     * @see #EXTRA_ANOMALY_DESCRIPTION
      * @hide
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public static final String ACTION_DEBUG_EVENT = "android.telephony.action.DEBUG_EVENT";
+    public static final String ACTION_ANOMALY_REPORTED =
+            "android.telephony.action.ANOMALY_REPORTED";
 
     /**
      * An arbitrary ParcelUuid which should be consistent for each occurrence of a DebugEvent.
      *
-     * This field must be included in all {@link ACTION_DEBUG_EVENT} events.
+     * This field must be included in all {@link ACTION_ANOMALY_REPORTED} events.
      *
-     * @see #ACTION_DEBUG_EVENT
+     * @see #ACTION_ANOMALY_REPORTED
      * @hide
      */
     @SystemApi
-    public static final String EXTRA_DEBUG_EVENT_ID = "android.telephony.extra.DEBUG_EVENT_ID";
+    public static final String EXTRA_ANOMALY_ID = "android.telephony.extra.ANOMALY_ID";
 
     /**
-     * A freeform string description of the DebugEvent.
+     * A freeform string description of the Anomaly.
      *
-     * This field is optional for all {@link ACTION_DEBUG_EVENT}s, as a guideline should not
+     * This field is optional for all {@link ACTION_ANOMALY_REPORTED}s, as a guideline should not
      * exceed 80 characters, and should be as short as possible to convey the essence of the event.
      *
-     * @see #ACTION_DEBUG_EVENT
+     * @see #ACTION_ANOMALY_REPORTED
      * @hide
      */
     @SystemApi
-    public static final String EXTRA_DEBUG_EVENT_DESCRIPTION =
-            "android.telephony.extra.DEBUG_EVENT_DESCRIPTION";
+    public static final String EXTRA_ANOMALY_DESCRIPTION =
+            "android.telephony.extra.ANOMALY_DESCRIPTION";
 
     //
     //
@@ -8913,17 +8920,23 @@
     }
 
     /**
-     * Returns fine-grained carrier id of the current subscription.
+     * Returns fine-grained carrier ID of the current subscription.
      *
-     * <p>The precise carrier id can be used to further differentiate a carrier by different
-     * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
-     * carrier id returned by {@link #getSimCarrierId()} but could have multiple precise carrier id.
-     * e.g, {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM,
-     * while {@link #getSimPreciseCarrierId()} can return Tracfone AT&T or Tracfone T-Mobile based
-     * on the current subscription IMSI.
+     * A specific carrier ID can represent the fact that a carrier may be in effect an aggregation
+     * of other carriers (ie in an MVNO type scenario) where each of these specific carriers which
+     * are used to make up the actual carrier service may have different carrier configurations.
+     * A specific carrier ID could also be used, for example, in a scenario where a carrier requires
+     * different carrier configuration for different service offering such as a prepaid plan.
      *
-     * <p>For carriers without any fine-grained carrier ids, return {@link #getSimCarrierId()}
-     * <p>Precise carrier ids are defined in the same way as carrier id
+     * the specific carrier ID would be used for configuration purposes, but apps wishing to know
+     * about the carrier itself should use the regular carrier ID returned by
+     * {@link #getSimCarrierId()}.
+     *
+     * e.g, Tracfone SIMs could return different specific carrier ID based on IMSI from current
+     * subscription while carrier ID remains the same.
+     *
+     * <p>For carriers without fine-grained specific carrier ids, return {@link #getSimCarrierId()}
+     * <p>Specific carrier ids are defined in the same way as carrier id
      * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
      * except each with a "parent" id linking to its top-level carrier id.
      *
@@ -8931,11 +8944,11 @@
      * Return {@link #UNKNOWN_CARRIER_ID} if the subscription is unavailable or the carrier cannot
      * be identified.
      */
-    public int getSimPreciseCarrierId() {
+    public int getSimSpecificCarrierId() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.getSubscriptionPreciseCarrierId(getSubId());
+                return service.getSubscriptionSpecificCarrierId(getSubId());
             }
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
@@ -8945,18 +8958,22 @@
 
     /**
      * Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
-     * precise carrier id returned by {@link #getSimPreciseCarrierId()}.
+     * specific carrier id returned by {@link #getSimSpecificCarrierId()}.
+     *
+     * The specific carrier ID would be used for configuration purposes, but apps wishing to know
+     * about the carrier itself should use the regular carrier ID returned by
+     * {@link #getSimCarrierIdName()}.
      *
      * <p>The returned name is unlocalized.
      *
-     * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+     * @return user-facing name of the subscription specific carrier id. Return {@code null} if the
      * subscription is unavailable or the carrier cannot be identified.
      */
-    public @Nullable CharSequence getSimPreciseCarrierIdName() {
+    public @Nullable CharSequence getSimSpecificCarrierIdName() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.getSubscriptionPreciseCarrierName(getSubId());
+                return service.getSubscriptionSpecificCarrierName(getSubId());
             }
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
@@ -9704,7 +9721,7 @@
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 return telephony.getNumberOfModemsWithSimultaneousDataConnections(
-                        getSubId(), mContext.getOpPackageName());
+                        getSubId(), getOpPackageName());
             }
         } catch (RemoteException ex) {
             // This could happen if binder process crashes.
@@ -10109,6 +10126,64 @@
         return false;
     }
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"SET_OPPORTUNISTIC_SUB"}, value = {
+            SET_OPPORTUNISTIC_SUB_SUCCESS,
+            SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED,
+            SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER})
+    public @interface SetOpportunisticSubscriptionResult {}
+
+    /**
+     * No error. Operation succeeded.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_SUCCESS = 0;
+
+    /**
+     * Validation failed when trying to switch to preferred subscription.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_VALIDATION_FAILED = 1;
+
+    /**
+     * The parameter passed in is invalid.
+     */
+    public static final int SET_OPPORTUNISTIC_SUB_INVALID_PARAMETER = 2;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"UPDATE_AVAILABLE_NETWORKS"}, value = {
+            UPDATE_AVAILABLE_NETWORKS_SUCCESS,
+            UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE,
+            UPDATE_AVAILABLE_NETWORKS_ABORTED,
+            UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS,
+            UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE})
+    public @interface UpdateAvailableNetworksResult {}
+
+    /**
+     * No error. Operation succeeded.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_SUCCESS = 0;
+
+    /**
+     * There is a unknown failure happened.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_UNKNOWN_FAILURE = 1;
+
+    /**
+     * The request is aborted.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_ABORTED = 2;
+
+    /**
+     * The parameter passed in is invalid.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS = 3;
+
+    /**
+     * No carrier privilege.
+     */
+    public static final int UPDATE_AVAILABLE_NETWORKS_NO_CARRIER_PRIVILEGE = 4;
+
     /**
      * Set preferred opportunistic data subscription id.
      *
@@ -10169,31 +10244,49 @@
     /**
      * Update availability of a list of networks in the current location.
      *
-     * This api should be called to inform OpportunisticNetwork Service about the availability
-     * of a network at the current location. This information will be used by OpportunisticNetwork
-     * service to decide to attach to the network opportunistically. If an empty list is passed,
-     * it is assumed that no network is available.
+     * This api should be called by opportunistic network selection app to inform
+     * OpportunisticNetwork Service about the availability of a network at the current location.
+     * This information will be used by OpportunisticNetwork service to decide to attach to the
+     * network opportunistically.
+     * If an empty list is passed, it is assumed that no network is available.
      * Requires that the calling app has carrier privileges on both primary and
      * secondary subscriptions (see {@link #hasCarrierPrivileges}), or has permission
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      * @param availableNetworks is a list of available network information.
-     * @return true if request is accepted
+     * @param executor The executor of where the callback will execute.
+     * @param callback Callback will be triggered once it succeeds or failed.
      *
      */
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
-    public boolean updateAvailableNetworks(List<AvailableNetworkInfo> availableNetworks) {
+    public void updateAvailableNetworks(@NonNull List<AvailableNetworkInfo> availableNetworks,
+            @Nullable @CallbackExecutor Executor executor,
+            @UpdateAvailableNetworksResult @Nullable Consumer<Integer> callback) {
         String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>";
-        boolean ret = false;
         try {
             IOns iOpportunisticNetworkService = getIOns();
-            if (iOpportunisticNetworkService != null && availableNetworks != null) {
-                ret = iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks,
-                        pkgForDebug);
+            if (iOpportunisticNetworkService == null || availableNetworks == null) {
+                Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                    callback.accept(UPDATE_AVAILABLE_NETWORKS_INVALID_ARGUMENTS);
+                }));
+                return;
             }
+            IUpdateAvailableNetworksCallback callbackStub =
+                    new IUpdateAvailableNetworksCallback.Stub() {
+                        @Override
+                        public void onComplete(int result) {
+                            if (executor == null || callback == null) {
+                                return;
+                            }
+                            Binder.withCleanCallingIdentity(() -> executor.execute(() -> {
+                                callback.accept(result);
+                            }));
+                        }
+                    };
+            iOpportunisticNetworkService.updateAvailableNetworks(availableNetworks, callbackStub,
+                    pkgForDebug);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "updateAvailableNetworks RemoteException", ex);
         }
-        return ret;
     }
 
     /**
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index 1607817..ae2c1d1 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1641,6 +1641,7 @@
          *
          * @param entryName the entry name to set for the APN
          */
+        @NonNull
         public Builder setEntryName(String entryName) {
             this.mEntryName = entryName;
             return this;
@@ -1651,6 +1652,7 @@
          *
          * @param apnName the name to set for the APN
          */
+        @NonNull
         public Builder setApnName(String apnName) {
             this.mApnName = apnName;
             return this;
@@ -1681,6 +1683,7 @@
          *
          * @param proxy the proxy address to set for the APN
          */
+        @NonNull
         public Builder setProxyAddress(String proxy) {
             this.mProxyAddress = proxy;
             return this;
@@ -1691,6 +1694,7 @@
          *
          * @param port the proxy port to set for the APN
          */
+        @NonNull
         public Builder setProxyPort(int port) {
             this.mProxyPort = port;
             return this;
@@ -1701,6 +1705,7 @@
          *
          * @param mmsc the MMSC Uri to set for the APN
          */
+        @NonNull
         public Builder setMmsc(Uri mmsc) {
             this.mMmsc = mmsc;
             return this;
@@ -1732,6 +1737,7 @@
          *
          * @param mmsProxy the MMS proxy address to set for the APN
          */
+        @NonNull
         public Builder setMmsProxyAddress(String mmsProxy) {
             this.mMmsProxyAddress = mmsProxy;
             return this;
@@ -1742,6 +1748,7 @@
          *
          * @param mmsPort the MMS proxy port to set for the APN
          */
+        @NonNull
         public Builder setMmsProxyPort(int mmsPort) {
             this.mMmsProxyPort = mmsPort;
             return this;
@@ -1752,6 +1759,7 @@
          *
          * @param user the APN username to set for the APN
          */
+        @NonNull
         public Builder setUser(String user) {
             this.mUser = user;
             return this;
@@ -1763,6 +1771,7 @@
          * @see android.provider.Telephony.Carriers#PASSWORD
          * @param password the APN password to set for the APN
          */
+        @NonNull
         public Builder setPassword(String password) {
             this.mPassword = password;
             return this;
@@ -1773,6 +1782,7 @@
          *
          * @param authType the authentication type to set for the APN
          */
+        @NonNull
         public Builder setAuthType(@AuthType int authType) {
             this.mAuthType = authType;
             return this;
@@ -1789,6 +1799,7 @@
          *
          * @param apnTypeBitmask a bitmask describing the types of the APN
          */
+        @NonNull
         public Builder setApnTypeBitmask(@ApnType int apnTypeBitmask) {
             this.mApnTypeBitmask = apnTypeBitmask;
             return this;
@@ -1801,6 +1812,7 @@
          *
          * @param operatorNumeric the numeric operator ID to set for this entry
          */
+        @NonNull
         public Builder setOperatorNumeric(String operatorNumeric) {
             this.mOperatorNumeric = operatorNumeric;
             return this;
@@ -1813,6 +1825,7 @@
          *
          * @param protocol the protocol to set to use to connect to this APN
          */
+        @NonNull
         public Builder setProtocol(@ProtocolType int protocol) {
             this.mProtocol = protocol;
             return this;
@@ -1825,6 +1838,7 @@
          *
          * @param roamingProtocol the protocol to set to use to connect to this APN when roaming
          */
+        @NonNull
         public Builder setRoamingProtocol(@ProtocolType  int roamingProtocol) {
             this.mRoamingProtocol = roamingProtocol;
             return this;
@@ -1835,6 +1849,7 @@
          *
          * @param carrierEnabled the current status to set for this APN
          */
+        @NonNull
         public Builder setCarrierEnabled(boolean carrierEnabled) {
             this.mCarrierEnabled = carrierEnabled;
             return this;
@@ -1845,6 +1860,7 @@
          *
          * @param networkTypeBitmask the Radio Technology (Network Type) info
          */
+        @NonNull
         public Builder setNetworkTypeBitmask(int networkTypeBitmask) {
             this.mNetworkTypeBitmask = networkTypeBitmask;
             return this;
@@ -1855,6 +1871,7 @@
          *
          * @param mvnoType the MVNO match type to set for this APN
          */
+        @NonNull
         public Builder setMvnoType(@MvnoType int mvnoType) {
             this.mMvnoType = mvnoType;
             return this;
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index 9104d9f..d12cda8 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -154,7 +154,7 @@
          * @param item the IMS provisioning key constant, as defined by the OEM.
          * @param value the new String value of the IMS configuration constant.
          */
-        public void onProvisioningStringChanged(int item, String value) {
+        public void onProvisioningStringChanged(int item, @NonNull String value) {
             // Base Implementation
         }
 
diff --git a/telephony/java/com/android/internal/telephony/IOns.aidl b/telephony/java/com/android/internal/telephony/IOns.aidl
index 0e3d12b..4672e2d 100755
--- a/telephony/java/com/android/internal/telephony/IOns.aidl
+++ b/telephony/java/com/android/internal/telephony/IOns.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import android.telephony.AvailableNetworkInfo;
+import com.android.internal.telephony.IUpdateAvailableNetworksCallback;
 
 interface IOns {
 
@@ -93,9 +94,9 @@
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      *  @param availableNetworks is a list of available network information.
      *  @param callingPackage caller's package name
-     *  @return true if request is accepted
+     *  @param callback callback upon request completion.
      *
      */
-    boolean updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
-            String callingPackage);
+    void updateAvailableNetworks(in List<AvailableNetworkInfo> availableNetworks,
+            IUpdateAvailableNetworksCallback callbackStub, String callingPackage);
 }
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 322ce45..4a263f0 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -54,7 +54,7 @@
     void onCarrierNetworkChange(in boolean active);
     void onUserMobileDataStateChanged(in boolean enabled);
     void onPhoneCapabilityChanged(in PhoneCapability capability);
-    void onPreferredDataSubIdChanged(in int subId);
+    void onActiveDataSubIdChanged(in int subId);
     void onRadioPowerStateChanged(in int state);
     void onCallAttributesChanged(in CallAttributes callAttributes);
     void onEmergencyNumberListChanged(in Map emergencyNumberList);
diff --git a/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
new file mode 100644
index 0000000..7a78f34
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Callback to provide asynchronous result of setPreferredOpportunisticData.
+ * @hide
+ */
+oneway interface ISetOpportunisticDataCallback {
+    void onComplete(int result);
+}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 7b92ec0..c08da44 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import android.telephony.SubscriptionInfo;
+import com.android.internal.telephony.ISetOpportunisticDataCallback;
 
 interface ISub {
     /**
@@ -217,10 +218,14 @@
      * designed to overwrite default data subscription temporarily.
      *
      * @param subId which subscription is preferred to for cellular data.
+     * @param needValidation whether validation is needed before switching.
+     * @param callback callback upon request completion.
+     *
      * @hide
      *
      */
-    void setPreferredDataSubscriptionId(int subId);
+    void setPreferredDataSubscriptionId(int subId, boolean needValidation,
+                     ISetOpportunisticDataCallback callback);
 
     /**
      * Get which subscription is preferred for cellular data.
@@ -274,7 +279,7 @@
     void clearDefaultsForInactiveSubIds();
 
     @UnsupportedAppUsage
-    int[] getActiveSubIdList();
+    int[] getActiveSubIdList(boolean visibleOnly);
 
     int setSubscriptionProperty(int subId, String propKey, String propValue);
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 6366b91..9e1332a 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1369,7 +1369,7 @@
     /**
      * Returns fine-grained carrier id of the current subscription.
      *
-     * <p>The precise carrier id can be used to further differentiate a carrier by different
+     * <p>The specific carrier id can be used to further differentiate a carrier by different
      * networks, by prepaid v.s.postpaid or even by 4G v.s.3G plan. Each carrier has a unique
      * carrier id {@link #getSimCarrierId()} but can have multiple precise carrier id. e.g,
      * {@link #getSimCarrierId()} will always return Tracfone (id 2022) for a Tracfone SIM, while
@@ -1383,19 +1383,19 @@
      * be identified.
      * @hide
      */
-    int getSubscriptionPreciseCarrierId(int subId);
+    int getSubscriptionSpecificCarrierId(int subId);
 
     /**
      * Similar like {@link #getSimCarrierIdName()}, returns user-facing name of the
-     * precise carrier id {@link #getSimPreciseCarrierId()}
+     * specific carrier id {@link #getSimSpecificCarrierId()}
      *
      * <p>The returned name is unlocalized.
      *
-     * @return user-facing name of the subscription precise carrier id. Return {@code null} if the
+     * @return user-facing name of the subscription specific carrier id. Return {@code null} if the
      * subscription is unavailable or the carrier cannot be identified.
      * @hide
      */
-    String getSubscriptionPreciseCarrierName(int subId);
+    String getSubscriptionSpecificCarrierName(int subId);
 
     /**
      * Returns carrier id based on MCCMNC only. This will return a MNO carrier id used for fallback
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index fd85281..0610c5d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -85,7 +85,7 @@
     void notifyCarrierNetworkChange(in boolean active);
     void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state);
     void notifyPhoneCapabilityChanged(in PhoneCapability capability);
-    void notifyPreferredDataSubIdChanged(int preferredSubId);
+    void notifyActiveDataSubIdChanged(int activeDataSubId);
     void notifyRadioPowerStateChanged(in int state);
     void notifyEmergencyNumberList();
     void notifyCallQualityChanged(in CallQuality callQuality, int phoneId, int callNetworkType);
diff --git a/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
new file mode 100644
index 0000000..ed77ff31
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony;
+
+/**
+ * Callback to provide asynchronous result of updateAvailableNetworks.
+ * @hide
+ */
+oneway interface IUpdateAvailableNetworksCallback {
+    void onComplete(int result);
+}
\ No newline at end of file
diff --git a/tests/AccessibilityEventsLogger/Android.bp b/tests/AccessibilityEventsLogger/Android.bp
new file mode 100644
index 0000000..ead1656
--- /dev/null
+++ b/tests/AccessibilityEventsLogger/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "AccessibilityEventsLogger",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/AccessibilityEventsLogger/Android.mk b/tests/AccessibilityEventsLogger/Android.mk
deleted file mode 100644
index 4224017..0000000
--- a/tests/AccessibilityEventsLogger/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AccessibilityEventsLogger
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/Android.mk b/tests/AccessoryDisplay/Android.mk
deleted file mode 100644
index 85cb309..0000000
--- a/tests/AccessoryDisplay/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/AccessoryDisplay/common/Android.bp b/tests/AccessoryDisplay/common/Android.bp
new file mode 100644
index 0000000..3ce4c57
--- /dev/null
+++ b/tests/AccessoryDisplay/common/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+java_library_static {
+    name: "AccessoryDisplayCommon",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+}
diff --git a/tests/AccessoryDisplay/common/Android.mk b/tests/AccessoryDisplay/common/Android.mk
deleted file mode 100644
index 2d4de15..0000000
--- a/tests/AccessoryDisplay/common/Android.mk
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_MODULE := AccessoryDisplayCommon
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/AccessoryDisplay/sink/Android.bp b/tests/AccessoryDisplay/sink/Android.bp
new file mode 100644
index 0000000..4e50a81
--- /dev/null
+++ b/tests/AccessoryDisplay/sink/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "AccessoryDisplaySink",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/sink/Android.mk b/tests/AccessoryDisplay/sink/Android.mk
deleted file mode 100644
index 772ce0c..0000000
--- a/tests/AccessoryDisplay/sink/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySink
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/AccessoryDisplay/source/Android.bp b/tests/AccessoryDisplay/source/Android.bp
new file mode 100644
index 0000000..6d8087f
--- /dev/null
+++ b/tests/AccessoryDisplay/source/Android.bp
@@ -0,0 +1,22 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "AccessoryDisplaySource",
+    sdk_version: "current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    static_libs: ["AccessoryDisplayCommon"],
+}
diff --git a/tests/AccessoryDisplay/source/Android.mk b/tests/AccessoryDisplay/source/Android.mk
deleted file mode 100644
index 5d1085d..0000000
--- a/tests/AccessoryDisplay/source/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := AccessoryDisplaySource
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_STATIC_JAVA_LIBRARIES := AccessoryDisplayCommon
-include $(BUILD_PACKAGE)
diff --git a/tests/ActivityTests/Android.bp b/tests/ActivityTests/Android.bp
new file mode 100644
index 0000000..0182862
--- /dev/null
+++ b/tests/ActivityTests/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "ActivityTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+}
diff --git a/tests/ActivityTests/Android.mk b/tests/ActivityTests/Android.mk
deleted file mode 100644
index 94294f6..0000000
--- a/tests/ActivityTests/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ActivityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_USE_AAPT2 := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/AmSlam/Android.bp b/tests/AmSlam/Android.bp
new file mode 100644
index 0000000..a8e575a
--- /dev/null
+++ b/tests/AmSlam/Android.bp
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_test {
+    name: "AmSlam",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    min_sdk_version: "21",
+    java_version: "1.8",
+}
diff --git a/tests/AmSlam/Android.mk b/tests/AmSlam/Android.mk
deleted file mode 100644
index 934bae0..0000000
--- a/tests/AmSlam/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AmSlam
-
-LOCAL_SDK_VERSION := current
-LOCAL_MIN_SDK_VERSION := 21
-LOCAL_JAVA_LANGUAGE_VERSION := 1.8
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Assist/Android.bp b/tests/Assist/Android.bp
new file mode 100644
index 0000000..216e751
--- /dev/null
+++ b/tests/Assist/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "Assist",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/Assist/Android.mk b/tests/Assist/Android.mk
deleted file mode 100644
index d0d3eca..0000000
--- a/tests/Assist/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := Assist
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BandwidthTests/Android.bp b/tests/BandwidthTests/Android.bp
new file mode 100644
index 0000000..523f522
--- /dev/null
+++ b/tests/BandwidthTests/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "BandwidthEnforcementTest",
+    platform_apis: true,
+    srcs: ["src/**/*.java"],
+}
diff --git a/tests/BandwidthTests/Android.mk b/tests/BandwidthTests/Android.mk
deleted file mode 100644
index d00fdc6..0000000
--- a/tests/BandwidthTests/Android.mk
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := BandwidthEnforcementTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BatteryWaster/Android.bp b/tests/BatteryWaster/Android.bp
new file mode 100644
index 0000000..4698910
--- /dev/null
+++ b/tests/BatteryWaster/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "BatteryWaster",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/BatteryWaster/Android.mk b/tests/BatteryWaster/Android.mk
deleted file mode 100644
index fb244a8..0000000
--- a/tests/BatteryWaster/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := BatteryWaster
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/BiDiTests/Android.bp b/tests/BiDiTests/Android.bp
new file mode 100644
index 0000000..c659e8c
--- /dev/null
+++ b/tests/BiDiTests/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2011 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.
+
+android_test {
+    name: "BiDiTests",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+}
diff --git a/tests/BiDiTests/Android.mk b/tests/BiDiTests/Android.mk
deleted file mode 100644
index 78cf4be..0000000
--- a/tests/BiDiTests/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (C) 2011 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BiDiTests
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/BrowserPowerTest/Android.bp b/tests/BrowserPowerTest/Android.bp
new file mode 100644
index 0000000..1d358cb
--- /dev/null
+++ b/tests/BrowserPowerTest/Android.bp
@@ -0,0 +1,26 @@
+// Copyright 2008, 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.
+
+android_test {
+    name: "BrowserPowerTests",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    //LOCAL_INSTRUMENTATION_FOR := browserpowertest
+}
diff --git a/tests/BrowserPowerTest/Android.mk b/tests/BrowserPowerTest/Android.mk
deleted file mode 100644
index 0934889..0000000
--- a/tests/BrowserPowerTest/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright 2008, 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := BrowserPowerTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-#LOCAL_INSTRUMENTATION_FOR := browserpowertest
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Camera2Tests/Android.mk b/tests/Camera2Tests/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/tests/Camera2Tests/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/Android.mk b/tests/Camera2Tests/SmartCamera/Android.mk
deleted file mode 100644
index 3fa8f54..0000000
--- a/tests/Camera2Tests/SmartCamera/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2013 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.
-include $(call all-subdir-makefiles)
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
index 0b16b0e..a23ac38 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/jni/Android.bp
@@ -15,9 +15,7 @@
 
 cc_test_library {
     name: "libsmartcamera_jni",
-
     sdk_version: "14",
-
     srcs: [
         "contrast.cpp",
         "brightness.cpp",
@@ -29,13 +27,11 @@
         "sobeloperator.cpp",
         "stats_scorer.cpp",
     ],
-
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
         "-Wno-unused-parameter",
     ],
-
     stl: "c++_static",
 }
diff --git a/tests/CameraPrewarmTest/Android.bp b/tests/CameraPrewarmTest/Android.bp
new file mode 100644
index 0000000..eaf453b
--- /dev/null
+++ b/tests/CameraPrewarmTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "CameraPrewarmTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/CameraPrewarmTest/Android.mk b/tests/CameraPrewarmTest/Android.mk
deleted file mode 100644
index e128504..0000000
--- a/tests/CameraPrewarmTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := CameraPrewarmTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/CoreTests/Android.mk b/tests/CoreTests/Android.mk
deleted file mode 100644
index 8338432..0000000
--- a/tests/CoreTests/Android.mk
+++ /dev/null
@@ -1,2 +0,0 @@
-include $(call all-subdir-makefiles)
-
diff --git a/tests/CoreTests/android/Android.bp b/tests/CoreTests/android/Android.bp
new file mode 100644
index 0000000..24134e8
--- /dev/null
+++ b/tests/CoreTests/android/Android.bp
@@ -0,0 +1,11 @@
+android_test {
+    name: "LegacyCoreTests",
+    srcs: ["**/*.java"],
+    libs: [
+        "android.test.runner.stubs",
+        "org.apache.http.legacy",
+        "android.test.base.stubs",
+    ],
+    sdk_version: "current",
+    static_libs: ["junit"],
+}
diff --git a/tests/CoreTests/android/Android.mk b/tests/CoreTests/android/Android.mk
deleted file mode 100644
index 04f6739..0000000
--- a/tests/CoreTests/android/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := \
-	$(call all-subdir-java-files)
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner.stubs \
-    org.apache.http.legacy \
-    android.test.base.stubs \
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_PACKAGE_NAME := LegacyCoreTests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DataIdleTest/Android.bp b/tests/DataIdleTest/Android.bp
new file mode 100644
index 0000000..19656ce
--- /dev/null
+++ b/tests/DataIdleTest/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "DataIdleTest",
+    platform_apis: true,
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    srcs: ["src/**/*.java"],
+    // We need to sign it to get access to the network usage history.
+    certificate: "platform",
+}
diff --git a/tests/DataIdleTest/Android.mk b/tests/DataIdleTest/Android.mk
deleted file mode 100644
index bcf3599..0000000
--- a/tests/DataIdleTest/Android.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := DataIdleTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# We need to sign it to get access to the network usage history.
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/DozeTest/Android.bp b/tests/DozeTest/Android.bp
new file mode 100644
index 0000000..f1be029
--- /dev/null
+++ b/tests/DozeTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "DozeTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/DozeTest/Android.mk b/tests/DozeTest/Android.mk
deleted file mode 100644
index ec250ff..0000000
--- a/tests/DozeTest/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DozeTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/DpiTest/Android.bp b/tests/DpiTest/Android.bp
new file mode 100644
index 0000000..7d6a78b
--- /dev/null
+++ b/tests/DpiTest/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "DensityTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    aaptflags: [
+        "-c",
+        "120dpi,240dpi,160dpi,nodpi",
+    ],
+}
diff --git a/tests/DpiTest/Android.mk b/tests/DpiTest/Android.mk
deleted file mode 100644
index e69d082..0000000
--- a/tests/DpiTest/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DensityTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/base/Android.bp b/tests/FeatureSplit/base/Android.bp
new file mode 100644
index 0000000..ab25464
--- /dev/null
+++ b/tests/FeatureSplit/base/Android.bp
@@ -0,0 +1,22 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test_helper_app {
+    name: "FeatureSplitBase",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    export_package_resources: true,
+}
diff --git a/tests/FeatureSplit/base/Android.mk b/tests/FeatureSplit/base/Android.mk
deleted file mode 100644
index 8646460..0000000
--- a/tests/FeatureSplit/base/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplitBase
-LOCAL_SDK_VERSION := current
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature1/Android.bp b/tests/FeatureSplit/feature1/Android.bp
new file mode 100644
index 0000000..1a93e84
--- /dev/null
+++ b/tests/FeatureSplit/feature1/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test {
+    name: "FeatureSplit1",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: ["FeatureSplitBase"],
+    aaptflags: [
+        "--package-id",
+        "0x80",
+    ] + [
+        "--custom-package",
+        "com.android.test.split.feature.one",
+    ],
+}
diff --git a/tests/FeatureSplit/feature1/Android.mk b/tests/FeatureSplit/feature1/Android.mk
deleted file mode 100644
index d4d2589..0000000
--- a/tests/FeatureSplit/feature1/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit1
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x80
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.one
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FeatureSplit/feature2/Android.bp b/tests/FeatureSplit/feature2/Android.bp
new file mode 100644
index 0000000..a363482
--- /dev/null
+++ b/tests/FeatureSplit/feature2/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test {
+    name: "FeatureSplit2",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: ["FeatureSplitBase"],
+    aaptflags: [
+        "--package-id",
+        "0x81",
+        "--custom-package",
+        "com.android.test.split.feature.two",
+    ],
+}
diff --git a/tests/FeatureSplit/feature2/Android.mk b/tests/FeatureSplit/feature2/Android.mk
deleted file mode 100644
index 5e5e78b..0000000
--- a/tests/FeatureSplit/feature2/Android.mk
+++ /dev/null
@@ -1,32 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := FeatureSplit2
-LOCAL_SDK_VERSION := current
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_APK_LIBRARIES := FeatureSplitBase
-LOCAL_RES_LIBRARIES := FeatureSplitBase
-
-LOCAL_AAPT_FLAGS += --package-id 0x81
-LOCAL_AAPT_FLAGS += --custom-package com.android.test.split.feature.two
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FixVibrateSetting/Android.bp b/tests/FixVibrateSetting/Android.bp
new file mode 100644
index 0000000..5608a2b
--- /dev/null
+++ b/tests/FixVibrateSetting/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "FixVibrateSetting",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/FixVibrateSetting/Android.mk b/tests/FixVibrateSetting/Android.mk
deleted file mode 100644
index 86db09e..0000000
--- a/tests/FixVibrateSetting/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FixVibrateSetting
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/FrameworkPerf/Android.bp b/tests/FrameworkPerf/Android.bp
new file mode 100644
index 0000000..a259ebd
--- /dev/null
+++ b/tests/FrameworkPerf/Android.bp
@@ -0,0 +1,14 @@
+android_test {
+    name: "FrameworkPerf",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    aaptflags: [
+        "-c",
+        "120dpi,240dpi,160dpi,161dpi,320dpi,nodpi",
+    ],
+}
diff --git a/tests/FrameworkPerf/Android.mk b/tests/FrameworkPerf/Android.mk
deleted file mode 100644
index 0664d4d..0000000
--- a/tests/FrameworkPerf/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := FrameworkPerf
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-LOCAL_AAPT_FLAGS = -c 120dpi,240dpi,160dpi,161dpi,320dpi,nodpi
-
-include $(BUILD_PACKAGE)
diff --git a/tests/GridLayoutTest/Android.bp b/tests/GridLayoutTest/Android.bp
new file mode 100644
index 0000000..b4b5ba5
--- /dev/null
+++ b/tests/GridLayoutTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2010 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.
+//
+
+android_test {
+    name: "GridLayoutTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/GridLayoutTest/Android.mk b/tests/GridLayoutTest/Android.mk
deleted file mode 100644
index e7e3ccd..0000000
--- a/tests/GridLayoutTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2010 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := GridLayoutTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HierarchyViewerTest/Android.bp b/tests/HierarchyViewerTest/Android.bp
new file mode 100644
index 0000000..814c883
--- /dev/null
+++ b/tests/HierarchyViewerTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "HierarchyViewerTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    libs: [
+        "android.test.runner.stubs",
+        "android.test.base.stubs",
+    ],
+    static_libs: ["junit"],
+}
diff --git a/tests/HierarchyViewerTest/Android.mk b/tests/HierarchyViewerTest/Android.mk
deleted file mode 100644
index cf1a512..0000000
--- a/tests/HierarchyViewerTest/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := HierarchyViewerTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs android.test.base.stubs
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
diff --git a/tests/HugeBackup/Android.bp b/tests/HugeBackup/Android.bp
new file mode 100644
index 0000000..b44c457
--- /dev/null
+++ b/tests/HugeBackup/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "HugeBackup",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+    optimize: {
+        proguard_flags_files: ["proguard.flags"],
+    },
+}
diff --git a/tests/HugeBackup/Android.mk b/tests/HugeBackup/Android.mk
deleted file mode 100644
index 4789bc8..0000000
--- a/tests/HugeBackup/Android.mk
+++ /dev/null
@@ -1,15 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := HugeBackup
-
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-
-include $(BUILD_PACKAGE)
diff --git a/tests/JobSchedulerTestApp/Android.bp b/tests/JobSchedulerTestApp/Android.bp
new file mode 100644
index 0000000..bac0220
--- /dev/null
+++ b/tests/JobSchedulerTestApp/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "JobSchedulerTestApp",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    sdk_version: "current",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/JobSchedulerTestApp/Android.mk b/tests/JobSchedulerTestApp/Android.mk
deleted file mode 100644
index 48ee1f6..0000000
--- a/tests/JobSchedulerTestApp/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := JobSchedulerTestApp
-LOCAL_SDK_VERSION := current
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/LargeAssetTest/Android.bp b/tests/LargeAssetTest/Android.bp
new file mode 100644
index 0000000..499e6a0
--- /dev/null
+++ b/tests/LargeAssetTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "LargeAssetTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/LargeAssetTest/Android.mk b/tests/LargeAssetTest/Android.mk
deleted file mode 100644
index f6d98bf..0000000
--- a/tests/LargeAssetTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LargeAssetTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LegacyAssistant/Android.bp b/tests/LegacyAssistant/Android.bp
new file mode 100644
index 0000000..fef924d
--- /dev/null
+++ b/tests/LegacyAssistant/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "LegacyAssistant",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/LegacyAssistant/Android.mk b/tests/LegacyAssistant/Android.mk
deleted file mode 100644
index a583369..0000000
--- a/tests/LegacyAssistant/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LegacyAssistant
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LocationTracker/Android.bp b/tests/LocationTracker/Android.bp
new file mode 100644
index 0000000..f0075a9
--- /dev/null
+++ b/tests/LocationTracker/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "LocationTracker",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/LocationTracker/Android.mk b/tests/LocationTracker/Android.mk
deleted file mode 100644
index 0d51b3b..0000000
--- a/tests/LocationTracker/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LocationTracker
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LotsOfApps/Android.bp b/tests/LotsOfApps/Android.bp
new file mode 100644
index 0000000..68b9f88
--- /dev/null
+++ b/tests/LotsOfApps/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "LotsOfApps",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/LotsOfApps/Android.mk b/tests/LotsOfApps/Android.mk
deleted file mode 100644
index bee3bcc..0000000
--- a/tests/LotsOfApps/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := LotsOfApps
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/LowStorageTest/Android.bp b/tests/LowStorageTest/Android.bp
new file mode 100644
index 0000000..e72e4a5
--- /dev/null
+++ b/tests/LowStorageTest/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2009 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.
+
+android_test {
+    name: "lowstoragetest",
+    certificate: "platform",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/LowStorageTest/Android.mk b/tests/LowStorageTest/Android.mk
deleted file mode 100644
index bdde6bd..0000000
--- a/tests/LowStorageTest/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2009 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.
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := lowstoragetest
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/MemoryUsage/Android.bp b/tests/MemoryUsage/Android.bp
new file mode 100644
index 0000000..aeb5338
--- /dev/null
+++ b/tests/MemoryUsage/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "MemoryUsage",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+}
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
deleted file mode 100644
index 5040d5a..0000000
--- a/tests/MemoryUsage/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := MemoryUsage
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/NetworkSecurityConfigTest/Android.bp b/tests/NetworkSecurityConfigTest/Android.bp
new file mode 100644
index 0000000..cf8ca57
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "NetworkSecurityConfigTests",
+    certificate: "platform",
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/NetworkSecurityConfigTest/Android.mk b/tests/NetworkSecurityConfigTest/Android.mk
deleted file mode 100644
index a6c21db..0000000
--- a/tests/NetworkSecurityConfigTest/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner \
-    android.test.base \
-
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := NetworkSecurityConfigTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/Android.bp b/tests/OdmApps/Android.bp
new file mode 100644
index 0000000..d86f9cc
--- /dev/null
+++ b/tests/OdmApps/Android.bp
@@ -0,0 +1,20 @@
+// Copyright (C) 2018 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.
+
+java_test_host {
+    name: "OdmAppsTest",
+    srcs: ["src/**/*.java"],
+    libs: ["tradefed"],
+    test_suites: ["device-tests"],
+}
diff --git a/tests/OdmApps/Android.mk b/tests/OdmApps/Android.mk
deleted file mode 100644
index 64fa653..0000000
--- a/tests/OdmApps/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := OdmAppsTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_JAVA_LIBRARIES := tradefed
-LOCAL_COMPATIBILITY_SUITE := device-tests
-include $(BUILD_HOST_JAVA_LIBRARY)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/OdmApps/app/Android.bp b/tests/OdmApps/app/Android.bp
new file mode 100644
index 0000000..5eb8590
--- /dev/null
+++ b/tests/OdmApps/app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 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.
+
+android_test {
+    name: "TestOdmApp",
+    test_suites: ["device-tests"],
+    sdk_version: "current",
+}
diff --git a/tests/OdmApps/app/Android.mk b/tests/OdmApps/app/Android.mk
deleted file mode 100644
index 9eec0cc..0000000
--- a/tests/OdmApps/app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OdmApps/priv-app/Android.bp b/tests/OdmApps/priv-app/Android.bp
new file mode 100644
index 0000000..9dd477cf
--- /dev/null
+++ b/tests/OdmApps/priv-app/Android.bp
@@ -0,0 +1,19 @@
+// Copyright (C) 2018 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.
+
+android_test {
+    name: "TestOdmPrivApp",
+    test_suites: ["device-tests"],
+    sdk_version: "current",
+}
diff --git a/tests/OdmApps/priv-app/Android.mk b/tests/OdmApps/priv-app/Android.mk
deleted file mode 100644
index d423133..0000000
--- a/tests/OdmApps/priv-app/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-# Copyright (C) 2018 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.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := TestOdmPrivApp
-LOCAL_MODULE_TAGS := tests
-LOCAL_COMPATIBILITY_SUITE := device-tests
-LOCAL_SDK_VERSION := current
-include $(BUILD_PACKAGE)
diff --git a/tests/OneMedia/Android.bp b/tests/OneMedia/Android.bp
new file mode 100644
index 0000000..11e12f35
--- /dev/null
+++ b/tests/OneMedia/Android.bp
@@ -0,0 +1,13 @@
+android_app {
+    name: "OneMedia",
+    srcs: [
+        "**/*.java",
+        "src/**/I*.aidl",
+    ],
+    platform_apis: true,
+    certificate: "platform",
+    libs: ["org.apache.http.legacy"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/OneMedia/Android.mk b/tests/OneMedia/Android.mk
deleted file mode 100644
index 41f3f64..0000000
--- a/tests/OneMedia/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files) \
-        $(call all-Iaidl-files-under, src)
-
-LOCAL_PACKAGE_NAME := OneMedia
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_JAVA_LIBRARIES += org.apache.http.legacy
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/RemoteDisplayProvider/Android.bp b/tests/RemoteDisplayProvider/Android.bp
new file mode 100644
index 0000000..6c7798f
--- /dev/null
+++ b/tests/RemoteDisplayProvider/Android.bp
@@ -0,0 +1,23 @@
+// Copyright (C) 2013 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.
+
+// Build the application.
+android_test {
+    name: "RemoteDisplayProviderTest",
+    sdk_version: "system_current",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    libs: ["com.android.media.remotedisplay"],
+    certificate: "platform",
+}
diff --git a/tests/RemoteDisplayProvider/Android.mk b/tests/RemoteDisplayProvider/Android.mk
deleted file mode 100644
index 43bf024..0000000
--- a/tests/RemoteDisplayProvider/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright (C) 2013 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.
-
-LOCAL_PATH := $(call my-dir)
-
-# Build the application.
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := RemoteDisplayProviderTest
-LOCAL_MODULE_TAGS := tests
-LOCAL_SDK_VERSION := system_current
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR = $(LOCAL_PATH)/res
-LOCAL_JAVA_LIBRARIES := com.android.media.remotedisplay
-LOCAL_CERTIFICATE := platform
-include $(BUILD_PACKAGE)
diff --git a/tests/RenderThreadTest/Android.bp b/tests/RenderThreadTest/Android.bp
new file mode 100644
index 0000000..1659776
--- /dev/null
+++ b/tests/RenderThreadTest/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "RenderThreadTest",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    static_libs: ["android-common"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/RenderThreadTest/Android.mk b/tests/RenderThreadTest/Android.mk
deleted file mode 100644
index 4e5f35b..0000000
--- a/tests/RenderThreadTest/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := RenderThreadTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SerialChat/Android.bp b/tests/SerialChat/Android.bp
new file mode 100644
index 0000000..3c18035
--- /dev/null
+++ b/tests/SerialChat/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "SerialChat",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/SerialChat/Android.mk b/tests/SerialChat/Android.mk
deleted file mode 100644
index ed6ca999..0000000
--- a/tests/SerialChat/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SerialChat
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/client/Android.bp b/tests/SharedLibrary/client/Android.bp
new file mode 100644
index 0000000..dbf6dc9
--- /dev/null
+++ b/tests/SharedLibrary/client/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "SharedLibraryClient",
+    srcs: ["**/*.java"],
+    libs: ["SharedLibrary"],
+    sdk_version: "current",
+}
diff --git a/tests/SharedLibrary/client/Android.mk b/tests/SharedLibrary/client/Android.mk
deleted file mode 100644
index 9e76c40..0000000
--- a/tests/SharedLibrary/client/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_RES_LIBRARIES := SharedLibrary
-
-LOCAL_PACKAGE_NAME := SharedLibraryClient
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SharedLibrary/lib/Android.bp b/tests/SharedLibrary/lib/Android.bp
new file mode 100644
index 0000000..f69d388
--- /dev/null
+++ b/tests/SharedLibrary/lib/Android.bp
@@ -0,0 +1,11 @@
+android_app {
+    name: "SharedLibrary",
+    srcs: ["**/*.java"],
+    aaptflags: ["--shared-lib"],
+    sdk_version: "current",
+    export_package_resources: true,
+    privileged: true,
+    optimize: {
+        proguard_flags_files: ["proguard.proguard"],
+    },
+}
diff --git a/tests/SharedLibrary/lib/Android.mk b/tests/SharedLibrary/lib/Android.mk
deleted file mode 100644
index 3c1ca87..0000000
--- a/tests/SharedLibrary/lib/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_USE_AAPT2 := true
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_AAPT_FLAGS := --shared-lib
-LOCAL_PACKAGE_NAME := SharedLibrary
-LOCAL_SDK_VERSION := current
-
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PROGUARD_FLAG_FILES := proguard.proguard
-
-include $(BUILD_PACKAGE)
diff --git a/tests/ShowWhenLockedApp/Android.bp b/tests/ShowWhenLockedApp/Android.bp
new file mode 100644
index 0000000..dba564c
--- /dev/null
+++ b/tests/ShowWhenLockedApp/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "ShowWhenLocked",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/ShowWhenLockedApp/Android.mk b/tests/ShowWhenLockedApp/Android.mk
deleted file mode 100644
index 41e0ac4..0000000
--- a/tests/ShowWhenLockedApp/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := ShowWhenLocked
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
\ No newline at end of file
diff --git a/tests/SmokeTest/Android.bp b/tests/SmokeTest/Android.bp
new file mode 100644
index 0000000..bc45ee6
--- /dev/null
+++ b/tests/SmokeTest/Android.bp
@@ -0,0 +1,6 @@
+android_test {
+    name: "SmokeTestApp",
+    // This builds "SmokeTestApp"
+    srcs: ["src/**/*.java"],
+    sdk_version: "8",
+}
diff --git a/tests/SmokeTest/Android.mk b/tests/SmokeTest/Android.mk
deleted file mode 100644
index 591a84e..0000000
--- a/tests/SmokeTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-# This builds "SmokeTestApp"
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
-# This builds "SmokeTest"
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SmokeTest/tests/Android.bp b/tests/SmokeTest/tests/Android.bp
new file mode 100644
index 0000000..ceb2d19
--- /dev/null
+++ b/tests/SmokeTest/tests/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "SmokeTest",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    // Notice that we don't have to include the src files of SmokeTestApp because, by
+    // running the tests using an instrumentation targeting SmokeTestApp, we
+    // automatically get all of its classes loaded into our environment.
+    instrumentation_for: "SmokeTestApp",
+    sdk_version: "8",
+}
diff --git a/tests/SmokeTest/tests/Android.mk b/tests/SmokeTest/tests/Android.mk
deleted file mode 100644
index 18e682e..0000000
--- a/tests/SmokeTest/tests/Android.mk
+++ /dev/null
@@ -1,21 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-# Notice that we don't have to include the src files of SmokeTestApp because, by
-# running the tests using an instrumentation targeting SmokeTestApp, we
-# automatically get all of its classes loaded into our environment.
-
-LOCAL_PACKAGE_NAME := SmokeTest
-
-LOCAL_INSTRUMENTATION_FOR := SmokeTestApp
-
-LOCAL_SDK_VERSION := 8
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/SmokeTestApps/Android.bp b/tests/SmokeTestApps/Android.bp
new file mode 100644
index 0000000..0feb0004
--- /dev/null
+++ b/tests/SmokeTestApps/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "SmokeTestTriggerApps",
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/SmokeTestApps/Android.mk b/tests/SmokeTestApps/Android.mk
deleted file mode 100644
index 1f564e0..0000000
--- a/tests/SmokeTestApps/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := SmokeTestTriggerApps
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/SoundTriggerTestApp/Android.bp b/tests/SoundTriggerTestApp/Android.bp
new file mode 100644
index 0000000..d3a1300
--- /dev/null
+++ b/tests/SoundTriggerTestApp/Android.bp
@@ -0,0 +1,7 @@
+android_app {
+    name: "SoundTriggerTestApp",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    privileged: true,
+    certificate: "platform",
+}
diff --git a/tests/SoundTriggerTestApp/Android.mk b/tests/SoundTriggerTestApp/Android.mk
deleted file mode 100644
index 73fb5e8..0000000
--- a/tests/SoundTriggerTestApp/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := SoundTriggerTestApp
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/Split/Android.bp b/tests/Split/Android.bp
new file mode 100644
index 0000000..d8c89ba
--- /dev/null
+++ b/tests/Split/Android.bp
@@ -0,0 +1,27 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test {
+    name: "Split",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    package_splits: [
+        "mdpi-v4",
+        "hdpi-v4",
+        "xhdpi-v4",
+        "xxhdpi-v4",
+    ],
+}
diff --git a/tests/Split/Android.mk b/tests/Split/Android.mk
deleted file mode 100644
index 4d15b2d..0000000
--- a/tests/Split/Android.mk
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := Split
-LOCAL_SDK_VERSION := current
-
-LOCAL_PACKAGE_SPLITS := mdpi-v4 hdpi-v4 xhdpi-v4 xxhdpi-v4
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/StatusBar/Android.bp b/tests/StatusBar/Android.bp
new file mode 100644
index 0000000..0b650ed
--- /dev/null
+++ b/tests/StatusBar/Android.bp
@@ -0,0 +1,9 @@
+android_test {
+    name: "StatusBarTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/StatusBar/Android.mk b/tests/StatusBar/Android.mk
deleted file mode 100644
index e845335..0000000
--- a/tests/StatusBar/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := StatusBarTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_CERTIFICATE := platform
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/tests/SystemUIDemoModeController/Android.bp b/tests/SystemUIDemoModeController/Android.bp
new file mode 100644
index 0000000..1e4c437
--- /dev/null
+++ b/tests/SystemUIDemoModeController/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "DemoModeController",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/SystemUIDemoModeController/Android.mk b/tests/SystemUIDemoModeController/Android.mk
deleted file mode 100644
index cc6fa8d..0000000
--- a/tests/SystemUIDemoModeController/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := DemoModeController
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TouchLatency/Android.bp b/tests/TouchLatency/Android.bp
new file mode 100644
index 0000000..1174bcb0
--- /dev/null
+++ b/tests/TouchLatency/Android.bp
@@ -0,0 +1,10 @@
+android_test {
+    name: "TouchLatency",
+    manifest: "app/src/main/AndroidManifest.xml",
+    // omit gradle 'build' dir
+    srcs: ["app/src/main/java/**/*.java"],
+    resource_dirs: ["app/src/main/res"],
+    aaptflags: ["--auto-add-overlay"],
+    sdk_version: "current",
+    test_suites: ["device-tests"],
+}
diff --git a/tests/TouchLatency/Android.mk b/tests/TouchLatency/Android.mk
deleted file mode 100644
index 2334bd8..0000000
--- a/tests/TouchLatency/Android.mk
+++ /dev/null
@@ -1,22 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_MANIFEST_FILE := app/src/main/AndroidManifest.xml
-
-# omit gradle 'build' dir
-LOCAL_SRC_FILES := $(call all-java-files-under,app/src/main/java)
-
-LOCAL_RESOURCE_DIR := \
-    $(LOCAL_PATH)/app/src/main/res
-
-LOCAL_AAPT_FLAGS := \
-    --auto-add-overlay
-
-LOCAL_PACKAGE_NAME := TouchLatency
-LOCAL_SDK_VERSION := current
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransformTest/Android.bp b/tests/TransformTest/Android.bp
new file mode 100644
index 0000000..fd7aaeb
--- /dev/null
+++ b/tests/TransformTest/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "TransformTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/TransformTest/Android.mk b/tests/TransformTest/Android.mk
deleted file mode 100644
index 5340cdd..0000000
--- a/tests/TransformTest/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := TransformTest
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/TransitionTests/Android.bp b/tests/TransitionTests/Android.bp
new file mode 100644
index 0000000..57f19e3
--- /dev/null
+++ b/tests/TransitionTests/Android.bp
@@ -0,0 +1,10 @@
+android_app {
+    name: "TransitionTests",
+    // Only compile source java files in this apk.
+    srcs: ["src/**/*.java"],
+    platform_apis: true,
+    static_libs: ["android-common"],
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/TransitionTests/Android.mk b/tests/TransitionTests/Android.mk
deleted file mode 100644
index a696156..0000000
--- a/tests/TransitionTests/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-# Only compile source java files in this apk.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := TransitionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES += android-common
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
-# Use the following include to make our test apk.
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/TtsTests/Android.bp b/tests/TtsTests/Android.bp
new file mode 100644
index 0000000..b137523
--- /dev/null
+++ b/tests/TtsTests/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2011 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.
+//
+
+android_test {
+    name: "TtsTests",
+    srcs: ["**/*.java"],
+    static_libs: ["mockito-target"],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    platform_apis: true,
+}
diff --git a/tests/TtsTests/Android.mk b/tests/TtsTests/Android.mk
deleted file mode 100644
index 116cc0a..0000000
--- a/tests/TtsTests/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_STATIC_JAVA_LIBRARIES := mockito-target
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base
-
-LOCAL_PACKAGE_NAME := TtsTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/UsesFeature2Test/Android.bp b/tests/UsesFeature2Test/Android.bp
new file mode 100644
index 0000000..a1b77d0
--- /dev/null
+++ b/tests/UsesFeature2Test/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test {
+    name: "UsesFeature2Test",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/UsesFeature2Test/Android.mk b/tests/UsesFeature2Test/Android.mk
deleted file mode 100644
index 4cba4ff..0000000
--- a/tests/UsesFeature2Test/Android.mk
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-LOCAL_PACKAGE_NAME := UsesFeature2Test
-LOCAL_SDK_VERSION := current
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VectorDrawableTest/Android.bp b/tests/VectorDrawableTest/Android.bp
new file mode 100644
index 0000000..13f318e
--- /dev/null
+++ b/tests/VectorDrawableTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2014 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.
+//
+
+android_test {
+    name: "VectorDrawableTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/VectorDrawableTest/Android.mk b/tests/VectorDrawableTest/Android.mk
deleted file mode 100644
index 155b2bc..0000000
--- a/tests/VectorDrawableTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2014 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VectorDrawableTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceEnrollment/Android.bp b/tests/VoiceEnrollment/Android.bp
new file mode 100644
index 0000000..e43b38c
--- /dev/null
+++ b/tests/VoiceEnrollment/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "VoiceEnrollment",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+    privileged: true,
+}
diff --git a/tests/VoiceEnrollment/Android.mk b/tests/VoiceEnrollment/Android.mk
deleted file mode 100644
index 725e2bd..0000000
--- a/tests/VoiceEnrollment/Android.mk
+++ /dev/null
@@ -1,13 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceEnrollment
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_PRIVILEGED_MODULE := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/VoiceInteraction/Android.bp b/tests/VoiceInteraction/Android.bp
new file mode 100644
index 0000000..7059473
--- /dev/null
+++ b/tests/VoiceInteraction/Android.bp
@@ -0,0 +1,5 @@
+android_test {
+    name: "VoiceInteraction",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/VoiceInteraction/Android.mk b/tests/VoiceInteraction/Android.mk
deleted file mode 100644
index aa48b42..0000000
--- a/tests/VoiceInteraction/Android.mk
+++ /dev/null
@@ -1,11 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := VoiceInteraction
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
diff --git a/tests/WallpaperTest/Android.bp b/tests/WallpaperTest/Android.bp
new file mode 100644
index 0000000..f68b6ec
--- /dev/null
+++ b/tests/WallpaperTest/Android.bp
@@ -0,0 +1,9 @@
+android_app {
+    name: "WallpaperTest",
+    srcs: ["src/**/*.java"],
+    resource_dirs: ["res"],
+    platform_apis: true,
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/tests/WallpaperTest/Android.mk b/tests/WallpaperTest/Android.mk
deleted file mode 100644
index 4815500..0000000
--- a/tests/WallpaperTest/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_PACKAGE_NAME := WallpaperTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/WindowManagerStressTest/Android.bp b/tests/WindowManagerStressTest/Android.bp
new file mode 100644
index 0000000..98749a7
--- /dev/null
+++ b/tests/WindowManagerStressTest/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2016 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.
+//
+
+android_test {
+    name: "WindowManagerStressTest",
+    srcs: ["**/*.java"],
+    platform_apis: true,
+}
diff --git a/tests/WindowManagerStressTest/Android.mk b/tests/WindowManagerStressTest/Android.mk
deleted file mode 100644
index 6f4403f..0000000
--- a/tests/WindowManagerStressTest/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2016 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := WindowManagerStressTest
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.bp b/tests/appwidgets/AppWidgetHostTest/Android.bp
new file mode 100644
index 0000000..24b7613
--- /dev/null
+++ b/tests/appwidgets/AppWidgetHostTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "AppWidgetHostTest",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetHostTest/Android.mk b/tests/appwidgets/AppWidgetHostTest/Android.mk
deleted file mode 100644
index c9e6c6b..0000000
--- a/tests/appwidgets/AppWidgetHostTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetHostTest
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.bp b/tests/appwidgets/AppWidgetProviderTest/Android.bp
new file mode 100644
index 0000000..a1a5991
--- /dev/null
+++ b/tests/appwidgets/AppWidgetProviderTest/Android.bp
@@ -0,0 +1,6 @@
+android_app {
+    name: "AppWidgetProvider",
+    srcs: ["**/*.java"],
+    sdk_version: "current",
+    certificate: "platform",
+}
diff --git a/tests/appwidgets/AppWidgetProviderTest/Android.mk b/tests/appwidgets/AppWidgetProviderTest/Android.mk
deleted file mode 100644
index b26c60b..0000000
--- a/tests/appwidgets/AppWidgetProviderTest/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
-
-LOCAL_PACKAGE_NAME := AppWidgetProvider
-LOCAL_SDK_VERSION := current
-LOCAL_CERTIFICATE := platform
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
new file mode 100644
index 0000000..2539c0f
--- /dev/null
+++ b/tests/net/Android.bp
@@ -0,0 +1,27 @@
+//########################################################################
+// Build FrameworksNetTests package
+//########################################################################
+
+android_test {
+    name: "FrameworksNetTests",
+    // Include all test java files.
+    srcs: ["java/**/*.java"],
+    static_libs: [
+        "frameworks-base-testutils",
+        "framework-protos",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+        "platform-test-annotations",
+        "services.core",
+        "services.ipmemorystore",
+        "services.net",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+    platform_apis: true,
+    test_suites: ["device-tests"],
+    certificate: "platform",
+}
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
deleted file mode 100644
index 2ef141f..0000000
--- a/tests/net/Android.mk
+++ /dev/null
@@ -1,37 +0,0 @@
-#########################################################################
-# Build FrameworksNetTests package
-#########################################################################
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, java)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    frameworks-base-testutils \
-    framework-protos \
-    androidx.test.rules \
-    mockito-target-minus-junit4 \
-    platform-test-annotations \
-    services.core \
-    services.ipmemorystore \
-    services.net
-
-LOCAL_JAVA_LIBRARIES := \
-    android.test.runner \
-    android.test.base \
-    android.test.mock
-
-LOCAL_PACKAGE_NAME := FrameworksNetTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-
-include $(BUILD_PACKAGE)
diff --git a/tests/net/OWNERS b/tests/net/OWNERS
index 7311eee..d3836d4 100644
--- a/tests/net/OWNERS
+++ b/tests/net/OWNERS
@@ -1,8 +1,8 @@
 set noparent
 
 codewiz@google.com
-ek@google.com
 jchalard@google.com
+junyulai@google.com
 lorenzo@google.com
 reminv@google.com
 satk@google.com
diff --git a/tests/net/java/android/net/DnsPacketTest.java b/tests/net/java/android/net/DnsPacketTest.java
index 91ff6b3..9ede2b8 100644
--- a/tests/net/java/android/net/DnsPacketTest.java
+++ b/tests/net/java/android/net/DnsPacketTest.java
@@ -36,19 +36,19 @@
             int qCount, int aCount, int nsCount, int arCount) {
         assertEquals(header.id, id);
         assertEquals(header.flags, flag);
-        assertEquals(header.getSectionCount(DnsPacket.QDSECTION), qCount);
-        assertEquals(header.getSectionCount(DnsPacket.ANSECTION), aCount);
-        assertEquals(header.getSectionCount(DnsPacket.NSSECTION), nsCount);
-        assertEquals(header.getSectionCount(DnsPacket.ARSECTION), arCount);
+        assertEquals(header.getRecordCount(DnsPacket.QDSECTION), qCount);
+        assertEquals(header.getRecordCount(DnsPacket.ANSECTION), aCount);
+        assertEquals(header.getRecordCount(DnsPacket.NSSECTION), nsCount);
+        assertEquals(header.getRecordCount(DnsPacket.ARSECTION), arCount);
     }
 
-    private void assertSectionParses(DnsPacket.DnsSection section, String dname,
+    private void assertRecordParses(DnsPacket.DnsRecord record, String dname,
             int dtype, int dclass, int ttl, byte[] rr) {
-        assertEquals(section.dName, dname);
-        assertEquals(section.nsType, dtype);
-        assertEquals(section.nsClass, dclass);
-        assertEquals(section.ttl, ttl);
-        assertTrue(Arrays.equals(section.getRR(), rr));
+        assertEquals(record.dName, dname);
+        assertEquals(record.nsType, dtype);
+        assertEquals(record.nsClass, dclass);
+        assertEquals(record.ttl, ttl);
+        assertTrue(Arrays.equals(record.getRR(), rr));
     }
 
     class TestDnsPacket extends DnsPacket {
@@ -59,8 +59,8 @@
         public DnsHeader getHeader() {
             return mHeader;
         }
-        public List<DnsSection> getSectionList(int secType) {
-            return mSections[secType];
+        public List<DnsRecord> getRecordList(int secType) {
+            return mRecords[secType];
         }
     }
 
@@ -101,16 +101,16 @@
         // Header part
         assertHeaderParses(packet.getHeader(), 0x5566, 0x8180, 1, 1, 0, 0);
 
-        // Section part
-        List<DnsPacket.DnsSection> qdSectionList =
-                packet.getSectionList(DnsPacket.QDSECTION);
-        assertEquals(qdSectionList.size(), 1);
-        assertSectionParses(qdSectionList.get(0), "www.google.com", 1, 1, 0, null);
+        // Record part
+        List<DnsPacket.DnsRecord> qdRecordList =
+                packet.getRecordList(DnsPacket.QDSECTION);
+        assertEquals(qdRecordList.size(), 1);
+        assertRecordParses(qdRecordList.get(0), "www.google.com", 1, 1, 0, null);
 
-        List<DnsPacket.DnsSection> anSectionList =
-                packet.getSectionList(DnsPacket.ANSECTION);
-        assertEquals(anSectionList.size(), 1);
-        assertSectionParses(anSectionList.get(0), "www.google.com", 1, 1, 0x12b,
+        List<DnsPacket.DnsRecord> anRecordList =
+                packet.getRecordList(DnsPacket.ANSECTION);
+        assertEquals(anRecordList.size(), 1);
+        assertRecordParses(anRecordList.get(0), "www.google.com", 1, 1, 0x12b,
                 new byte[]{ (byte) 0xac, (byte) 0xd9, (byte) 0xa1, (byte) 0x84 });
     }
 
@@ -143,16 +143,16 @@
         // Header part
         assertHeaderParses(packet.getHeader(), 0x7722, 0x8180, 1, 1, 0, 0);
 
-        // Section part
-        List<DnsPacket.DnsSection> qdSectionList =
-                packet.getSectionList(DnsPacket.QDSECTION);
-        assertEquals(qdSectionList.size(), 1);
-        assertSectionParses(qdSectionList.get(0), "www.google.com", 28, 1, 0, null);
+        // Record part
+        List<DnsPacket.DnsRecord> qdRecordList =
+                packet.getRecordList(DnsPacket.QDSECTION);
+        assertEquals(qdRecordList.size(), 1);
+        assertRecordParses(qdRecordList.get(0), "www.google.com", 28, 1, 0, null);
 
-        List<DnsPacket.DnsSection> anSectionList =
-                packet.getSectionList(DnsPacket.ANSECTION);
-        assertEquals(anSectionList.size(), 1);
-        assertSectionParses(anSectionList.get(0), "www.google.com", 28, 1, 0x37,
+        List<DnsPacket.DnsRecord> anRecordList =
+                packet.getRecordList(DnsPacket.ANSECTION);
+        assertEquals(anRecordList.size(), 1);
+        assertRecordParses(anRecordList.get(0), "www.google.com", 28, 1, 0x37,
                 new byte[]{ 0x24, 0x04, 0x68, 0x00, 0x40, 0x05, 0x08, 0x0d,
                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04 });
     }
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 4d4915b..ad76388 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -20,6 +20,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_MMS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
@@ -27,6 +28,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
 import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
@@ -335,6 +337,24 @@
     }
 
     @Test
+    public void testConnectivityManagedCapabilities() {
+        NetworkCapabilities nc = new NetworkCapabilities();
+        assertFalse(nc.hasConnectivityManagedCapability());
+        // Check every single system managed capability.
+        nc.addCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        assertTrue(nc.hasConnectivityManagedCapability());
+        nc.removeCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        nc.addCapability(NET_CAPABILITY_FOREGROUND);
+        assertTrue(nc.hasConnectivityManagedCapability());
+        nc.removeCapability(NET_CAPABILITY_FOREGROUND);
+        nc.addCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        assertTrue(nc.hasConnectivityManagedCapability());
+        nc.removeCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY);
+        nc.addCapability(NET_CAPABILITY_VALIDATED);
+        assertTrue(nc.hasConnectivityManagedCapability());
+    }
+
+    @Test
     public void testEqualsNetCapabilities() {
         NetworkCapabilities nc1 = new NetworkCapabilities();
         NetworkCapabilities nc2 = new NetworkCapabilities();
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 9453a80..3093629 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -28,6 +28,7 @@
 import static android.net.ConnectivityManager.TYPE_NONE;
 import static android.net.ConnectivityManager.TYPE_WIFI;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_INVALID;
+import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
 import static android.net.INetworkMonitor.NETWORK_TEST_RESULT_VALID;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
@@ -43,6 +44,7 @@
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VPN;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_RCS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_SUPL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
@@ -152,6 +154,7 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -187,6 +190,8 @@
 
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -203,6 +208,7 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Consumer;
 import java.util.function.Predicate;
 
 /**
@@ -442,6 +448,11 @@
             mNmValidationRedirectUrl = redirectUrl;
         }
 
+        void setNetworkPartial() {
+            mNmValidationResult = NETWORK_TEST_RESULT_PARTIAL_CONNECTIVITY;
+            mNmValidationRedirectUrl = null;
+        }
+
         MockNetworkAgent(int transport) {
             this(transport, new LinkProperties());
         }
@@ -484,6 +495,7 @@
             try {
                 doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
                 doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
+                doAnswer(validateAnswer).when(mNetworkMonitor).notifyAcceptPartialConnectivity();
             } catch (RemoteException e) {
                 fail(e.getMessage());
             }
@@ -499,7 +511,7 @@
 
             mNetworkAgent = new NetworkAgent(mHandlerThread.getLooper(), mServiceContext,
                     "Mock-" + typeName, mNetworkInfo, mNetworkCapabilities,
-                    linkProperties, mScore, new NetworkMisc()) {
+                    linkProperties, mScore, new NetworkMisc(), NetworkFactory.SerialNumber.NONE) {
                 @Override
                 public void unwanted() { mDisconnected.open(); }
 
@@ -669,6 +681,11 @@
             connect(false);
         }
 
+        public void connectWithPartialConnectivity() {
+            setNetworkPartial();
+            connect(false);
+        }
+
         public void suspend() {
             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -729,7 +746,7 @@
     /**
      * A NetworkFactory that allows tests to wait until any in-flight NetworkRequest add or remove
      * operations have been processed. Before ConnectivityService can add or remove any requests,
-     * the factory must be told to expect those operations by calling expectAddRequests or
+     * the factory must be told to expect those operations by calling expectAddRequestsWithScores or
      * expectRemoveRequests.
      */
     private static class MockNetworkFactory extends NetworkFactory {
@@ -738,19 +755,26 @@
         private final AtomicBoolean mNetworkStarted = new AtomicBoolean(false);
 
         // Used to expect that requests be removed or added on a separate thread, without sleeping.
-        // Callers can call either expectAddRequests() or expectRemoveRequests() exactly once, then
-        // cause some other thread to add or remove requests, then call waitForRequests(). We can
-        // either expect requests to be added or removed, but not both, because CountDownLatch can
-        // only count in one direction.
-        private CountDownLatch mExpectations;
+        // Callers can call either expectAddRequestsWithScores() or expectRemoveRequests() exactly
+        // once, then cause some other thread to add or remove requests, then call
+        // waitForRequests().
+        // It is not possible to wait for both add and remove requests. When adding, the queue
+        // contains the expected score. When removing, the value is unused, all matters is the
+        // number of objects in the queue.
+        private final LinkedBlockingQueue<Integer> mExpectations;
 
         // Whether we are currently expecting requests to be added or removed. Valid only if
-        // mExpectations is non-null.
+        // mExpectations is non-empty.
         private boolean mExpectingAdditions;
 
+        // Used to collect the networks requests managed by this factory. This is a duplicate of
+        // the internal information stored in the NetworkFactory (which is private).
+        private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
+
         public MockNetworkFactory(Looper looper, Context context, String logTag,
                 NetworkCapabilities filter) {
             super(looper, context, logTag, filter);
+            mExpectations = new LinkedBlockingQueue<>();
         }
 
         public int getMyRequestCount() {
@@ -782,74 +806,96 @@
         }
 
         @Override
-        protected void handleAddRequest(NetworkRequest request, int score) {
-            // If we're expecting anything, we must be expecting additions.
-            if (mExpectations != null && !mExpectingAdditions) {
-                fail("Can't add requests while expecting requests to be removed");
-            }
+        protected void handleAddRequest(NetworkRequest request, int score,
+                int factorySerialNumber) {
+            synchronized (mExpectations) {
+                final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
 
-            // Add the request.
-            super.handleAddRequest(request, score);
+                assertNotNull("Added more requests than expected (" + request + " score : "
+                        + score + ")", expectedScore);
+                // If we're expecting anything, we must be expecting additions.
+                if (!mExpectingAdditions) {
+                    fail("Can't add requests while expecting requests to be removed");
+                }
+                if (expectedScore != score) {
+                    fail("Expected score was " + expectedScore + " but actual was " + score
+                            + " in added request");
+                }
 
-            // Reduce the number of request additions we're waiting for.
-            if (mExpectingAdditions) {
-                assertTrue("Added more requests than expected", mExpectations.getCount() > 0);
-                mExpectations.countDown();
+                // Add the request.
+                mNetworkRequests.put(request.requestId, request);
+                super.handleAddRequest(request, score, factorySerialNumber);
+                mExpectations.notify();
             }
         }
 
         @Override
         protected void handleRemoveRequest(NetworkRequest request) {
-            // If we're expecting anything, we must be expecting removals.
-            if (mExpectations != null && mExpectingAdditions) {
-                fail("Can't remove requests while expecting requests to be added");
-            }
+            synchronized (mExpectations) {
+                final Integer expectedScore = mExpectations.poll(); // null if the queue is empty
 
-            // Remove the request.
-            super.handleRemoveRequest(request);
+                assertTrue("Removed more requests than expected", expectedScore != null);
+                // If we're expecting anything, we must be expecting removals.
+                if (mExpectingAdditions) {
+                    fail("Can't remove requests while expecting requests to be added");
+                }
 
-            // Reduce the number of request removals we're waiting for.
-            if (!mExpectingAdditions) {
-                assertTrue("Removed more requests than expected", mExpectations.getCount() > 0);
-                mExpectations.countDown();
+                // Remove the request.
+                mNetworkRequests.remove(request.requestId);
+                super.handleRemoveRequest(request);
+                mExpectations.notify();
             }
         }
 
+        // Trigger releasing the request as unfulfillable
+        public void triggerUnfulfillable(NetworkRequest r) {
+            super.releaseRequestAsUnfulfillableByAnyFactory(r);
+        }
+
         private void assertNoExpectations() {
-            if (mExpectations != null) {
-                fail("Can't add expectation, " + mExpectations.getCount() + " already pending");
+            if (mExpectations.size() != 0) {
+                fail("Can't add expectation, " + mExpectations.size() + " already pending");
             }
         }
 
-        // Expects that count requests will be added.
-        public void expectAddRequests(final int count) {
+        // Expects that requests with the specified scores will be added.
+        public void expectAddRequestsWithScores(final int... scores) {
             assertNoExpectations();
             mExpectingAdditions = true;
-            mExpectations = new CountDownLatch(count);
+            for (int score : scores) {
+                mExpectations.add(score);
+            }
         }
 
         // Expects that count requests will be removed.
         public void expectRemoveRequests(final int count) {
             assertNoExpectations();
             mExpectingAdditions = false;
-            mExpectations = new CountDownLatch(count);
+            for (int i = 0; i < count; ++i) {
+                mExpectations.add(0); // For removals the score is ignored so any value will do.
+            }
         }
 
         // Waits for the expected request additions or removals to happen within a timeout.
         public void waitForRequests() throws InterruptedException {
-            assertNotNull("Nothing to wait for", mExpectations);
-            mExpectations.await(TIMEOUT_MS, TimeUnit.MILLISECONDS);
-            final long count = mExpectations.getCount();
+            final long deadline = SystemClock.elapsedRealtime() + TIMEOUT_MS;
+            synchronized (mExpectations) {
+                while (mExpectations.size() > 0 && SystemClock.elapsedRealtime() < deadline) {
+                    mExpectations.wait(deadline - SystemClock.elapsedRealtime());
+                }
+            }
+            final long count = mExpectations.size();
             final String msg = count + " requests still not " +
                     (mExpectingAdditions ? "added" : "removed") +
                     " after " + TIMEOUT_MS + " ms";
             assertEquals(msg, 0, count);
-            mExpectations = null;
         }
 
-        public void waitForNetworkRequests(final int count) throws InterruptedException {
+        public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
+                throws InterruptedException {
             waitForRequests();
             assertEquals(count, getMyRequestCount());
+            return mNetworkRequests;
         }
     }
 
@@ -2299,6 +2345,12 @@
         callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
     }
 
+    private int[] makeIntArray(final int size, final int value) {
+        final int[] array = new int[size];
+        Arrays.fill(array, value);
+        return array;
+    }
+
     private void tryNetworkFactoryRequests(int capability) throws Exception {
         // Verify NOT_RESTRICTED is set appropriately
         final NetworkCapabilities nc = new NetworkRequest.Builder().addCapability(capability)
@@ -2320,7 +2372,7 @@
                 mServiceContext, "testFactory", filter);
         testFactory.setScoreFilter(40);
         ConditionVariable cv = testFactory.getNetworkStartedCV();
-        testFactory.expectAddRequests(1);
+        testFactory.expectAddRequestsWithScores(0);
         testFactory.register();
         testFactory.waitForNetworkRequests(1);
         int expectedRequestCount = 1;
@@ -2331,7 +2383,7 @@
             assertFalse(testFactory.getMyStartRequested());
             NetworkRequest request = new NetworkRequest.Builder().addCapability(capability).build();
             networkCallback = new NetworkCallback();
-            testFactory.expectAddRequests(1);
+            testFactory.expectAddRequestsWithScores(0);  // New request
             mCm.requestNetwork(request, networkCallback);
             expectedRequestCount++;
             testFactory.waitForNetworkRequests(expectedRequestCount);
@@ -2351,7 +2403,7 @@
         // When testAgent connects, ConnectivityService will re-send us all current requests with
         // the new score. There are expectedRequestCount such requests, and we must wait for all of
         // them.
-        testFactory.expectAddRequests(expectedRequestCount);
+        testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 50));
         testAgent.connect(false);
         testAgent.addCapability(capability);
         waitFor(cv);
@@ -2359,7 +2411,7 @@
         assertFalse(testFactory.getMyStartRequested());
 
         // Bring in a bunch of requests.
-        testFactory.expectAddRequests(10);
+        testFactory.expectAddRequestsWithScores(makeIntArray(10, 50));
         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
         ConnectivityManager.NetworkCallback[] networkCallbacks =
                 new ConnectivityManager.NetworkCallback[10];
@@ -2382,8 +2434,11 @@
 
         // Drop the higher scored network.
         cv = testFactory.getNetworkStartedCV();
+        // With the default network disconnecting, the requests are sent with score 0 to factories.
+        testFactory.expectAddRequestsWithScores(makeIntArray(expectedRequestCount, 0));
         testAgent.disconnect();
         waitFor(cv);
+        testFactory.waitForNetworkRequests(expectedRequestCount);
         assertEquals(expectedRequestCount, testFactory.getMyRequestCount());
         assertTrue(testFactory.getMyStartRequested());
 
@@ -2497,6 +2552,107 @@
         verifyActiveNetwork(TRANSPORT_CELLULAR);
     }
 
+    // TODO: deflake and re-enable
+    // @Test
+    public void testPartialConnectivity() {
+        // Register network callback.
+        NetworkRequest request = new NetworkRequest.Builder()
+                .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
+                .build();
+        TestNetworkCallback callback = new TestNetworkCallback();
+        mCm.registerNetworkCallback(request, callback);
+
+        // Bring up validated mobile data.
+        mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+        mCellNetworkAgent.connect(true);
+        callback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
+
+        // Bring up wifi with partial connectivity.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connectWithPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+
+        // Mobile data should be the default network.
+        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        callback.assertNoCallback();
+
+        // If the user chooses yes to use this partial connectivity wifi, switch the default
+        // network to wifi and check if wifi becomes valid or not.
+        mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
+                false /* always */);
+        // With https probe disabled, NetworkMonitor should pass the network validation with http
+        // probe.
+        mWiFiNetworkAgent.setNetworkValid();
+        waitForIdle();
+        try {
+            verify(mWiFiNetworkAgent.mNetworkMonitor,
+                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+        } catch (RemoteException e) {
+            fail(e.getMessage());
+        }
+        callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
+                mWiFiNetworkAgent);
+        assertTrue(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+        // Disconnect and reconnect wifi with partial connectivity again.
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.connectWithPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+
+        // Mobile data should be the default network.
+        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
+        // If the user chooses no, disconnect wifi immediately.
+        mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), false/* accept */,
+                false /* always */);
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+        // If user accepted partial connectivity before, and device reconnects to that network
+        // again, but now the network has full connectivity. The network shouldn't contain
+        // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        // acceptUnvalidated is also used as setting for accepting partial networks.
+        mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
+        mWiFiNetworkAgent.connect(true);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+        // Wifi should be the default network.
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+        // If user accepted partial connectivity before, and now the device reconnects to the
+        // partial connectivity network. The network should be valid and contain
+        // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
+        mWiFiNetworkAgent.connectWithPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
+        // NetworkMonitor detects partial connectivity
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mWiFiNetworkAgent.setNetworkValid();
+        waitForIdle();
+        try {
+            verify(mWiFiNetworkAgent.mNetworkMonitor,
+                    timeout(TIMEOUT_MS).times(1)).notifyAcceptPartialConnectivity();
+        } catch (RemoteException e) {
+            fail(e.getMessage());
+        }
+        callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
+        // Wifi should be the default network.
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+    }
+
     @Test
     public void testCaptivePortal() {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
@@ -3205,22 +3361,23 @@
         testFactory.setScoreFilter(40);
 
         // Register the factory and expect it to start looking for a network.
-        testFactory.expectAddRequests(1);
+        testFactory.expectAddRequestsWithScores(0);  // Score 0 as the request is not served yet.
         testFactory.register();
         testFactory.waitForNetworkRequests(1);
         assertTrue(testFactory.getMyStartRequested());
 
         // Bring up wifi. The factory stops looking for a network.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
-        testFactory.expectAddRequests(2);  // Because the default request changes score twice.
+        // Score 60 - 40 penalty for not validated yet, then 60 when it validates
+        testFactory.expectAddRequestsWithScores(20, 60);
         mWiFiNetworkAgent.connect(true);
-        testFactory.waitForNetworkRequests(1);
+        testFactory.waitForRequests();
         assertFalse(testFactory.getMyStartRequested());
 
         ContentResolver cr = mServiceContext.getContentResolver();
 
         // Turn on mobile data always on. The factory starts looking again.
-        testFactory.expectAddRequests(1);
+        testFactory.expectAddRequestsWithScores(0);  // Always on requests comes up with score 0
         setAlwaysOnNetworks(true);
         testFactory.waitForNetworkRequests(2);
         assertTrue(testFactory.getMyStartRequested());
@@ -3228,7 +3385,7 @@
         // Bring up cell data and check that the factory stops looking.
         assertLength(1, mCm.getAllNetworks());
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
-        testFactory.expectAddRequests(2);  // Because the cell request changes score twice.
+        testFactory.expectAddRequestsWithScores(10, 50);  // Unvalidated, then validated
         mCellNetworkAgent.connect(true);
         cellNetworkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
         testFactory.waitForNetworkRequests(2);
@@ -3523,6 +3680,55 @@
         networkCallback.assertNoCallback();
     }
 
+    /**
+     * Validate the callback flow for a factory releasing a request as unfulfillable.
+     */
+    @Test
+    public void testUnfulfillableNetworkRequest() throws Exception {
+        NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
+                NetworkCapabilities.TRANSPORT_WIFI).build();
+        final TestNetworkCallback networkCallback = new TestNetworkCallback();
+
+        final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
+        handlerThread.start();
+        NetworkCapabilities filter = new NetworkCapabilities()
+                .addTransportType(TRANSPORT_WIFI)
+                .addCapability(NET_CAPABILITY_INTERNET);
+        final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+                mServiceContext, "testFactory", filter);
+        testFactory.setScoreFilter(40);
+
+        // Register the factory and expect it to receive the default request.
+        testFactory.expectAddRequestsWithScores(0); // default request score is 0, not served yet
+        testFactory.register();
+        SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
+
+        assertEquals(1, requests.size()); // have 1 request at this point
+        int origRequestId = requests.valueAt(0).requestId;
+
+        // Now file the test request and expect it.
+        testFactory.expectAddRequestsWithScores(0);
+        mCm.requestNetwork(nr, networkCallback);
+        requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
+
+        int newRequestId = 0;
+        for (int i = 0; i < requests.size(); ++i) {
+            if (requests.valueAt(i).requestId != origRequestId) {
+                newRequestId = requests.valueAt(i).requestId;
+                break;
+            }
+        }
+
+        // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
+        testFactory.expectRemoveRequests(1);
+        testFactory.triggerUnfulfillable(requests.get(newRequestId));
+        networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+        testFactory.waitForRequests();
+
+        testFactory.unregister();
+        handlerThread.quit();
+    }
+
     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
 
         public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
@@ -3816,17 +4022,24 @@
         callback3.expectStopped();
     }
 
-    @Test
-    public void testNattSocketKeepalives_SingleThreadExecutor() throws Exception {
+    // Helper method to prepare the executor and run test
+    private void runTestWithSerialExecutors(Consumer<Executor> functor) {
         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
-        doTestNattSocketKeepalivesWithExecutor(executorSingleThread);
+        final Executor executorInline = (Runnable r) -> r.run();
+        functor.accept(executorSingleThread);
         executorSingleThread.shutdown();
+        functor.accept(executorInline);
     }
 
     @Test
-    public void testNattSocketKeepalives_InlineExecutor() throws Exception {
-        final Executor executorInline = (Runnable r) -> r.run();
-        doTestNattSocketKeepalivesWithExecutor(executorInline);
+    public void testNattSocketKeepalives() {
+        runTestWithSerialExecutors(executor -> {
+            try {
+                doTestNattSocketKeepalivesWithExecutor(executor);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        });
     }
 
     private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
@@ -3967,6 +4180,81 @@
 
         mWiFiNetworkAgent.disconnect();
         waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+        mWiFiNetworkAgent = null;
+    }
+
+    @Test
+    public void testTcpSocketKeepalives() {
+        runTestWithSerialExecutors(executor -> {
+            try {
+                doTestTcpSocketKeepalivesWithExecutor(executor);
+            } catch (Exception e) {
+                fail(e.getMessage());
+            }
+        });
+    }
+
+    private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
+        final int srcPortV4 = 12345;
+        final int srcPortV6 = 23456;
+        final InetAddress myIPv4 = InetAddress.getByName("127.0.0.1");
+        final InetAddress myIPv6 = InetAddress.getByName("::1");
+
+        final int validKaInterval = 15;
+        final int invalidKaInterval = 9;
+
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName("wlan12");
+        lp.addLinkAddress(new LinkAddress(myIPv6, 64));
+        lp.addLinkAddress(new LinkAddress(myIPv4, 25));
+        lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
+        lp.addRoute(new RouteInfo(InetAddress.getByName("127.0.0.254")));
+
+        final Network notMyNet = new Network(61234);
+        final Network myNet = connectKeepaliveNetwork(lp);
+
+        final Socket testSocketV4 = new Socket();
+        final Socket testSocketV6 = new Socket();
+
+        TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
+        SocketKeepalive ka;
+
+        // Attempt to start Tcp keepalives with invalid parameters and check for errors.
+        // Invalid network.
+        ka = mCm.createSocketKeepalive(notMyNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
+
+        // Invalid Socket (socket is not bound with IPv4 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Invalid Socket (socket is not bound with IPv6 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Bind the socket address
+        testSocketV4.bind(new InetSocketAddress(myIPv4, srcPortV4));
+        testSocketV6.bind(new InetSocketAddress(myIPv6, srcPortV6));
+
+        // Invalid Socket (socket is bound with IPv4 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV4, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        // Invalid Socket (socket is bound with IPv6 address).
+        ka = mCm.createSocketKeepalive(myNet, testSocketV6, executor, callback);
+        ka.start(validKaInterval);
+        callback.expectError(SocketKeepalive.ERROR_INVALID_SOCKET);
+
+        testSocketV4.close();
+        testSocketV6.close();
+
+        mWiFiNetworkAgent.disconnect();
+        waitFor(mWiFiNetworkAgent.getDisconnectedCV());
+        mWiFiNetworkAgent = null;
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
index 38352b3..6de4aa1 100644
--- a/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
+++ b/tests/net/java/com/android/server/connectivity/LingerMonitorTest.java
@@ -35,6 +35,7 @@
 import android.net.INetd;
 import android.net.Network;
 import android.net.NetworkCapabilities;
+import android.net.NetworkFactory;
 import android.net.NetworkInfo;
 import android.net.NetworkMisc;
 import android.os.INetworkManagementService;
@@ -352,7 +353,8 @@
         caps.addCapability(0);
         caps.addTransportType(transport);
         NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
-                caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS);
+                caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS,
+                NetworkFactory.SerialNumber.NONE);
         nai.everValidated = true;
         return nai;
     }
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index a12b0a0..fdba723 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -68,6 +68,7 @@
 import android.net.INetd;
 import android.net.INetworkPolicyManager;
 import android.net.INetworkStatsService;
+import android.net.ITetheringEventCallback;
 import android.net.InterfaceConfiguration;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
@@ -123,6 +124,7 @@
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Vector;
 
 @RunWith(AndroidJUnit4.class)
@@ -918,6 +920,67 @@
                 expectedInteractionsWithShowNotification);
     }
 
+    private class TestTetheringEventCallback extends ITetheringEventCallback.Stub {
+        private final ArrayList<Network> mActualUpstreams = new ArrayList<>();
+
+        public void expectUpstreamChanged(Network... networks) {
+            final ArrayList<Network> expectedUpstreams =
+                    new ArrayList<Network>(Arrays.asList(networks));
+            for (Network upstream : expectedUpstreams) {
+                // throws OOB if no expectations
+                assertEquals(mActualUpstreams.remove(0), upstream);
+            }
+            assertNoCallback();
+        }
+
+        @Override
+        public void onUpstreamChanged(Network network) {
+            mActualUpstreams.add(network);
+        }
+
+        public void assertNoCallback() {
+            assertTrue(mActualUpstreams.isEmpty());
+        }
+    }
+
+    @Test
+    public void testRegisterTetheringEventCallback() throws Exception {
+        TestTetheringEventCallback callback1 = new TestTetheringEventCallback();
+        TestTetheringEventCallback callback2 = new TestTetheringEventCallback();
+
+        // 1. Register one callback and run usb tethering.
+        mTethering.registerTetheringEventCallback(callback1);
+        mLooper.dispatchAll();
+        callback1.expectUpstreamChanged(new Network[] {null});
+        NetworkState upstreamState = buildMobileDualStackUpstreamState();
+        runUsbTethering(upstreamState);
+        callback1.expectUpstreamChanged(upstreamState.network);
+        // 2. Register second callback.
+        mTethering.registerTetheringEventCallback(callback2);
+        mLooper.dispatchAll();
+        callback2.expectUpstreamChanged(upstreamState.network);
+        // 3. Disable usb tethering.
+        mTethering.stopTethering(TETHERING_USB);
+        mLooper.dispatchAll();
+        sendUsbBroadcast(false, false, false);
+        mLooper.dispatchAll();
+        callback1.expectUpstreamChanged(new Network[] {null});
+        callback2.expectUpstreamChanged(new Network[] {null});
+        // 4. Unregister first callback and run hotspot.
+        mTethering.unregisterTetheringEventCallback(callback1);
+        mLooper.dispatchAll();
+        when(mUpstreamNetworkMonitor.getCurrentPreferredUpstream()).thenReturn(upstreamState);
+        when(mUpstreamNetworkMonitor.selectPreferredUpstreamType(any()))
+                .thenReturn(upstreamState);
+        when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+        mTethering.startTethering(TETHERING_WIFI, null, false);
+        mLooper.dispatchAll();
+        mTethering.interfaceStatusChanged(TEST_WLAN_IFNAME, true);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, TEST_WLAN_IFNAME, IFACE_IP_MODE_TETHERED);
+        mLooper.dispatchAll();
+        callback1.assertNoCallback();
+        callback2.expectUpstreamChanged(upstreamState.network);
+    }
 
     // TODO: Test that a request for hotspot mode doesn't interfere with an
     // already operating tethering mode interface.
diff --git a/tests/notification/Android.bp b/tests/notification/Android.bp
new file mode 100644
index 0000000..f05edaf
--- /dev/null
+++ b/tests/notification/Android.bp
@@ -0,0 +1,7 @@
+android_test {
+    name: "NotificationTests",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    libs: ["android.test.runner.stubs"],
+    sdk_version: "21",
+}
diff --git a/tests/notification/Android.mk b/tests/notification/Android.mk
deleted file mode 100644
index 255e6e7..0000000
--- a/tests/notification/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner.stubs
-LOCAL_PACKAGE_NAME := NotificationTests
-
-LOCAL_SDK_VERSION := 21
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/permission/Android.bp b/tests/permission/Android.bp
new file mode 100644
index 0000000..bd07009
--- /dev/null
+++ b/tests/permission/Android.bp
@@ -0,0 +1,12 @@
+android_test {
+    name: "FrameworkPermissionTests",
+    // Include all test java files.
+    srcs: ["src/**/*.java"],
+    libs: [
+        "android.test.runner",
+        "telephony-common",
+        "android.test.base",
+    ],
+    static_libs: ["junit"],
+    platform_apis: true,
+}
diff --git a/tests/permission/Android.mk b/tests/permission/Android.mk
deleted file mode 100644
index dd2f3ec..0000000
--- a/tests/permission/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_JAVA_LIBRARIES := android.test.runner telephony-common android.test.base
-LOCAL_STATIC_JAVA_LIBRARIES := junit
-LOCAL_PACKAGE_NAME := FrameworkPermissionTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/testables/Android.bp b/tests/testables/Android.bp
index 0bad7a4..eb6811c 100644
--- a/tests/testables/Android.bp
+++ b/tests/testables/Android.bp
@@ -15,18 +15,12 @@
 //
 
 java_library {
-
     name: "testables",
-    // ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_MODULE_TAG
-    // LOCAL_MODULE_TAG := tests
-
     srcs: ["src/**/*.java"],
-
     libs: [
         "android.test.runner",
         "android.test.mock",
         "androidx.test.rules",
         "mockito-target-inline-minus-junit4",
     ],
-
 }
diff --git a/tests/testables/tests/Android.bp b/tests/testables/tests/Android.bp
new file mode 100644
index 0000000..e1a58be
--- /dev/null
+++ b/tests/testables/tests/Android.bp
@@ -0,0 +1,41 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "TestablesTests",
+    platform_apis: true,
+    srcs: [
+        "src/**/*.java",
+        "src/**/I*.aidl",
+    ],
+    resource_dirs: ["res"],
+    static_libs: [
+        "androidx.test.rules",
+        "hamcrest-library",
+        "mockito-target-inline-minus-junit4",
+        "testables",
+    ],
+    compile_multilib: "both",
+    jni_libs: [
+        "libdexmakerjvmtiagent",
+        "libmultiplejvmtiagentsinterferenceagent",
+    ],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+    certificate: "platform",
+    test_suites: ["device-tests"],
+}
diff --git a/tests/testables/tests/Android.mk b/tests/testables/tests/Android.mk
deleted file mode 100644
index 16fbb18..0000000
--- a/tests/testables/tests/Android.mk
+++ /dev/null
@@ -1,47 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_PACKAGE_NAME := TestablesTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src) \
-    $(call all-Iaidl-files-under, src)
-
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules hamcrest-library \
-    mockito-target-inline-minus-junit4 \
-	testables
-
-LOCAL_MULTILIB := both
-
-LOCAL_JNI_SHARED_LIBRARIES := \
-    libdexmakerjvmtiagent \
-    libmultiplejvmtiagentsinterferenceagent
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
diff --git a/tests/touchlag/Android.bp b/tests/touchlag/Android.bp
index 2610cb3..092eea9 100644
--- a/tests/touchlag/Android.bp
+++ b/tests/touchlag/Android.bp
@@ -1,14 +1,11 @@
 cc_test {
     name: "test-touchlag",
     gtest: false,
-
     srcs: ["touchlag.cpp"],
-
     shared_libs: [
         "libcutils",
         "libutils",
     ],
-
     cflags: [
         "-Wall",
         "-Wextra",
diff --git a/tests/utils/Android.mk b/tests/utils/Android.mk
deleted file mode 100644
index c141484..0000000
--- a/tests/utils/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-include $(call all-subdir-makefiles)
diff --git a/tests/utils/DummyIME/Android.bp b/tests/utils/DummyIME/Android.bp
new file mode 100644
index 0000000..4a44b3b
--- /dev/null
+++ b/tests/utils/DummyIME/Android.bp
@@ -0,0 +1,21 @@
+//
+// Copyright (C) 2012 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.
+//
+
+android_test {
+    name: "DummyIME",
+    srcs: ["src/**/*.java"],
+    sdk_version: "current",
+}
diff --git a/tests/utils/DummyIME/Android.mk b/tests/utils/DummyIME/Android.mk
deleted file mode 100644
index 0f6c988..0000000
--- a/tests/utils/DummyIME/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-#
-# Copyright (C) 2012 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE_TAGS := tests
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_PACKAGE_NAME := DummyIME
-LOCAL_SDK_VERSION := current
-
-include $(BUILD_PACKAGE)
diff --git a/tests/utils/testutils/Android.bp b/tests/utils/testutils/Android.bp
index 4be6534..0a9e964 100644
--- a/tests/utils/testutils/Android.bp
+++ b/tests/utils/testutils/Android.bp
@@ -19,7 +19,7 @@
 
     srcs: ["java/**/*.java"],
 
-    static_libs: ["android-support-test"],
+    static_libs: ["junit"],
 
     libs: [
         "android.test.runner",
diff --git a/tools/hiddenapi/generate_hiddenapi_lists.py b/tools/hiddenapi/generate_hiddenapi_lists.py
index 2a8f695..6781eba 100755
--- a/tools/hiddenapi/generate_hiddenapi_lists.py
+++ b/tools/hiddenapi/generate_hiddenapi_lists.py
@@ -29,6 +29,9 @@
 FLAG_GREYLIST_MAX_O = "greylist-max-o"
 FLAG_GREYLIST_MAX_P = "greylist-max-p"
 FLAG_CORE_PLATFORM_API = "core-platform-api"
+FLAG_PUBLIC_API = "public-api"
+FLAG_SYSTEM_API = "system-api"
+FLAG_TEST_API = "test-api"
 
 # List of all known flags.
 FLAGS_API_LIST = [
@@ -38,7 +41,12 @@
     FLAG_GREYLIST_MAX_O,
     FLAG_GREYLIST_MAX_P,
 ]
-ALL_FLAGS = FLAGS_API_LIST + [ FLAG_CORE_PLATFORM_API ]
+ALL_FLAGS = FLAGS_API_LIST + [
+    FLAG_CORE_PLATFORM_API,
+    FLAG_PUBLIC_API,
+    FLAG_SYSTEM_API,
+    FLAG_TEST_API,
+    ]
 
 FLAGS_API_LIST_SET = set(FLAGS_API_LIST)
 ALL_FLAGS_SET = set(ALL_FLAGS)
@@ -203,14 +211,19 @@
 
         # Iterate over all CSV lines, find entry in dict and append flags to it.
         for csv in csv_values:
-            self._dict[csv[0]].update(csv[1:])
+            flags = csv[1:]
+            if (FLAG_PUBLIC_API in flags) or (FLAG_SYSTEM_API in flags):
+                flags.append(FLAG_WHITELIST)
+            elif FLAG_TEST_API in flags:
+                flags.append(FLAG_GREYLIST)
+            self._dict[csv[0]].update(flags)
 
     def assign_flag(self, flag, apis, source="<unknown>"):
         """Assigns a flag to given subset of entries.
 
         Args:
             flag (string): One of ALL_FLAGS.
-            apis (set): Subset of APIs to recieve the flag.
+            apis (set): Subset of APIs to receive the flag.
             source (string): Origin of `entries_subset`. Will be printed in error messages.
 
         Throws: