Merge "Added implementation for VTI add/remove address"
diff --git a/Android.bp b/Android.bp
index 010f496..cbb4369 100644
--- a/Android.bp
+++ b/Android.bp
@@ -784,3 +784,182 @@
         "fontTools",
     ],
 }
+
+// TODO: Don't rely on this list once droiddoc can take a list of packages to document
+frameworks_base_subdirs = [
+    "core/java",
+    "graphics/java",
+    "location/java",
+    "media/java",
+    "media/mca/effect/java",
+    "media/mca/filterfw/java",
+    "media/mca/filterpacks/java",
+    "drm/java",
+    "opengl/java",
+    "sax/java",
+    "telecomm/java",
+    "telephony/java",
+    "wifi/java",
+    "lowpan/java",
+    "keystore/java",
+    "rs/java",
+]
+
+packages_to_document = [
+    "android",
+    "javax/microedition/khronos",
+    "org/apache/http/conn",
+    "org/apache/http/params",
+]
+
+// The since flag (-since N.xml API_LEVEL) is used to add API Level information
+// to the reference documentation. Must be in order of oldest to newest.
+//
+// Conscrypt (com.android.org.conscrypt) is an implementation detail and should
+// not be referenced in the documentation.
+framework_docs_args = "-android -manifest $(location core/res/AndroidManifest.xml) " +
+     "-hidePackage com.android.okhttp -hidePackage com.android.org.conscrypt -hidePackage com.android.server " +
+     "-since $(location api/1.xml) 1 " +
+     "-since $(location api/2.xml) 2 " +
+     "-since $(location api/3.xml) 3 " +
+     "-since $(location api/4.xml) 4 " +
+     "-since $(location api/5.xml) 5 " +
+     "-since $(location api/6.xml) 6 " +
+     "-since $(location api/7.xml) 7 " +
+     "-since $(location api/8.xml) 8 " +
+     "-since $(location api/9.xml) 9 " +
+     "-since $(location api/10.xml) 10 " +
+     "-since $(location api/11.xml) 11 " +
+     "-since $(location api/12.xml) 12 " +
+     "-since $(location api/13.xml) 13 " +
+     "-since $(location api/14.txt) 14 " +
+     "-since $(location api/15.txt) 15 " +
+     "-since $(location api/16.txt) 16 " +
+     "-since $(location api/17.txt) 17 " +
+     "-since $(location api/18.txt) 18 " +
+     "-since $(location api/19.txt) 19 " +
+     "-since $(location api/20.txt) 20 " +
+     "-since $(location api/21.txt) 21 " +
+     "-since $(location api/22.txt) 22 " +
+     "-since $(location api/23.txt) 23 " +
+     "-since $(location api/24.txt) 24 " +
+     "-since $(location api/25.txt) 25 " +
+     "-since $(location api/26.txt) 26 " +
+     "-since $(location api/27.txt) 27 " +
+     "-werror -lerror -hide 111 -hide 113 -hide 125 -hide 126 -hide 127 -hide 128 " +
+     "-overview $(location core/java/overview.html) " +
+     // Federate Support Library references against local API file.
+     "-federate SupportLib https://developer.android.com " +
+     "-federationapi SupportLib $(location current/support-api.txt) "
+
+doc_defaults {
+    name: "framework-docs-default",
+    srcs: [
+        // test mock src files.
+        "test-mock/src/android/test/mock/**/*.java",
+        // test runner excluding mock src files.
+        "test-runner/src/**/*.java",
+        "test-base/src/**/*.java",
+        ":opt-telephony-srcs",
+        ":opt-net-voip-srcs",
+        ":openjdk_javadoc_files",
+        ":non_openjdk_javadoc_files",
+        ":android_icu4j_src_files_for_docs",
+        ":gen-ojluni-jaif-annotated-srcs",
+    ],
+    exclude_srcs: [
+        ":annotated_ojluni_files",
+    ],
+    srcs_lib: "framework",
+    srcs_lib_whitelist_dirs: frameworks_base_subdirs,
+    srcs_lib_whitelist_pkgs: packages_to_document,
+    libs: [
+        "core-oj",
+        "core-libart",
+        "conscrypt",
+        "bouncycastle",
+        "okhttp",
+        "ext",
+        "framework",
+        "voip-common",
+        "android.test.mock",
+    ],
+    local_sourcepaths: frameworks_base_subdirs,
+    html_dirs: [
+        "docs/html",
+    ],
+    knowntags: [
+        "docs/knowntags.txt",
+        ":known-oj-tags",
+    ],
+    custom_template: "droiddoc-templates-sdk",
+    hdf: [
+        "dac true",
+        "sdk.codename O",
+        "sdk.preview.version 1",
+        "sdk.version 7.0",
+        "sdk.rel.id 1",
+        "sdk.preview 0",
+    ],
+    resourcesdir: "docs/html/reference/images",
+    resourcesoutdir: "reference/android/images",
+}
+
+droiddoc {
+    name: "api-stubs-docs",
+    defaults: ["framework-docs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+        ":api-version-xml",
+        "core/java/overview.html",
+        ":current-support-api",
+    ],
+    args: framework_docs_args +
+          "-referenceonly -api $(genDir)/PACKAGING/public_api.txt -privateApi $(genDir)/PACKAGING/private.txt "+
+          "-privateDexApi $(genDir)/PACKAGING/private-dex.txt -removedApi $(genDir)/PACKAGING/removed.txt -nodocs",
+    out: [
+        "PACKAGING/public_api.txt",
+        "PACKAGING/private.txt",
+        "PACKAGING/private-dex.txt",
+    ]
+}
+
+droiddoc {
+    name: "system-api-stubs-docs",
+    defaults: ["framework-docs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+        ":api-version-xml",
+        "core/java/overview.html",
+        ":current-support-api",
+    ],
+    args: framework_docs_args +
+          "-referenceonly -showAnnotation android.annotation.SystemApi " +
+          "-api $(genDir)/PACKAGING/system-api.txt -privateApi $(genDir)/PACKAGING/system-private.txt " +
+          "-privateDexApi $(genDir)/PACKAGING/system-private-dex.txt -removedApi $(genDir)/PACKAGING/system-removed.txt " +
+          "-exactApi $(genDir)/PACKAGING/system-exact.txt -nodocs",
+    out: [
+        "PACKAGING/system-api.txt",
+        "PACKAGING/system-private.txt",
+        "PACKAGING/system-private-dex.txt",
+    ]
+}
+
+droiddoc {
+    name: "test-api-stubs-docs",
+    defaults: ["framework-docs-default"],
+    arg_files: [
+        "core/res/AndroidManifest.xml",
+        ":api-version-xml",
+        "core/java/overview.html",
+        ":current-support-api",
+    ],
+    args: framework_docs_args +
+          "-referenceonly -showAnnotation android.annotation.TestApi " +
+          "-api $(genDir)/PACKAGING/test-api.txt " +
+          "-removedApi $(genDir)/PACKAGING/test-removed.txt " +
+          "-exactApi $(genDir)/PACKAGING/test-exact.txt -nodocs",
+    out: [
+        "PACKAGING/test-api.txt",
+    ]
+}
diff --git a/Android.mk b/Android.mk
index 2517f6b..147d2cf 100644
--- a/Android.mk
+++ b/Android.mk
@@ -173,6 +173,8 @@
     -knowntags ./frameworks/base/docs/knowntags.txt \
     -knowntags ./libcore/known_oj_tags.txt \
     -manifest ./frameworks/base/core/res/AndroidManifest.xml \
+    -hidePackage com.android.internal \
+    -hidePackage com.android.internal.util \
     -hidePackage com.android.okhttp \
     -hidePackage com.android.org.conscrypt \
     -hidePackage com.android.server \
diff --git a/api/current.txt b/api/current.txt
index 8df028c..047a20e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -21435,6 +21435,7 @@
     field public static final java.lang.String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
     field public static final java.lang.String ACTION_HDMI_AUDIO_PLUG = "android.media.action.HDMI_AUDIO_PLUG";
     field public static final java.lang.String ACTION_HEADSET_PLUG = "android.intent.action.HEADSET_PLUG";
+    field public static final java.lang.String ACTION_MICROPHONE_MUTE_CHANGED = "android.media.action.MICROPHONE_MUTE_CHANGED";
     field public static final deprecated java.lang.String ACTION_SCO_AUDIO_STATE_CHANGED = "android.media.SCO_AUDIO_STATE_CHANGED";
     field public static final java.lang.String ACTION_SCO_AUDIO_STATE_UPDATED = "android.media.ACTION_SCO_AUDIO_STATE_UPDATED";
     field public static final int ADJUST_LOWER = -1; // 0xffffffff
@@ -25735,17 +25736,17 @@
     field public static final int RESTRICT_BACKGROUND_STATUS_DISABLED = 1; // 0x1
     field public static final int RESTRICT_BACKGROUND_STATUS_ENABLED = 3; // 0x3
     field public static final int RESTRICT_BACKGROUND_STATUS_WHITELISTED = 2; // 0x2
-    field public static final int TYPE_BLUETOOTH = 7; // 0x7
-    field public static final int TYPE_DUMMY = 8; // 0x8
-    field public static final int TYPE_ETHERNET = 9; // 0x9
-    field public static final int TYPE_MOBILE = 0; // 0x0
-    field public static final int TYPE_MOBILE_DUN = 4; // 0x4
+    field public static final deprecated int TYPE_BLUETOOTH = 7; // 0x7
+    field public static final deprecated int TYPE_DUMMY = 8; // 0x8
+    field public static final deprecated int TYPE_ETHERNET = 9; // 0x9
+    field public static final deprecated int TYPE_MOBILE = 0; // 0x0
+    field public static final deprecated int TYPE_MOBILE_DUN = 4; // 0x4
     field public static final deprecated int TYPE_MOBILE_HIPRI = 5; // 0x5
     field public static final deprecated int TYPE_MOBILE_MMS = 2; // 0x2
     field public static final deprecated int TYPE_MOBILE_SUPL = 3; // 0x3
-    field public static final int TYPE_VPN = 17; // 0x11
-    field public static final int TYPE_WIFI = 1; // 0x1
-    field public static final int TYPE_WIMAX = 6; // 0x6
+    field public static final deprecated int TYPE_VPN = 17; // 0x11
+    field public static final deprecated int TYPE_WIFI = 1; // 0x1
+    field public static final deprecated int TYPE_WIMAX = 6; // 0x6
   }
 
   public static class ConnectivityManager.NetworkCallback {
@@ -26022,16 +26023,16 @@
     method public int describeContents();
     method public android.net.NetworkInfo.DetailedState getDetailedState();
     method public java.lang.String getExtraInfo();
-    method public java.lang.String getReason();
-    method public android.net.NetworkInfo.State getState();
+    method public deprecated java.lang.String getReason();
+    method public deprecated android.net.NetworkInfo.State getState();
     method public int getSubtype();
     method public java.lang.String getSubtypeName();
-    method public int getType();
-    method public java.lang.String getTypeName();
-    method public boolean isAvailable();
+    method public deprecated int getType();
+    method public deprecated java.lang.String getTypeName();
+    method public deprecated boolean isAvailable();
     method public boolean isConnected();
-    method public boolean isConnectedOrConnecting();
-    method public boolean isFailover();
+    method public deprecated boolean isConnectedOrConnecting();
+    method public deprecated boolean isFailover();
     method public deprecated boolean isRoaming();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
@@ -27545,7 +27546,7 @@
     field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID";
     field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES";
     field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence";
-    field public static final java.lang.String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+    field public static final java.lang.String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
     field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG";
     field public static final int FLAG_READER_NFC_A = 1; // 0x1
     field public static final int FLAG_READER_NFC_B = 2; // 0x2
@@ -33430,7 +33431,7 @@
     field public static final java.lang.String FEATURES = "features";
     field public static final int FEATURES_HD_CALL = 4; // 0x4
     field public static final int FEATURES_PULLED_EXTERNALLY = 2; // 0x2
-    field public static final int FEATURES_RTT = 16; // 0x10
+    field public static final int FEATURES_RTT = 32; // 0x20
     field public static final int FEATURES_VIDEO = 1; // 0x1
     field public static final int FEATURES_WIFI = 8; // 0x8
     field public static final java.lang.String GEOCODED_LOCATION = "geocoded_location";
@@ -35554,11 +35555,11 @@
     field public static final java.lang.String ADDRESS = "address";
   }
 
-  public static final class Telephony.CarrierIdentification implements android.provider.BaseColumns {
+  public static final class Telephony.CarrierId implements android.provider.BaseColumns {
     method public static android.net.Uri getUriForSubscriptionId(int);
-    field public static final java.lang.String CID = "carrier_id";
+    field public static final java.lang.String CARRIER_ID = "carrier_id";
+    field public static final java.lang.String CARRIER_NAME = "carrier_name";
     field public static final android.net.Uri CONTENT_URI;
-    field public static final java.lang.String NAME = "carrier_name";
   }
 
   public static final class Telephony.Carriers implements android.provider.BaseColumns {
@@ -39192,10 +39193,10 @@
     method public void onStateChanged(android.telecom.Call, int);
     method public void onVideoCallChanged(android.telecom.Call, android.telecom.InCallService.VideoCall);
     field public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1; // 0x1
-    field public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3; // 0x3
-    field public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2; // 0x2
-    field public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4; // 0x4
-    field public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2; // 0x2
+    field public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4; // 0x4
+    field public static final int HANDOVER_FAILURE_UNKNOWN = 5; // 0x5
+    field public static final int HANDOVER_FAILURE_USER_REJECTED = 3; // 0x3
   }
 
   public static class Call.Details {
@@ -39952,11 +39953,9 @@
 package android.telephony {
 
   public final class AccessNetworkConstants {
-    ctor public AccessNetworkConstants();
   }
 
   public static final class AccessNetworkConstants.AccessNetworkType {
-    ctor public AccessNetworkConstants.AccessNetworkType();
     field public static final int CDMA2000 = 4; // 0x4
     field public static final int EUTRAN = 3; // 0x3
     field public static final int GERAN = 1; // 0x1
@@ -39966,7 +39965,6 @@
   }
 
   public static final class AccessNetworkConstants.EutranBand {
-    ctor public AccessNetworkConstants.EutranBand();
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_10 = 10; // 0xa
     field public static final int BAND_11 = 11; // 0xb
@@ -40018,7 +40016,6 @@
   }
 
   public static final class AccessNetworkConstants.GeranBand {
-    ctor public AccessNetworkConstants.GeranBand();
     field public static final int BAND_450 = 3; // 0x3
     field public static final int BAND_480 = 4; // 0x4
     field public static final int BAND_710 = 5; // 0x5
@@ -40036,7 +40033,6 @@
   }
 
   public static final class AccessNetworkConstants.UtranBand {
-    ctor public AccessNetworkConstants.UtranBand();
     field public static final int BAND_1 = 1; // 0x1
     field public static final int BAND_10 = 10; // 0xa
     field public static final int BAND_11 = 11; // 0xb
@@ -40089,6 +40085,8 @@
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_ESCAPED_CHARS_STRING = "carrier_instant_lettering_escaped_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_INVALID_CHARS_STRING = "carrier_instant_lettering_invalid_chars_string";
     field public static final java.lang.String KEY_CARRIER_INSTANT_LETTERING_LENGTH_LIMIT_INT = "carrier_instant_lettering_length_limit_int";
+    field public static final java.lang.String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
+    field public static final java.lang.String KEY_CARRIER_NAME_STRING = "carrier_name_string";
     field public static final java.lang.String KEY_CARRIER_SETTINGS_ENABLE_BOOL = "carrier_settings_enable_bool";
     field public static final java.lang.String KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL = "carrier_use_ims_first_for_emergency_bool";
     field public static final java.lang.String KEY_CARRIER_VOLTE_AVAILABLE_BOOL = "carrier_volte_available_bool";
@@ -40233,9 +40231,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40249,9 +40247,9 @@
     method public int getCi();
     method public int getEarfcn();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40265,8 +40263,8 @@
     method public int getCid();
     method public int getCpid();
     method public int getLac();
-    method public java.lang.String getMccStr();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMccString();
+    method public java.lang.String getMncString();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.CellIdentityTdscdma> CREATOR;
   }
@@ -40275,9 +40273,9 @@
     method public int getCid();
     method public int getLac();
     method public deprecated int getMcc();
-    method public java.lang.String getMccStr();
+    method public java.lang.String getMccString();
     method public deprecated int getMnc();
-    method public java.lang.String getMncStr();
+    method public java.lang.String getMncString();
     method public java.lang.String getMobileNetworkOperator();
     method public java.lang.CharSequence getOperatorAlphaLong();
     method public java.lang.CharSequence getOperatorAlphaShort();
@@ -40471,7 +40469,8 @@
   }
 
   public class NetworkScan {
-    method public void stop() throws android.os.RemoteException;
+    method public deprecated void stop() throws android.os.RemoteException;
+    method public void stopScan();
     field public static final int ERROR_INTERRUPTED = 10002; // 0x2712
     field public static final int ERROR_INVALID_SCAN = 2; // 0x2
     field public static final int ERROR_INVALID_SCANID = 10001; // 0x2711
@@ -40608,17 +40607,17 @@
     ctor public ServiceState(android.os.Parcel);
     method protected void copyFrom(android.telephony.ServiceState);
     method public int describeContents();
+    method public int getCdmaNetworkId();
+    method public int getCdmaSystemId();
     method public int[] getCellBandwidths();
     method public int getChannelNumber();
     method public int getDuplexMode();
     method public boolean getIsManualSelection();
-    method public int getNetworkId();
     method public java.lang.String getOperatorAlphaLong();
     method public java.lang.String getOperatorAlphaShort();
     method public java.lang.String getOperatorNumeric();
     method public boolean getRoaming();
     method public int getState();
-    method public int getSystemId();
     method public void setIsManualSelection(boolean);
     method public void setOperatorName(java.lang.String, java.lang.String, java.lang.String);
     method public void setRoaming(boolean);
@@ -40832,8 +40831,6 @@
     method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
     method public java.util.List<android.telephony.CellInfo> getAllCellInfo();
-    method public int getAndroidCarrierIdForSubscription();
-    method public java.lang.CharSequence getAndroidCarrierNameForSubscription();
     method public int getCallState();
     method public android.os.PersistableBundle getCarrierConfig();
     method public deprecated android.telephony.CellLocation getCellLocation();
@@ -40864,6 +40861,8 @@
     method public int getPhoneType();
     method public android.telephony.ServiceState getServiceState();
     method public android.telephony.SignalStrength getSignalStrength();
+    method public int getSimCarrierId();
+    method public java.lang.CharSequence getSimCarrierIdName();
     method public java.lang.String getSimCountryIso();
     method public java.lang.String getSimOperator();
     method public java.lang.String getSimOperatorName();
@@ -40895,7 +40894,8 @@
     method public boolean isVoicemailVibrationEnabled(android.telecom.PhoneAccountHandle);
     method public boolean isWorldPhone();
     method public void listen(android.telephony.PhoneStateListener, int);
-    method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
+    method public android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, java.util.concurrent.Executor, android.telephony.TelephonyScanManager.NetworkScanCallback);
+    method public deprecated android.telephony.NetworkScan requestNetworkScan(android.telephony.NetworkScanRequest, android.telephony.TelephonyScanManager.NetworkScanCallback);
     method public void sendDialerSpecialCode(java.lang.String);
     method public java.lang.String sendEnvelopeWithStatus(java.lang.String);
     method public void sendUssdRequest(java.lang.String, android.telephony.TelephonyManager.UssdResponseCallback, android.os.Handler);
diff --git a/api/system-current.txt b/api/system-current.txt
index d3f7260..29a328a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4111,7 +4111,6 @@
 package android.telephony {
 
   public static final class AccessNetworkConstants.TransportType {
-    ctor public AccessNetworkConstants.TransportType();
     field public static final int WLAN = 2; // 0x2
     field public static final int WWAN = 1; // 0x1
   }
@@ -4294,6 +4293,7 @@
     method public java.lang.String getCdmaMin(int);
     method public int getCurrentPhoneType();
     method public int getCurrentPhoneType(int);
+    method public int getDataActivationState();
     method public deprecated boolean getDataEnabled();
     method public deprecated boolean getDataEnabled(int);
     method public int getSimApplicationState();
@@ -4301,6 +4301,7 @@
     method public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
     method public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
     method public android.os.Bundle getVisualVoicemailSettings();
+    method public int getVoiceActivationState();
     method public boolean handlePinMmi(java.lang.String);
     method public boolean handlePinMmiForSubscriber(int, java.lang.String);
     method public boolean isDataConnectivityPossible();
@@ -4312,10 +4313,12 @@
     method public deprecated boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
     method public boolean needsOtaServiceProvisioning();
     method public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
+    method public void setDataActivationState(int);
     method public deprecated void setDataEnabled(int, boolean);
     method public boolean setRadio(boolean);
     method public boolean setRadioPower(boolean);
     method public deprecated void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
+    method public void setVoiceActivationState(int);
     method public deprecated void silenceRinger();
     method public boolean supplyPin(java.lang.String);
     method public int[] supplyPinReportResult(java.lang.String);
@@ -4334,6 +4337,11 @@
     field public static final java.lang.String EXTRA_SIM_STATE = "android.telephony.extra.SIM_STATE";
     field public static final java.lang.String EXTRA_VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL = "android.telephony.extra.VISUAL_VOICEMAIL_ENABLED_BY_USER_BOOL";
     field public static final java.lang.String EXTRA_VOICEMAIL_SCRAMBLED_PIN_STRING = "android.telephony.extra.VOICEMAIL_SCRAMBLED_PIN_STRING";
+    field public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2; // 0x2
+    field public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1; // 0x1
+    field public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3; // 0x3
+    field public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4; // 0x4
+    field public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0; // 0x0
     field public static final int SIM_STATE_LOADED = 10; // 0xa
     field public static final int SIM_STATE_PRESENT = 11; // 0xb
   }
@@ -4349,12 +4357,13 @@
   }
 
   public class UiccSlotInfo implements android.os.Parcelable {
-    ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int);
+    ctor public UiccSlotInfo(boolean, boolean, java.lang.String, int, int, boolean);
     method public int describeContents();
     method public java.lang.String getCardId();
     method public int getCardStateInfo();
     method public boolean getIsActive();
     method public boolean getIsEuicc();
+    method public boolean getIsExtendedApduSupported();
     method public int getLogicalSlotIdx();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -4505,6 +4514,7 @@
     field public static final int RESET_OPTION_DELETE_FIELD_LOADED_TEST_PROFILES = 2; // 0x2
     field public static final int RESET_OPTION_DELETE_OPERATIONAL_PROFILES = 1; // 0x1
     field public static final int RESET_OPTION_RESET_DEFAULT_SMDP_ADDRESS = 4; // 0x4
+    field public static final int RESULT_EUICC_NOT_FOUND = -2; // 0xfffffffe
     field public static final int RESULT_OK = 0; // 0x0
     field public static final int RESULT_UNKNOWN_ERROR = -1; // 0xffffffff
   }
@@ -5209,19 +5219,24 @@
   }
 
   public final class ImsFeatureConfiguration implements android.os.Parcelable {
-    ctor public ImsFeatureConfiguration();
     method public int describeContents();
-    method public int[] getServiceFeatures();
+    method public java.util.Set<android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair> getServiceFeatures();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telephony.ims.stub.ImsFeatureConfiguration> CREATOR;
   }
 
   public static class ImsFeatureConfiguration.Builder {
     ctor public ImsFeatureConfiguration.Builder();
-    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int);
+    method public android.telephony.ims.stub.ImsFeatureConfiguration.Builder addFeature(int, int);
     method public android.telephony.ims.stub.ImsFeatureConfiguration build();
   }
 
+  public static final class ImsFeatureConfiguration.FeatureSlotPair {
+    ctor public ImsFeatureConfiguration.FeatureSlotPair(int, int);
+    field public final int featureType;
+    field public final int slotId;
+  }
+
   public class ImsMultiEndpointImplBase {
     ctor public ImsMultiEndpointImplBase();
     method public final void onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>);
diff --git a/api/test-current.txt b/api/test-current.txt
index bf3d0c2..05f5c77 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -436,6 +436,10 @@
     field public static final java.lang.String MBMS_STREAMING_SERVICE_OVERRIDE_METADATA = "mbms-streaming-service-override";
   }
 
+  public class ServiceState implements android.os.Parcelable {
+    method public void setCdmaSystemAndNetworkId(int, int);
+  }
+
 }
 
 package android.telephony.mbms {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 565eaeb..bae2a26 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -612,7 +612,7 @@
                         streamingOutput);
                 profiling = true;
             } catch (RuntimeException e) {
-                Slog.w(TAG, "Profiling failed on path " + profileFile);
+                Slog.w(TAG, "Profiling failed on path " + profileFile, e);
                 try {
                     profileFd.close();
                     profileFd = null;
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index d33af4f..6ca2349 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -24,7 +24,6 @@
 import android.net.NetworkTemplate;
 import android.net.TrafficStats;
 import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.util.IntArray;
 import android.util.Log;
 
@@ -98,9 +97,8 @@
 
     /** @hide */
     NetworkStats(Context context, NetworkTemplate template, int flags, long startTimestamp,
-            long endTimestamp) throws RemoteException, SecurityException {
-        final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
+            long endTimestamp, INetworkStatsService statsService)
+            throws RemoteException, SecurityException {
         // Open network stats session
         mSession = statsService.openSessionForUsageStats(flags, context.getOpPackageName());
         mCloseGuard.open("close");
diff --git a/core/java/android/app/usage/NetworkStatsManager.java b/core/java/android/app/usage/NetworkStatsManager.java
index 5576e86..2357637 100644
--- a/core/java/android/app/usage/NetworkStatsManager.java
+++ b/core/java/android/app/usage/NetworkStatsManager.java
@@ -37,6 +37,8 @@
 import android.os.ServiceManager.ServiceNotFoundException;
 import android.util.Log;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 /**
  * Provides access to network usage history and statistics. Usage data is collected in
  * discrete bins of time called 'Buckets'. See {@link NetworkStats.Bucket} for details.
@@ -107,9 +109,15 @@
      * {@hide}
      */
     public NetworkStatsManager(Context context) throws ServiceNotFoundException {
+        this(context, INetworkStatsService.Stub.asInterface(
+                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE)));
+    }
+
+    /** @hide */
+    @VisibleForTesting
+    public NetworkStatsManager(Context context, INetworkStatsService service) {
         mContext = context;
-        mService = INetworkStatsService.Stub.asInterface(
-                ServiceManager.getServiceOrThrow(Context.NETWORK_STATS_SERVICE));
+        mService = service;
         setPollOnOpen(true);
     }
 
@@ -135,7 +143,8 @@
     public Bucket querySummaryForDevice(NetworkTemplate template,
             long startTime, long endTime) throws SecurityException, RemoteException {
         Bucket bucket = null;
-        NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        NetworkStats stats = new NetworkStats(mContext, template, mFlags, startTime, endTime,
+                mService);
         bucket = stats.getDeviceSummaryForNetwork();
 
         stats.close();
@@ -208,7 +217,7 @@
         }
 
         NetworkStats stats;
-        stats = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        stats = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         stats.startSummaryEnumeration();
 
         stats.close();
@@ -245,7 +254,7 @@
         }
 
         NetworkStats result;
-        result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         result.startSummaryEnumeration();
 
         return result;
@@ -295,7 +304,7 @@
 
         NetworkStats result;
         try {
-            result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+            result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
             result.startHistoryEnumeration(uid, tag);
         } catch (RemoteException e) {
             Log.e(TAG, "Error while querying stats for uid=" + uid + " tag=" + tag, e);
@@ -341,7 +350,7 @@
         }
 
         NetworkStats result;
-        result = new NetworkStats(mContext, template, mFlags, startTime, endTime);
+        result = new NetworkStats(mContext, template, mFlags, startTime, endTime, mService);
         result.startUserUidEnumeration();
         return result;
     }
@@ -451,19 +460,20 @@
     }
 
     private static NetworkTemplate createTemplate(int networkType, String subscriberId) {
-        NetworkTemplate template = null;
+        final NetworkTemplate template;
         switch (networkType) {
-            case ConnectivityManager.TYPE_MOBILE: {
-                template = NetworkTemplate.buildTemplateMobileAll(subscriberId);
-                } break;
-            case ConnectivityManager.TYPE_WIFI: {
+            case ConnectivityManager.TYPE_MOBILE:
+                template = subscriberId == null
+                        ? NetworkTemplate.buildTemplateMobileWildcard()
+                        : NetworkTemplate.buildTemplateMobileAll(subscriberId);
+                break;
+            case ConnectivityManager.TYPE_WIFI:
                 template = NetworkTemplate.buildTemplateWifiWildcard();
-                } break;
-            default: {
+                break;
+            default:
                 throw new IllegalArgumentException("Cannot create template for network type "
                         + networkType + ", subscriberId '"
                         + NetworkIdentity.scrubSubscriberId(subscriberId) + "'.");
-            }
         }
         return template;
     }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index dc76152..6aabe18 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -537,13 +537,14 @@
             "android.bluetooth.adapter.action.BLE_ACL_DISCONNECTED";
 
     /** The profile is in disconnected state */
-    public static final int STATE_DISCONNECTED = 0;
+    public static final int STATE_DISCONNECTED = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED;
     /** The profile is in connecting state */
-    public static final int STATE_CONNECTING = 1;
+    public static final int STATE_CONNECTING = BluetoothProtoEnums.CONNECTION_STATE_CONNECTING;
     /** The profile is in connected state */
-    public static final int STATE_CONNECTED = 2;
+    public static final int STATE_CONNECTED = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED;
     /** The profile is in disconnecting state */
-    public static final int STATE_DISCONNECTING = 3;
+    public static final int STATE_DISCONNECTING =
+            BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTING;
 
     /** @hide */
     public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
@@ -675,6 +676,10 @@
         if (!getLeAccess()) {
             return null;
         }
+        if (!isMultipleAdvertisementSupported()) {
+            Log.e(TAG, "Bluetooth LE advertising not supported");
+            return null;
+        }
         synchronized (mLock) {
             if (sBluetoothLeAdvertiser == null) {
                 sBluetoothLeAdvertiser = new BluetoothLeAdvertiser(mManagerService);
diff --git a/core/java/android/bluetooth/BluetoothProfile.java b/core/java/android/bluetooth/BluetoothProfile.java
index 656188f..6aeb94d 100644
--- a/core/java/android/bluetooth/BluetoothProfile.java
+++ b/core/java/android/bluetooth/BluetoothProfile.java
@@ -38,7 +38,7 @@
      * This extra represents the current connection state of the profile of the
      * Bluetooth device.
      */
-    public static final String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
+    String EXTRA_STATE = "android.bluetooth.profile.extra.STATE";
 
     /**
      * Extra for the connection state intents of the individual profiles.
@@ -46,123 +46,130 @@
      * This extra represents the previous connection state of the profile of the
      * Bluetooth device.
      */
-    public static final String EXTRA_PREVIOUS_STATE =
+    String EXTRA_PREVIOUS_STATE =
             "android.bluetooth.profile.extra.PREVIOUS_STATE";
 
     /** The profile is in disconnected state */
-    public static final int STATE_DISCONNECTED = 0;
+    int STATE_DISCONNECTED = 0;
     /** The profile is in connecting state */
-    public static final int STATE_CONNECTING = 1;
+    int STATE_CONNECTING = 1;
     /** The profile is in connected state */
-    public static final int STATE_CONNECTED = 2;
+    int STATE_CONNECTED = 2;
     /** The profile is in disconnecting state */
-    public static final int STATE_DISCONNECTING = 3;
+    int STATE_DISCONNECTING = 3;
 
     /**
      * Headset and Handsfree profile
      */
-    public static final int HEADSET = 1;
+    int HEADSET = 1;
 
     /**
      * A2DP profile.
      */
-    public static final int A2DP = 2;
+    int A2DP = 2;
 
     /**
      * Health Profile
      */
-    public static final int HEALTH = 3;
+    int HEALTH = 3;
 
     /**
      * HID Host
      *
      * @hide
      */
-    public static final int HID_HOST = 4;
+    int HID_HOST = 4;
 
     /**
      * PAN Profile
      *
      * @hide
      */
-    public static final int PAN = 5;
+    int PAN = 5;
 
     /**
      * PBAP
      *
      * @hide
      */
-    public static final int PBAP = 6;
+    int PBAP = 6;
 
     /**
      * GATT
      */
-    public static final int GATT = 7;
+    int GATT = 7;
 
     /**
      * GATT_SERVER
      */
-    public static final int GATT_SERVER = 8;
+    int GATT_SERVER = 8;
 
     /**
      * MAP Profile
      *
      * @hide
      */
-    public static final int MAP = 9;
+    int MAP = 9;
 
     /*
      * SAP Profile
      * @hide
      */
-    public static final int SAP = 10;
+    int SAP = 10;
 
     /**
      * A2DP Sink Profile
      *
      * @hide
      */
-    public static final int A2DP_SINK = 11;
+    int A2DP_SINK = 11;
 
     /**
      * AVRCP Controller Profile
      *
      * @hide
      */
-    public static final int AVRCP_CONTROLLER = 12;
+    int AVRCP_CONTROLLER = 12;
+
+    /**
+     * AVRCP Target Profile
+     *
+     * @hide
+     */
+    int AVRCP = 13;
 
     /**
      * Headset Client - HFP HF Role
      *
      * @hide
      */
-    public static final int HEADSET_CLIENT = 16;
+    int HEADSET_CLIENT = 16;
 
     /**
      * PBAP Client
      *
      * @hide
      */
-    public static final int PBAP_CLIENT = 17;
+    int PBAP_CLIENT = 17;
 
     /**
      * MAP Messaging Client Equipment (MCE)
      *
      * @hide
      */
-    public static final int MAP_CLIENT = 18;
+    int MAP_CLIENT = 18;
 
     /**
      * HID Device
      */
-    public static final int HID_DEVICE = 19;
+    int HID_DEVICE = 19;
 
     /**
      * Object Push Profile (OPP)
      *
      * @hide
      */
-    public static final int OPP = 20;
+    int OPP = 20;
 
     /**
      * Hearing Aid Device
@@ -185,7 +192,7 @@
      *
      * @hide
      **/
-    public static final int PRIORITY_AUTO_CONNECT = 1000;
+    int PRIORITY_AUTO_CONNECT = 1000;
 
     /**
      * Default priority for devices that allow incoming
@@ -194,7 +201,7 @@
      * @hide
      **/
     @SystemApi
-    public static final int PRIORITY_ON = 100;
+    int PRIORITY_ON = 100;
 
     /**
      * Default priority for devices that does not allow incoming
@@ -203,14 +210,14 @@
      * @hide
      **/
     @SystemApi
-    public static final int PRIORITY_OFF = 0;
+    int PRIORITY_OFF = 0;
 
     /**
      * Default priority when not set or when the device is unpaired
      *
      * @hide
      */
-    public static final int PRIORITY_UNDEFINED = -1;
+    int PRIORITY_UNDEFINED = -1;
 
     /**
      * Get connected devices for this specific profile.
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 3a8a254..f136e27 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -453,133 +453,177 @@
     public static final int TYPE_NONE        = -1;
 
     /**
-     * The Mobile data connection.  When active, all data traffic
-     * will use this network type's interface by default
-     * (it has a default route)
+     * A Mobile data connection. Devices may support more than one.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
+    @Deprecated
     public static final int TYPE_MOBILE      = 0;
+
     /**
-     * The WIFI data connection.  When active, all data traffic
-     * will use this network type's interface by default
-     * (it has a default route).
+     * A WIFI data connection. Devices may support more than one.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
+    @Deprecated
     public static final int TYPE_WIFI        = 1;
+
     /**
      * An MMS-specific Mobile data connection.  This network type may use the
      * same network interface as {@link #TYPE_MOBILE} or it may use a different
      * one.  This is used by applications needing to talk to the carrier's
      * Multimedia Messaging Service servers.
      *
-     * @deprecated Applications should instead use
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
      *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability.
      */
     @Deprecated
     public static final int TYPE_MOBILE_MMS  = 2;
+
     /**
      * A SUPL-specific Mobile data connection.  This network type may use the
      * same network interface as {@link #TYPE_MOBILE} or it may use a different
      * one.  This is used by applications needing to talk to the carrier's
      * Secure User Plane Location servers for help locating the device.
      *
-     * @deprecated Applications should instead use
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
      *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
      *         provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability.
      */
     @Deprecated
     public static final int TYPE_MOBILE_SUPL = 3;
+
     /**
      * A DUN-specific Mobile data connection.  This network type may use the
      * same network interface as {@link #TYPE_MOBILE} or it may use a different
      * one.  This is sometimes by the system when setting up an upstream connection
      * for tethering so that the carrier is aware of DUN traffic.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasCapability} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
+     *         provides the {@link NetworkCapabilities#NET_CAPABILITY_DUN} capability.
      */
+    @Deprecated
     public static final int TYPE_MOBILE_DUN  = 4;
+
     /**
      * A High Priority Mobile data connection.  This network type uses the
      * same network interface as {@link #TYPE_MOBILE} but the routing setup
      * is different.
      *
-     * @deprecated Applications should instead use
-     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request a network that
-     *         uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport.
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
     @Deprecated
     public static final int TYPE_MOBILE_HIPRI = 5;
+
     /**
-     * The WiMAX data connection.  When active, all data traffic
-     * will use this network type's interface by default
-     * (it has a default route).
+     * A WiMAX data connection.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
+    @Deprecated
     public static final int TYPE_WIMAX       = 6;
 
     /**
-     * The Bluetooth data connection.  When active, all data traffic
-     * will use this network type's interface by default
-     * (it has a default route).
+     * A Bluetooth data connection.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
+    @Deprecated
     public static final int TYPE_BLUETOOTH   = 7;
 
     /**
      * Dummy data connection.  This should not be used on shipping devices.
+     * @deprecated This is not used any more.
      */
+    @Deprecated
     public static final int TYPE_DUMMY       = 8;
 
     /**
-     * The Ethernet data connection.  When active, all data traffic
-     * will use this network type's interface by default
-     * (it has a default route).
+     * An Ethernet data connection.
+     *
+     * @deprecated Applications should instead use {@link NetworkCapabilities#hasTransport} or
+     *         {@link #requestNetwork(NetworkRequest, NetworkCallback)} to request an
+     *         appropriate network. {@see NetworkCapabilities} for supported transports.
      */
+    @Deprecated
     public static final int TYPE_ETHERNET    = 9;
 
     /**
      * Over the air Administration.
+     * @deprecated Use {@link NetworkCapabilities} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_MOBILE_FOTA = 10;
 
     /**
      * IP Multimedia Subsystem.
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IMS} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_MOBILE_IMS  = 11;
 
     /**
      * Carrier Branded Services.
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_CBS} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_MOBILE_CBS  = 12;
 
     /**
      * A Wi-Fi p2p connection. Only requesting processes will have access to
      * the peers connected.
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_WIFI_P2P} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_WIFI_P2P    = 13;
 
     /**
      * The network to use for initially attaching to the network
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_IA} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_MOBILE_IA = 14;
 
     /**
      * Emergency PDN connection for emergency services.  This
      * may include IMS and MMS in emergency situations.
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_EIMS} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_MOBILE_EMERGENCY = 15;
 
     /**
      * The network that uses proxy to achieve connectivity.
+     * @deprecated Use {@link NetworkCapabilities} instead.
      * {@hide}
      */
+    @Deprecated
     public static final int TYPE_PROXY = 16;
 
     /**
      * A virtual network using one or more native bearers.
      * It may or may not be providing security services.
+     * @deprecated Applications should use {@link NetworkCapabilities#TRANSPORT_VPN} instead.
      */
+    @Deprecated
     public static final int TYPE_VPN = 17;
 
     /** {@hide} */
@@ -686,8 +730,10 @@
      * @param type the type needing naming
      * @return a String for the given type, or a string version of the type ("87")
      * if no name is known.
+     * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
      * {@hide}
      */
+    @Deprecated
     public static String getNetworkTypeName(int type) {
         switch (type) {
           case TYPE_NONE:
@@ -738,8 +784,10 @@
      * This should be replaced in the future by a network property.
      * @param networkType the type to check
      * @return a boolean - {@code true} if uses cellular network, else {@code false}
+     * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
      * {@hide}
      */
+    @Deprecated
     public static boolean isNetworkTypeMobile(int networkType) {
         switch (networkType) {
             case TYPE_MOBILE:
@@ -761,8 +809,10 @@
     /**
      * Checks if the given network type is backed by a Wi-Fi radio.
      *
+     * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
      * @hide
      */
+    @Deprecated
     public static boolean isNetworkTypeWifi(int networkType) {
         switch (networkType) {
             case TYPE_WIFI:
@@ -1529,6 +1579,8 @@
      * IllegalArgumentException if no mapping from the legacy type to
      * NetworkCapabilities is known.
      *
+     * @deprecated Types are deprecated. Use {@link NetworkCallback} or {@link NetworkRequest}
+     *     to find the network instead.
      * @hide
      */
     public static NetworkCapabilities networkCapabilitiesForType(int type) {
@@ -2380,6 +2432,7 @@
      *
      * @param networkType The type of network you want to report on
      * @param percentage The quality of the connection 0 is bad, 100 is good
+     * @deprecated Types are deprecated. Use {@link #reportNetworkConnectivity} instead.
      * {@hide}
      */
     public void reportInetCondition(int networkType, int percentage) {
@@ -2511,9 +2564,10 @@
      *
      * @param networkType The network type we'd like to check
      * @return {@code true} if supported, else {@code false}
-     *
+     * @deprecated Types are deprecated. Use {@link NetworkCapabilities} instead.
      * @hide
      */
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
     public boolean isNetworkSupported(int networkType) {
         try {
diff --git a/core/java/android/net/INetdEventCallback.aidl b/core/java/android/net/INetdEventCallback.aidl
index 1fd9423..1e75bf4 100644
--- a/core/java/android/net/INetdEventCallback.aidl
+++ b/core/java/android/net/INetdEventCallback.aidl
@@ -20,8 +20,9 @@
 oneway interface INetdEventCallback {
 
     // Possible addNetdEventCallback callers.
-    const int CALLBACK_CALLER_DEVICE_POLICY = 0;
-    const int CALLBACK_CALLER_NETWORK_WATCHLIST = 1;
+    const int CALLBACK_CALLER_CONNECTIVITY_SERVICE = 0;
+    const int CALLBACK_CALLER_DEVICE_POLICY = 1;
+    const int CALLBACK_CALLER_NETWORK_WATCHLIST = 2;
 
     /**
      * Reports a single DNS lookup function call.
@@ -39,6 +40,18 @@
             int uid);
 
     /**
+     * Represents a private DNS validation success or failure.
+     * This method must not block or perform long-running operations.
+     *
+     * @param netId the ID of the network the validation was performed on.
+     * @param ipAddress the IP address for which validation was performed.
+     * @param hostname the hostname for which validation was performed.
+     * @param validated whether or not validation was successful.
+     */
+    void onPrivateDnsValidationEvent(int netId, String ipAddress, String hostname,
+            boolean validated);
+
+    /**
      * Reports a single connect library call.
      * This method must not block or perform long-running operations.
      *
diff --git a/core/java/android/net/IpPrefix.java b/core/java/android/net/IpPrefix.java
index 6e2654e..4631c56 100644
--- a/core/java/android/net/IpPrefix.java
+++ b/core/java/android/net/IpPrefix.java
@@ -25,6 +25,7 @@
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.util.Arrays;
+import java.util.Comparator;
 
 /**
  * This class represents an IP prefix, i.e., a contiguous block of IP addresses aligned on a
@@ -187,6 +188,20 @@
     }
 
     /**
+     * Returns whether the specified prefix is entirely contained in this prefix.
+     *
+     * Note this is mathematical inclusion, so a prefix is always contained within itself.
+     * @param otherPrefix the prefix to test
+     * @hide
+     */
+    public boolean containsPrefix(IpPrefix otherPrefix) {
+        if (otherPrefix.getPrefixLength() < prefixLength) return false;
+        final byte[] otherAddress = otherPrefix.getRawAddress();
+        NetworkUtils.maskRawAddress(otherAddress, prefixLength);
+        return Arrays.equals(otherAddress, address);
+    }
+
+    /**
      * @hide
      */
     public boolean isIPv6() {
@@ -230,6 +245,38 @@
     }
 
     /**
+     * Returns a comparator ordering IpPrefixes by length, shorter to longer.
+     * Contents of the address will break ties.
+     * @hide
+     */
+    public static Comparator<IpPrefix> lengthComparator() {
+        return new Comparator<IpPrefix>() {
+            @Override
+            public int compare(IpPrefix prefix1, IpPrefix prefix2) {
+                if (prefix1.isIPv4()) {
+                    if (prefix2.isIPv6()) return -1;
+                } else {
+                    if (prefix2.isIPv4()) return 1;
+                }
+                final int p1len = prefix1.getPrefixLength();
+                final int p2len = prefix2.getPrefixLength();
+                if (p1len < p2len) return -1;
+                if (p2len < p1len) return 1;
+                final byte[] a1 = prefix1.address;
+                final byte[] a2 = prefix2.address;
+                final int len = a1.length < a2.length ? a1.length : a2.length;
+                for (int i = 0; i < len; ++i) {
+                    if (a1[i] < a2[i]) return -1;
+                    if (a1[i] > a2[i]) return 1;
+                }
+                if (a2.length < len) return 1;
+                if (a1.length < len) return -1;
+                return 0;
+            }
+        };
+    }
+
+    /**
      * Implement the Parcelable interface.
      */
     public static final Creator<IpPrefix> CREATOR =
diff --git a/core/java/android/net/IpSecManager.java b/core/java/android/net/IpSecManager.java
index f1beef1..4e1f834 100644
--- a/core/java/android/net/IpSecManager.java
+++ b/core/java/android/net/IpSecManager.java
@@ -58,14 +58,18 @@
     private static final String TAG = "IpSecManager";
 
     /**
-     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
-     * applies to traffic towards the host.
+     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
+     * towards the host.
+     *
+     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
      */
     public static final int DIRECTION_IN = 0;
 
     /**
-     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
-     * applies to traffic from the host.
+     * Used when applying a transform to direct traffic through an {@link IpSecTransform}
+     * away from the host.
+     *
+     * <p>See {@link #applyTransportModeTransform(Socket, int, IpSecTransform)}.
      */
     public static final int DIRECTION_OUT = 1;
 
@@ -301,19 +305,21 @@
      *
      * <h4>Rekey Procedure</h4>
      *
-     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
-     * inbound traffic on the old transform will continue to be decrypted until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
-     * where both transforms are valid until both endpoints are using the new transform and all
-     * in-flight packets have been received.
+     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+     * will be removed and the new transform will take effect immediately, sending all traffic on
+     * the new transform; however, when applying a transform in the inbound direction, traffic
+     * on the old transform will continue to be decrypted and delivered until that transform is
+     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+     * procedures where both transforms are valid until both endpoints are using the new transform
+     * and all in-flight packets have been received.
      *
      * @param socket a stream socket
-     * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
+     * @param direction the direction in which the transform should be applied
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
     public void applyTransportModeTransform(
-            Socket socket, int direction, IpSecTransform transform)
+            Socket socket, @PolicyDirection int direction, IpSecTransform transform)
             throws IOException {
         applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
@@ -334,19 +340,22 @@
      *
      * <h4>Rekey Procedure</h4>
      *
-     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
-     * inbound traffic on the old transform will continue to be decrypted until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
-     * where both transforms are valid until both endpoints are using the new transform and all
-     * in-flight packets have been received.
+     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+     * will be removed and the new transform will take effect immediately, sending all traffic on
+     * the new transform; however, when applying a transform in the inbound direction, traffic
+     * on the old transform will continue to be decrypted and delivered until that transform is
+     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+     * procedures where both transforms are valid until both endpoints are using the new transform
+     * and all in-flight packets have been received.
      *
      * @param socket a datagram socket
-     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
+     * @param direction the direction in which the transform should be applied
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
     public void applyTransportModeTransform(
-            DatagramSocket socket, int direction, IpSecTransform transform) throws IOException {
+            DatagramSocket socket, @PolicyDirection int direction, IpSecTransform transform)
+            throws IOException {
         applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
     }
 
@@ -366,19 +375,21 @@
      *
      * <h4>Rekey Procedure</h4>
      *
-     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
-     * inbound traffic on the old transform will continue to be decrypted until that transform is
-     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
-     * where both transforms are valid until both endpoints are using the new transform and all
-     * in-flight packets have been received.
+     * <p>When applying a new tranform to a socket in the outbound direction, the previous transform
+     * will be removed and the new transform will take effect immediately, sending all traffic on
+     * the new transform; however, when applying a transform in the inbound direction, traffic
+     * on the old transform will continue to be decrypted and delivered until that transform is
+     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows lossless rekey
+     * procedures where both transforms are valid until both endpoints are using the new transform
+     * and all in-flight packets have been received.
      *
      * @param socket a socket file descriptor
-     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
+     * @param direction the direction in which the transform should be applied
      * @param transform a transport mode {@code IpSecTransform}
      * @throws IOException indicating that the transform could not be applied
      */
     public void applyTransportModeTransform(
-            FileDescriptor socket, int direction, IpSecTransform transform)
+            FileDescriptor socket, @PolicyDirection int direction, IpSecTransform transform)
             throws IOException {
         // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
         // constructor takes control and closes the user's FD when we exit the method.
@@ -390,21 +401,6 @@
     }
 
     /**
-     * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
-     * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
-     * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
-     * Applications should probably not use this API directly. Instead, they should use {@link
-     * VpnService} to provide VPN capability in a more generic fashion.
-     *
-     * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
-     *
-     * @param net a {@link Network} that will be tunneled via IP Sec.
-     * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
-     * @hide
-     */
-    public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
-
-    /**
      * Remove an IPsec transform from a stream socket.
      *
      * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
@@ -778,7 +774,12 @@
     }
 
     /**
-     * Apply a transform to the IpSecTunnelInterface
+     * Apply an active Tunnel Mode IPsec Transform to a {@link IpSecTunnelInterface}, which will
+     * tunnel all traffic for the given direction through the underlying network's interface with
+     * IPsec (applies an outer IP header and IPsec Header to all traffic, and expects an additional
+     * IP header and IPsec Header on all inbound traffic).
+     * <p>Applications should probably not use this API directly.
+     *
      *
      * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
      *        transform.
@@ -791,8 +792,8 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
-    public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
-            IpSecTransform transform) throws IOException {
+    public void applyTunnelModeTransform(IpSecTunnelInterface tunnel,
+            @PolicyDirection int direction, IpSecTransform transform) throws IOException {
         try {
             mService.applyTunnelModeTransform(
                     tunnel.getResourceId(), direction, transform.getResourceId());
@@ -800,6 +801,7 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
     /**
      * Construct an instance of IpSecManager within an application context.
      *
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index d8e1741..22cffcc 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -68,6 +68,7 @@
             mSignalStrength = nc.mSignalStrength;
             mUids = nc.mUids;
             mEstablishingVpnAppUid = nc.mEstablishingVpnAppUid;
+            mUnwantedNetworkCapabilities = nc.mUnwantedNetworkCapabilities;
         }
     }
 
@@ -77,7 +78,7 @@
      * @hide
      */
     public void clearAll() {
-        mNetworkCapabilities = mTransportTypes = 0;
+        mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
         mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
         mNetworkSpecifier = null;
         mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
@@ -91,6 +92,11 @@
      */
     private long mNetworkCapabilities;
 
+    /**
+     * If any capabilities specified here they must not exist in the matching Network.
+     */
+    private long mUnwantedNetworkCapabilities;
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
@@ -338,31 +344,55 @@
      * 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.
+     * <p>
+     * If the given capability was previously added to the list of unwanted capabilities
+     * then the capability will also be removed from the list of unwanted capabilities.
      *
      * @param capability the capability to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
     public NetworkCapabilities addCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            throw new IllegalArgumentException("NetworkCapability out of range");
-        }
+        checkValidCapability(capability);
         mNetworkCapabilities |= 1 << capability;
+        mUnwantedNetworkCapabilities &= ~(1 << capability);  // remove from unwanted capability list
         return this;
     }
 
     /**
+     * Adds the given capability to the list of unwanted capabilities of this
+     * {@code NetworkCapability} instance.  Multiple unwanted capabilities may be applied
+     * sequentially.  Note that when searching for a network to satisfy a request, the network
+     * must not contain any capability from unwanted capability list.
+     * <p>
+     * If the capability was previously added to the list of required capabilities (for
+     * example, it was there by default or added using {@link #addCapability(int)} method), then
+     * it will be removed from the list of required capabilities as well.
+     *
+     * @see #addCapability(int)
+     * @hide
+     */
+    public void addUnwantedCapability(@NetCapability int capability) {
+        checkValidCapability(capability);
+        mUnwantedNetworkCapabilities |= 1 << capability;
+        mNetworkCapabilities &= ~(1 << capability);  // remove from requested capabilities
+    }
+
+    /**
      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
+     * <p>
+     * Note that this method removes capabilities that were added via {@link #addCapability(int)},
+     * {@link #addUnwantedCapability(int)} or {@link #setCapabilities(int[], int[])} .
      *
      * @param capability the capability to be removed.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
     public NetworkCapabilities removeCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            throw new IllegalArgumentException("NetworkCapability out of range");
-        }
-        mNetworkCapabilities &= ~(1 << capability);
+        checkValidCapability(capability);
+        final long mask = ~(1 << capability);
+        mNetworkCapabilities &= mask;
+        mUnwantedNetworkCapabilities &= mask;
         return this;
     }
 
@@ -392,30 +422,58 @@
     }
 
     /**
+     * Gets all the unwanted capabilities set on this {@code NetworkCapability} instance.
+     *
+     * @return an array of unwanted capability values for this instance.
+     * @hide
+     */
+    public @NetCapability int[] getUnwantedCapabilities() {
+        return BitUtils.unpackBits(mUnwantedNetworkCapabilities);
+    }
+
+
+    /**
      * Sets all the capabilities set on this {@code NetworkCapability} instance.
      * This overwrites any existing capabilities.
      *
      * @hide
      */
-    public void setCapabilities(@NetCapability int[] capabilities) {
+    public void setCapabilities(@NetCapability int[] capabilities,
+            @NetCapability int[] unwantedCapabilities) {
         mNetworkCapabilities = BitUtils.packBits(capabilities);
+        mUnwantedNetworkCapabilities = BitUtils.packBits(unwantedCapabilities);
     }
 
     /**
-     * Tests for the presence of a capabilitity on this instance.
+     * @deprecated use {@link #setCapabilities(int[], int[])}
+     * @hide
+     */
+    @Deprecated
+    public void setCapabilities(@NetCapability int[] capabilities) {
+        setCapabilities(capabilities, new int[] {});
+    }
+
+    /**
+     * Tests for the presence of a capability on this instance.
      *
      * @param capability the capabilities to be tested for.
      * @return {@code true} if set on this instance.
      */
     public boolean hasCapability(@NetCapability int capability) {
-        if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
-            return false;
-        }
-        return ((mNetworkCapabilities & (1 << capability)) != 0);
+        return isValidCapability(capability)
+                && ((mNetworkCapabilities & (1 << capability)) != 0);
     }
 
+    /** @hide */
+    public boolean hasUnwantedCapability(@NetCapability int capability) {
+        return isValidCapability(capability)
+                && ((mUnwantedNetworkCapabilities & (1 << capability)) != 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;
+        this.mUnwantedNetworkCapabilities |= nc.mUnwantedNetworkCapabilities;
     }
 
     /**
@@ -426,7 +484,9 @@
      * @hide
      */
     public String describeFirstNonRequestableCapability() {
-        final long nonRequestable = (mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES);
+        final long nonRequestable = (mNetworkCapabilities | mUnwantedNetworkCapabilities)
+                & NON_REQUESTABLE_CAPABILITIES;
+
         if (nonRequestable != 0) {
             return capabilityNameOf(BitUtils.unpackBits(nonRequestable)[0]);
         }
@@ -436,21 +496,29 @@
     }
 
     private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
-        long networkCapabilities = this.mNetworkCapabilities;
+        long requestedCapabilities = mNetworkCapabilities;
+        long requestedUnwantedCapabilities = mUnwantedNetworkCapabilities;
+        long providedCapabilities = nc.mNetworkCapabilities;
+
         if (onlyImmutable) {
-            networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES;
+            requestedCapabilities &= ~MUTABLE_CAPABILITIES;
+            requestedUnwantedCapabilities &= ~MUTABLE_CAPABILITIES;
         }
-        return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities);
+        return ((providedCapabilities & requestedCapabilities) == requestedCapabilities)
+                && ((requestedUnwantedCapabilities & providedCapabilities) == 0);
     }
 
     /** @hide */
     public boolean equalsNetCapabilities(NetworkCapabilities nc) {
-        return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
+        return (nc.mNetworkCapabilities == this.mNetworkCapabilities)
+                && (nc.mUnwantedNetworkCapabilities == this.mUnwantedNetworkCapabilities);
     }
 
     private boolean equalsNetCapabilitiesRequestable(NetworkCapabilities that) {
         return ((this.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
-                (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
+                (that.mNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES))
+                && ((this.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES) ==
+                (that.mUnwantedNetworkCapabilities & ~NON_REQUESTABLE_CAPABILITIES));
     }
 
     /**
@@ -890,7 +958,16 @@
     /**
      * List of UIDs this network applies to. No restriction if null.
      * <p>
-     * This is typically (and at this time, only) used by VPN. This network is only available to
+     * For networks, mUids represent the list of network this applies to, and null means this
+     * network applies to all UIDs.
+     * For requests, mUids is the list of UIDs this network MUST apply to to match ; ALL UIDs
+     * must be included in a network so that they match. As an exception to the general rule,
+     * a null mUids field for requests mean "no requirements" rather than what the general rule
+     * would suggest ("must apply to all UIDs") : this is because this has shown to be what users
+     * of this API expect in practice. A network that must match all UIDs can still be
+     * expressed with a set ranging the entire set of possible UIDs.
+     * <p>
+     * mUids is typically (and at this time, only) used by VPN. This network is only available to
      * the UIDs in this list, and it is their default network. Apps in this list that wish to
      * bypass the VPN can do so iff the VPN app allows them to or if they are privileged. If this
      * member is null, then the network is not restricted by app UID. If it's an empty list, then
@@ -1012,8 +1089,7 @@
      * @hide
      */
     public boolean satisfiedByUids(NetworkCapabilities nc) {
-        if (null == nc.mUids) return true; // The network satisfies everything.
-        if (null == mUids) return false; // Not everything allowed but requires everything
+        if (null == nc.mUids || null == mUids) return true; // The network satisfies everything.
         for (UidRange requiredRange : mUids) {
             if (requiredRange.contains(nc.mEstablishingVpnAppUid)) return true;
             if (!nc.appliesToUidRange(requiredRange)) {
@@ -1056,7 +1132,11 @@
     }
 
     /**
-     * Combine a set of Capabilities to this one.  Useful for coming up with the complete set
+     * Combine a set of Capabilities to this one.  Useful for coming up with the complete set.
+     * <p>
+     * Note that this method may break an invariant of having a particular capability in either
+     * wanted or unwanted lists but never in both.  Requests that have the same capability in
+     * both lists will never be satisfied.
      * @hide
      */
     public void combineCapabilities(NetworkCapabilities nc) {
@@ -1178,15 +1258,17 @@
 
     @Override
     public int hashCode() {
-        return ((int) (mNetworkCapabilities & 0xFFFFFFFF)
+        return (int) (mNetworkCapabilities & 0xFFFFFFFF)
                 + ((int) (mNetworkCapabilities >> 32) * 3)
-                + ((int) (mTransportTypes & 0xFFFFFFFF) * 5)
-                + ((int) (mTransportTypes >> 32) * 7)
-                + (mLinkUpBandwidthKbps * 11)
-                + (mLinkDownBandwidthKbps * 13)
-                + Objects.hashCode(mNetworkSpecifier) * 17
-                + (mSignalStrength * 19)
-                + Objects.hashCode(mUids) * 23);
+                + ((int) (mUnwantedNetworkCapabilities & 0xFFFFFFFF) * 5)
+                + ((int) (mUnwantedNetworkCapabilities >> 32) * 7)
+                + ((int) (mTransportTypes & 0xFFFFFFFF) * 11)
+                + ((int) (mTransportTypes >> 32) * 13)
+                + (mLinkUpBandwidthKbps * 17)
+                + (mLinkDownBandwidthKbps * 19)
+                + Objects.hashCode(mNetworkSpecifier) * 23
+                + (mSignalStrength * 29)
+                + Objects.hashCode(mUids) * 31;
     }
 
     @Override
@@ -1196,6 +1278,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(mNetworkCapabilities);
+        dest.writeLong(mUnwantedNetworkCapabilities);
         dest.writeLong(mTransportTypes);
         dest.writeInt(mLinkUpBandwidthKbps);
         dest.writeInt(mLinkDownBandwidthKbps);
@@ -1211,6 +1294,7 @@
                 NetworkCapabilities netCap = new NetworkCapabilities();
 
                 netCap.mNetworkCapabilities = in.readLong();
+                netCap.mUnwantedNetworkCapabilities = in.readLong();
                 netCap.mTransportTypes = in.readLong();
                 netCap.mLinkUpBandwidthKbps = in.readInt();
                 netCap.mLinkDownBandwidthKbps = in.readInt();
@@ -1239,6 +1323,11 @@
             appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities,
                     NetworkCapabilities::capabilityNameOf, "&");
         }
+        if (0 != mNetworkCapabilities) {
+            sb.append(" Unwanted: ");
+            appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities,
+                    NetworkCapabilities::capabilityNameOf, "&");
+        }
         if (mLinkUpBandwidthKbps > 0) {
             sb.append(" LinkUpBandwidth>=").append(mLinkUpBandwidthKbps).append("Kbps");
         }
@@ -1364,4 +1453,13 @@
         Preconditions.checkArgument(
                 isValidTransport(transport), "Invalid TransportType " + transport);
     }
+
+    private static boolean isValidCapability(@NetworkCapabilities.NetCapability int capability) {
+        return capability >= MIN_NET_CAPABILITY && capability <= MAX_NET_CAPABILITY;
+    }
+
+    private static void checkValidCapability(@NetworkCapabilities.NetCapability int capability) {
+        Preconditions.checkArgument(isValidCapability(capability),
+                "NetworkCapability " + capability + "out of range");
+    }
 }
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index e6ad89a..999771a 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -38,14 +38,18 @@
      * <table>
      * <tr><td><b>Detailed state</b></td><td><b>Coarse-grained state</b></td></tr>
      * <tr><td><code>IDLE</code></td><td><code>DISCONNECTED</code></td></tr>
-     * <tr><td><code>SCANNING</code></td><td><code>CONNECTING</code></td></tr>
+     * <tr><td><code>SCANNING</code></td><td><code>DISCONNECTED</code></td></tr>
      * <tr><td><code>CONNECTING</code></td><td><code>CONNECTING</code></td></tr>
      * <tr><td><code>AUTHENTICATING</code></td><td><code>CONNECTING</code></td></tr>
+     * <tr><td><code>OBTAINING_IPADDR</code></td><td><code>CONNECTING</code></td></tr>
+     * <tr><td><code>VERIFYING_POOR_LINK</code></td><td><code>CONNECTING</code></td></tr>
+     * <tr><td><code>CAPTIVE_PORTAL_CHECK</code></td><td><code>CONNECTING</code></td></tr>
      * <tr><td><code>CONNECTED</code></td><td><code>CONNECTED</code></td></tr>
+     * <tr><td><code>SUSPENDED</code></td><td><code>SUSPENDED</code></td></tr>
      * <tr><td><code>DISCONNECTING</code></td><td><code>DISCONNECTING</code></td></tr>
      * <tr><td><code>DISCONNECTED</code></td><td><code>DISCONNECTED</code></td></tr>
-     * <tr><td><code>UNAVAILABLE</code></td><td><code>DISCONNECTED</code></td></tr>
      * <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
+     * <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
      * </table>
      */
     public enum State {
@@ -163,8 +167,17 @@
      * @return one of {@link ConnectivityManager#TYPE_MOBILE}, {@link
      * ConnectivityManager#TYPE_WIFI}, {@link ConnectivityManager#TYPE_WIMAX}, {@link
      * ConnectivityManager#TYPE_ETHERNET},  {@link ConnectivityManager#TYPE_BLUETOOTH}, or other
-     * types defined by {@link ConnectivityManager}
+     * types defined by {@link ConnectivityManager}.
+     * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport}
+     *             instead with one of the NetworkCapabilities#TRANSPORT_* constants :
+     *             {@link #getType} and {@link #getTypeName} cannot account for networks using
+     *             multiple transports. Note that generally apps should not care about transport;
+     *             {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and
+     *             {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that
+     *             apps concerned with meteredness or bandwidth should be looking at, as they
+     *             offer this information with much better accuracy.
      */
+    @Deprecated
     public int getType() {
         synchronized (this) {
             return mNetworkType;
@@ -172,8 +185,10 @@
     }
 
     /**
+     * @deprecated Use {@link NetworkCapabilities} instead
      * @hide
      */
+    @Deprecated
     public void setType(int type) {
         synchronized (this) {
             mNetworkType = type;
@@ -205,7 +220,16 @@
      * Return a human-readable name describe the type of the network,
      * for example "WIFI" or "MOBILE".
      * @return the name of the network type
+     * @deprecated Callers should switch to checking {@link NetworkCapabilities#hasTransport}
+     *             instead with one of the NetworkCapabilities#TRANSPORT_* constants :
+     *             {@link #getType} and {@link #getTypeName} cannot account for networks using
+     *             multiple transports. Note that generally apps should not care about transport;
+     *             {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED} and
+     *             {@link NetworkCapabilities#getLinkDownstreamBandwidthKbps} are calls that
+     *             apps concerned with meteredness or bandwidth should be looking at, as they
+     *             offer this information with much better accuracy.
      */
+    @Deprecated
     public String getTypeName() {
         synchronized (this) {
             return mTypeName;
@@ -230,7 +254,15 @@
      * that the network is fully usable.
      * @return {@code true} if network connectivity exists or is in the process
      * of being established, {@code false} otherwise.
+     * @deprecated Apps should instead use the
+     *             {@link android.net.ConnectivityManager.NetworkCallback} API to
+     *             learn about connectivity changes.
+     *             {@link ConnectivityManager#registerDefaultNetworkCallback} and
+     *             {@link ConnectivityManager#registerNetworkCallback}. These will
+     *             give a more accurate picture of the connectivity state of
+     *             the device and let apps react more easily and quickly to changes.
      */
+    @Deprecated
     public boolean isConnectedOrConnecting() {
         synchronized (this) {
             return mState == State.CONNECTED || mState == State.CONNECTING;
@@ -259,8 +291,18 @@
      * data roaming has been disabled.</li>
      * <li>The device's radio is turned off, e.g., because airplane mode is enabled.</li>
      * </ul>
+     * Since Android L, this always returns {@code true}, because the system only
+     * returns info for available networks.
      * @return {@code true} if the network is available, {@code false} otherwise
+     * @deprecated Apps should instead use the
+     *             {@link android.net.ConnectivityManager.NetworkCallback} API to
+     *             learn about connectivity changes.
+     *             {@link ConnectivityManager#registerDefaultNetworkCallback} and
+     *             {@link ConnectivityManager#registerNetworkCallback}. These will
+     *             give a more accurate picture of the connectivity state of
+     *             the device and let apps react more easily and quickly to changes.
      */
+    @Deprecated
     public boolean isAvailable() {
         synchronized (this) {
             return mIsAvailable;
@@ -270,9 +312,11 @@
     /**
      * Sets if the network is available, ie, if the connectivity is possible.
      * @param isAvailable the new availability value.
+     * @deprecated Use {@link NetworkCapabilities} instead
      *
      * @hide
      */
+    @Deprecated
     public void setIsAvailable(boolean isAvailable) {
         synchronized (this) {
             mIsAvailable = isAvailable;
@@ -285,7 +329,10 @@
      * network following a disconnect from another network.
      * @return {@code true} if this is a failover attempt, {@code false}
      * otherwise.
+     * @deprecated This field is not populated in recent Android releases,
+     *             and does not make a lot of sense in a multi-network world.
      */
+    @Deprecated
     public boolean isFailover() {
         synchronized (this) {
             return mIsFailover;
@@ -296,8 +343,10 @@
      * Set the failover boolean.
      * @param isFailover {@code true} to mark the current connection attempt
      * as a failover.
+     * @deprecated This hasn't been set in any recent Android release.
      * @hide
      */
+    @Deprecated
     public void setFailover(boolean isFailover) {
         synchronized (this) {
             mIsFailover = isFailover;
@@ -322,7 +371,10 @@
         }
     }
 
-    /** {@hide} */
+    /**
+     * @deprecated Use {@link NetworkCapabilities#NET_CAPABILITY_NOT_ROAMING} instead.
+     * {@hide}
+     */
     @VisibleForTesting
     @Deprecated
     public void setRoaming(boolean isRoaming) {
@@ -334,7 +386,15 @@
     /**
      * Reports the current coarse-grained state of the network.
      * @return the coarse-grained state
+     * @deprecated Apps should instead use the
+     *             {@link android.net.ConnectivityManager.NetworkCallback} API to
+     *             learn about connectivity changes.
+     *             {@link ConnectivityManager#registerDefaultNetworkCallback} and
+     *             {@link ConnectivityManager#registerNetworkCallback}. These will
+     *             give a more accurate picture of the connectivity state of
+     *             the device and let apps react more easily and quickly to changes.
      */
+    @Deprecated
     public State getState() {
         synchronized (this) {
             return mState;
@@ -358,8 +418,10 @@
      * if one was supplied. May be {@code null}.
      * @param extraInfo an optional {@code String} providing addditional network state
      * information passed up from the lower networking layers.
+     * @deprecated Use {@link NetworkCapabilities} instead.
      * @hide
      */
+    @Deprecated
     public void setDetailedState(DetailedState detailedState, String reason, String extraInfo) {
         synchronized (this) {
             this.mDetailedState = detailedState;
@@ -385,6 +447,8 @@
      * Report the reason an attempt to establish connectivity failed,
      * if one is available.
      * @return the reason for failure, or null if not available
+     * @deprecated This method does not have a consistent contract that could make it useful
+     *             to callers.
      */
     public String getReason() {
         synchronized (this) {
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 97ded2d..96826f8 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.Process;
 import android.text.TextUtils;
 
 import java.util.Objects;
@@ -131,12 +132,18 @@
      * needed in terms of {@link NetworkCapabilities} features
      */
     public static class Builder {
-        private final NetworkCapabilities mNetworkCapabilities = new NetworkCapabilities();
+        private final NetworkCapabilities mNetworkCapabilities;
 
         /**
          * Default constructor for Builder.
          */
-        public Builder() {}
+        public Builder() {
+            // By default, restrict this request to networks available to this app.
+            // Apps can rescind this restriction, but ConnectivityService will enforce
+            // it for apps that do not have the NETWORK_SETTINGS permission.
+            mNetworkCapabilities = new NetworkCapabilities();
+            mNetworkCapabilities.setSingleUid(Process.myUid());
+        }
 
         /**
          * Build {@link NetworkRequest} give the current set of capabilities.
@@ -157,6 +164,9 @@
          * the requested network's required capabilities.  Note that when searching
          * for a network to satisfy a request, all capabilities requested must be
          * satisfied.
+         * <p>
+         * If the given capability was previously added to the list of unwanted capabilities
+         * then the capability will also be removed from the list of unwanted capabilities.
          *
          * @param capability The capability to add.
          * @return The builder to facilitate chaining
@@ -168,7 +178,8 @@
         }
 
         /**
-         * Removes (if found) the given capability from this builder instance.
+         * Removes (if found) the given capability from this builder instance from both required
+         * and unwanted capabilities lists.
          *
          * @param capability The capability to remove.
          * @return The builder to facilitate chaining.
@@ -193,6 +204,24 @@
         }
 
         /**
+         * Add a capability that must not exist in the requested network.
+         * <p>
+         * If the capability was previously added to the list of required capabilities (for
+         * example, it was there by default or added using {@link #addCapability(int)} method), then
+         * it will be removed from the list of required capabilities as well.
+         *
+         * @see #addCapability(int)
+         *
+         * @param capability The capability to add to unwanted capability list.
+         * @return The builder to facilitate chaining.
+         * @hide
+         */
+        public Builder addUnwantedCapability(@NetworkCapabilities.NetCapability int capability) {
+            mNetworkCapabilities.addUnwantedCapability(capability);
+            return this;
+        }
+
+        /**
          * Completely clears all the {@code NetworkCapabilities} from this builder instance,
          * removing even the capabilities that are set by default when the object is constructed.
          *
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index fe9563d..9a5d502 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -16,19 +16,20 @@
 
 package android.net;
 
-import java.io.FileDescriptor;
-import java.net.InetAddress;
-import java.net.Inet4Address;
-import java.net.Inet6Address;
-import java.net.SocketException;
-import java.net.UnknownHostException;
-import java.util.Collection;
-import java.util.Locale;
-
 import android.os.Parcel;
 import android.util.Log;
 import android.util.Pair;
 
+import java.io.FileDescriptor;
+import java.math.BigInteger;
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.TreeSet;
 
 /**
  * Native methods for managing network interfaces.
@@ -385,4 +386,72 @@
         result = builder.toString();
         return result;
     }
+
+    /**
+     * Returns a prefix set without overlaps.
+     *
+     * This expects the src set to be sorted from shorter to longer. Results are undefined
+     * failing this condition. The returned prefix set is sorted in the same order as the
+     * passed set, with the same comparator.
+     */
+    private static TreeSet<IpPrefix> deduplicatePrefixSet(final TreeSet<IpPrefix> src) {
+        final TreeSet<IpPrefix> dst = new TreeSet<>(src.comparator());
+        // Prefixes match addresses that share their upper part up to their length, therefore
+        // the only kind of possible overlap in two prefixes is strict inclusion of the longer
+        // (more restrictive) in the shorter (including equivalence if they have the same
+        // length).
+        // Because prefixes in the src set are sorted from shorter to longer, deduplicating
+        // is done by simply iterating in order, and not adding any longer prefix that is
+        // already covered by a shorter one.
+        newPrefixes:
+        for (IpPrefix newPrefix : src) {
+            for (IpPrefix existingPrefix : dst) {
+                if (existingPrefix.containsPrefix(newPrefix)) {
+                    continue newPrefixes;
+                }
+            }
+            dst.add(newPrefix);
+        }
+        return dst;
+    }
+
+    /**
+     * Returns how many IPv4 addresses match any of the prefixes in the passed ordered set.
+     *
+     * Obviously this returns an integral value between 0 and 2**32.
+     * The behavior is undefined if any of the prefixes is not an IPv4 prefix or if the
+     * set is not ordered smallest prefix to longer prefix.
+     *
+     * @param prefixes the set of prefixes, ordered by length
+     */
+    public static long routedIPv4AddressCount(final TreeSet<IpPrefix> prefixes) {
+        long routedIPCount = 0;
+        for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
+            if (!prefix.isIPv4()) {
+                Log.wtf(TAG, "Non-IPv4 prefix in routedIPv4AddressCount");
+            }
+            int rank = 32 - prefix.getPrefixLength();
+            routedIPCount += 1L << rank;
+        }
+        return routedIPCount;
+    }
+
+    /**
+     * Returns how many IPv6 addresses match any of the prefixes in the passed ordered set.
+     *
+     * This returns a BigInteger between 0 and 2**128.
+     * The behavior is undefined if any of the prefixes is not an IPv6 prefix or if the
+     * set is not ordered smallest prefix to longer prefix.
+     */
+    public static BigInteger routedIPv6AddressCount(final TreeSet<IpPrefix> prefixes) {
+        BigInteger routedIPCount = BigInteger.ZERO;
+        for (final IpPrefix prefix : deduplicatePrefixSet(prefixes)) {
+            if (!prefix.isIPv6()) {
+                Log.wtf(TAG, "Non-IPv6 prefix in routedIPv6AddressCount");
+            }
+            int rank = 128 - prefix.getPrefixLength();
+            routedIPCount = routedIPCount.add(BigInteger.ONE.shiftLeft(rank));
+        }
+        return routedIPCount;
+    }
 }
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index a94b928..f8a63ce 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -40,11 +40,12 @@
     public static final int ERROR_STARTING_IPV6                   = 5;
     public static final int ERROR_STARTING_IPREACHABILITYMONITOR  = 6;
     public static final int ERROR_INVALID_PROVISIONING            = 7;
+    public static final int ERROR_INTERFACE_NOT_FOUND             = 8;
 
     @IntDef(value = {
             PROVISIONING_OK, PROVISIONING_FAIL, COMPLETE_LIFECYCLE,
             ERROR_STARTING_IPV4, ERROR_STARTING_IPV6, ERROR_STARTING_IPREACHABILITYMONITOR,
-            ERROR_INVALID_PROVISIONING,
+            ERROR_INVALID_PROVISIONING, ERROR_INTERFACE_NOT_FOUND,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface EventType {}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index b02d48d..c3f23a1 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -225,7 +225,7 @@
      * Indicates the Secure Element on which the transaction occurred.
      * eSE1...eSEn for Embedded Secure Elements, SIM1...SIMn for UICC, etc.
      */
-    public static final String EXTRA_SE_NAME = "android.nfc.extra.SE_NAME";
+    public static final String EXTRA_SECURE_ELEMENT_NAME = "android.nfc.extra.SECURE_ELEMENT_NAME";
 
     public static final int STATE_OFF = 1;
     public static final int STATE_TURNING_ON = 2;
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 5e6f5f5..d693ee8 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -140,6 +140,12 @@
     public static final int CAMERASERVER_UID = 1047;
 
     /**
+     * Defines the UID/GID for the tethering DNS resolver (currently dnsmasq).
+     * @hide
+     */
+    public static final int DNS_TETHER_UID = 1052;
+
+    /**
      * Defines the UID/GID for the WebView zygote process.
      * @hide
      */
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3b6df5d..0789afd 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -196,9 +196,14 @@
      */
     public static final int DETECT_UNBUFFERED_IO = 0x20;  // for ThreadPolicy
 
+    /**
+     * @hide
+     */
+    public static final int DETECT_EXPLICIT_GC = 0x40;  // for ThreadPolicy
+
     private static final int ALL_THREAD_DETECT_BITS =
             DETECT_DISK_WRITE | DETECT_DISK_READ | DETECT_NETWORK | DETECT_CUSTOM |
-            DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO;
+            DETECT_RESOURCE_MISMATCH | DETECT_UNBUFFERED_IO | DETECT_EXPLICIT_GC;
 
     // Byte 2: Process-policy
 
@@ -557,6 +562,27 @@
             }
 
             /**
+             * Detect explicit GC requests, i.e. calls to Runtime.gc().
+             *
+             * @hide
+             */
+            public Builder detectExplicitGc() {
+                // TODO(b/3400644): Un-hide this for next API update
+                // TODO(b/3400644): Call this from detectAll in next API update
+                return enable(DETECT_EXPLICIT_GC);
+            }
+
+            /**
+             * Disable detection of explicit GC requests, i.e. calls to Runtime.gc().
+             *
+             * @hide
+             */
+            public Builder permitExplicitGc() {
+                // TODO(b/3400644): Un-hide this for next API update
+                return disable(DETECT_EXPLICIT_GC);
+            }
+
+            /**
              * Show an annoying dialog to the developer on detected
              * violations, rate-limited to be only a little annoying.
              */
@@ -1094,6 +1120,15 @@
     }
 
     /**
+     * @hide
+     */
+    private static class StrictModeExplicitGcViolation extends StrictModeViolation {
+        StrictModeExplicitGcViolation(int policyMask) {
+            super(policyMask, DETECT_EXPLICIT_GC, null);
+        }
+    }
+
+    /**
      * Returns the bitmask of the current thread's policy.
      *
      * @return the bitmask of all the DETECT_* and PENALTY_* bits currently enabled
@@ -1414,7 +1449,7 @@
             startHandlingViolationException(e);
         }
 
-        // Part of BlockGuard.Policy; just part of StrictMode:
+        // Part of BlockGuard.Policy interface:
         public void onUnbufferedIO() {
             if ((mPolicyMask & DETECT_UNBUFFERED_IO) == 0) {
                 return;
@@ -1457,6 +1492,20 @@
             startHandlingViolationException(e);
         }
 
+        // Part of BlockGuard.Policy interface:
+        public void onExplicitGc() {
+            if ((mPolicyMask & DETECT_EXPLICIT_GC) == 0) {
+                return;
+            }
+            if (tooManyViolationsThisLoop()) {
+                return;
+            }
+            BlockGuard.BlockGuardPolicyException e =
+                    new StrictModeExplicitGcViolation(mPolicyMask);
+            e.fillInStackTrace();
+            startHandlingViolationException(e);
+        }
+
         public void setPolicyMask(int policyMask) {
             mPolicyMask = policyMask;
         }
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 4f6d322..89168ae 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -189,7 +189,12 @@
             }
             ArrayList<Runnable> callbacks = new ArrayList<Runnable>(sChangeCallbacks);
             for (int i=0; i<callbacks.size(); i++) {
-                callbacks.get(i).run();
+                try {
+                    callbacks.get(i).run();
+                } catch (Throwable t) {
+                    Log.wtf(TAG, "Exception in SystemProperties change callback", t);
+                    // Ignore and try to go on.
+                }
             }
         }
     }
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.aidl b/core/java/android/os/connectivity/CellularBatteryStats.aidl
new file mode 100644
index 0000000..ca0a585
--- /dev/null
+++ b/core/java/android/os/connectivity/CellularBatteryStats.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+package android.os.connectivity;
+
+/** {@hide} */
+parcelable CellularBatteryStats;
\ No newline at end of file
diff --git a/core/java/android/os/connectivity/CellularBatteryStats.java b/core/java/android/os/connectivity/CellularBatteryStats.java
new file mode 100644
index 0000000..2593c85
--- /dev/null
+++ b/core/java/android/os/connectivity/CellularBatteryStats.java
@@ -0,0 +1,242 @@
+/*
+ * 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.
+ */
+package android.os.connectivity;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import android.telephony.ModemActivityInfo;
+import android.telephony.SignalStrength;
+
+import java.util.Arrays;
+
+/**
+ * API for Cellular power stats
+ *
+ * @hide
+ */
+public final class CellularBatteryStats implements Parcelable {
+
+  private long mLoggingDurationMs;
+  private long mKernelActiveTimeMs;
+  private long mNumPacketsTx;
+  private long mNumBytesTx;
+  private long mNumPacketsRx;
+  private long mNumBytesRx;
+  private long mSleepTimeMs;
+  private long mIdleTimeMs;
+  private long mRxTimeMs;
+  private long mEnergyConsumedMaMs;
+  private long[] mTimeInRatMs;
+  private long[] mTimeInRxSignalStrengthLevelMs;
+  private long[] mTxTimeMs;
+
+  public static final Parcelable.Creator<CellularBatteryStats> CREATOR = new
+      Parcelable.Creator<CellularBatteryStats>() {
+        public CellularBatteryStats createFromParcel(Parcel in) {
+          return new CellularBatteryStats(in);
+        }
+
+        public CellularBatteryStats[] newArray(int size) {
+          return new CellularBatteryStats[size];
+        }
+      };
+
+  public CellularBatteryStats() {
+    initialize();
+  }
+
+  public void writeToParcel(Parcel out, int flags) {
+    out.writeLong(mLoggingDurationMs);
+    out.writeLong(mKernelActiveTimeMs);
+    out.writeLong(mNumPacketsTx);
+    out.writeLong(mNumBytesTx);
+    out.writeLong(mNumPacketsRx);
+    out.writeLong(mNumBytesRx);
+    out.writeLong(mSleepTimeMs);
+    out.writeLong(mIdleTimeMs);
+    out.writeLong(mRxTimeMs);
+    out.writeLong(mEnergyConsumedMaMs);
+    out.writeLongArray(mTimeInRatMs);
+    out.writeLongArray(mTimeInRxSignalStrengthLevelMs);
+    out.writeLongArray(mTxTimeMs);
+  }
+
+  public void readFromParcel(Parcel in) {
+    mLoggingDurationMs = in.readLong();
+    mKernelActiveTimeMs = in.readLong();
+    mNumPacketsTx = in.readLong();
+    mNumBytesTx = in.readLong();
+    mNumPacketsRx = in.readLong();
+    mNumBytesRx = in.readLong();
+    mSleepTimeMs = in.readLong();
+    mIdleTimeMs = in.readLong();
+    mRxTimeMs = in.readLong();
+    mEnergyConsumedMaMs = in.readLong();
+    in.readLongArray(mTimeInRatMs);
+    in.readLongArray(mTimeInRxSignalStrengthLevelMs);
+    in.readLongArray(mTxTimeMs);
+  }
+
+  public long getLoggingDurationMs() {
+    return mLoggingDurationMs;
+  }
+
+  public long getKernelActiveTimeMs() {
+    return mKernelActiveTimeMs;
+  }
+
+  public long getNumPacketsTx() {
+    return mNumPacketsTx;
+  }
+
+  public long getNumBytesTx() {
+    return mNumBytesTx;
+  }
+
+  public long getNumPacketsRx() {
+    return mNumPacketsRx;
+  }
+
+  public long getNumBytesRx() {
+    return mNumBytesRx;
+  }
+
+  public long getSleepTimeMs() {
+    return mSleepTimeMs;
+  }
+
+  public long getIdleTimeMs() {
+    return mIdleTimeMs;
+  }
+
+  public long getRxTimeMs() {
+    return mRxTimeMs;
+  }
+
+  public long getEnergyConsumedMaMs() {
+    return mEnergyConsumedMaMs;
+  }
+
+  public long[] getTimeInRatMs() {
+    return mTimeInRatMs;
+  }
+
+  public long[] getTimeInRxSignalStrengthLevelMs() {
+    return mTimeInRxSignalStrengthLevelMs;
+  }
+
+  public long[] getTxTimeMs() {
+    return mTxTimeMs;
+  }
+
+  public void setLoggingDurationMs(long t) {
+    mLoggingDurationMs = t;
+    return;
+  }
+
+  public void setKernelActiveTimeMs(long t) {
+    mKernelActiveTimeMs = t;
+    return;
+  }
+
+  public void setNumPacketsTx(long n) {
+    mNumPacketsTx = n;
+    return;
+  }
+
+  public void setNumBytesTx(long b) {
+    mNumBytesTx = b;
+    return;
+  }
+
+  public void setNumPacketsRx(long n) {
+    mNumPacketsRx = n;
+    return;
+  }
+
+  public void setNumBytesRx(long b) {
+    mNumBytesRx = b;
+    return;
+  }
+
+  public void setSleepTimeMs(long t) {
+    mSleepTimeMs = t;
+    return;
+  }
+
+  public void setIdleTimeMs(long t) {
+    mIdleTimeMs = t;
+    return;
+  }
+
+  public void setRxTimeMs(long t) {
+    mRxTimeMs = t;
+    return;
+  }
+
+  public void setEnergyConsumedMaMs(long e) {
+    mEnergyConsumedMaMs = e;
+    return;
+  }
+
+  public void setTimeInRatMs(long[] t) {
+    mTimeInRatMs = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, BatteryStats.NUM_DATA_CONNECTION_TYPES));
+    return;
+  }
+
+  public void setTimeInRxSignalStrengthLevelMs(long[] t) {
+    mTimeInRxSignalStrengthLevelMs = Arrays.copyOfRange(t, 0,
+        Math.min(t.length, SignalStrength.NUM_SIGNAL_STRENGTH_BINS));
+    return;
+  }
+
+  public void setTxTimeMs(long[] t) {
+    mTxTimeMs = Arrays.copyOfRange(t, 0, Math.min(t.length, ModemActivityInfo.TX_POWER_LEVELS));
+    return;
+  }
+
+  public int describeContents() {
+    return 0;
+  }
+
+  private CellularBatteryStats(Parcel in) {
+    initialize();
+    readFromParcel(in);
+  }
+
+  private void initialize() {
+    mLoggingDurationMs = 0;
+    mKernelActiveTimeMs = 0;
+    mNumPacketsTx = 0;
+    mNumBytesTx = 0;
+    mNumPacketsRx = 0;
+    mNumBytesRx = 0;
+    mSleepTimeMs = 0;
+    mIdleTimeMs = 0;
+    mRxTimeMs = 0;
+    mEnergyConsumedMaMs = 0;
+    mTimeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+    Arrays.fill(mTimeInRatMs, 0);
+    mTimeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+    Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0);
+    mTxTimeMs = new long[ModemActivityInfo.TX_POWER_LEVELS];
+    Arrays.fill(mTxTimeMs, 0);
+    return;
+  }
+}
\ No newline at end of file
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index fb11d00..8aef012 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -228,6 +228,25 @@
     /** @hide */
     public static final String RES_CAN_BLOCK_NUMBERS = "can_block";
 
+    /** @hide */
+    public static final String RES_ENHANCED_SETTING_IS_ENABLED = "enhanced_setting_enabled";
+
+    /** @hide */
+    public static final String RES_SHOW_EMERGENCY_CALL_NOTIFICATION =
+            "show_emergency_call_notification";
+
+    /** @hide */
+    public static final String EXTRA_ENHANCED_SETTING_KEY = "extra_enhanced_setting_key";
+
+    /** @hide */
+    public static final String EXTRA_ENHANCED_SETTING_VALUE = "extra_enhanced_setting_value";
+
+    /** @hide */
+    public static final String EXTRA_CONTACT_EXIST = "extra_contact_exist";
+
+    /** @hide */
+    public static final String EXTRA_CALL_PRESENTATION = "extra_call_presentation";
+
     /**
      * Returns whether a given number is in the blocked list.
      *
@@ -314,11 +333,33 @@
         public static final String METHOD_GET_BLOCK_SUPPRESSION_STATUS =
                 "get_block_suppression_status";
 
+        public static final String METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION =
+                "should_show_emergency_call_notification";
+
         public static final String RES_IS_BLOCKING_SUPPRESSED = "blocking_suppressed";
 
         public static final String RES_BLOCKING_SUPPRESSED_UNTIL_TIMESTAMP =
                 "blocking_suppressed_until_timestamp";
 
+        public static final String METHOD_GET_ENHANCED_BLOCK_SETTING = "get_enhanced_block_setting";
+        public static final String METHOD_SET_ENHANCED_BLOCK_SETTING = "set_enhanced_block_setting";
+
+        /* Preference key of block numbers not in contacts setting. */
+        public static final String ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED =
+                "block_numbers_not_in_contacts_setting";
+        /* Preference key of block private number calls setting. */
+        public static final String ENHANCED_SETTING_KEY_BLOCK_PRIVATE =
+                "block_private_number_calls_setting";
+        /* Preference key of block payphone calls setting. */
+        public static final String ENHANCED_SETTING_KEY_BLOCK_PAYPHONE =
+                "block_payphone_calls_setting";
+        /* Preference key of block unknown calls setting. */
+        public static final String ENHANCED_SETTING_KEY_BLOCK_UNKNOWN =
+                "block_unknown_calls_setting";
+        /* Preference key for whether should show an emergency call notification. */
+        public static final String ENHANCED_SETTING_KEY_SHOW_EMERGENCY_CALL_NOTIFICATION =
+                "show_emergency_call_notification";
+
         /**
          * Notifies the provider that emergency services were contacted by the user.
          * <p> This results in {@link #shouldSystemBlockNumber} returning {@code false} independent
@@ -342,13 +383,19 @@
 
         /**
          * Returns {@code true} if {@code phoneNumber} is blocked taking
-         * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services have
-         * not been contacted recently, this method is equivalent to
-         * {@link #isBlocked(Context, String)}.
+         * {@link #notifyEmergencyContact(Context)} into consideration. If emergency services
+         * have not been contacted recently and enhanced call blocking not been enabled, this
+         * method is equivalent to {@link #isBlocked(Context, String)}.
+         *
+         * @param context the context of the caller.
+         * @param phoneNumber the number to check.
+         * @param extras the extra attribute of the number.
+         * @return {@code true} if should block the number. {@code false} otherwise.
          */
-        public static boolean shouldSystemBlockNumber(Context context, String phoneNumber) {
+        public static boolean shouldSystemBlockNumber(Context context, String phoneNumber,
+                Bundle extras) {
             final Bundle res = context.getContentResolver().call(
-                    AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, null);
+                    AUTHORITY_URI, METHOD_SHOULD_SYSTEM_BLOCK_NUMBER, phoneNumber, extras);
             return res != null && res.getBoolean(RES_NUMBER_IS_BLOCKED, false);
         }
 
@@ -363,9 +410,62 @@
         }
 
         /**
-         * Represents the current status of {@link #shouldSystemBlockNumber(Context, String)}. If
-         * emergency services have been contacted recently, {@link #isSuppressed} is {@code true},
-         * and blocking is disabled until the timestamp {@link #untilTimestampMillis}.
+         * Check whether should show the emergency call notification.
+         *
+         * @param context the context of the caller.
+         * @return {@code true} if should show emergency call notification. {@code false} otherwise.
+         */
+        public static boolean shouldShowEmergencyCallNotification(Context context) {
+            final Bundle res = context.getContentResolver().call(
+                    AUTHORITY_URI, METHOD_SHOULD_SHOW_EMERGENCY_CALL_NOTIFICATION, null, null);
+            return res != null && res.getBoolean(RES_SHOW_EMERGENCY_CALL_NOTIFICATION, false);
+        }
+
+        /**
+         * Check whether the enhanced block setting is enabled.
+         *
+         * @param context the context of the caller.
+         * @param key the key of the setting to check, can be
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
+         *        {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING}
+         * @return {@code true} if the setting is enabled. {@code false} otherwise.
+         */
+        public static boolean getEnhancedBlockSetting(Context context, String key) {
+            Bundle extras = new Bundle();
+            extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
+            final Bundle res = context.getContentResolver().call(
+                    AUTHORITY_URI, METHOD_GET_ENHANCED_BLOCK_SETTING, null, extras);
+            return res != null && res.getBoolean(RES_ENHANCED_SETTING_IS_ENABLED, false);
+        }
+
+        /**
+         * Set the enhanced block setting enabled status.
+         *
+         * @param context the context of the caller.
+         * @param key the key of the setting to set, can be
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_PRIVATE}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_PAYPHONE}
+         *        {@link #ENHANCED_SETTING_KEY_BLOCK_UNKNOWN}
+         *        {@link #ENHANCED_SETTING_KEY_EMERGENCY_CALL_NOTIFICATION_SHOWING}
+         * @param value the enabled statue of the setting to set.
+         */
+        public static void setEnhancedBlockSetting(Context context, String key, boolean value) {
+            Bundle extras = new Bundle();
+            extras.putString(EXTRA_ENHANCED_SETTING_KEY, key);
+            extras.putBoolean(EXTRA_ENHANCED_SETTING_VALUE, value);
+            context.getContentResolver().call(AUTHORITY_URI, METHOD_SET_ENHANCED_BLOCK_SETTING,
+                    null, extras);
+        }
+
+        /**
+         * Represents the current status of
+         * {@link #shouldSystemBlockNumber(Context, String, Bundle)}. If emergency services
+         * have been contacted recently, {@link #isSuppressed} is {@code true}, and blocking
+         * is disabled until the timestamp {@link #untilTimestampMillis}.
          */
         public static class BlockSuppressionStatus {
             public final boolean isSuppressed;
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 60df467..70de09e 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -223,14 +223,14 @@
         /** Call was WIFI call. */
         public static final int FEATURES_WIFI = 1 << 3;
 
-        /** Call was on RTT at some point */
-        public static final int FEATURES_RTT = 1 << 4;
-
         /**
          * Indicates the call underwent Assisted Dialing.
          * @hide
          */
-        public static final Integer FEATURES_ASSISTED_DIALING_USED = 0x10;
+        public static final int FEATURES_ASSISTED_DIALING_USED = 1 << 4;
+
+        /** Call was on RTT at some point */
+        public static final int FEATURES_RTT = 1 << 5;
 
         /**
          * The phone number as the user entered it.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index ca3f5e9..517995e 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8706,6 +8706,12 @@
         public static final String BLE_SCAN_LOW_LATENCY_INTERVAL_MS =
                 "ble_scan_low_latency_interval_ms";
 
+        /**
+         * The mode that BLE scanning clients will be moved to when in the background.
+         * @hide
+         */
+        public static final String BLE_SCAN_BACKGROUND_MODE = "ble_scan_background_mode";
+
        /**
         * Used to save the Wifi_ON state prior to tethering.
         * This state will be checked to restore Wifi after
diff --git a/core/java/android/se/omapi/Session.java b/core/java/android/se/omapi/Session.java
index 19a018e..3d8b74b 100644
--- a/core/java/android/se/omapi/Session.java
+++ b/core/java/android/se/omapi/Session.java
@@ -301,12 +301,6 @@
      *         provide a new logical channel.
      */
     public @Nullable Channel openLogicalChannel(byte[] aid, byte p2) throws IOException {
-
-        if ((mReader.getName().startsWith("SIM")) && (aid == null)) {
-            Log.e(TAG, "NULL AID not supported on " + mReader.getName());
-            return null;
-        }
-
         if (!mService.isConnected()) {
             throw new IllegalStateException("service not connected to system");
         }
diff --git a/core/java/android/service/euicc/EuiccProfileInfo.java b/core/java/android/service/euicc/EuiccProfileInfo.java
index cb4f104..4bbee61 100644
--- a/core/java/android/service/euicc/EuiccProfileInfo.java
+++ b/core/java/android/service/euicc/EuiccProfileInfo.java
@@ -441,7 +441,7 @@
                 + ", state="
                 + mState
                 + ", CarrierIdentifier="
-                + mCarrierIdentifier.toString()
+                + mCarrierIdentifier
                 + ", policyRules="
                 + mPolicyRules
                 + ", accessRules="
diff --git a/core/java/android/util/StatsLog.java b/core/java/android/util/StatsLog.java
new file mode 100644
index 0000000..a4ffbe4
--- /dev/null
+++ b/core/java/android/util/StatsLog.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * @hide
+ * Temporary dummy class for StatsLog. Will be removed.
+ */
+public final class StatsLog {
+    private static final String TAG = "StatsManager";
+
+    public static final int BLUETOOTH_ENABLED_STATE_CHANGED = 0;
+    public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN = 0;
+    public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED = 1;
+    public static final int BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED = 2;
+
+    public static final int BLUETOOTH_CONNECTION_STATE_CHANGED = 1;
+
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED = 2;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__UNKNOWN = 0;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__PLAY = 1;
+    public static final int BLUETOOTH_A2DP_AUDIO_STATE_CHANGED__STATE__STOP = 2;
+
+    private StatsLog() {}
+
+    public static void write(int id, int field1) {}
+
+    public static void write(int id, int field1, int field2, int field3) {}
+
+    public static void write_non_chained(int id, int uid, String tag,
+            int field1, int field2, String field3) {}
+}
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index e576a0f..79f42df 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -397,4 +397,10 @@
      * Return the touch region for the current IME window, or an empty region if there is none.
      */
     Region getCurrentImeTouchRegion();
+
+    /**
+     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+     * on the next user activity.
+     */
+    void requestUserActivityNotification();
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index c4ffb4c..8e4f5b4 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -159,6 +159,12 @@
     public final static boolean WATCH_POINTER = false;
 
     /**
+     * Broadcast sent when a user activity is detected.
+     */
+    public final static String ACTION_USER_ACTIVITY_NOTIFICATION =
+            "android.intent.action.USER_ACTIVITY_NOTIFICATION";
+
+    /**
      * Sticky broadcast of the current HDMI plugged state.
      */
     public final static String ACTION_HDMI_PLUGGED = "android.intent.action.HDMI_PLUGGED";
@@ -1741,4 +1747,10 @@
      * @return true if ready; false otherwise.
      */
     boolean canDismissBootAnimation();
+
+    /**
+     * Requests that the WindowManager sends WindowManagerPolicy#ACTION_USER_ACTIVITY_NOTIFICATION
+     * on the next user activity.
+     */
+    public void requestUserActivityNotification();
 }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 4275e0b..f4f4317 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -22,6 +22,7 @@
 import android.net.wifi.WifiActivityEnergyInfo;
 import android.os.ParcelFileDescriptor;
 import android.os.WorkSource;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ModemActivityInfo;
@@ -134,6 +135,9 @@
     void noteResetBleScan();
     void noteBleScanResults(in WorkSource ws, int numNewResults);
 
+    /** {@hide} */
+    CellularBatteryStats getCellularBatteryStats();
+
     HealthStatsParceler takeUidSnapshot(int uid);
     HealthStatsParceler[] takeUidSnapshots(in int[] uid);
 
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index f26c0cd..10618d4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -30,6 +30,7 @@
 import android.os.BatteryManager;
 import android.os.BatteryStats;
 import android.os.Build;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.FileUtils;
 import android.os.Handler;
 import android.os.IBatteryPropertiesRegistrar;
@@ -11262,6 +11263,51 @@
         return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
     }
 
+    /*@hide */
+    public CellularBatteryStats getCellularBatteryStats() {
+        CellularBatteryStats s = new CellularBatteryStats();
+        final int which = STATS_SINCE_CHARGED;
+        final long rawRealTime = SystemClock.elapsedRealtime() * 1000;
+        final ControllerActivityCounter counter = getModemControllerActivity();
+        final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which);
+        final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which);
+        final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which);
+        long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES];
+        for (int i = 0; i < timeInRatMs.length; i++) {
+           timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000;
+        }
+        long[] timeInRxSignalStrengthLevelMs = new long[SignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+        for (int i = 0; i < timeInRxSignalStrengthLevelMs.length; i++) {
+           timeInRxSignalStrengthLevelMs[i]
+               = getPhoneSignalStrengthTime(i, rawRealTime, which) / 1000;
+        }
+        long[] txTimeMs = new long[Math.min(ModemActivityInfo.TX_POWER_LEVELS,
+            counter.getTxTimeCounters().length)];
+        long totalTxTimeMs = 0;
+        for (int i = 0; i < txTimeMs.length; i++) {
+            txTimeMs[i] = counter.getTxTimeCounters()[i].getCountLocked(which);
+            totalTxTimeMs += txTimeMs[i];
+        }
+        final long totalControllerActivityTimeMs
+            = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000;
+        final long sleepTimeMs
+            = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + totalTxTimeMs);
+        s.setLoggingDurationMs(computeBatteryRealtime(rawRealTime, which) / 1000);
+        s.setKernelActiveTimeMs(getMobileRadioActiveTime(rawRealTime, which) / 1000);
+        s.setNumPacketsTx(getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
+        s.setNumBytesTx(getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
+        s.setNumPacketsRx(getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
+        s.setNumBytesRx(getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
+        s.setSleepTimeMs(sleepTimeMs);
+        s.setIdleTimeMs(idleTimeMs);
+        s.setRxTimeMs(rxTimeMs);
+        s.setEnergyConsumedMaMs(energyConsumedMaMs);
+        s.setTimeInRatMs(timeInRatMs);
+        s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs);
+        s.setTxTimeMs(txTimeMs);
+        return s;
+    }
+
     @Override
     public LevelStepTracker getChargeLevelStepTracker() {
         return mChargeStepTracker;
diff --git a/core/java/com/android/server/net/BaseNetdEventCallback.java b/core/java/com/android/server/net/BaseNetdEventCallback.java
new file mode 100644
index 0000000..fdba2f3
--- /dev/null
+++ b/core/java/com/android/server/net/BaseNetdEventCallback.java
@@ -0,0 +1,44 @@
+/*
+ * 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.net;
+
+import android.net.INetdEventCallback;
+
+/**
+ * Base {@link INetdEventCallback} that provides no-op
+ * implementations which can be overridden.
+ *
+ * @hide
+ */
+public class BaseNetdEventCallback extends INetdEventCallback.Stub {
+    @Override
+    public void onDnsEvent(String hostname, String[] ipAddresses,
+            int ipAddressesCount, long timestamp, int uid) {
+        // default no-op
+    }
+
+    @Override
+    public void onPrivateDnsValidationEvent(int netId, String ipAddress,
+            String hostname, boolean validated) {
+        // default no-op
+    }
+
+    @Override
+    public void onConnectEvent(String ipAddr, int port, long timestamp, int uid) {
+        // default no-op
+    }
+}
diff --git a/core/jni/android_os_SystemProperties.cpp b/core/jni/android_os_SystemProperties.cpp
index a94cac0..9ec7517 100644
--- a/core/jni/android_os_SystemProperties.cpp
+++ b/core/jni/android_os_SystemProperties.cpp
@@ -124,6 +124,12 @@
         if (sVM->GetEnv((void **)&env, JNI_VERSION_1_4) >= 0) {
             //ALOGI("Java SystemProperties: calling %p", sCallChangeCallbacks);
             env->CallStaticVoidMethod(sClazz, sCallChangeCallbacks);
+            // There should not be any exceptions. But we must guarantee
+            // there are none on return.
+            if (env->ExceptionCheck()) {
+                env->ExceptionClear();
+                LOG(ERROR) << "Exception pending after sysprop_change!";
+            }
         }
     }
 }
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3f95cf4..f1b736b 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -71,6 +71,9 @@
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 
+#define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
+                              append(StringPrintf(__VA_ARGS__))
+
 static pid_t gSystemServerPid = 0;
 
 static const char kZygoteClassName[] = "com/android/internal/os/Zygote";
@@ -186,30 +189,32 @@
 
 // Calls POSIX setgroups() using the int[] object as an argument.
 // A NULL argument is tolerated.
-static void SetGids(JNIEnv* env, jintArray javaGids) {
+static bool SetGids(JNIEnv* env, jintArray javaGids, std::string* error_msg) {
   if (javaGids == NULL) {
-    return;
+    return true;
   }
 
   ScopedIntArrayRO gids(env, javaGids);
   if (gids.get() == NULL) {
-    RuntimeAbort(env, __LINE__, "Getting gids int array failed");
+    *error_msg = CREATE_ERROR("Getting gids int array failed");
+    return false;
   }
   int rc = setgroups(gids.size(), reinterpret_cast<const gid_t*>(&gids[0]));
   if (rc == -1) {
-    std::ostringstream oss;
-    oss << "setgroups failed: " << strerror(errno) << ", gids.size=" << gids.size();
-    RuntimeAbort(env, __LINE__, oss.str().c_str());
+    *error_msg = CREATE_ERROR("setgroups failed: %s, gids.size=%zu", strerror(errno), gids.size());
+    return false;
   }
+
+  return true;
 }
 
 // Sets the resource limits via setrlimit(2) for the values in the
 // two-dimensional array of integers that's passed in. The second dimension
 // contains a tuple of length 3: (resource, rlim_cur, rlim_max). NULL is
 // treated as an empty array.
-static void SetRLimits(JNIEnv* env, jobjectArray javaRlimits) {
+static bool SetRLimits(JNIEnv* env, jobjectArray javaRlimits, std::string* error_msg) {
   if (javaRlimits == NULL) {
-    return;
+    return true;
   }
 
   rlimit rlim;
@@ -219,7 +224,8 @@
     ScopedLocalRef<jobject> javaRlimitObject(env, env->GetObjectArrayElement(javaRlimits, i));
     ScopedIntArrayRO javaRlimit(env, reinterpret_cast<jintArray>(javaRlimitObject.get()));
     if (javaRlimit.size() != 3) {
-      RuntimeAbort(env, __LINE__, "rlimits array must have a second dimension of size 3");
+      *error_msg = CREATE_ERROR("rlimits array must have a second dimension of size 3");
+      return false;
     }
 
     rlim.rlim_cur = javaRlimit[1];
@@ -227,11 +233,13 @@
 
     int rc = setrlimit(javaRlimit[0], &rlim);
     if (rc == -1) {
-      ALOGE("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
+      *error_msg = CREATE_ERROR("setrlimit(%d, {%ld, %ld}) failed", javaRlimit[0], rlim.rlim_cur,
             rlim.rlim_max);
-      RuntimeAbort(env, __LINE__, "setrlimit failed");
+      return false;
     }
   }
+
+  return true;
 }
 
 // The debug malloc library needs to know whether it's the zygote or a child.
@@ -259,14 +267,16 @@
   }
 }
 
-static void EnableKeepCapabilities(JNIEnv* env) {
+static bool EnableKeepCapabilities(std::string* error_msg) {
   int rc = prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
   if (rc == -1) {
-    RuntimeAbort(env, __LINE__, "prctl(PR_SET_KEEPCAPS) failed");
+    *error_msg = CREATE_ERROR("prctl(PR_SET_KEEPCAPS) failed: %s", strerror(errno));
+    return false;
   }
+  return true;
 }
 
-static void DropCapabilitiesBoundingSet(JNIEnv* env) {
+static bool DropCapabilitiesBoundingSet(std::string* error_msg) {
   for (int i = 0; prctl(PR_CAPBSET_READ, i, 0, 0, 0) >= 0; i++) {
     int rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
     if (rc == -1) {
@@ -274,14 +284,15 @@
         ALOGE("prctl(PR_CAPBSET_DROP) failed with EINVAL. Please verify "
               "your kernel is compiled with file capabilities support");
       } else {
-        ALOGE("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
-        RuntimeAbort(env, __LINE__, "prctl(PR_CAPBSET_DROP) failed");
+        *error_msg = CREATE_ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s", i, strerror(errno));
+        return false;
       }
     }
   }
+  return true;
 }
 
-static void SetInheritable(JNIEnv* env, uint64_t inheritable) {
+static bool SetInheritable(uint64_t inheritable, std::string* error_msg) {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
   capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -289,21 +300,23 @@
 
   __user_cap_data_struct capdata[2];
   if (capget(&capheader, &capdata[0]) == -1) {
-    ALOGE("capget failed: %s", strerror(errno));
-    RuntimeAbort(env, __LINE__, "capget failed");
+    *error_msg = CREATE_ERROR("capget failed: %s", strerror(errno));
+    return false;
   }
 
   capdata[0].inheritable = inheritable;
   capdata[1].inheritable = inheritable >> 32;
 
   if (capset(&capheader, &capdata[0]) == -1) {
-    ALOGE("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
-    RuntimeAbort(env, __LINE__, "capset failed");
+    *error_msg = CREATE_ERROR("capset(inh=%" PRIx64 ") failed: %s", inheritable, strerror(errno));
+    return false;
   }
+
+  return true;
 }
 
-static void SetCapabilities(JNIEnv* env, uint64_t permitted, uint64_t effective,
-                            uint64_t inheritable) {
+static bool SetCapabilities(uint64_t permitted, uint64_t effective, uint64_t inheritable,
+                            std::string* error_msg) {
   __user_cap_header_struct capheader;
   memset(&capheader, 0, sizeof(capheader));
   capheader.version = _LINUX_CAPABILITY_VERSION_3;
@@ -319,18 +332,20 @@
   capdata[1].inheritable = inheritable >> 32;
 
   if (capset(&capheader, &capdata[0]) == -1) {
-    ALOGE("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") failed: %s", permitted,
-          effective, inheritable, strerror(errno));
-    RuntimeAbort(env, __LINE__, "capset failed");
+    *error_msg = CREATE_ERROR("capset(perm=%" PRIx64 ", eff=%" PRIx64 ", inh=%" PRIx64 ") "
+                              "failed: %s", permitted, effective, inheritable, strerror(errno));
+    return false;
   }
+  return true;
 }
 
-static void SetSchedulerPolicy(JNIEnv* env) {
+static bool SetSchedulerPolicy(std::string* error_msg) {
   errno = -set_sched_policy(0, SP_DEFAULT);
   if (errno != 0) {
-    ALOGE("set_sched_policy(0, SP_DEFAULT) failed");
-    RuntimeAbort(env, __LINE__, "set_sched_policy(0, SP_DEFAULT) failed");
+    *error_msg = CREATE_ERROR("set_sched_policy(0, SP_DEFAULT) failed: %s", strerror(errno));
+    return false;
   }
+  return true;
 }
 
 static int UnmountTree(const char* path) {
@@ -364,7 +379,7 @@
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static bool MountEmulatedStorage(uid_t uid, jint mount_mode,
-        bool force_mount_namespace) {
+        bool force_mount_namespace, std::string* error_msg) {
     // See storage config details at http://source.android.com/tech/storage/
 
     String8 storageSource;
@@ -381,7 +396,7 @@
 
     // Create a second private mount namespace for our process
     if (unshare(CLONE_NEWNS) == -1) {
-        ALOGW("Failed to unshare(): %s", strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to unshare(): %s", strerror(errno));
         return false;
     }
 
@@ -392,7 +407,9 @@
 
     if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
             NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
-        ALOGW("Failed to mount %s to /storage: %s", storageSource.string(), strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to mount %s to /storage: %s",
+                                  storageSource.string(),
+                                  strerror(errno));
         return false;
     }
 
@@ -400,11 +417,14 @@
     userid_t user_id = multiuser_get_user_id(uid);
     const String8 userSource(String8::format("/mnt/user/%d", user_id));
     if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+        *error_msg = CREATE_ERROR("fs_prepare_dir failed on %s", userSource.string());
         return false;
     }
     if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
             NULL, MS_BIND, NULL)) == -1) {
-        ALOGW("Failed to mount %s to /storage/self: %s", userSource.string(), strerror(errno));
+        *error_msg = CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+                                  userSource.string(),
+                                  strerror(errno));
         return false;
     }
 
@@ -436,31 +456,32 @@
 // descriptor (if any) is closed via dup2(), replacing it with a valid
 // (open) descriptor to /dev/null.
 
-static void DetachDescriptors(JNIEnv* env, jintArray fdsToClose) {
+static bool DetachDescriptors(JNIEnv* env, jintArray fdsToClose, std::string* error_msg) {
   if (!fdsToClose) {
-    return;
+    return true;
   }
   jsize count = env->GetArrayLength(fdsToClose);
   ScopedIntArrayRO ar(env, fdsToClose);
   if (ar.get() == NULL) {
-      RuntimeAbort(env, __LINE__, "Bad fd array");
+    *error_msg = "Bad fd array";
+    return false;
   }
   jsize i;
   int devnull;
   for (i = 0; i < count; i++) {
     devnull = open("/dev/null", O_RDWR);
     if (devnull < 0) {
-      ALOGE("Failed to open /dev/null: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Failed to open /dev/null");
-      continue;
+      *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
+      return false;
     }
     ALOGV("Switching descriptor %d to /dev/null: %s", ar[i], strerror(errno));
     if (dup2(devnull, ar[i]) < 0) {
-      ALOGE("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
-      RuntimeAbort(env, __LINE__, "Failed dup2()");
+      *error_msg = StringPrintf("Failed dup2() on descriptor %d: %s", ar[i], strerror(errno));
+      return false;
     }
     close(devnull);
   }
+  return true;
 }
 
 void SetThreadName(const char* thread_name) {
@@ -488,25 +509,30 @@
   if (errno != 0) {
     ALOGW("Unable to set the name of current thread to '%s': %s", buf, strerror(errno));
   }
+  // Update base::logging default tag.
+  android::base::SetDefaultTag(buf);
 }
 
 // The list of open zygote file descriptors.
 static FileDescriptorTable* gOpenFdTable = NULL;
 
-static void FillFileDescriptorVector(JNIEnv* env,
+static bool FillFileDescriptorVector(JNIEnv* env,
                                      jintArray java_fds,
-                                     std::vector<int>* fds) {
+                                     std::vector<int>* fds,
+                                     std::string* error_msg) {
   CHECK(fds != nullptr);
   if (java_fds != nullptr) {
     ScopedIntArrayRO ar(env, java_fds);
     if (ar.get() == nullptr) {
-      RuntimeAbort(env, __LINE__, "Bad fd array");
+      *error_msg = "Bad fd array";
+      return false;
     }
     fds->reserve(ar.size());
     for (size_t i = 0; i < ar.size(); ++i) {
       fds->push_back(ar[i]);
     }
   }
+  return true;
 }
 
 // Utility routine to fork zygote and specialize the child process.
@@ -524,32 +550,53 @@
   sigemptyset(&sigchld);
   sigaddset(&sigchld, SIGCHLD);
 
+  auto fail_fn = [env, java_se_name, is_system_server](const std::string& msg)
+      __attribute__ ((noreturn)) {
+    const char* se_name_c_str = nullptr;
+    std::unique_ptr<ScopedUtfChars> se_name;
+    if (java_se_name != nullptr) {
+      se_name.reset(new ScopedUtfChars(env, java_se_name));
+      se_name_c_str = se_name->c_str();
+    }
+    if (se_name_c_str == nullptr && is_system_server) {
+      se_name_c_str = "system_server";
+    }
+    const std::string& error_msg = (se_name_c_str == nullptr)
+        ? msg
+        : StringPrintf("(%s) %s", se_name_c_str, msg.c_str());
+    env->FatalError(error_msg.c_str());
+    __builtin_unreachable();
+  };
+
   // Temporarily block SIGCHLD during forks. The SIGCHLD handler might
   // log, which would result in the logging FDs we close being reopened.
   // This would cause failures because the FDs are not whitelisted.
   //
   // Note that the zygote process is single threaded at this point.
   if (sigprocmask(SIG_BLOCK, &sigchld, nullptr) == -1) {
-    ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-    RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_BLOCK, { SIGCHLD }) failed.");
+    fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
   }
 
   // Close any logging related FDs before we start evaluating the list of
   // file descriptors.
   __android_log_close();
 
+  std::string error_msg;
+
   // If this is the first fork for this zygote, create the open FD table.
   // If it isn't, we just need to check whether the list of open files has
   // changed (and it shouldn't in the normal case).
   std::vector<int> fds_to_ignore;
-  FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore);
+  if (!FillFileDescriptorVector(env, fdsToIgnore, &fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
+  }
   if (gOpenFdTable == NULL) {
-    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore);
+    gOpenFdTable = FileDescriptorTable::Create(fds_to_ignore, &error_msg);
     if (gOpenFdTable == NULL) {
-      RuntimeAbort(env, __LINE__, "Unable to construct file descriptor table.");
+      fail_fn(error_msg);
     }
-  } else if (!gOpenFdTable->Restat(fds_to_ignore)) {
-    RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
+  } else if (!gOpenFdTable->Restat(fds_to_ignore, &error_msg)) {
+    fail_fn(error_msg);
   }
 
   pid_t pid = fork();
@@ -558,17 +605,18 @@
     PreApplicationInit();
 
     // Clean up any descriptors which must be closed immediately
-    DetachDescriptors(env, fdsToClose);
+    if (!DetachDescriptors(env, fdsToClose, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
     // Re-open all remaining open file descriptors so that they aren't shared
     // with the zygote across a fork.
-    if (!gOpenFdTable->ReopenOrDetach()) {
-      RuntimeAbort(env, __LINE__, "Unable to reopen whitelisted descriptors.");
+    if (!gOpenFdTable->ReopenOrDetach(&error_msg)) {
+      fail_fn(error_msg);
     }
 
     if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
-      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
     }
 
     // Must be called when the new process still has CAP_SYS_ADMIN.  The other alternative is to
@@ -578,11 +626,17 @@
 
     // Keep capabilities across UID change, unless we're staying root.
     if (uid != 0) {
-      EnableKeepCapabilities(env);
+      if (!EnableKeepCapabilities(&error_msg)) {
+        fail_fn(error_msg);
+      }
     }
 
-    SetInheritable(env, permittedCapabilities);
-    DropCapabilitiesBoundingSet(env);
+    if (!SetInheritable(permittedCapabilities, &error_msg)) {
+      fail_fn(error_msg);
+    }
+    if (!DropCapabilitiesBoundingSet(&error_msg)) {
+      fail_fn(error_msg);
+    }
 
     bool use_native_bridge = !is_system_server && (instructionSet != NULL)
         && android::NativeBridgeAvailable();
@@ -599,8 +653,8 @@
       ALOGW("Native bridge will not be used because dataDir == NULL.");
     }
 
-    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge)) {
-      ALOGW("Failed to mount emulated storage: %s", strerror(errno));
+    if (!MountEmulatedStorage(uid, mount_external, use_native_bridge, &error_msg)) {
+      ALOGW("Failed to mount emulated storage: %s (%s)", error_msg.c_str(), strerror(errno));
       if (errno == ENOTCONN || errno == EROFS) {
         // When device is actively encrypting, we get ENOTCONN here
         // since FUSE was mounted before the framework restarted.
@@ -608,7 +662,7 @@
         // FUSE hasn't been created yet by init.
         // In either case, continue without external storage.
       } else {
-        RuntimeAbort(env, __LINE__, "Cannot continue without emulated storage");
+        fail_fn(error_msg);
       }
     }
 
@@ -623,9 +677,14 @@
         }
     }
 
-    SetGids(env, javaGids);
+    std::string error_msg;
+    if (!SetGids(env, javaGids, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
-    SetRLimits(env, javaRlimits);
+    if (!SetRLimits(env, javaRlimits, &error_msg)) {
+      fail_fn(error_msg);
+    }
 
     if (use_native_bridge) {
       ScopedUtfChars isa_string(env, instructionSet);
@@ -635,14 +694,12 @@
 
     int rc = setresgid(gid, gid, gid);
     if (rc == -1) {
-      ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
-      RuntimeAbort(env, __LINE__, "setresgid failed");
+      fail_fn(CREATE_ERROR("setresgid(%d) failed: %s", gid, strerror(errno)));
     }
 
     rc = setresuid(uid, uid, uid);
     if (rc == -1) {
-      ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
-      RuntimeAbort(env, __LINE__, "setresuid failed");
+      fail_fn(CREATE_ERROR("setresuid(%d) failed: %s", uid, strerror(errno)));
     }
 
     if (NeedsNoRandomizeWorkaround()) {
@@ -654,9 +711,14 @@
         }
     }
 
-    SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
+    if (!SetCapabilities(permittedCapabilities, effectiveCapabilities, permittedCapabilities,
+                         &error_msg)) {
+      fail_fn(error_msg);
+    }
 
-    SetSchedulerPolicy(env);
+    if (!SetSchedulerPolicy(&error_msg)) {
+      fail_fn(error_msg);
+    }
 
     const char* se_info_c_str = NULL;
     ScopedUtfChars* se_info = NULL;
@@ -664,7 +726,7 @@
         se_info = new ScopedUtfChars(env, java_se_info);
         se_info_c_str = se_info->c_str();
         if (se_info_c_str == NULL) {
-          RuntimeAbort(env, __LINE__, "se_info_c_str == NULL");
+          fail_fn("se_info_c_str == NULL");
         }
     }
     const char* se_name_c_str = NULL;
@@ -673,22 +735,21 @@
         se_name = new ScopedUtfChars(env, java_se_name);
         se_name_c_str = se_name->c_str();
         if (se_name_c_str == NULL) {
-          RuntimeAbort(env, __LINE__, "se_name_c_str == NULL");
+          fail_fn("se_name_c_str == NULL");
         }
     }
     rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
     if (rc == -1) {
-      ALOGE("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
-            is_system_server, se_info_c_str, se_name_c_str);
-      RuntimeAbort(env, __LINE__, "selinux_android_setcontext failed");
+      fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
+            is_system_server, se_info_c_str, se_name_c_str));
     }
 
     // Make it easier to debug audit logs by setting the main thread's name to the
     // nice name rather than "app_process".
-    if (se_info_c_str == NULL && is_system_server) {
+    if (se_name_c_str == NULL && is_system_server) {
       se_name_c_str = "system_server";
     }
-    if (se_info_c_str != NULL) {
+    if (se_name_c_str != NULL) {
       SetThreadName(se_name_c_str);
     }
 
@@ -701,15 +762,14 @@
     env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                               is_system_server, is_child_zygote, instructionSet);
     if (env->ExceptionCheck()) {
-      RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
+      fail_fn("Error calling post fork hooks.");
     }
   } else if (pid > 0) {
     // the parent process
 
     // We blocked SIGCHLD prior to a fork, we unblock it here.
     if (sigprocmask(SIG_UNBLOCK, &sigchld, nullptr) == -1) {
-      ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
-      RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
+      fail_fn(CREATE_ERROR("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno)));
     }
   }
   return pid;
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 1383bbd..b19848b 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -119,14 +119,57 @@
 
 FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
 
+// Keeps track of all relevant information (flags, offset etc.) of an
+// open zygote file descriptor.
+class FileDescriptorInfo {
+ public:
+  // Create a FileDescriptorInfo for a given file descriptor. Returns
+  // |NULL| if an error occurred.
+  static FileDescriptorInfo* CreateFromFd(int fd, std::string* error_msg);
+
+  // Checks whether the file descriptor associated with this object
+  // refers to the same description.
+  bool Restat() const;
+
+  bool ReopenOrDetach(std::string* error_msg) const;
+
+  const int fd;
+  const struct stat stat;
+  const std::string file_path;
+  const int open_flags;
+  const int fd_flags;
+  const int fs_flags;
+  const off_t offset;
+  const bool is_sock;
+
+ private:
+  FileDescriptorInfo(int fd);
+
+  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
+                     int fd_flags, int fs_flags, off_t offset);
+
+  // Returns the locally-bound name of the socket |fd|. Returns true
+  // iff. all of the following hold :
+  //
+  // - the socket's sa_family is AF_UNIX.
+  // - the length of the path is greater than zero (i.e, not an unnamed socket).
+  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
+  //   address).
+  static bool GetSocketName(const int fd, std::string* result);
+
+  bool DetachSocket(std::string* error_msg) const;
+
+  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
+};
+
 // static
-FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd) {
+FileDescriptorInfo* FileDescriptorInfo::CreateFromFd(int fd, std::string* error_msg) {
   struct stat f_stat;
   // This should never happen; the zygote should always have the right set
   // of permissions required to stat all its open files.
   if (TEMP_FAILURE_RETRY(fstat(fd, &f_stat)) == -1) {
-    PLOG(ERROR) << "Unable to stat fd " << fd;
-    return NULL;
+    *error_msg = android::base::StringPrintf("Unable to stat %d", fd);
+    return nullptr;
   }
 
   const FileDescriptorWhitelist* whitelist = FileDescriptorWhitelist::Get();
@@ -134,13 +177,15 @@
   if (S_ISSOCK(f_stat.st_mode)) {
     std::string socket_name;
     if (!GetSocketName(fd, &socket_name)) {
-      return NULL;
+      *error_msg = "Unable to get socket name";
+      return nullptr;
     }
 
     if (!whitelist->IsAllowed(socket_name)) {
-      LOG(ERROR) << "Socket name not whitelisted : " << socket_name
-                 << " (fd=" << fd << ")";
-      return NULL;
+      *error_msg = android::base::StringPrintf("Socket name not whitelisted : %s (fd=%d)",
+                                               socket_name.c_str(),
+                                               fd);
+      return nullptr;
     }
 
     return new FileDescriptorInfo(fd);
@@ -157,19 +202,22 @@
   // with the child process across forks but those should have been closed
   // before we got to this point.
   if (!S_ISCHR(f_stat.st_mode) && !S_ISREG(f_stat.st_mode)) {
-    LOG(ERROR) << "Unsupported st_mode " << f_stat.st_mode;
-    return NULL;
+    *error_msg = android::base::StringPrintf("Unsupported st_mode %u", f_stat.st_mode);
+    return nullptr;
   }
 
   std::string file_path;
   const std::string fd_path = android::base::StringPrintf("/proc/self/fd/%d", fd);
   if (!android::base::Readlink(fd_path, &file_path)) {
-    return NULL;
+    *error_msg = android::base::StringPrintf("Could not read fd link %s: %s",
+                                             fd_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   if (!whitelist->IsAllowed(file_path)) {
-    LOG(ERROR) << "Not whitelisted : " << file_path;
-    return NULL;
+    *error_msg = std::string("Not whitelisted : ").append(file_path);
+    return nullptr;
   }
 
   // File descriptor flags : currently on FD_CLOEXEC. We can set these
@@ -177,8 +225,11 @@
   // there won't be any races.
   const int fd_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD));
   if (fd_flags == -1) {
-    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFD)";
-    return NULL;
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFD) (%s): %s",
+                                             fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   // File status flags :
@@ -195,8 +246,11 @@
   //   their presence and pass them in to open().
   int fs_flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
   if (fs_flags == -1) {
-    PLOG(ERROR) << "Failed fcntl(" << fd << ", F_GETFL)";
-    return NULL;
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_GETFL) (%s): %s",
+                                             fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
+    return nullptr;
   }
 
   // File offset : Ignore the offset for non seekable files.
@@ -221,9 +275,9 @@
   return f_stat.st_ino == stat.st_ino && f_stat.st_dev == stat.st_dev;
 }
 
-bool FileDescriptorInfo::ReopenOrDetach() const {
+bool FileDescriptorInfo::ReopenOrDetach(std::string* error_msg) const {
   if (is_sock) {
-    return DetachSocket();
+    return DetachSocket(error_msg);
   }
 
   // NOTE: This might happen if the file was unlinked after being opened.
@@ -232,31 +286,49 @@
   const int new_fd = TEMP_FAILURE_RETRY(open(file_path.c_str(), open_flags));
 
   if (new_fd == -1) {
-    PLOG(ERROR) << "Failed open(" << file_path << ", " << open_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed open(%s, %i): %s",
+                                             file_path.c_str(),
+                                             open_flags,
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFD, fd_flags)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFD, " << fd_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFD, %d) (%s): %s",
+                                             new_fd,
+                                             fd_flags,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(fcntl(new_fd, F_SETFL, fs_flags)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed fcntl(" << new_fd << ", F_SETFL, " << fs_flags << ")";
+    *error_msg = android::base::StringPrintf("Failed fcntl(%d, F_SETFL, %d) (%s): %s",
+                                             new_fd,
+                                             fs_flags,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (offset != -1 && TEMP_FAILURE_RETRY(lseek64(new_fd, offset, SEEK_SET)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed lseek64(" << new_fd << ", SEEK_SET)";
+    *error_msg = android::base::StringPrintf("Failed lseek64(%d, SEEK_SET) (%s): %s",
+                                             new_fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
   if (TEMP_FAILURE_RETRY(dup2(new_fd, fd)) == -1) {
     close(new_fd);
-    PLOG(ERROR) << "Failed dup2(" << fd << ", " << new_fd << ")";
+    *error_msg = android::base::StringPrintf("Failed dup2(%d, %d) (%s): %s",
+                                             fd,
+                                             new_fd,
+                                             file_path.c_str(),
+                                             strerror(errno));
     return false;
   }
 
@@ -332,20 +404,22 @@
   return true;
 }
 
-bool FileDescriptorInfo::DetachSocket() const {
+bool FileDescriptorInfo::DetachSocket(std::string* error_msg) const {
   const int dev_null_fd = open("/dev/null", O_RDWR);
   if (dev_null_fd < 0) {
-    PLOG(ERROR) << "Failed to open /dev/null";
+    *error_msg = std::string("Failed to open /dev/null: ").append(strerror(errno));
     return false;
   }
 
   if (dup2(dev_null_fd, fd) == -1) {
-    PLOG(ERROR) << "Failed dup2 on socket descriptor " << fd;
+    *error_msg = android::base::StringPrintf("Failed dup2 on socket descriptor %d: %s",
+                                             fd,
+                                             strerror(errno));
     return false;
   }
 
   if (close(dev_null_fd) == -1) {
-    PLOG(ERROR) << "Failed close(" << dev_null_fd << ")";
+    *error_msg = android::base::StringPrintf("Failed close(%d): %s", dev_null_fd, strerror(errno));
     return false;
   }
 
@@ -353,11 +427,12 @@
 }
 
 // static
-FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore) {
+FileDescriptorTable* FileDescriptorTable::Create(const std::vector<int>& fds_to_ignore,
+                                                 std::string* error_msg) {
   DIR* d = opendir(kFdPath);
-  if (d == NULL) {
-    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
-    return NULL;
+  if (d == nullptr) {
+    *error_msg = std::string("Unable to open directory ").append(kFdPath);
+    return nullptr;
   }
   int dir_fd = dirfd(d);
   dirent* e;
@@ -373,7 +448,7 @@
       continue;
     }
 
-    FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+    FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
     if (info == NULL) {
       if (closedir(d) == -1) {
         PLOG(ERROR) << "Unable to close directory";
@@ -384,19 +459,21 @@
   }
 
   if (closedir(d) == -1) {
-    PLOG(ERROR) << "Unable to close directory";
-    return NULL;
+    *error_msg = "Unable to close directory";
+    return nullptr;
   }
   return new FileDescriptorTable(open_fd_map);
 }
 
-bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore) {
+bool FileDescriptorTable::Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg) {
   std::set<int> open_fds;
 
   // First get the list of open descriptors.
   DIR* d = opendir(kFdPath);
   if (d == NULL) {
-    PLOG(ERROR) << "Unable to open directory " << std::string(kFdPath);
+    *error_msg = android::base::StringPrintf("Unable to open directory %s: %s",
+                                             kFdPath,
+                                             strerror(errno));
     return false;
   }
 
@@ -416,21 +493,21 @@
   }
 
   if (closedir(d) == -1) {
-    PLOG(ERROR) << "Unable to close directory";
+    *error_msg = android::base::StringPrintf("Unable to close directory: %s", strerror(errno));
     return false;
   }
 
-  return RestatInternal(open_fds);
+  return RestatInternal(open_fds, error_msg);
 }
 
 // Reopens all file descriptors that are contained in the table. Returns true
 // if all descriptors were successfully re-opened or detached, and false if an
 // error occurred.
-bool FileDescriptorTable::ReopenOrDetach() {
+bool FileDescriptorTable::ReopenOrDetach(std::string* error_msg) {
   std::unordered_map<int, FileDescriptorInfo*>::const_iterator it;
   for (it = open_fd_map_.begin(); it != open_fd_map_.end(); ++it) {
     const FileDescriptorInfo* info = it->second;
-    if (info == NULL || !info->ReopenOrDetach()) {
+    if (info == NULL || !info->ReopenOrDetach(error_msg)) {
       return false;
     }
   }
@@ -443,7 +520,7 @@
     : open_fd_map_(map) {
 }
 
-bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds) {
+bool FileDescriptorTable::RestatInternal(std::set<int>& open_fds, std::string* error_msg) {
   bool error = false;
 
   // Iterate through the list of file descriptors we've already recorded
@@ -451,6 +528,8 @@
   //
   // (a) they continue to be open.
   // (b) they refer to the same file.
+  //
+  // We'll only store the last error message.
   std::unordered_map<int, FileDescriptorInfo*>::iterator it = open_fd_map_.begin();
   while (it != open_fd_map_.end()) {
     std::set<int>::const_iterator element = open_fds.find(it->first);
@@ -471,7 +550,7 @@
         // The file descriptor refers to a different description. We must
         // update our entry in the table.
         delete it->second;
-        it->second = FileDescriptorInfo::CreateFromFd(*element);
+        it->second = FileDescriptorInfo::CreateFromFd(*element, error_msg);
         if (it->second == NULL) {
           // The descriptor no longer no longer refers to a whitelisted file.
           // We flag an error and remove it from the list of files we're
@@ -506,7 +585,7 @@
     std::set<int>::const_iterator it;
     for (it = open_fds.begin(); it != open_fds.end(); ++it) {
       const int fd = (*it);
-      FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd);
+      FileDescriptorInfo* info = FileDescriptorInfo::CreateFromFd(fd, error_msg);
       if (info == NULL) {
         // A newly opened file is not on the whitelist. Flag an error and
         // continue.
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a39e387..a3570d7 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -28,6 +28,8 @@
 
 #include <android-base/macros.h>
 
+class FileDescriptorInfo;
+
 // Whitelist of open paths that the zygote is allowed to keep open.
 //
 // In addition to the paths listed in kPathWhitelist in file_utils.cpp, and
@@ -66,49 +68,6 @@
   DISALLOW_COPY_AND_ASSIGN(FileDescriptorWhitelist);
 };
 
-// Keeps track of all relevant information (flags, offset etc.) of an
-// open zygote file descriptor.
-class FileDescriptorInfo {
- public:
-  // Create a FileDescriptorInfo for a given file descriptor. Returns
-  // |NULL| if an error occurred.
-  static FileDescriptorInfo* CreateFromFd(int fd);
-
-  // Checks whether the file descriptor associated with this object
-  // refers to the same description.
-  bool Restat() const;
-
-  bool ReopenOrDetach() const;
-
-  const int fd;
-  const struct stat stat;
-  const std::string file_path;
-  const int open_flags;
-  const int fd_flags;
-  const int fs_flags;
-  const off_t offset;
-  const bool is_sock;
-
- private:
-  FileDescriptorInfo(int fd);
-
-  FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
-                     int fd_flags, int fs_flags, off_t offset);
-
-  // Returns the locally-bound name of the socket |fd|. Returns true
-  // iff. all of the following hold :
-  //
-  // - the socket's sa_family is AF_UNIX.
-  // - the length of the path is greater than zero (i.e, not an unnamed socket).
-  // - the first byte of the path isn't zero (i.e, not a socket with an abstract
-  //   address).
-  static bool GetSocketName(const int fd, std::string* result);
-
-  bool DetachSocket() const;
-
-  DISALLOW_COPY_AND_ASSIGN(FileDescriptorInfo);
-};
-
 // A FileDescriptorTable is a collection of FileDescriptorInfo objects
 // keyed by their FDs.
 class FileDescriptorTable {
@@ -116,19 +75,20 @@
   // Creates a new FileDescriptorTable. This function scans
   // /proc/self/fd for the list of open file descriptors and collects
   // information about them. Returns NULL if an error occurs.
-  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore);
+  static FileDescriptorTable* Create(const std::vector<int>& fds_to_ignore,
+                                     std::string* error_msg);
 
-  bool Restat(const std::vector<int>& fds_to_ignore);
+  bool Restat(const std::vector<int>& fds_to_ignore, std::string* error_msg);
 
   // Reopens all file descriptors that are contained in the table. Returns true
   // if all descriptors were successfully re-opened or detached, and false if an
   // error occurred.
-  bool ReopenOrDetach();
+  bool ReopenOrDetach(std::string* error_msg);
 
  private:
   FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
 
-  bool RestatInternal(std::set<int>& open_fds);
+  bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
 
   static int ParseFd(dirent* e, int dir_fd);
 
diff --git a/core/proto/android/bluetooth/enums.proto b/core/proto/android/bluetooth/enums.proto
new file mode 100644
index 0000000..9e459e6
--- /dev/null
+++ b/core/proto/android/bluetooth/enums.proto
@@ -0,0 +1,43 @@
+/*
+ * Copyright 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.
+ */
+
+syntax = "proto2";
+package android.bluetooth;
+
+option java_outer_classname = "BluetoothProtoEnums";
+option java_multiple_files = true;
+
+// Bluetooth connection states.
+enum ConnectionStateEnum {
+  CONNECTION_STATE_DISCONNECTED = 0;
+  CONNECTION_STATE_CONNECTING = 1;
+  CONNECTION_STATE_CONNECTED = 2;
+  CONNECTION_STATE_DISCONNECTING = 3;
+}
+
+// Bluetooth Adapter Enable and Disable Reasons
+enum EnableDisableReasonEnum {
+  ENABLE_DISABLE_REASON_UNSPECIFIED = 0;
+  ENABLE_DISABLE_REASON_APPLICATION_REQUEST = 1;
+  ENABLE_DISABLE_REASON_AIRPLANE_MODE = 2;
+  ENABLE_DISABLE_REASON_DISALLOWED = 3;
+  ENABLE_DISABLE_REASON_RESTARTED = 4;
+  ENABLE_DISABLE_REASON_START_ERROR = 5;
+  ENABLE_DISABLE_REASON_SYSTEM_BOOT = 6;
+  ENABLE_DISABLE_REASON_CRASH = 7;
+  ENABLE_DISABLE_REASON_USER_SWITCH = 8;
+  ENABLE_DISABLE_REASON_RESTORE_USER_SETTING = 9;
+}
\ No newline at end of file
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4ea2d10..9b13d0b 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -86,6 +86,7 @@
     <protected-broadcast android:name="android.intent.action.OVERLAY_CHANGED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_REMOVED" />
     <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" />
+    <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
 
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 23159f7..3dd950e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1579,7 +1579,7 @@
     <integer translatable="false" name="config_bluetooth_operating_voltage_mv">0</integer>
 
     <!-- Max number of connected audio devices supported by Bluetooth stack -->
-    <integer name="config_bluetooth_max_connected_audio_devices">1</integer>
+    <integer name="config_bluetooth_max_connected_audio_devices">5</integer>
 
     <!-- Whether supported profiles should be reloaded upon enabling bluetooth -->
     <bool name="config_bluetooth_reload_supported_profiles_when_enabled">false</bool>
@@ -2093,6 +2093,9 @@
     <!-- Whether UI for multi user should be shown -->
     <bool name="config_enableMultiUserUI">false</bool>
 
+    <!-- Whether the new Auto Selection Network UI should be shown -->
+    <bool name="config_enableNewAutoSelectNetworkUI">false</bool>
+
     <!-- If true, then we do not ask user for permission for apps to connect to USB devices.
          Do not set this to true for production devices. Doing so will cause you to fail CTS. -->
     <bool name="config_disableUsbPermissionDialogs">false</bool>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index dc14b23..e0ae966 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -138,25 +138,25 @@
     <string name="CLIRPermanent">You can\'t change the caller ID setting.</string>
 
     <!-- Notification title to tell the user that data service is blocked by access control. -->
-    <string name="RestrictedOnDataTitle">No data service</string>
+    <string name="RestrictedOnDataTitle">No mobile data service</string>
     <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
-    <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
+    <string name="RestrictedOnEmergencyTitle">Emergency calling unavailable</string>
     <!-- Notification title to tell the user that normal service is blocked by access control. -->
     <string name="RestrictedOnNormalTitle">No voice service</string>
     <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
-    <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
+    <string name="RestrictedOnAllVoiceTitle">No voice service or emergency calling</string>
 
     <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
-    <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
+    <string name="RestrictedStateContent">Temporarily turned off by your carrier</string>
 
     <!-- Displayed to tell the user that they should switch their network preference. -->
-    <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
+    <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach mobile network</string>
     <!-- Displayed to tell the user that they should switch their network preference. -->
-    <string name="NetworkPreferenceSwitchSummary">To improve reception, try changing the type selected at Settings &gt; Network &amp; Internet &gt; Mobile networks &gt; Preferred network type."</string>
+    <string name="NetworkPreferenceSwitchSummary">Try changing preferred network. Tap to change.</string>
     <!-- Displayed to tell the user that emergency calls might not be available. -->
-    <string name="EmergencyCallWarningTitle">Wi\u2011Fi calling is active</string>
+    <string name="EmergencyCallWarningTitle">Emergency calling unavailable</string>
     <!-- Displayed to tell the user that emergency calls might not be available. -->
-    <string name="EmergencyCallWarningSummary">Emergency calls require a mobile network.</string>
+    <string name="EmergencyCallWarningSummary">Can\u2019t make emergency calls over Wi\u2011Fi</string>
 
     <!-- Telephony notification channel name for a channel containing network alert notifications. -->
     <string name="notification_channel_network_alert">Alerts</string>
@@ -4682,11 +4682,11 @@
     <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for others -->
     <string name="etws_primary_default_message_others"></string>
 
-    <!-- Title of notification when UE fails to register network with MM reject cause code. -->
-    <string name="mmcc_authentication_reject">SIM not allowed</string>
-    <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned</string>
-    <string name="mmcc_illegal_ms">SIM not allowed</string>
-    <string name="mmcc_illegal_me">Phone not allowed</string>
+    <!-- Title of notification when UE fails CS registration network with MM reject cause code from network. -->
+    <string name="mmcc_authentication_reject">SIM not allowed for voice</string>
+    <string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned for voice</string>
+    <string name="mmcc_illegal_ms">SIM not allowed for voice</string>
+    <string name="mmcc_illegal_me">Phone not allowed for voice</string>
 
     <!-- Popup window default title to be read by a screen reader-->
     <string name="popup_window_default_title">Popup Window</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index ad5af95..f089ff0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -311,6 +311,7 @@
   <java-symbol type="bool" name="config_forceDefaultOrientation" />
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
+  <java-symbol type="bool" name="config_enableNewAutoSelectNetworkUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
   <java-symbol type="bool" name="config_hasRecents" />
   <java-symbol type="bool" name="config_windowShowCircularMask" />
diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk
index c409e3a..69bae86 100644
--- a/core/tests/BroadcastRadioTests/Android.mk
+++ b/core/tests/BroadcastRadioTests/Android.mk
@@ -23,6 +23,7 @@
 LOCAL_MODULE_TAGS := tests
 # TODO(b/13282254): uncomment when b/13282254 is fixed
 # LOCAL_SDK_VERSION := current
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util android-support-test testng
 
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 757a70c..16c0b8c 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -117,6 +117,7 @@
                     Settings.Global.BLE_SCAN_BALANCED_INTERVAL_MS,
                     Settings.Global.BLE_SCAN_LOW_LATENCY_WINDOW_MS,
                     Settings.Global.BLE_SCAN_LOW_LATENCY_INTERVAL_MS,
+                    Settings.Global.BLE_SCAN_BACKGROUND_MODE,
                     Settings.Global.BLUETOOTH_A2DP_SINK_PRIORITY_PREFIX,
                     Settings.Global.BLUETOOTH_A2DP_SRC_PRIORITY_PREFIX,
                     Settings.Global.BLUETOOTH_A2DP_SUPPORTS_OPTIONAL_CODECS_PREFIX,
diff --git a/core/tests/overlaytests/OverlayTest/Android.mk b/core/tests/overlaytests/OverlayTest/Android.mk
index 964348f..8f4b829 100644
--- a/core/tests/overlaytests/OverlayTest/Android.mk
+++ b/core/tests/overlaytests/OverlayTest/Android.mk
@@ -5,6 +5,8 @@
 
 LOCAL_PACKAGE_NAME := OverlayTest
 
+LOCAL_PRIVATE_PLATFORM_APIS := true
+
 LOCAL_DEX_PREOPT := false
 
 LOCAL_JAVA_LIBRARIES += legacy-test
diff --git a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
index 282b001..933e54e 100644
--- a/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
+++ b/core/tests/systemproperties/src/android/os/SystemPropertiesTest.java
@@ -16,6 +16,9 @@
 
 package android.os;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 import junit.framework.TestCase;
 
 import android.os.SystemProperties;
@@ -141,4 +144,48 @@
         } catch (NullPointerException npe) {
         }
     }
+
+    @SmallTest
+    public void testCallbacks() {
+        // Latches are not really necessary, but are easy to use.
+        final CountDownLatch wait1 = new CountDownLatch(1);
+        final CountDownLatch wait2 = new CountDownLatch(1);
+
+        Runnable r1 = new Runnable() {
+            boolean done = false;
+            @Override
+            public void run() {
+                if (done) {
+                    return;
+                }
+                done = true;
+
+                wait1.countDown();
+                throw new RuntimeException("test");
+            }
+        };
+
+        Runnable r2 = new Runnable() {
+            @Override
+            public void run() {
+                wait2.countDown();
+            }
+        };
+
+        SystemProperties.addChangeCallback(r1);
+        SystemProperties.addChangeCallback(r2);
+
+        SystemProperties.reportSyspropChanged();
+
+        try {
+            assertTrue(wait1.await(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail("InterruptedException");
+        }
+        try {
+            assertTrue(wait2.await(5, TimeUnit.SECONDS));
+        } catch (InterruptedException e) {
+            fail("InterruptedException");
+        }
+    }
 }
diff --git a/data/etc/hiddenapi-package-whitelist.xml b/data/etc/hiddenapi-package-whitelist.xml
index 1d46d42..bacddf14 100644
--- a/data/etc/hiddenapi-package-whitelist.xml
+++ b/data/etc/hiddenapi-package-whitelist.xml
@@ -25,55 +25,67 @@
   <hidden-api-whitelisted-app package="android.car.input.service" />
   <hidden-api-whitelisted-app package="android.car.usb.handler" />
   <hidden-api-whitelisted-app package="android.ext.services" />
-  <hidden-api-whitelisted-app package="android.ext.shared" />
+  <hidden-api-whitelisted-app package="com.android.apps.tag" />
   <hidden-api-whitelisted-app package="com.android.backupconfirm" />
+  <hidden-api-whitelisted-app package="com.android.basicsmsreceiver" />
   <hidden-api-whitelisted-app package="com.android.bluetooth" />
   <hidden-api-whitelisted-app package="com.android.bluetoothdebug" />
   <hidden-api-whitelisted-app package="com.android.bluetoothmidiservice" />
+  <hidden-api-whitelisted-app package="com.android.bookmarkprovider" />
   <hidden-api-whitelisted-app package="com.android.calllogbackup" />
+  <hidden-api-whitelisted-app package="com.android.camera" />
   <hidden-api-whitelisted-app package="com.android.captiveportallogin" />
   <hidden-api-whitelisted-app package="com.android.car" />
+  <hidden-api-whitelisted-app package="com.android.car.dialer" />
   <hidden-api-whitelisted-app package="com.android.car.hvac" />
   <hidden-api-whitelisted-app package="com.android.car.mapsplaceholder" />
   <hidden-api-whitelisted-app package="com.android.car.media" />
   <hidden-api-whitelisted-app package="com.android.car.media.localmediaplayer" />
+  <hidden-api-whitelisted-app package="com.android.car.messenger" />
+  <hidden-api-whitelisted-app package="com.android.car.overview" />
   <hidden-api-whitelisted-app package="com.android.car.radio" />
   <hidden-api-whitelisted-app package="com.android.car.settings" />
+  <hidden-api-whitelisted-app package="com.android.car.stream" />
   <hidden-api-whitelisted-app package="com.android.car.systemupdater" />
   <hidden-api-whitelisted-app package="com.android.car.trust" />
   <hidden-api-whitelisted-app package="com.android.carrierconfig" />
   <hidden-api-whitelisted-app package="com.android.carrierdefaultapp" />
   <hidden-api-whitelisted-app package="com.android.cellbroadcastreceiver" />
   <hidden-api-whitelisted-app package="com.android.certinstaller" />
+  <hidden-api-whitelisted-app package="com.android.companiondevicemanager" />
   <hidden-api-whitelisted-app package="com.android.customlocale2" />
   <hidden-api-whitelisted-app package="com.android.defcontainer" />
   <hidden-api-whitelisted-app package="com.android.documentsui" />
+  <hidden-api-whitelisted-app package="com.android.dreams.basic" />
   <hidden-api-whitelisted-app package="com.android.egg" />
-  <hidden-api-whitelisted-app package="com.android.email.policy" />
   <hidden-api-whitelisted-app package="com.android.emergency" />
   <hidden-api-whitelisted-app package="com.android.externalstorage" />
   <hidden-api-whitelisted-app package="com.android.fakeoemfeatures" />
   <hidden-api-whitelisted-app package="com.android.gallery" />
   <hidden-api-whitelisted-app package="com.android.hotspot2" />
-  <hidden-api-whitelisted-app package="com.android.inputdevices" />
   <hidden-api-whitelisted-app package="com.android.keychain" />
   <hidden-api-whitelisted-app package="com.android.location.fused" />
   <hidden-api-whitelisted-app package="com.android.managedprovisioning" />
   <hidden-api-whitelisted-app package="com.android.mms.service" />
   <hidden-api-whitelisted-app package="com.android.mtp" />
+  <hidden-api-whitelisted-app package="com.android.musicfx" />
   <hidden-api-whitelisted-app package="com.android.nfc" />
   <hidden-api-whitelisted-app package="com.android.osu" />
   <hidden-api-whitelisted-app package="com.android.packageinstaller" />
   <hidden-api-whitelisted-app package="com.android.pacprocessor" />
   <hidden-api-whitelisted-app package="com.android.phone" />
   <hidden-api-whitelisted-app package="com.android.pmc" />
+  <hidden-api-whitelisted-app package="com.android.printservice.recommendation" />
+  <hidden-api-whitelisted-app package="com.android.printspooler" />
   <hidden-api-whitelisted-app package="com.android.providers.blockednumber" />
+  <hidden-api-whitelisted-app package="com.android.providers.calendar" />
   <hidden-api-whitelisted-app package="com.android.providers.contacts" />
   <hidden-api-whitelisted-app package="com.android.providers.downloads" />
   <hidden-api-whitelisted-app package="com.android.providers.downloads.ui" />
   <hidden-api-whitelisted-app package="com.android.providers.media" />
   <hidden-api-whitelisted-app package="com.android.providers.settings" />
   <hidden-api-whitelisted-app package="com.android.providers.telephony" />
+  <hidden-api-whitelisted-app package="com.android.providers.tv" />
   <hidden-api-whitelisted-app package="com.android.providers.userdictionary" />
   <hidden-api-whitelisted-app package="com.android.provision" />
   <hidden-api-whitelisted-app package="com.android.proxyhandler" />
@@ -85,10 +97,15 @@
   <hidden-api-whitelisted-app package="com.android.settings" />
   <hidden-api-whitelisted-app package="com.android.sharedstoragebackup" />
   <hidden-api-whitelisted-app package="com.android.shell" />
+  <hidden-api-whitelisted-app package="com.android.smspush" />
+  <hidden-api-whitelisted-app package="com.android.spare_parts" />
+  <hidden-api-whitelisted-app package="com.android.statementservice" />
   <hidden-api-whitelisted-app package="com.android.stk" />
+  <hidden-api-whitelisted-app package="com.android.storagemanager" />
   <hidden-api-whitelisted-app package="com.android.support.car.lenspicker" />
   <hidden-api-whitelisted-app package="com.android.systemui" />
-  <hidden-api-whitelisted-app package="com.android.systemui.theme.dark" />
+  <hidden-api-whitelisted-app package="com.android.systemui.plugins" />
+  <hidden-api-whitelisted-app package="com.android.terminal" />
   <hidden-api-whitelisted-app package="com.android.timezone.updater" />
   <hidden-api-whitelisted-app package="com.android.traceur" />
   <hidden-api-whitelisted-app package="com.android.tv.settings" />
@@ -97,5 +114,5 @@
   <hidden-api-whitelisted-app package="com.android.wallpaperbackup" />
   <hidden-api-whitelisted-app package="com.android.wallpapercropper" />
   <hidden-api-whitelisted-app package="com.googlecode.android_scripting" />
+  <hidden-api-whitelisted-app package="jp.co.omronsoft.openwnn" />
 </config>
-
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index ede172c..a80c741 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1552,6 +1552,21 @@
     }
 
     /**
+     * Broadcast Action: microphone muting state changed.
+     *
+     * You <em>cannot</em> receive this through components declared
+     * in manifests, only by explicitly registering for it with
+     * {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
+     * Context.registerReceiver()}.
+     *
+     * <p>The intent has no extra values, use {@link #isMicrophoneMute} to check whether the
+     * microphone is muted.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_MICROPHONE_MUTE_CHANGED =
+            "android.media.action.MICROPHONE_MUTE_CHANGED";
+
+    /**
      * Sets the audio mode.
      * <p>
      * The audio mode encompasses audio routing AND the behavior of
diff --git a/packages/CaptivePortalLogin/Android.mk b/packages/CaptivePortalLogin/Android.mk
index 576debc..7dc23ff 100644
--- a/packages/CaptivePortalLogin/Android.mk
+++ b/packages/CaptivePortalLogin/Android.mk
@@ -2,10 +2,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_MODULE_TAGS := optional
+LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CaptivePortalLogin
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
index 2324593..c292323 100644
--- a/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
+++ b/packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
@@ -27,12 +27,17 @@
             android:layout_height="wrap_content" />
       </FrameLayout>
 
-      <WebView
-          android:id="@+id/webview"
-          android:layout_width="match_parent"
-          android:layout_height="match_parent"
-          android:layout_alignParentBottom="false"
-          android:layout_alignParentRight="false" />
+      <android.support.v4.widget.SwipeRefreshLayout
+            android:id="@+id/swipe_refresh"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+        <WebView
+              android:id="@+id/webview"
+              android:layout_width="match_parent"
+              android:layout_height="match_parent"
+              android:layout_alignParentBottom="false"
+              android:layout_alignParentRight="false" />
+      </android.support.v4.widget.SwipeRefreshLayout>
 
     </LinearLayout>
 </FrameLayout>
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index e13aba7..4db0034 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -34,6 +34,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.provider.Settings;
+import android.support.v4.widget.SwipeRefreshLayout;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.TypedValue;
@@ -88,6 +89,7 @@
     private ConnectivityManager mCm;
     private boolean mLaunchBrowser = false;
     private MyWebViewClient mWebViewClient;
+    private SwipeRefreshLayout mSwipeRefreshLayout;
     // Ensures that done() happens once exactly, handling concurrent callers with atomic operations.
     private final AtomicBoolean isDone = new AtomicBoolean(false);
 
@@ -159,6 +161,13 @@
         // Start initial page load so WebView finishes loading proxy settings.
         // Actual load of mUrl is initiated by MyWebViewClient.
         webview.loadData("", "text/html", null);
+
+        mSwipeRefreshLayout = findViewById(R.id.swipe_refresh);
+        mSwipeRefreshLayout.setOnRefreshListener(() -> {
+                webview.reload();
+                mSwipeRefreshLayout.setRefreshing(true);
+            });
+
     }
 
     // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
@@ -393,6 +402,7 @@
         public void onPageFinished(WebView view, String url) {
             mPagesLoaded++;
             getProgressBar().setVisibility(View.INVISIBLE);
+            mSwipeRefreshLayout.setRefreshing(false);
             if (mPagesLoaded == 1) {
                 // Now that WebView has loaded at least one page we know it has read in the proxy
                 // settings.  Now prompt the WebView read the Network-specific proxy settings.
diff --git a/packages/CarrierDefaultApp/Android.mk b/packages/CarrierDefaultApp/Android.mk
index 82be132..df88afd 100644
--- a/packages/CarrierDefaultApp/Android.mk
+++ b/packages/CarrierDefaultApp/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CarrierDefaultApp
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 
 include $(BUILD_PACKAGE)
diff --git a/packages/CarrierDefaultApp/tests/unit/Android.mk b/packages/CarrierDefaultApp/tests/unit/Android.mk
index 63bd0b1..a95ccfe 100644
--- a/packages/CarrierDefaultApp/tests/unit/Android.mk
+++ b/packages/CarrierDefaultApp/tests/unit/Android.mk
@@ -27,6 +27,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_PACKAGE_NAME := CarrierDefaultAppUnitTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 
 LOCAL_INSTRUMENTATION_FOR := CarrierDefaultApp
 
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index e261570..4000226 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -73,4 +73,9 @@
          fraction of a pixel.-->
     <fraction name="battery_subpixel_smoothing_left">0%</fraction>
     <fraction name="battery_subpixel_smoothing_right">0%</fraction>
+
+    <!-- SignalDrawable -->
+    <dimen name="signal_icon_size">17dp</dimen>
+    <!-- How far to inset the rounded edges -->
+    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 3cda9c9..784c714 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -444,6 +444,7 @@
 
     private void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice,
                                              int bluetoothProfile) {
+        mDeviceManager.onActiveDeviceChanged(activeDevice, bluetoothProfile);
         synchronized (mCallbacks) {
             for (BluetoothCallback callback : mCallbacks) {
                 callback.onActiveDeviceChanged(activeDevice, bluetoothProfile);
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index e1ebbc4..f6ec6a8 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -27,6 +27,7 @@
 import android.text.TextUtils;
 import android.util.Log;
 import android.bluetooth.BluetoothAdapter;
+import android.support.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
 
@@ -461,12 +462,12 @@
     }
 
     /**
-     * Set the device status as active or non-active per Bluetooth profile.
+     * Update the device status as active or non-active per Bluetooth profile.
      *
      * @param isActive true if the device is active
      * @param bluetoothProfile the Bluetooth profile
      */
-    public void setActiveDevice(boolean isActive, int bluetoothProfile) {
+    public void onActiveDeviceChanged(boolean isActive, int bluetoothProfile) {
         boolean changed = false;
         switch (bluetoothProfile) {
         case BluetoothProfile.A2DP:
@@ -478,7 +479,7 @@
             mIsActiveDeviceHeadset = isActive;
             break;
         default:
-            Log.w(TAG, "setActiveDevice: unknown profile " + bluetoothProfile +
+            Log.w(TAG, "onActiveDeviceChanged: unknown profile " + bluetoothProfile +
                     " isActive " + isActive);
             break;
         }
@@ -487,6 +488,26 @@
         }
     }
 
+    /**
+     * Get the device status as active or non-active per Bluetooth profile.
+     *
+     * @param bluetoothProfile the Bluetooth profile
+     * @return true if the device is active
+     */
+    @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
+    public boolean isActiveDevice(int bluetoothProfile) {
+        switch (bluetoothProfile) {
+            case BluetoothProfile.A2DP:
+                return mIsActiveDeviceA2dp;
+            case BluetoothProfile.HEADSET:
+                return mIsActiveDeviceHeadset;
+            default:
+                Log.w(TAG, "getActiveDevice: unknown profile " + bluetoothProfile);
+                break;
+        }
+        return false;
+    }
+
     void setRssi(short rssi) {
         if (mRssi != rssi) {
             mRssi = rssi;
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
index c3ff617..a8e0039 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java
@@ -24,6 +24,7 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import java.util.Objects;
 
 /**
  * CachedBluetoothDeviceManager manages the set of remote Bluetooth devices.
@@ -167,6 +168,15 @@
             }
         }
     }
+
+    public synchronized void onActiveDeviceChanged(CachedBluetoothDevice activeDevice,
+                                                   int bluetoothProfile) {
+        for (CachedBluetoothDevice cachedDevice : mCachedDevices) {
+            boolean isActive = Objects.equals(cachedDevice, activeDevice);
+            cachedDevice.onActiveDeviceChanged(isActive, bluetoothProfile);
+        }
+    }
+
     private void log(String msg) {
         if (DEBUG) {
             Log.d(TAG, msg);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
rename to packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
index 15ef742..846e30d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SignalDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/SignalDrawable.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.settingslib.graph;
 
 import android.animation.ArgbEvaluator;
 import android.annotation.IntRange;
@@ -36,7 +36,6 @@
 
 import com.android.settingslib.R;
 import com.android.settingslib.Utils;
-import com.android.systemui.qs.SlashDrawable;
 
 public class SignalDrawable extends Drawable {
 
@@ -458,6 +457,7 @@
     }
 
     private final class SlashArtist {
+        private static final float CORNER_RADIUS = 1f;
         // These values are derived in un-rotated (vertical) orientation
         private static final float SLASH_WIDTH = 1.8384776f;
         private static final float SLASH_HEIGHT = 22f;
@@ -478,7 +478,7 @@
 
         void draw(int height, int width, @NonNull Canvas canvas, Paint paint) {
             Matrix m = new Matrix();
-            final float radius = scale(SlashDrawable.CORNER_RADIUS, width);
+            final float radius = scale(CORNER_RADIUS, width);
             updateRect(
                     scale(LEFT, width),
                     scale(TOP, height),
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index 7ace048..5bd9e4c 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -25,6 +25,7 @@
 LOCAL_JACK_FLAGS := --multi-dex native
 
 LOCAL_PACKAGE_NAME := SettingsLibTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_STATIC_JAVA_LIBRARIES := \
diff --git a/packages/SettingsLib/tests/robotests/Android.mk b/packages/SettingsLib/tests/robotests/Android.mk
index 55b635e..bc28863 100644
--- a/packages/SettingsLib/tests/robotests/Android.mk
+++ b/packages/SettingsLib/tests/robotests/Android.mk
@@ -21,6 +21,7 @@
 include $(CLEAR_VARS)
 
 LOCAL_PACKAGE_NAME := SettingsLibShell
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_PRIVILEGED_MODULE := true
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
new file mode 100644
index 0000000..d6b2006
--- /dev/null
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManagerTest.java
@@ -0,0 +1,283 @@
+/*
+ * 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.settingslib.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+
+import com.android.settingslib.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.Collection;
+
+@RunWith(RobolectricTestRunner.class)
+public class CachedBluetoothDeviceManagerTest {
+    private final static String DEVICE_NAME_1 = "TestName_1";
+    private final static String DEVICE_NAME_2 = "TestName_2";
+    private final static String DEVICE_ALIAS_1 = "TestAlias_1";
+    private final static String DEVICE_ALIAS_2 = "TestAlias_2";
+    private final static String DEVICE_ADDRESS_1 = "AA:BB:CC:DD:EE:11";
+    private final static String DEVICE_ADDRESS_2 = "AA:BB:CC:DD:EE:22";
+    private final BluetoothClass DEVICE_CLASS_1 =
+        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES);
+    private final BluetoothClass DEVICE_CLASS_2 =
+        new BluetoothClass(BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE);
+    @Mock
+    private LocalBluetoothAdapter mLocalAdapter;
+    @Mock
+    private LocalBluetoothProfileManager mLocalProfileManager;
+    @Mock
+    private LocalBluetoothManager mLocalBluetoothManager;
+    @Mock
+    private BluetoothEventManager mBluetoothEventManager;
+    @Mock
+    private HeadsetProfile mHfpProfile;
+    @Mock
+    private A2dpProfile mA2dpProfile;
+    @Mock
+    private PanProfile mPanProfile;
+    @Mock
+    private BluetoothDevice mDevice1;
+    @Mock
+    private BluetoothDevice mDevice2;
+    private CachedBluetoothDeviceManager mCachedDeviceManager;
+    private Context mContext;
+    private String[] mActiveDeviceStringsArray;
+    private String mActiveDeviceStringNone;
+    private String mActiveDeviceStringAll;
+    private String mActiveDeviceStringMedia;
+    private String mActiveDeviceStringPhone;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContext = RuntimeEnvironment.application;
+        when(mDevice1.getAddress()).thenReturn(DEVICE_ADDRESS_1);
+        when(mDevice2.getAddress()).thenReturn(DEVICE_ADDRESS_2);
+        when(mDevice1.getName()).thenReturn(DEVICE_NAME_1);
+        when(mDevice2.getName()).thenReturn(DEVICE_NAME_2);
+        when(mDevice1.getAliasName()).thenReturn(DEVICE_ALIAS_1);
+        when(mDevice2.getAliasName()).thenReturn(DEVICE_ALIAS_2);
+        when(mDevice1.getBluetoothClass()).thenReturn(DEVICE_CLASS_1);
+        when(mDevice2.getBluetoothClass()).thenReturn(DEVICE_CLASS_2);
+
+        when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+        when(mLocalAdapter.getBluetoothState()).thenReturn(BluetoothAdapter.STATE_ON);
+        when(mHfpProfile.isProfileReady()).thenReturn(true);
+        when(mA2dpProfile.isProfileReady()).thenReturn(true);
+        when(mPanProfile.isProfileReady()).thenReturn(true);
+        mCachedDeviceManager = new CachedBluetoothDeviceManager(mContext, mLocalBluetoothManager);
+    }
+
+    /**
+     * Test to verify addDevice().
+     */
+    @Test
+    public void testAddDevice_validCachedDevices_devicesAdded() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).contains(cachedDevice2);
+
+        assertThat(mCachedDeviceManager.findDevice(mDevice1)).isEqualTo(cachedDevice1);
+        assertThat(mCachedDeviceManager.findDevice(mDevice2)).isEqualTo(cachedDevice2);
+    }
+
+    /**
+     * Test to verify getName().
+     */
+    @Test
+    public void testGetName_validCachedDevice_nameFound() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(mCachedDeviceManager.getName(mDevice1)).isEqualTo(DEVICE_ALIAS_1);
+    }
+
+    /**
+     * Test to verify onDeviceNameUpdated().
+     */
+    @Test
+    public void testOnDeviceNameUpdated_validName_nameUpdated() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(cachedDevice1.getName()).isEqualTo(DEVICE_ALIAS_1);
+
+        final String newAliasName = "NewAliasName";
+        when(mDevice1.getAliasName()).thenReturn(newAliasName);
+        mCachedDeviceManager.onDeviceNameUpdated(mDevice1);
+        assertThat(cachedDevice1.getName()).isEqualTo(newAliasName);
+    }
+
+    /**
+     * Test to verify clearNonBondedDevices().
+     */
+    @Test
+    public void testClearNonBondedDevices_bondedAndNonBondedDevices_nonBondedDevicesCleared() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDING);
+        mCachedDeviceManager.clearNonBondedDevices();
+        Collection<CachedBluetoothDevice> devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).contains(cachedDevice2);
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        mCachedDeviceManager.clearNonBondedDevices();
+        devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).contains(cachedDevice1);
+        assertThat(devices).doesNotContain(cachedDevice2);
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        mCachedDeviceManager.clearNonBondedDevices();
+        devices = mCachedDeviceManager.getCachedDevicesCopy();
+        assertThat(devices).doesNotContain(cachedDevice1);
+        assertThat(devices).doesNotContain(cachedDevice2);
+    }
+
+    /**
+     * Test to verify onBtClassChanged().
+     */
+    @Test
+    public void testOnBtClassChanged_validBtClass_classChanged() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        assertThat(cachedDevice1.getBtClass()).isEqualTo(DEVICE_CLASS_1);
+
+        final BluetoothClass newBluetoothClass = DEVICE_CLASS_2;
+        when(mDevice1.getBluetoothClass()).thenReturn(newBluetoothClass);
+        mCachedDeviceManager.onBtClassChanged(mDevice1);
+        assertThat(cachedDevice1.getBtClass()).isEqualTo(newBluetoothClass);
+    }
+
+    /**
+     * Test to verify onDeviceDisappeared().
+     */
+    @Test
+    public void testOnDeviceDisappeared_deviceBondedUnbonded_unbondedDeviceDisappeared() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isFalse();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_NONE);
+        assertThat(mCachedDeviceManager.onDeviceDisappeared(cachedDevice1)).isTrue();
+    }
+
+    /**
+     * Test to verify onActiveDeviceChanged().
+     */
+    @Test
+    public void testOnActiveDeviceChanged_connectedDevices_activeDeviceChanged() {
+        CachedBluetoothDevice cachedDevice1 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice1);
+        assertThat(cachedDevice1).isNotNull();
+        CachedBluetoothDevice cachedDevice2 = mCachedDeviceManager.addDevice(mLocalAdapter,
+                mLocalProfileManager, mDevice2);
+        assertThat(cachedDevice2).isNotNull();
+
+        when(mDevice1.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+        when(mDevice2.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
+
+        // Connect both devices for A2DP and HFP
+        cachedDevice1.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice1.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+        cachedDevice2.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
+
+        // Verify that both devices are connected and none is Active
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+        // The first device is active for A2DP, the second device is active for HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.A2DP);
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // The first device is active for A2DP and HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice1, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+
+        // The second device is active for A2DP and HFP
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.A2DP);
+        mCachedDeviceManager.onActiveDeviceChanged(cachedDevice2, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isTrue();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // No active device for A2DP
+        mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.A2DP);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isTrue();
+
+        // No active device for HFP
+        mCachedDeviceManager.onActiveDeviceChanged(null, BluetoothProfile.HEADSET);
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice1.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.A2DP)).isFalse();
+        assertThat(cachedDevice2.isActiveDevice(BluetoothProfile.HEADSET)).isFalse();
+    }
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
index 1481161..2c91d5a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceTest.java
@@ -152,7 +152,7 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
 
         // Test with battery level
@@ -168,7 +168,7 @@
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set A2DP profile to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(media)");
 
         // Set A2DP profile to be disconnected and test connection state summary
@@ -184,7 +184,7 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for HFP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
 
         // Test with battery level
@@ -200,7 +200,7 @@
         mBatteryLevel = BluetoothDevice.BATTERY_LEVEL_UNKNOWN;
         // Set HFP profile to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active(phone)");
 
         // Set HFP profile to be disconnected and test connection state summary
@@ -217,8 +217,8 @@
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected");
 
         // Set device as Active for A2DP and HFP and test connection state summary
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
 
         // Test with battery level
@@ -227,16 +227,16 @@
                 "Connected, battery 10%, active");
 
         // Disconnect A2DP only and test connection state summary
-        mCachedDevice.setActiveDevice(false, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.A2DP);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_DISCONNECTED);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "Connected (no media), battery 10%, active(phone)");
 
         // Disconnect HFP only and test connection state summary
-        mCachedDevice.setActiveDevice(false, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(false, BluetoothProfile.HEADSET);
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_DISCONNECTED);
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo(
                 "Connected (no phone), battery 10%, active(media)");
 
@@ -245,8 +245,8 @@
         // Set A2DP and HFP profiles to be connected, Active and test connection state summary
         mCachedDevice.onProfileStateChanged(mA2dpProfile, BluetoothProfile.STATE_CONNECTED);
         mCachedDevice.onProfileStateChanged(mHfpProfile, BluetoothProfile.STATE_CONNECTED);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.A2DP);
-        mCachedDevice.setActiveDevice(true, BluetoothProfile.HEADSET);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.A2DP);
+        mCachedDevice.onActiveDeviceChanged(true, BluetoothProfile.HEADSET);
         assertThat(mCachedDevice.getConnectionSummary()).isEqualTo("Connected, active");
 
         // Set A2DP and HFP profiles to be disconnected and test connection state summary
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 27d461b..1822db3 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -40,6 +40,7 @@
 import android.provider.Settings;
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -2601,15 +2602,26 @@
             loadSetting(stmt, Settings.Global.CALL_AUTO_RETRY, 0);
 
             // Set the preferred network mode to target desired value or Default
-            // value defined in RILConstants
-            int type;
-            type = RILConstants.PREFERRED_NETWORK_MODE;
-            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, type);
+            // value defined in system property
+            String val = "";
+            String mode;
+            for (int phoneId = 0;
+                    phoneId < TelephonyManager.getDefault().getPhoneCount(); phoneId++) {
+                mode = TelephonyManager.getTelephonyProperty(phoneId,
+                        "ro.telephony.default_network",
+                        Integer.toString(RILConstants.PREFERRED_NETWORK_MODE));
+                if (phoneId == 0) {
+                    val = mode;
+                } else {
+                    val = val + "," + mode;
+                }
+            }
+            loadSetting(stmt, Settings.Global.PREFERRED_NETWORK_MODE, val);
 
             // Set the preferred cdma subscription source to target desired value or default
             // value defined in Phone
-            type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
-                        Phone.PREFERRED_CDMA_SUBSCRIPTION);
+            int type = SystemProperties.getInt("ro.telephony.default_cdma_sub",
+                    Phone.PREFERRED_CDMA_SUBSCRIPTION);
             loadSetting(stmt, Settings.Global.CDMA_SUBSCRIPTION_MODE, type);
 
             loadIntegerSetting(stmt, Settings.Global.LOW_BATTERY_SOUND_TIMEOUT,
diff --git a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java b/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
index 449738e..659696e 100644
--- a/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
+++ b/packages/StatementService/src/com/android/statementservice/DirectStatementService.java
@@ -155,17 +155,20 @@
     @Override
     public void onDestroy() {
         super.onDestroy();
-        if (mThread != null) {
-            mThread.quit();
-        }
-
-        try {
-            if (mHttpResponseCache != null) {
-                mHttpResponseCache.delete();
+        final HttpResponseCache responseCache = mHttpResponseCache;
+        mHandler.post(new Runnable() {
+            public void run() {
+                try {
+                    if (responseCache != null) {
+                        responseCache.delete();
+                    }
+                } catch (IOException e) {
+                    Log.i(TAG, "HTTP(S) response cache deletion failed:" + e);
+                }
+                Looper.myLooper().quit();
             }
-        } catch (IOException e) {
-            Log.i(TAG, "HTTP(S) response cache deletion failed:" + e);
-        }
+        });
+        mHttpResponseCache = null;
     }
 
     @Override
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index 2fd7e87..2bfd3a5 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -48,6 +48,7 @@
 LOCAL_JAVA_LIBRARIES += android.car
 
 LOCAL_PACKAGE_NAME := SystemUI
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_CERTIFICATE := platform
 LOCAL_PRIVILEGED_MODULE := true
 
diff --git a/packages/SystemUI/plugin/Android.mk b/packages/SystemUI/plugin/Android.mk
index e22dddb..8634684 100644
--- a/packages/SystemUI/plugin/Android.mk
+++ b/packages/SystemUI/plugin/Android.mk
@@ -32,6 +32,7 @@
 
 # Dummy to generate .toc files.
 LOCAL_PACKAGE_NAME := PluginDummyLib
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
 LOCAL_JAVA_LIBRARIES := SystemUIPluginLib
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8a1e0b9..bba9ed4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -133,6 +133,9 @@
     <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
     <bool name="config_show4GForLTE">true</bool>
 
+    <!-- Show indicator for Wifi on but not connected. -->
+    <bool name="config_showWifiIndicatorWhenEnabled">false</bool>
+
     <!-- Should "LTE"/"4G" be shown instead of "LTE+"/"4G+" when on NETWORK_TYPE_LTE_CA? -->
     <bool name="config_hideLtePlus">false</bool>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 9901f6f..acc8b6d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -822,8 +822,6 @@
     <dimen name="default_gear_space">18dp</dimen>
     <dimen name="cell_overlay_padding">18dp</dimen>
 
-    <dimen name="signal_icon_size">17dp</dimen>
-
     <dimen name="hwui_edge_margin">16dp</dimen>
 
     <dimen name="global_actions_panel_width">120dp</dimen>
@@ -850,11 +848,6 @@
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
 
-    <!-- Intended corner radius when drawing the mobile signal -->
-    <dimen name="stat_sys_mobile_signal_corner_radius">0.75dp</dimen>
-    <!-- How far to inset the rounded edges -->
-    <dimen name="stat_sys_mobile_signal_circle_inset">0.9dp</dimen>
-
     <!-- Home button padding for sizing -->
     <dimen name="home_padding">15dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
index 5f26093..e7eefe8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/CellTileView.java
@@ -19,12 +19,12 @@
 import android.service.quicksettings.Tile;
 import android.widget.ImageView;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile.Icon;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import java.util.Objects;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 52b4c0a..9845c51 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -174,6 +174,7 @@
 
     @Override
     protected void handleUpdateState(BooleanState state, Object arg) {
+        if (mController == null) return;
         final int zen = arg instanceof Integer ? (Integer) arg : mController.getZen();
         final boolean newValue = zen != ZEN_MODE_OFF;
         final boolean valueChanged = state.value != newValue;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 274244e..ad6261b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -35,9 +35,9 @@
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher.DarkReceiver;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
index 677fa81..0304086 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/ConnectedDeviceSignalController.java
@@ -16,10 +16,10 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.ImageView;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ScalingDrawableWrapper;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.BluetoothController;
 
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 8516278..f0854ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -35,8 +35,8 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 2819624..36cfe57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -78,8 +78,10 @@
     @Override
     public void notifyListeners(SignalCallback callback) {
         // only show wifi in the cluster if connected or if wifi-only
+        boolean visibleWhenEnabled = mContext.getResources().getBoolean(
+                R.bool.config_showWifiIndicatorWhenEnabled);
         boolean wifiVisible = mCurrentState.enabled
-                && (mCurrentState.connected || !mHasMobileData);
+                && (mCurrentState.connected || !mHasMobileData || visibleWhenEnabled);
         String wifiDesc = wifiVisible ? mCurrentState.ssid : null;
         boolean ssidPresent = wifiVisible && mCurrentState.ssid != null;
         String contentDescription = getStringIfExists(getContentDescription());
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index 27c16d5..fce71b9 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -26,6 +26,7 @@
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 
 LOCAL_PACKAGE_NAME := SystemUITests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index d14b23e..96d623e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -31,14 +31,15 @@
 import android.telephony.TelephonyManager;
 import android.util.Log;
 import com.android.internal.telephony.cdma.EriInfo;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
-import com.android.systemui.statusbar.phone.SignalDrawable;
+import com.android.systemui.SysuiTestCase;
+
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.statusbar.policy.NetworkController.IconState;
 import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.Config;
 import com.android.systemui.statusbar.policy.NetworkControllerImpl.SubscriptionDefaults;
-import com.android.systemui.SysuiTestCase;
 
 import org.junit.Before;
 import org.junit.Rule;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
index 173cc4c..d5294ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
@@ -28,9 +28,9 @@
 
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyIntents;
+import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.net.DataUsageController;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SignalDrawable;
 
 import org.junit.Ignore;
 import org.junit.Test;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 2077790..029dc7b 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -21,6 +21,7 @@
 import android.app.AppGlobals;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothProtoEnums;
 import android.bluetooth.IBluetooth;
 import android.bluetooth.IBluetoothCallback;
 import android.bluetooth.IBluetoothGatt;
@@ -87,14 +88,6 @@
 
     private static final int ACTIVE_LOG_MAX_SIZE = 20;
     private static final int CRASH_LOG_MAX_SIZE = 100;
-    private static final String REASON_AIRPLANE_MODE = "airplane mode";
-    private static final String REASON_DISALLOWED = "disallowed by system";
-    private static final String REASON_RESTARTED = "automatic restart";
-    private static final String REASON_START_CRASH = "turn-on crash";
-    private static final String REASON_SYSTEM_BOOT = "system boot";
-    private static final String REASON_UNEXPECTED = "unexpected crash";
-    private static final String REASON_USER_SWITCH = "user switch";
-    private static final String REASON_RESTORE_USER_SETTING = "restore user setting";
 
     private static final int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
     //Maximum msec to wait for service restart
@@ -163,7 +156,7 @@
     private boolean mQuietEnable = false;
     private boolean mEnable;
 
-    private CharSequence timeToLog(long timestamp) {
+    private static CharSequence timeToLog(long timestamp) {
         return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
     }
 
@@ -171,29 +164,27 @@
      * Used for tracking apps that enabled / disabled Bluetooth.
      */
     private class ActiveLog {
+        private int mReason;
         private String mPackageName;
         private boolean mEnable;
         private long mTimestamp;
 
-        ActiveLog(String packageName, boolean enable, long timestamp) {
+        ActiveLog(int reason, String packageName, boolean enable, long timestamp) {
+            mReason = reason;
             mPackageName = packageName;
             mEnable = enable;
             mTimestamp = timestamp;
         }
 
-        public long getTime() {
-            return mTimestamp;
-        }
-
         public String toString() {
-            return timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ") + " by "
-                    + mPackageName;
+            return timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ")
+                    + " due to " + getEnableDisableReasonString(mReason) + " by " + mPackageName;
         }
 
     }
 
-    private LinkedList<ActiveLog> mActiveLogs;
-    private LinkedList<Long> mCrashTimestamps;
+    private final LinkedList<ActiveLog> mActiveLogs = new LinkedList<>();
+    private final LinkedList<Long> mCrashTimestamps = new LinkedList<>();
     private int mCrashes;
     private long mLastEnabledTime;
 
@@ -213,8 +204,7 @@
 
     // Save a ProfileServiceConnections object for each of the bound
     // bluetooth profile services
-    private final Map<Integer, ProfileServiceConnections> mProfileServices =
-            new HashMap<Integer, ProfileServiceConnections>();
+    private final Map<Integer, ProfileServiceConnections> mProfileServices = new HashMap<>();
 
     private final boolean mPermissionReviewRequired;
 
@@ -246,7 +236,8 @@
                         if (userId == UserHandle.USER_SYSTEM && newRestrictions.getBoolean(
                                 UserManager.DISALLOW_BLUETOOTH)) {
                             updateOppLauncherComponentState(userId, true); // Sharing disallowed
-                            sendDisableMsg(REASON_DISALLOWED);
+                            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED,
+                                    mContext.getPackageName());
                         } else {
                             updateOppLauncherComponentState(userId, newRestrictions.getBoolean(
                                     UserManager.DISALLOW_BLUETOOTH_SHARING));
@@ -303,10 +294,13 @@
                             mBluetoothLock.readLock().unlock();
                         }
                     } else if (st == BluetoothAdapter.STATE_ON) {
-                        sendDisableMsg(REASON_AIRPLANE_MODE);
+                        sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                                mContext.getPackageName());
                     }
                 } else if (mEnableExternal) {
-                    sendEnableMsg(mQuietEnableExternal, REASON_AIRPLANE_MODE);
+                    sendEnableMsg(mQuietEnableExternal,
+                            BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE,
+                            mContext.getPackageName());
                 }
             }
         }
@@ -369,8 +363,6 @@
         mPermissionReviewRequired = context.getResources()
                 .getBoolean(com.android.internal.R.bool.config_permissionReviewRequired);
 
-        mActiveLogs = new LinkedList<ActiveLog>();
-        mCrashTimestamps = new LinkedList<Long>();
         mCrashes = 0;
         mBluetooth = null;
         mBluetoothBinder = null;
@@ -671,8 +663,8 @@
             return false;
         }
         try {
-            return (Settings.Global.getInt(mContentResolver,
-                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE)) != 0;
+            return Settings.Global.getInt(mContentResolver,
+                    Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE) != 0;
         } catch (SettingNotFoundException e) {
         }
         return false;
@@ -867,7 +859,8 @@
         synchronized (mReceiver) {
             mQuietEnableExternal = true;
             mEnableExternal = true;
-            sendEnableMsg(true, packageName);
+            sendEnableMsg(true,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
         }
         return true;
     }
@@ -907,7 +900,8 @@
             mQuietEnableExternal = false;
             mEnableExternal = true;
             // waive WRITE_SECURE_SETTINGS permission check
-            sendEnableMsg(false, packageName);
+            sendEnableMsg(false,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST, packageName);
         }
         if (DBG) {
             Slog.d(TAG, "enable returning");
@@ -943,7 +937,8 @@
                 persistBluetoothSetting(BLUETOOTH_OFF);
             }
             mEnableExternal = false;
-            sendDisableMsg(packageName);
+            sendDisableMsg(BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST,
+                    packageName);
         }
         return true;
     }
@@ -1103,7 +1098,9 @@
             if (DBG) {
                 Slog.d(TAG, "Auto-enabling Bluetooth.");
             }
-            sendEnableMsg(mQuietEnableExternal, REASON_SYSTEM_BOOT);
+            sendEnableMsg(mQuietEnableExternal,
+                    BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT,
+                    mContext.getPackageName());
         } else if (!isNameAndAddressSet()) {
             if (DBG) {
                 Slog.d(TAG, "Getting adapter name and address");
@@ -1545,20 +1542,25 @@
                     break;
 
                 case MESSAGE_RESTORE_USER_SETTING:
-                    try {
-                        if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
-                            if (DBG) {
-                                Slog.d(TAG, "Restore Bluetooth state to disabled");
-                            }
-                            disable(REASON_RESTORE_USER_SETTING, true);
-                        } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
-                            if (DBG) {
-                                Slog.d(TAG, "Restore Bluetooth state to enabled");
-                            }
-                            enable(REASON_RESTORE_USER_SETTING);
+                    if ((msg.arg1 == RESTORE_SETTING_TO_OFF) && mEnable) {
+                        if (DBG) {
+                            Slog.d(TAG, "Restore Bluetooth state to disabled");
                         }
-                    } catch (RemoteException e) {
-                        Slog.e(TAG, "Unable to change Bluetooth On setting", e);
+                        persistBluetoothSetting(BLUETOOTH_OFF);
+                        mEnableExternal = false;
+                        sendDisableMsg(
+                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+                                mContext.getPackageName());
+                    } else if ((msg.arg1 == RESTORE_SETTING_TO_ON) && !mEnable) {
+                        if (DBG) {
+                            Slog.d(TAG, "Restore Bluetooth state to enabled");
+                        }
+                        mQuietEnableExternal = false;
+                        mEnableExternal = true;
+                        // waive WRITE_SECURE_SETTINGS permission check
+                        sendEnableMsg(false,
+                                BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING,
+                                mContext.getPackageName());
                     }
                     break;
 
@@ -1585,7 +1587,7 @@
                     break;
                 }
                 case MESSAGE_ADD_PROXY_DELAYED: {
-                    ProfileServiceConnections psc = mProfileServices.get(new Integer(msg.arg1));
+                    ProfileServiceConnections psc = mProfileServices.get(msg.arg1);
                     if (psc == null) {
                         break;
                     }
@@ -1734,7 +1736,8 @@
 
                     // log the unexpected crash
                     addCrashLog();
-                    addActiveLog(REASON_UNEXPECTED, false);
+                    addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH,
+                            mContext.getPackageName(), false);
                     if (mEnable) {
                         mEnable = false;
                         // Send a Bluetooth Restart message
@@ -1768,7 +1771,8 @@
                      it doesnt change when IBluetooth
                      service restarts */
                     mEnable = true;
-                    addActiveLog(REASON_RESTARTED, true);
+                    addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED,
+                            mContext.getPackageName(), true);
                     handleEnable(mQuietEnable);
                     break;
                 }
@@ -1824,7 +1828,8 @@
 
                         unbindAllBluetoothProfileServices();
                         // disable
-                        addActiveLog(REASON_USER_SWITCH, false);
+                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+                                mContext.getPackageName(), false);
                         handleDisable();
                         // Pbap service need receive STATE_TURNING_OFF intent to close
                         bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
@@ -1862,7 +1867,8 @@
                         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
-                        addActiveLog(REASON_USER_SWITCH, true);
+                        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH,
+                                mContext.getPackageName(), true);
                         // mEnable flag could have been reset on disableBLE. Reenable it.
                         mEnable = true;
                         handleEnable(mQuietEnable);
@@ -2129,23 +2135,24 @@
         return false;
     }
 
-    private void sendDisableMsg(String packageName) {
+    private void sendDisableMsg(int reason, String packageName) {
         mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_DISABLE));
-        addActiveLog(packageName, false);
+        addActiveLog(reason, packageName, false);
     }
 
-    private void sendEnableMsg(boolean quietMode, String packageName) {
+    private void sendEnableMsg(boolean quietMode, int reason, String packageName) {
         mHandler.sendMessage(mHandler.obtainMessage(MESSAGE_ENABLE, quietMode ? 1 : 0, 0));
-        addActiveLog(packageName, true);
+        addActiveLog(reason, packageName, true);
         mLastEnabledTime = SystemClock.elapsedRealtime();
     }
 
-    private void addActiveLog(String packageName, boolean enable) {
+    private void addActiveLog(int reason, String packageName, boolean enable) {
         synchronized (mActiveLogs) {
             if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
                 mActiveLogs.remove();
             }
-            mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
+            mActiveLogs.add(
+                    new ActiveLog(reason, packageName, enable, System.currentTimeMillis()));
         }
     }
 
@@ -2176,7 +2183,8 @@
         SystemClock.sleep(500);
 
         // disable
-        addActiveLog(REASON_START_CRASH, false);
+        addActiveLog(BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR,
+                mContext.getPackageName(), false);
         handleDisable();
 
         waitForOnOff(false, true);
@@ -2320,4 +2328,29 @@
             writer.println(errorMsg);
         }
     }
+
+    private static String getEnableDisableReasonString(int reason) {
+        switch (reason) {
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_APPLICATION_REQUEST:
+                return "APPLICATION_REQUEST";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_AIRPLANE_MODE:
+                return "AIRPLANE_MODE";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_DISALLOWED:
+                return "DISALLOWED";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTARTED:
+                return "RESTARTED";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR:
+                return "START_ERROR";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT:
+                return "SYSTEM_BOOT";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_CRASH:
+                return "CRASH";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH:
+                return "USER_SWITCH";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_RESTORE_USER_SETTING:
+                return "RESTORE_USER_SETTING";
+            case BluetoothProtoEnums.ENABLE_DISABLE_REASON_UNSPECIFIED:
+            default: return "UNKNOWN[" + reason + "]";
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index fd2ef18..6c24e94 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -17,6 +17,7 @@
 package com.android.server;
 
 import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
 import static android.net.ConnectivityManager.NETID_UNSET;
 import static android.net.ConnectivityManager.TYPE_ETHERNET;
@@ -1329,9 +1330,8 @@
         if (nai != null) {
             synchronized (nai) {
                 if (nai.networkCapabilities != null) {
-                    // TODO : don't remove the UIDs when communicating with processes
-                    // that have the NETWORK_SETTINGS permission.
-                    return networkCapabilitiesWithoutUids(nai.networkCapabilities);
+                    return networkCapabilitiesWithoutUidsUnlessAllowed(nai.networkCapabilities,
+                            Binder.getCallingPid(), Binder.getCallingUid());
                 }
             }
         }
@@ -1344,10 +1344,18 @@
         return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
     }
 
-    private NetworkCapabilities networkCapabilitiesWithoutUids(NetworkCapabilities nc) {
+    private NetworkCapabilities networkCapabilitiesWithoutUidsUnlessAllowed(
+            NetworkCapabilities nc, int callerPid, int callerUid) {
+        if (checkSettingsPermission(callerPid, callerUid)) return new NetworkCapabilities(nc);
         return new NetworkCapabilities(nc).setUids(null);
     }
 
+    private void restrictRequestUidsForCaller(NetworkCapabilities nc) {
+        if (!checkSettingsPermission()) {
+            nc.setSingleUid(Binder.getCallingUid());
+        }
+    }
+
     @Override
     public NetworkState[] getAllNetworkState() {
         // Require internal since we're handing out IMSI details
@@ -1546,6 +1554,16 @@
                 "ConnectivityService");
     }
 
+    private boolean checkSettingsPermission() {
+        return PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.NETWORK_SETTINGS);
+    }
+
+    private boolean checkSettingsPermission(int pid, int uid) {
+        return PERMISSION_GRANTED == mContext.checkPermission(
+                android.Manifest.permission.NETWORK_SETTINGS, pid, uid);
+    }
+
     private void enforceTetherAccessPermission() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.ACCESS_NETWORK_STATE,
@@ -4213,13 +4231,12 @@
             enforceMeteredApnPolicy(networkCapabilities);
         }
         ensureRequestableCapabilities(networkCapabilities);
-        // Set the UID range for this request to the single UID of the requester.
+        // Set the UID range for this request to the single UID of the requester, or to an empty
+        // set of UIDs if the caller has the appropriate permission and UIDs have not been set.
         // This will overwrite any allowed UIDs in the requested capabilities. Though there
         // are no visible methods to set the UIDs, an app could use reflection to try and get
         // networks for other apps so it's essential that the UIDs are overwritten.
-        // TODO : don't forcefully set the UID when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        networkCapabilities.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(networkCapabilities);
 
         if (timeoutMs < 0) {
             throw new IllegalArgumentException("Bad timeout specified");
@@ -4293,9 +4310,7 @@
         enforceMeteredApnPolicy(networkCapabilities);
         ensureRequestableCapabilities(networkCapabilities);
         ensureValidNetworkSpecifier(networkCapabilities);
-        // TODO : don't forcefully set the UID when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        networkCapabilities.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(networkCapabilities);
 
         NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
                 nextNetworkRequestId(), NetworkRequest.Type.REQUEST);
@@ -4349,9 +4364,7 @@
         }
 
         NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
-        // TODO : don't forcefully set the UIDs when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        nc.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(nc);
         if (!ConnectivityManager.checkChangePermission(mContext)) {
             // Apps without the CHANGE_NETWORK_STATE permission can't use background networks, so
             // make all their listens include NET_CAPABILITY_FOREGROUND. That way, they will get
@@ -4381,9 +4394,7 @@
         ensureValidNetworkSpecifier(networkCapabilities);
 
         final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
-        // TODO : don't forcefully set the UIDs when communicating with processes
-        // that have the NETWORK_SETTINGS permission.
-        nc.setSingleUid(Binder.getCallingUid());
+        restrictRequestUidsForCaller(nc);
 
         NetworkRequest networkRequest = new NetworkRequest(nc, TYPE_NONE, nextNetworkRequestId(),
                 NetworkRequest.Type.LISTEN);
@@ -4947,8 +4958,8 @@
             }
             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
                 // networkAgent can't be null as it has been accessed a few lines above.
-                final NetworkCapabilities nc =
-                        networkCapabilitiesWithoutUids(networkAgent.networkCapabilities);
+                final NetworkCapabilities nc = networkCapabilitiesWithoutUidsUnlessAllowed(
+                        networkAgent.networkCapabilities, nri.mPid, nri.mUid);
                 putParcelable(bundle, nc);
                 break;
             }
@@ -5428,8 +5439,11 @@
         if (!networkAgent.everConnected && state == NetworkInfo.State.CONNECTED) {
             networkAgent.everConnected = true;
 
+            if (networkAgent.linkProperties == null) {
+                Slog.wtf(TAG, networkAgent.name() + " connected with null LinkProperties");
+            }
+
             updateLinkProperties(networkAgent, null);
-            notifyIfacesChangedForNetworkStats();
 
             networkAgent.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_CONNECTED);
             scheduleUnvalidatedPrompt(networkAgent);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index e202618..539c001 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -65,7 +65,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.NoSuchElementException;
 
@@ -90,6 +89,8 @@
     private static final boolean VDBG = false; // STOPSHIP if true
 
     private static class Record {
+        Context context;
+
         String callingPackage;
 
         IBinder binder;
@@ -108,8 +109,6 @@
 
         int phoneId = SubscriptionManager.INVALID_PHONE_INDEX;
 
-        boolean canReadPhoneState;
-
         boolean matchPhoneStateListenerEvent(int events) {
             return (callback != null) && ((events & this.events) != 0);
         }
@@ -118,6 +117,15 @@
             return (onSubscriptionsChangedListenerCallback != null);
         }
 
+        boolean canReadPhoneState() {
+            try {
+                return TelephonyPermissions.checkReadPhoneState(
+                        context, subId, callerPid, callerUid, callingPackage, "listen");
+            } catch (SecurityException e) {
+                return false;
+            }
+        }
+
         @Override
         public String toString() {
             return "{callingPackage=" + callingPackage + " binder=" + binder
@@ -125,8 +133,7 @@
                     + " onSubscriptionsChangedListenererCallback="
                                             + onSubscriptionsChangedListenerCallback
                     + " callerUid=" + callerUid + " subId=" + subId + " phoneId=" + phoneId
-                    + " events=" + Integer.toHexString(events)
-                    + " canReadPhoneState=" + canReadPhoneState + "}";
+                    + " events=" + Integer.toHexString(events) + "}";
         }
     }
 
@@ -164,14 +171,9 @@
 
     private int[] mDataActivity;
 
+    // Connection state of default APN type data (i.e. internet) of phones
     private int[] mDataConnectionState;
 
-    private ArrayList<String>[] mConnectedApns;
-
-    private LinkProperties[] mDataConnectionLinkProperties;
-
-    private NetworkCapabilities[] mDataConnectionNetworkCapabilities;
-
     private Bundle[] mCellLocation;
 
     private int[] mDataConnectionNetworkType;
@@ -203,16 +205,15 @@
     private PreciseDataConnectionState mPreciseDataConnectionState =
                 new PreciseDataConnectionState();
 
+    static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK =
+            PhoneStateListener.LISTEN_CELL_LOCATION
+                    | PhoneStateListener.LISTEN_CELL_INFO;
+
     static final int ENFORCE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
                 PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR |
                 PhoneStateListener.LISTEN_VOLTE_STATE;
 
-    static final int CHECK_PHONE_STATE_PERMISSION_MASK =
-                PhoneStateListener.LISTEN_CALL_STATE |
-                PhoneStateListener.LISTEN_DATA_ACTIVITY |
-                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
-
     static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                 PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
                 PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;
@@ -319,9 +320,8 @@
         mBatteryStats = BatteryStatsService.getService();
 
         int numPhones = TelephonyManager.getDefault().getPhoneCount();
-        if (DBG) log("TelephonyRegistor: ctor numPhones=" + numPhones);
+        if (DBG) log("TelephonyRegistry: ctor numPhones=" + numPhones);
         mNumPhones = numPhones;
-        mConnectedApns = new ArrayList[numPhones];
         mCallState = new int[numPhones];
         mDataActivity = new int[numPhones];
         mDataConnectionState = new int[numPhones];
@@ -335,8 +335,6 @@
         mMessageWaiting = new boolean[numPhones];
         mCallForwarding = new boolean[numPhones];
         mCellLocation = new Bundle[numPhones];
-        mDataConnectionLinkProperties = new LinkProperties[numPhones];
-        mDataConnectionNetworkCapabilities = new NetworkCapabilities[numPhones];
         mCellInfo = new ArrayList<List<CellInfo>>();
         mPhysicalChannelConfigs = new ArrayList<List<PhysicalChannelConfig>>();
         for (int i = 0; i < numPhones; i++) {
@@ -354,7 +352,6 @@
             mCellLocation[i] = new Bundle();
             mCellInfo.add(i, null);
             mPhysicalChannelConfigs.add(i, null);
-            mConnectedApns[i] = new ArrayList<String>();
         }
 
         // Note that location can be null for non-phone builds like
@@ -382,20 +379,13 @@
     public void addOnSubscriptionsChangedListener(String callingPackage,
             IOnSubscriptionsChangedListener callback) {
         int callerUserId = UserHandle.getCallingUserId();
-        mContext.getSystemService(AppOpsManager.class)
-                .checkPackage(Binder.getCallingUid(), callingPackage);
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         if (VDBG) {
             log("listen oscl: E pkg=" + callingPackage + " myUserId=" + UserHandle.myUserId()
                 + " callerUserId="  + callerUserId + " callback=" + callback
                 + " callback.asBinder=" + callback.asBinder());
         }
 
-        if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                mContext, callingPackage, "addOnSubscriptionsChangedListener")) {
-            return;
-        }
-
-
         synchronized (mRecords) {
             // register
             IBinder b = callback.asBinder();
@@ -405,12 +395,12 @@
                 return;
             }
 
+            r.context = mContext;
             r.onSubscriptionsChangedListenerCallback = callback;
             r.callingPackage = callingPackage;
             r.callerUid = Binder.getCallingUid();
             r.callerPid = Binder.getCallingPid();
             r.events = 0;
-            r.canReadPhoneState = true; // permission has been enforced above
             if (DBG) {
                 log("listen oscl:  Register r=" + r);
             }
@@ -479,8 +469,7 @@
     private void listen(String callingPackage, IPhoneStateListener callback, int events,
             boolean notifyNow, int subId) {
         int callerUserId = UserHandle.getCallingUserId();
-        mContext.getSystemService(AppOpsManager.class)
-                .checkPackage(Binder.getCallingUid(), callingPackage);
+        mAppOps.checkPackage(Binder.getCallingUid(), callingPackage);
         if (VDBG) {
             log("listen: E pkg=" + callingPackage + " events=0x" + Integer.toHexString(events)
                 + " notifyNow=" + notifyNow + " subId=" + subId + " myUserId="
@@ -491,7 +480,7 @@
             // Checks permission and throws SecurityException for disallowed operations. For pre-M
             // apps whose runtime permission has been revoked, we return immediately to skip sending
             // events to the app without crashing it.
-            if (!checkListenerPermission(events, callingPackage, "listen")) {
+            if (!checkListenerPermission(events, subId, callingPackage, "listen")) {
                 return;
             }
 
@@ -505,14 +494,11 @@
                     return;
                 }
 
+                r.context = mContext;
                 r.callback = callback;
                 r.callingPackage = callingPackage;
                 r.callerUid = Binder.getCallingUid();
                 r.callerPid = Binder.getCallingPid();
-                boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK
-                        | ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0;
-                r.canReadPhoneState =
-                        isPhoneStateEvent && canReadPhoneState(callingPackage, "listen");
                 // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID,
                 // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID
                 if (!SubscriptionManager.isValidSubscriptionId(subId)) {
@@ -680,18 +666,9 @@
         }
     }
 
-    private boolean canReadPhoneState(String callingPackage, String message) {
-        try {
-            return TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                    mContext, callingPackage, message);
-        } catch (SecurityException e) {
-            return false;
-        }
-    }
-
     private String getCallIncomingNumber(Record record, int phoneId) {
-        // Hide the number if record's process has no READ_PHONE_STATE permission
-        return record.canReadPhoneState ? mCallIncomingNumber[phoneId] : "";
+        // Hide the number if record's process can't currently read phone state.
+        return record.canReadPhoneState() ? mCallIncomingNumber[phoneId] : "";
     }
 
     private Record add(IBinder binder) {
@@ -766,7 +743,7 @@
                 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) &&
                         (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) {
                     try {
-                        String incomingNumberOrEmpty = r.canReadPhoneState ? incomingNumber : "";
+                        String incomingNumberOrEmpty = r.canReadPhoneState() ? incomingNumber : "";
                         r.callback.onCallStateChanged(state, incomingNumberOrEmpty);
                     } catch (RemoteException ex) {
                         mRemoveList.add(r.binder);
@@ -1212,36 +1189,12 @@
         int phoneId = SubscriptionManager.getPhoneId(subId);
         synchronized (mRecords) {
             if (validatePhoneId(phoneId)) {
-                boolean modified = false;
-                if (state == TelephonyManager.DATA_CONNECTED) {
-                    if (!mConnectedApns[phoneId].contains(apnType)) {
-                        mConnectedApns[phoneId].add(apnType);
-                        if (mDataConnectionState[phoneId] != state) {
-                            mDataConnectionState[phoneId] = state;
-                            modified = true;
-                        }
-                    }
-                } else {
-                    if (mConnectedApns[phoneId].remove(apnType)) {
-                        if (mConnectedApns[phoneId].isEmpty()) {
-                            mDataConnectionState[phoneId] = state;
-                            modified = true;
-                        } else {
-                            // leave mDataConnectionState as is and
-                            // send out the new status for the APN in question.
-                        }
-                    }
-                }
-                mDataConnectionLinkProperties[phoneId] = linkProperties;
-                mDataConnectionNetworkCapabilities[phoneId] = networkCapabilities;
-                if (mDataConnectionNetworkType[phoneId] != networkType) {
-                    mDataConnectionNetworkType[phoneId] = networkType;
-                    // need to tell registered listeners about the new network type
-                    modified = true;
-                }
-                if (modified) {
-                    String str = "onDataConnectionStateChanged(" + mDataConnectionState[phoneId]
-                            + ", " + mDataConnectionNetworkType[phoneId] + ")";
+                // We only call the callback when the change is for default APN type.
+                if (PhoneConstants.APN_TYPE_DEFAULT.equals(apnType)
+                        && (mDataConnectionState[phoneId] != state
+                        || mDataConnectionNetworkType[phoneId] != networkType)) {
+                    String str = "onDataConnectionStateChanged(" + state
+                            + ", " + networkType + ")";
                     log(str);
                     mLocalLog.log(str);
                     for (Record r : mRecords) {
@@ -1252,15 +1205,16 @@
                                 if (DBG) {
                                     log("Notify data connection state changed on sub: " + subId);
                                 }
-                                r.callback.onDataConnectionStateChanged(
-                                        mDataConnectionState[phoneId],
-                                        mDataConnectionNetworkType[phoneId]);
+                                r.callback.onDataConnectionStateChanged(state, networkType);
                             } catch (RemoteException ex) {
                                 mRemoveList.add(r.binder);
                             }
                         }
                     }
                     handleRemoveListLocked();
+
+                    mDataConnectionState[phoneId] = state;
+                    mDataConnectionNetworkType[phoneId] = networkType;
                 }
                 mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
                         apnType, apn, reason, linkProperties, "");
@@ -1496,14 +1450,10 @@
                 pw.println("mCallForwarding=" + mCallForwarding[i]);
                 pw.println("mDataActivity=" + mDataActivity[i]);
                 pw.println("mDataConnectionState=" + mDataConnectionState[i]);
-                pw.println("mDataConnectionLinkProperties=" + mDataConnectionLinkProperties[i]);
-                pw.println("mDataConnectionNetworkCapabilities=" +
-                        mDataConnectionNetworkCapabilities[i]);
                 pw.println("mCellLocation=" + mCellLocation[i]);
                 pw.println("mCellInfo=" + mCellInfo.get(i));
                 pw.decreaseIndent();
             }
-            pw.println("mConnectedApns=" + Arrays.toString(mConnectedApns));
             pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState);
             pw.println("mPreciseCallState=" + mPreciseCallState);
             pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState);
@@ -1720,22 +1670,20 @@
                 == PackageManager.PERMISSION_GRANTED;
     }
 
-    private boolean checkListenerPermission(int events, String callingPackage, String message) {
-        if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) {
+    private boolean checkListenerPermission(
+            int events, int subId, String callingPackage, String message) {
+        if ((events & ENFORCE_COARSE_LOCATION_PERMISSION_MASK) != 0) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
-        }
-
-        if ((events & PhoneStateListener.LISTEN_CELL_INFO) != 0) {
-            mContext.enforceCallingOrSelfPermission(
-                    android.Manifest.permission.ACCESS_COARSE_LOCATION, null);
-
+            if (mAppOps.noteOp(AppOpsManager.OP_COARSE_LOCATION, Binder.getCallingUid(),
+                    callingPackage) != AppOpsManager.MODE_ALLOWED) {
+                return false;
+            }
         }
 
         if ((events & ENFORCE_PHONE_STATE_PERMISSION_MASK) != 0) {
             if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(
-                    mContext, callingPackage, message)) {
+                    mContext, subId, callingPackage, message)) {
                 return false;
             }
         }
diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java
index be91f98..2af2f38 100644
--- a/services/core/java/com/android/server/accounts/TokenCache.java
+++ b/services/core/java/com/android/server/accounts/TokenCache.java
@@ -125,7 +125,7 @@
                  * This is recursive, but it won't spiral out of control because LruCache is
                  * thread safe and the Evictor can only be removed once.
                  */
-                Evictor evictor = mTokenEvictors.remove(oldVal.token);
+                Evictor evictor = mTokenEvictors.remove(new Pair<>(k.account.type, oldVal.token));
                 if (evictor != null) {
                     evictor.evict();
                 }
@@ -134,12 +134,13 @@
 
         public void putToken(Key k, Value v) {
             // Prepare for removal by token string.
-            Evictor tokenEvictor = mTokenEvictors.get(v.token);
+            Pair<String, String> mapKey = new Pair<>(k.account.type, v.token);
+            Evictor tokenEvictor = mTokenEvictors.get(mapKey);
             if (tokenEvictor == null) {
                 tokenEvictor = new Evictor();
             }
             tokenEvictor.add(k);
-            mTokenEvictors.put(new Pair<>(k.account.type, v.token), tokenEvictor);
+            mTokenEvictors.put(mapKey, tokenEvictor);
 
             // Prepare for removal by associated account.
             Evictor accountEvictor = mAccountEvictors.get(k.account);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6c60b74..4d839d2 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -23603,6 +23603,14 @@
                     } catch (IOException e) {
                     }
                     mProfilerInfo.profileFd = null;
+
+                    if (proc.pid == MY_PID) {
+                        // When profiling the system server itself, avoid closing the file
+                        // descriptor, as profilerControl will not create a copy.
+                        // Note: it is also not correct to just set profileFd to null, as the
+                        //       whole ProfilerInfo instance is passed down!
+                        profilerInfo = null;
+                    }
                 } else {
                     stopProfilerLocked(proc, profileType);
                     if (profilerInfo != null && profilerInfo.profileFd != null) {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index fae215f..3b89097 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -36,6 +36,7 @@
 import android.os.UserHandle;
 import android.os.UserManagerInternal;
 import android.os.WorkSource;
+import android.os.connectivity.CellularBatteryStats;
 import android.os.health.HealthStatsParceler;
 import android.os.health.HealthStatsWriter;
 import android.os.health.UidHealthStats;
@@ -1335,6 +1336,16 @@
     }
 
     /**
+     * Gets a snapshot of cellular stats
+     * @hide
+     */
+    public CellularBatteryStats getCellularBatteryStats() {
+        synchronized (mStats) {
+            return mStats.getCellularBatteryStats();
+        }
+    }
+
+    /**
      * Gets a snapshot of the system health for a particular uid.
      */
     @Override
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cb96bac..9e37c78 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2240,12 +2240,15 @@
         if (DEBUG_VOL) {
             Log.d(TAG, String.format("Mic mute %s, user=%d", on, userId));
         }
-        // If mute is for current user actually mute, else just persist the setting
-        // which will be loaded on user switch.
+        // only mute for the current user
         if (getCurrentUserId() == userId) {
+            final boolean currentMute = AudioSystem.isMicrophoneMuted();
             AudioSystem.muteMicrophone(on);
+            if (on != currentMute) {
+                mContext.sendBroadcast(new Intent(AudioManager.ACTION_MICROPHONE_MUTE_CHANGED)
+                        .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
+            }
         }
-        // Post a persist microphone msg.
     }
 
     @Override
diff --git a/services/core/java/com/android/server/connectivity/DnsManager.java b/services/core/java/com/android/server/connectivity/DnsManager.java
index a1c54bd..557828a 100644
--- a/services/core/java/com/android/server/connectivity/DnsManager.java
+++ b/services/core/java/com/android/server/connectivity/DnsManager.java
@@ -187,7 +187,7 @@
         Slog.w(TAG, "updatePrivateDns(" + network + ", " + cfg + ")");
         return (cfg != null)
                 ? mPrivateDnsMap.put(network.netId, cfg)
-                : mPrivateDnsMap.remove(network);
+                : mPrivateDnsMap.remove(network.netId);
     }
 
     public void setDnsConfigurationForNetwork(
diff --git a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
index e786bed..2d50dd5 100644
--- a/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
+++ b/services/core/java/com/android/server/connectivity/NetdEventListenerService.java
@@ -101,9 +101,12 @@
 
 
     /**
-     * There are only 2 possible callbacks.
+     * There are only 3 possible callbacks.
      *
-     * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY].
+     * mNetdEventCallbackList[CALLBACK_CALLER_CONNECTIVITY_SERVICE]
+     * Callback registered/unregistered by ConnectivityService.
+     *
+     * mNetdEventCallbackList[CALLBACK_CALLER_DEVICE_POLICY]
      * Callback registered/unregistered when logging is being enabled/disabled in DPM
      * by the device owner. It's DevicePolicyManager's responsibility to ensure that.
      *
@@ -112,6 +115,7 @@
      */
     @GuardedBy("this")
     private static final int[] ALLOWED_CALLBACK_TYPES = {
+        INetdEventCallback.CALLBACK_CALLER_CONNECTIVITY_SERVICE,
         INetdEventCallback.CALLBACK_CALLER_DEVICE_POLICY,
         INetdEventCallback.CALLBACK_CALLER_NETWORK_WATCHLIST
     };
@@ -211,6 +215,19 @@
     @Override
     // Called concurrently by multiple binder threads.
     // This method must not block or perform long-running operations.
+    public synchronized void onPrivateDnsValidationEvent(int netId,
+            String ipAddress, String hostname, boolean validated)
+            throws RemoteException {
+        for (INetdEventCallback callback : mNetdEventCallbackList) {
+            if (callback != null) {
+                callback.onPrivateDnsValidationEvent(netId, ipAddress, hostname, validated);
+            }
+        }
+    }
+
+    @Override
+    // Called concurrently by multiple binder threads.
+    // This method must not block or perform long-running operations.
     public synchronized void onConnectEvent(int netId, int error, int latencyMs, String ipAddr,
             int port, int uid) throws RemoteException {
         long timestamp = System.currentTimeMillis();
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index bb46d5e..c9bdcf1 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -57,6 +57,7 @@
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkMisc;
+import android.net.NetworkUtils;
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.Uri;
@@ -105,6 +106,7 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
@@ -113,6 +115,7 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Set;
 import java.util.SortedSet;
@@ -131,6 +134,24 @@
     // the device idle whitelist during service launch and VPN bootstrap.
     private static final long VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS = 60 * 1000;
 
+    // Settings for how much of the address space should be routed so that Vpn considers
+    // "most" of the address space is routed. This is used to determine whether this Vpn
+    // should be marked with the INTERNET capability.
+    private static final long MOST_IPV4_ADDRESSES_COUNT;
+    private static final BigInteger MOST_IPV6_ADDRESSES_COUNT;
+    static {
+        // 85% of the address space must be routed for Vpn to consider this VPN to provide
+        // INTERNET access.
+        final int howManyPercentIsMost = 85;
+
+        final long twoPower32 = 1L << 32;
+        MOST_IPV4_ADDRESSES_COUNT = twoPower32 * howManyPercentIsMost / 100;
+        final BigInteger twoPower128 = BigInteger.ONE.shiftLeft(128);
+        MOST_IPV6_ADDRESSES_COUNT = twoPower128
+                .multiply(BigInteger.valueOf(howManyPercentIsMost))
+                .divide(BigInteger.valueOf(100));
+    }
+
     // TODO: create separate trackers for each unique VPN to support
     // automated reconnection
 
@@ -830,10 +851,39 @@
         return lp;
     }
 
+    /**
+     * Analyzes the passed LinkedProperties to figure out whether it routes to most of the IP space.
+     *
+     * This returns true if the passed LinkedProperties contains routes to either most of the IPv4
+     * space or to most of the IPv6 address space, where "most" is defined by the value of the
+     * MOST_IPV{4,6}_ADDRESSES_COUNT constants : if more than this number of addresses are matched
+     * by any of the routes, then it's decided that most of the space is routed.
+     * @hide
+     */
+    @VisibleForTesting
+    static boolean providesRoutesToMostDestinations(LinkProperties lp) {
+        final Comparator<IpPrefix> prefixLengthComparator = IpPrefix.lengthComparator();
+        TreeSet<IpPrefix> ipv4Prefixes = new TreeSet<>(prefixLengthComparator);
+        TreeSet<IpPrefix> ipv6Prefixes = new TreeSet<>(prefixLengthComparator);
+        for (final RouteInfo route : lp.getAllRoutes()) {
+            IpPrefix destination = route.getDestination();
+            if (destination.isIPv4()) {
+                ipv4Prefixes.add(destination);
+            } else {
+                ipv6Prefixes.add(destination);
+            }
+        }
+        if (NetworkUtils.routedIPv4AddressCount(ipv4Prefixes) > MOST_IPV4_ADDRESSES_COUNT) {
+            return true;
+        }
+        return NetworkUtils.routedIPv6AddressCount(ipv6Prefixes)
+                .compareTo(MOST_IPV6_ADDRESSES_COUNT) >= 0;
+    }
+
     private void agentConnect() {
         LinkProperties lp = makeLinkProperties();
 
-        if (lp.hasIPv4DefaultRoute() || lp.hasIPv6DefaultRoute()) {
+        if (providesRoutesToMostDestinations(lp)) {
             mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
         } else {
             mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index bfc150e..8298127 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -153,8 +153,7 @@
     static final boolean LOGV = false;
 
     private static final int MSG_PERFORM_POLL = 1;
-    private static final int MSG_UPDATE_IFACES = 2;
-    private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
+    private static final int MSG_REGISTER_GLOBAL_ALERT = 2;
 
     /** Flags to control detail level of poll event. */
     private static final int FLAG_PERSIST_NETWORK = 0x1;
@@ -1533,10 +1532,6 @@
                     mService.performPoll(flags);
                     return true;
                 }
-                case MSG_UPDATE_IFACES: {
-                    mService.updateIfaces(null);
-                    return true;
-                }
                 case MSG_REGISTER_GLOBAL_ALERT: {
                     mService.registerGlobalAlert();
                     return true;
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ab3c999..504184c 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -40,7 +40,7 @@
 
     /* ***************************************************************************
      * IMPORTANT: These values are passed to native code. Keep them in sync with
-     * frameworks/native/cmds/installd/installd.h
+     * frameworks/native/cmds/installd/installd_constants.h
      * **************************************************************************/
     /** Application should be visible to everyone */
     public static final int DEXOPT_PUBLIC         = 1 << 1;
@@ -62,6 +62,8 @@
     public static final int DEXOPT_IDLE_BACKGROUND_JOB = 1 << 9;
     /** Indicates that dexopt should restrict access to private APIs. */
     public static final int DEXOPT_ENABLE_HIDDEN_API_CHECKS = 1 << 10;
+    /** Indicates that dexopt should convert to CompactDex. */
+    public static final int DEXOPT_GENERATE_COMPACT_DEX = 1 << 11;
 
     // NOTE: keep in sync with installd
     public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index b6804ba..faaa3ba 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -266,8 +266,8 @@
                     throws InstallerException {
                 final StringBuilder builder = new StringBuilder();
 
-                // The version. Right now it's 7.
-                builder.append("7 ");
+                // The current version.
+                builder.append("8 ");
 
                 builder.append("dexopt");
 
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 51e035b..5ea778b 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -57,6 +57,7 @@
 import static com.android.server.pm.Installer.DEXOPT_STORAGE_DE;
 import static com.android.server.pm.Installer.DEXOPT_IDLE_BACKGROUND_JOB;
 import static com.android.server.pm.Installer.DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+import static com.android.server.pm.Installer.DEXOPT_GENERATE_COMPACT_DEX;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
 
@@ -532,12 +533,22 @@
         // Some apps are executed with restrictions on hidden API usage. If this app is one
         // of them, pass a flag to dexopt to enable the same restrictions during compilation.
         int hiddenApiFlag = info.isAllowedToUseHiddenApi() ? 0 : DEXOPT_ENABLE_HIDDEN_API_CHECKS;
+        // Avoid generating CompactDex for modes that are latency critical.
+        final int compilationReason = options.getCompilationReason();
+        boolean generateCompactDex = true;
+        switch (compilationReason) {
+            case PackageManagerService.REASON_FIRST_BOOT:
+            case PackageManagerService.REASON_BOOT:
+            case PackageManagerService.REASON_INSTALL:
+                 generateCompactDex = false;
+        }
         int dexFlags =
                 (isPublic ? DEXOPT_PUBLIC : 0)
                 | (debuggable ? DEXOPT_DEBUGGABLE : 0)
                 | profileFlag
                 | (options.isBootComplete() ? DEXOPT_BOOTCOMPLETE : 0)
                 | (options.isDexoptIdleBackgroundJob() ? DEXOPT_IDLE_BACKGROUND_JOB : 0)
+                | (generateCompactDex ? DEXOPT_GENERATE_COMPACT_DEX : 0)
                 | hiddenApiFlag;
         return adjustDexoptFlags(dexFlags);
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 900e188..a54cf1a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3375,6 +3375,13 @@
         // "/data/system/package_cache/1"
         File cacheDir = FileUtils.createDir(cacheBaseDir, PACKAGE_PARSER_CACHE_VERSION);
 
+        if (cacheDir == null) {
+            // Something went wrong. Attempt to delete everything and return.
+            Slog.wtf(TAG, "Cache directory cannot be created - wiping base dir " + cacheBaseDir);
+            FileUtils.deleteContentsAndDir(cacheBaseDir);
+            return null;
+        }
+
         // The following is a workaround to aid development on non-numbered userdebug
         // builds or cases where "adb sync" is used on userdebug builds. If we detect that
         // the system partition is newer.
@@ -10206,6 +10213,17 @@
         mPackageUsage.writeNow(mPackages);
         mCompilerStats.writeNow();
         mDexManager.writePackageDexUsageNow();
+
+        // This is the last chance to write out pending restriction settings
+        synchronized (mPackages) {
+            if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
+                mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
+                for (int userId : mDirtyUsers) {
+                    mSettings.writePackageRestrictionsLPr(userId);
+                }
+                mDirtyUsers.clear();
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index d219476..2579e56 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -392,6 +392,8 @@
                 KeyEvent.KEYCODE_CALCULATOR, Intent.CATEGORY_APP_CALCULATOR);
     }
 
+    private static final int USER_ACTIVITY_NOTIFICATION_DELAY = 200;
+
     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
     static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
 
@@ -677,6 +679,7 @@
 
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
+    private boolean mNotifyUserActivity;
 
     boolean mShowingDream;
     private boolean mLastShowingDream;
@@ -722,6 +725,9 @@
     // Behavior of Back button while in-call and screen on
     int mIncallBackBehavior;
 
+    // Whether system navigation keys are enabled
+    boolean mSystemNavigationKeysEnabled;
+
     Display mDisplay;
 
     private int mDisplayRotation;
@@ -831,6 +837,7 @@
     private static final int MSG_DISPATCH_BACK_KEY_TO_AUTOFILL = 24;
     private static final int MSG_SYSTEM_KEY_PRESS = 25;
     private static final int MSG_HANDLE_ALL_APPS = 26;
+    private static final int MSG_NOTIFY_USER_ACTIVITY = 27;
 
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0;
     private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1;
@@ -926,6 +933,13 @@
                 case MSG_HANDLE_ALL_APPS:
                     launchAllAppsAction();
                     break;
+                case MSG_NOTIFY_USER_ACTIVITY:
+                    removeMessages(MSG_NOTIFY_USER_ACTIVITY);
+                    Intent intent = new Intent(ACTION_USER_ACTIVITY_NOTIFICATION);
+                    intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+                    mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
+                            android.Manifest.permission.USER_ACTIVITY);
+                    break;
             }
         }
     }
@@ -978,6 +992,9 @@
             resolver.registerContentObserver(Settings.Global.getUriFor(
                     Settings.Global.POLICY_CONTROL), false, this,
                     UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED), false, this,
+                    UserHandle.USER_ALL);
             updateSettings();
         }
 
@@ -2309,6 +2326,9 @@
                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR,
                     Settings.Secure.INCALL_BACK_BUTTON_BEHAVIOR_DEFAULT,
                     UserHandle.USER_CURRENT);
+            mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver,
+                    Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED,
+                    0, UserHandle.USER_CURRENT) == 1;
 
             // Configure wake gesture.
             boolean wakeGestureEnabledSetting = Settings.Secure.getIntForUser(resolver,
@@ -6298,7 +6318,7 @@
         if (event.getAction() == KeyEvent.ACTION_UP) {
             if (!mAccessibilityManager.isEnabled()
                     || !mAccessibilityManager.sendFingerprintGesture(event.getKeyCode())) {
-                if (areSystemNavigationKeysEnabled()) {
+                if (mSystemNavigationKeysEnabled) {
                     sendSystemKeyToStatusBarAsync(event.getKeyCode());
                 }
             }
@@ -7466,6 +7486,13 @@
         mHandler.sendEmptyMessage(MSG_HIDE_BOOT_MESSAGE);
     }
 
+    @Override
+    public void requestUserActivityNotification() {
+        if (!mNotifyUserActivity && !mHandler.hasMessages(MSG_NOTIFY_USER_ACTIVITY)) {
+            mNotifyUserActivity = true;
+        }
+    }
+
     /** {@inheritDoc} */
     @Override
     public void userActivity() {
@@ -7487,6 +7514,12 @@
                 mHandler.postDelayed(mScreenLockTimeout, mLockScreenTimeout);
             }
         }
+
+        if (mAwake && mNotifyUserActivity) {
+            mHandler.sendEmptyMessageDelayed(MSG_NOTIFY_USER_ACTIVITY,
+                    USER_ACTIVITY_NOTIFICATION_DELAY);
+            mNotifyUserActivity = false;
+        }
     }
 
     class ScreenLockTimeout implements Runnable {
@@ -7783,11 +7816,6 @@
                 Settings.Global.THEATER_MODE_ON, 0) == 1;
     }
 
-    private boolean areSystemNavigationKeysEnabled() {
-        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1;
-    }
-
     @Override
     public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {
         if (!mVibrator.hasVibrator()) {
diff --git a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
index 0450816..a123304 100644
--- a/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/CarrierIdInstallReceiver.java
@@ -22,7 +22,6 @@
 import android.content.Intent;
 import android.net.Uri;
 import android.provider.Telephony;
-import android.util.Log;
 
 public class CarrierIdInstallReceiver extends ConfigUpdateInstallReceiver {
 
@@ -33,7 +32,7 @@
     @Override
     protected void postInstall(Context context, Intent intent) {
         ContentResolver resolver = context.getContentResolver();
-        resolver.update(Uri.withAppendedPath(Telephony.CarrierIdentification.All.CONTENT_URI,
+        resolver.update(Uri.withAppendedPath(Telephony.CarrierId.All.CONTENT_URI,
                 "update_db"), new ContentValues(), null, null);
     }
 }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 4698d72..4303352 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -301,6 +301,9 @@
     }
 
     private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+        if (!mSurface.isValid()) {
+            throw new IllegalStateException("mSurface does not hold a valid surface.");
+        }
         final SurfaceSession session = new SurfaceSession(mSurface);
 
         // Keep a reference to it such that it doesn't get destroyed when finalized.
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0abc847..671b00b 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -7301,6 +7301,15 @@
         mPolicy.registerShortcutKey(shortcutCode, shortcutKeyReceiver);
     }
 
+    @Override
+    public void requestUserActivityNotification() {
+        if (!checkCallingPermission(android.Manifest.permission.USER_ACTIVITY,
+                "requestUserActivityNotification()")) {
+            throw new SecurityException("Requires USER_ACTIVITY permission");
+        }
+        mPolicy.requestUserActivityNotification();
+    }
+
     void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
         if (seamlesslyRotated == w.mSeamlesslyRotated) {
             return;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
index e097fac..14a9163 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/NetworkLogger.java
@@ -30,6 +30,7 @@
 import android.util.Slog;
 
 import com.android.server.ServiceThread;
+import com.android.server.net.BaseNetdEventCallback;
 
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -50,7 +51,7 @@
     private ServiceThread mHandlerThread;
     private NetworkLoggingHandler mNetworkLoggingHandler;
 
-    private final INetdEventCallback mNetdEventCallback = new INetdEventCallback.Stub() {
+    private final INetdEventCallback mNetdEventCallback = new BaseNetdEventCallback() {
         @Override
         public void onDnsEvent(String hostname, String[] ipAddresses, int ipAddressesCount,
                 long timestamp, int uid) {
diff --git a/services/net/java/android/net/ip/IpClient.java b/services/net/java/android/net/ip/IpClient.java
index 1f370a5..9863370 100644
--- a/services/net/java/android/net/ip/IpClient.java
+++ b/services/net/java/android/net/ip/IpClient.java
@@ -540,6 +540,8 @@
     // TODO: Revert this hack once IpClient and Nat464Xlat work in concert.
     private static final String CLAT_PREFIX = "v4-";
 
+    private static final int IMMEDIATE_FAILURE_DURATION = 0;
+
     private final State mStoppedState = new StoppedState();
     private final State mStoppingState = new StoppingState();
     private final State mStartedState = new StartedState();
@@ -551,6 +553,7 @@
     private final String mClatInterfaceName;
     @VisibleForTesting
     protected final Callback mCallback;
+    private final Dependencies mDependencies;
     private final CountDownLatch mShutdownLatch;
     private final INetworkManagementService mNwService;
     private final NetlinkTracker mNetlinkTracker;
@@ -579,10 +582,23 @@
     private boolean mMulticastFiltering;
     private long mStartTimeMillis;
 
+    public static class Dependencies {
+        public INetworkManagementService getNMS() {
+            return INetworkManagementService.Stub.asInterface(
+                    ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE));
+        }
+
+        public INetd getNetd() {
+            return NetdService.getInstance();
+        }
+
+        public InterfaceParams getInterfaceParams(String ifname) {
+            return InterfaceParams.getByName(ifname);
+        }
+    }
+
     public IpClient(Context context, String ifName, Callback callback) {
-        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
-                NetdService.getInstance());
+        this(context, ifName, callback, new Dependencies());
     }
 
     /**
@@ -591,27 +607,35 @@
      */
     public IpClient(Context context, String ifName, Callback callback,
             INetworkManagementService nwService) {
-        this(context, ifName, callback, nwService, NetdService.getInstance());
+        this(context, ifName, callback, new Dependencies() {
+            @Override
+            public INetworkManagementService getNMS() { return nwService; }
+        });
     }
 
     @VisibleForTesting
-    IpClient(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService, INetd netd) {
+    IpClient(Context context, String ifName, Callback callback, Dependencies deps) {
         super(IpClient.class.getSimpleName() + "." + ifName);
+        Preconditions.checkNotNull(ifName);
+        Preconditions.checkNotNull(callback);
+
         mTag = getName();
 
         mContext = context;
         mInterfaceName = ifName;
         mClatInterfaceName = CLAT_PREFIX + ifName;
         mCallback = new LoggingCallbackWrapper(callback);
+        mDependencies = deps;
         mShutdownLatch = new CountDownLatch(1);
-        mNwService = nwService;
+        mNwService = deps.getNMS();
 
         mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
         mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
         mMsgStateLogger = new MessageHandlingLogger();
 
-        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, netd, mLog);
+        // TODO: Consider creating, constructing, and passing in some kind of
+        // InterfaceController.Dependencies class.
+        mInterfaceCtrl = new InterfaceController(mInterfaceName, mNwService, deps.getNetd(), mLog);
 
         mNetlinkTracker = new NetlinkTracker(
                 mInterfaceName,
@@ -742,11 +766,11 @@
             return;
         }
 
-        mInterfaceParams = InterfaceParams.getByName(mInterfaceName);
+        mInterfaceParams = mDependencies.getInterfaceParams(mInterfaceName);
         if (mInterfaceParams == null) {
             logError("Failed to find InterfaceParams for " + mInterfaceName);
-            // TODO: call doImmediateProvisioningFailure() with an error code
-            // indicating something like "interface not ready".
+            doImmediateProvisioningFailure(IpManagerEvent.ERROR_INTERFACE_NOT_FOUND);
+            return;
         }
 
         mCallback.setNeighborDiscoveryOffload(true);
@@ -930,8 +954,11 @@
     }
 
     private void recordMetric(final int type) {
-        if (mStartTimeMillis <= 0) { Log.wtf(mTag, "Start time undefined!"); }
-        final long duration = SystemClock.elapsedRealtime() - mStartTimeMillis;
+        // We may record error metrics prior to starting.
+        // Map this to IMMEDIATE_FAILURE_DURATION.
+        final long duration = (mStartTimeMillis > 0)
+                ? (SystemClock.elapsedRealtime() - mStartTimeMillis)
+                : IMMEDIATE_FAILURE_DURATION;
         mMetricsLog.log(mInterfaceName, new IpManagerEvent(type, duration));
     }
 
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 3898145..508a43d 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -144,20 +144,7 @@
     }
 
     public IpManager(Context context, String ifName, Callback callback) {
-        this(context, ifName, callback, INetworkManagementService.Stub.asInterface(
-                ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)),
-                NetdService.getInstance());
-    }
-
-    public IpManager(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService) {
-        this(context, ifName, callback, nwService, NetdService.getInstance());
-    }
-
-    @VisibleForTesting
-    public IpManager(Context context, String ifName, Callback callback,
-            INetworkManagementService nwService, INetd netd) {
-        super(context, ifName, callback, nwService, netd);
+        super(context, ifName, callback);
     }
 
     public void startProvisioning(ProvisioningConfiguration req) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index eca27ee..108d2ea 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -670,4 +670,8 @@
     public boolean canDismissBootAnimation() {
         return true;
     }
+
+    @Override
+    public void requestUserActivityNotification() {
+    }
 }
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a79f2c9..1c0e260 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -879,42 +879,76 @@
         /**
          * @hide
          */
-        @IntDef({HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_DEST_NOT_SUPPORTED,
-                HANDOVER_FAILURE_DEST_INVALID_PERM, HANDOVER_FAILURE_DEST_USER_REJECTED,
-                HANDOVER_FAILURE_ONGOING_EMERG_CALL})
+        @IntDef(prefix = { "HANDOVER_" },
+                value = {HANDOVER_FAILURE_DEST_APP_REJECTED, HANDOVER_FAILURE_NOT_SUPPORTED,
+                HANDOVER_FAILURE_USER_REJECTED, HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL,
+                HANDOVER_FAILURE_UNKNOWN})
         @Retention(RetentionPolicy.SOURCE)
         public @interface HandoverFailureErrors {}
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the app
-         * to handover the call rejects handover.
+         * to handover the call to rejects the handover request.
+         * <p>
+         * Will be returned when {@link Call#handoverTo(PhoneAccountHandle, int, Bundle)} is called
+         * and the destination {@link PhoneAccountHandle}'s {@link ConnectionService} returns a
+         * {@code null} {@link Connection} from
+         * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+         * ConnectionRequest)}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
         public static final int HANDOVER_FAILURE_DEST_APP_REJECTED = 1;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there is
-         * an error associated with unsupported handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * is initiated but the source or destination app does not support handover.
+         * <p>
+         * Will be returned when a handover is requested via
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)} and the destination
+         * {@link PhoneAccountHandle} does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.  May also be returned when a handover is
+         * requested at the {@link PhoneAccountHandle} for the current call (i.e. the source call's
+         * {@link Details#getAccountHandle()}) does not declare
+         * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_NOT_SUPPORTED = 2;
+        public static final int HANDOVER_FAILURE_NOT_SUPPORTED = 2;
 
         /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
-         * are some permission errors associated with APIs doing handover.
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when the remote
+         * user rejects the handover request.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_DEST_INVALID_PERM = 3;
-
-        /**
-         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when user
-         * rejects handover.
-         */
-        public static final int HANDOVER_FAILURE_DEST_USER_REJECTED = 4;
+        public static final int HANDOVER_FAILURE_USER_REJECTED = 3;
 
         /**
          * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when there
          * is ongoing emergency call.
+         * <p>
+         * This error code is returned when {@link #handoverTo(PhoneAccountHandle, int, Bundle)} is
+         * called on an emergency call, or if any other call is an emergency call.
+         * <p>
+         * Handovers are not permitted while there are ongoing emergency calls.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
          */
-        public static final int HANDOVER_FAILURE_ONGOING_EMERG_CALL = 5;
+        public static final int HANDOVER_FAILURE_ONGOING_EMERGENCY_CALL = 4;
 
+        /**
+         * Handover failure reason returned via {@link #onHandoverFailed(Call, int)} when a handover
+         * fails for an unknown reason.
+         * <p>
+         * For more information on call handovers, see
+         * {@link #handoverTo(PhoneAccountHandle, int, Bundle)}.
+         */
+        public static final int HANDOVER_FAILURE_UNKNOWN = 5;
 
         /**
          * Invoked when the state of this {@code Call} has changed. See {@link #getState()}.
@@ -1055,6 +1089,10 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has completed successfully.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
          */
         public void onHandoverComplete(Call call) {}
@@ -1062,8 +1100,12 @@
         /**
          * Invoked when Call handover from one {@link PhoneAccount} to other {@link PhoneAccount}
          * has failed.
+         * <p>
+         * For a full discussion of the handover process and the APIs involved, see
+         * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+         *
          * @param call The call which had initiated handover.
-         * @param failureReason Error reason for failure
+         * @param failureReason Error reason for failure.
          */
         public void onHandoverFailed(Call call, @HandoverFailureErrors int failureReason) {}
     }
@@ -1260,7 +1302,7 @@
      * Instructs this {@link #STATE_RINGING} {@code Call} to answer.
      * @param videoState The video state in which to answer the call.
      */
-    public void answer(int videoState) {
+    public void answer(@VideoProfile.VideoState int videoState) {
         mInCallAdapter.answerCall(mTelecomCallId, videoState);
     }
 
@@ -1474,16 +1516,65 @@
      * by {@code toHandle}.  The videoState specified indicates the desired video state after the
      * handover.
      * <p>
-     * A handover request is initiated by the user from one app to indicate a desire
-     * to handover a call to another.
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the device this method is called on is considered the
+     * <em>initiating</em> device (since the user initiates the handover from this device), and the
+     * other device is considered the <em>receiving</em> device.
+     * <p>
+     * When this method is called on the <em>initiating</em> device, the Telecom framework will bind
+     * to the {@link ConnectionService} defined by the {@code toHandle} {@link PhoneAccountHandle}
+     * and invoke
+     * {@link ConnectionService#onCreateOutgoingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform the destination app that a request has been made to handover a
+     * call to it.  The app returns an instance of {@link Connection} to represent the handover call
+     * At this point the app should display UI to indicate to the user that a call
+     * handover is in process.
+     * <p>
+     * The destination app is responsible for communicating the handover request from the
+     * <em>initiating</em> device to the <em>receiving</em> device.
+     * <p>
+     * When the app on the <em>receiving</em> device receives the handover request, it calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to continue the handover
+     * process from the <em>initiating</em> device to the <em>receiving</em> device.  At this point
+     * the destination app on the <em>receiving</em> device should show UI to allow the user to
+     * choose whether they want to continue their call in the destination app.
+     * <p>
+     * When the destination app on the <em>receiving</em> device calls
+     * {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)}, Telecom will bind to its
+     * {@link ConnectionService} and call
+     * {@link ConnectionService#onCreateIncomingHandoverConnection(PhoneAccountHandle,
+     * ConnectionRequest)} to inform it of the handover request.  The app returns an instance of
+     * {@link Connection} to represent the handover call.
+     * <p>
+     * If the user of the <em>receiving</em> device accepts the handover, the app calls
+     * {@link Connection#setActive()} to complete the handover process; Telecom will disconnect the
+     * original call.  If the user rejects the handover, the app calls
+     * {@link Connection#setDisconnected(DisconnectCause)} and specifies a {@link DisconnectCause}
+     * of {@link DisconnectCause#CANCELED} to indicate that the handover has been cancelled.
+     * <p>
+     * Telecom will only allow handovers from {@link PhoneAccount}s which declare
+     * {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_FROM}.  Similarly, the {@link PhoneAccount}
+     * specified by {@code toHandle} must declare {@link PhoneAccount#EXTRA_SUPPORTS_HANDOVER_TO}.
+     * <p>
+     * Errors in the handover process are reported to the {@link InCallService} via
+     * {@link Callback#onHandoverFailed(Call, int)}.  Errors in the handover process are reported to
+     * the involved {@link ConnectionService}s via
+     * {@link ConnectionService#onHandoverFailed(ConnectionRequest, int)}.
      *
      * @param toHandle {@link PhoneAccountHandle} of the {@link ConnectionService} to handover
      *                 this call to.
-     * @param videoState Indicates the video state desired after the handover.
+     * @param videoState Indicates the video state desired after the handover (see the
+     *               {@code STATE_*} constants defined in {@link VideoProfile}).
      * @param extras Bundle containing extra information to be passed to the
      *               {@link ConnectionService}
      */
-    public void handoverTo(PhoneAccountHandle toHandle, int videoState, Bundle extras) {
+    public void handoverTo(PhoneAccountHandle toHandle, @VideoProfile.VideoState int videoState,
+            Bundle extras) {
         mInCallAdapter.handoverTo(mTelecomCallId, toHandle, videoState, extras);
     }
 
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index 593e12b..2fdbc71 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -2218,12 +2218,50 @@
     }
 
     /**
-     * Called by Telecom on the initiating side of the handover to create an instance of a
-     * handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * outgoing handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination {@link ConnectionService} on <em>initiating</em>
+     * device when the user initiates a handover request from one app to another.  The user request
+     * originates in the {@link InCallService} via
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  If your app does not wish to accept a handover to it at this time,
+     * you can return {@code null}.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   if (!isHandoverAvailable()) {
+     *       return null;
+     *   }
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
-     * @param request Details about the call which needs to be handover.
-     * @return Connection object corresponding to the handover call.
+     * @param request Details about the call to handover.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateOutgoingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2231,12 +2269,46 @@
     }
 
     /**
-     * Called by Telecom on the receiving side of the handover to request the
-     * {@link ConnectionService} to create an instance of a handover connection.
+     * Called by Telecom to request that a {@link ConnectionService} creates an instance of an
+     * incoming handover {@link Connection}.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * This method is called on the destination app on the <em>receiving</em> device when the
+     * destination app calls {@link TelecomManager#acceptHandover(Uri, int, PhoneAccountHandle)} to
+     * accept an incoming handover from the <em>initiating</em> device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * Implementations of this method should return an instance of {@link Connection} which
+     * represents the handover.  The code below shows an example of how this is done.
+     * <pre>
+     * {@code
+     * public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle
+     *     fromPhoneAccountHandle, ConnectionRequest request) {
+     *   // Given that your app requested to accept the handover, you should not return null here.
+     *   MyConnection connection = new MyConnection();
+     *   connection.setAddress(request.getAddress(), TelecomManager.PRESENTATION_ALLOWED);
+     *   connection.setVideoState(request.getVideoState());
+     *   return connection;
+     * }
+     * }
+     * </pre>
+     *
      * @param fromPhoneAccountHandle {@link PhoneAccountHandle} associated with the
      *                               ConnectionService which needs to handover the call.
      * @param request Details about the call which needs to be handover.
-     * @return {@link Connection} object corresponding to the handover call.
+     * @return {@link Connection} instance corresponding to the handover call.
      */
     public Connection onCreateIncomingHandoverConnection(PhoneAccountHandle fromPhoneAccountHandle,
                                                          ConnectionRequest request) {
@@ -2246,11 +2318,15 @@
     /**
      * Called by Telecom in response to a {@code TelecomManager#acceptHandover()}
      * invocation which failed.
-     * @param request Details about the call which needs to be handover.
-     * @param error Reason for handover failure as defined in
-     *              {@link android.telecom.Call.Callback#HANDOVER_FAILURE_DEST_INVALID_PERM}
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}
+     *
+     * @param request Details about the call which failed to handover.
+     * @param error Reason for handover failure.  Will be one of the
      */
-    public void onHandoverFailed(ConnectionRequest request, int error) {
+    public void onHandoverFailed(ConnectionRequest request,
+            @Call.Callback.HandoverFailureErrors int error) {
         return;
     }
 
diff --git a/telecomm/java/android/telecom/Logging/EventManager.java b/telecomm/java/android/telecom/Logging/EventManager.java
index 4fc3385..2bda648 100644
--- a/telecomm/java/android/telecom/Logging/EventManager.java
+++ b/telecomm/java/android/telecom/Logging/EventManager.java
@@ -24,21 +24,20 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.IndentingPrintWriter;
 
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.IllegalFormatException;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
-import java.util.TimeZone;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.stream.Collectors;
 
 /**
  * A utility class that provides the ability to define Events that a subsystem deems important, and
@@ -53,7 +52,8 @@
     public static final String TAG = "Logging.Events";
     @VisibleForTesting
     public static final int DEFAULT_EVENTS_TO_CACHE = 10;  // Arbitrarily chosen.
-    private final DateFormat sDateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
+    public static final DateTimeFormatter DATE_TIME_FORMATTER =
+            DateTimeFormatter.ofPattern("HH:mm:ss.SSS");
 
     public interface Loggable {
         /**
@@ -131,11 +131,17 @@
         public String sessionId;
         public long time;
         public Object data;
+        // String storing the date for display. This will be computed at the time/timezone when
+        // the event is recorded.
+        public final String timestampString;
 
         public Event(String eventId, String sessionId, long time, Object data) {
             this.eventId = eventId;
             this.sessionId = sessionId;
             this.time = time;
+            timestampString =
+                    ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault())
+                    .format(DATE_TIME_FORMATTER);
             this.data = data;
         }
     }
@@ -228,7 +234,7 @@
 
             pw.increaseIndent();
             for (Event event : mEvents) {
-                pw.print(sDateFormat.format(new Date(event.time)));
+                pw.print(event.timestampString);
                 pw.print(" - ");
                 pw.print(event.eventId);
                 if (event.data != null) {
@@ -269,7 +275,6 @@
 
     public EventManager(@NonNull SessionManager.ISessionIdQueryHandler l) {
         mSessionIdHandler = l;
-        sDateFormat.setTimeZone(TimeZone.getDefault());
     }
 
     public void event(Loggable recordEntry, String event, Object data) {
@@ -329,15 +334,15 @@
             }
         }
 
-        // Sort by event time.
-        Comparator<Pair<Loggable, Event>> byEventTime = (e1, e2) -> {
-          return Long.compare(e1.second.time, e2.second.time);
-        };
+        // Sort by event time. This might result in out-of-order seeming events if the timezone
+        // changes somewhere in the middle.
+        Comparator<Pair<Loggable, Event>> byEventTime =
+                Comparator.comparingLong(e -> e.second.time);
         events.sort(byEventTime);
 
         pw.increaseIndent();
         for (Pair<Loggable, Event> event : events) {
-            pw.print(sDateFormat.format(new Date(event.second.time)));
+            pw.print(event.second.timestampString);
             pw.print(",");
             pw.print(event.first.getId());
             pw.print(",");
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index 59ce590..bb4b483 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -93,6 +93,10 @@
                     // failure on the providing end, so immediately mark it destroyed
                     connection.setDestroyed();
                 }
+                connection.setStatusHints(parcel.getStatusHints());
+                connection.setIsVoipAudioMode(parcel.getIsVoipAudioMode());
+                connection.setRingbackRequested(parcel.isRingbackRequested());
+                connection.putExtras(parcel.getExtras());
             }
         }
 
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index c848f77..05a3020 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1257,7 +1257,7 @@
      * @hide
      */
     @SystemApi
-    public int getCallState() {
+    public @TelephonyManager.CallState int getCallState() {
         try {
             if (isServiceConnected()) {
                 return getTelecomService().getCallState();
@@ -1786,8 +1786,25 @@
     }
 
     /**
-     * Called from the recipient side of a handover to indicate a desire to accept the handover
-     * of an ongoing call to another {@link ConnectionService} identified by
+     * Called by an app to indicate that it wishes to accept the handover of an ongoing call to a
+     * {@link PhoneAccountHandle} it defines.
+     * <p>
+     * A call handover is the process where an ongoing call is transferred from one app (i.e.
+     * {@link ConnectionService} to another app.  The user could, for example, choose to continue a
+     * mobile network call in a video calling app.  The mobile network call via the Telephony stack
+     * is referred to as the source of the handover, and the video calling app is referred to as the
+     * destination.
+     * <p>
+     * When considering a handover scenario the <em>initiating</em> device is where a user initiated
+     * the handover process (e.g. by calling {@link android.telecom.Call#handoverTo(
+     * PhoneAccountHandle, int, Bundle)}, and the other device is considered the <em>receiving</em>
+     * device.
+     * <p>
+     * For a full discussion of the handover process and the APIs involved, see
+     * {@link android.telecom.Call#handoverTo(PhoneAccountHandle, int, Bundle)}.
+     * <p>
+     * This method is called from the <em>receiving</em> side of a handover to indicate a desire to
+     * accept the handover of an ongoing call to another {@link ConnectionService} identified by
      * {@link PhoneAccountHandle} destAcct. For managed {@link ConnectionService}s, the specified
      * {@link PhoneAccountHandle} must have been registered with {@link #registerPhoneAccount} and
      * the user must have enabled the corresponding {@link PhoneAccount}.  This can be checked using
@@ -1811,7 +1828,8 @@
      * @param videoState Video state after the handover.
      * @param destAcct The {@link PhoneAccountHandle} registered to the calling package.
      */
-    public void acceptHandover(Uri srcAddr, int videoState, PhoneAccountHandle destAcct) {
+    public void acceptHandover(Uri srcAddr, @VideoProfile.VideoState int videoState,
+            PhoneAccountHandle destAcct) {
         try {
             if (isServiceConnected()) {
                 getTelecomService().acceptHandover(srcAddr, videoState, destAcct);
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index e0e3a08..90ed36f 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -62,6 +62,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(
             flag = true,
+            prefix = { "STATE_" },
             value = {STATE_AUDIO_ONLY, STATE_TX_ENABLED, STATE_RX_ENABLED, STATE_BIDIRECTIONAL,
                     STATE_PAUSED})
     public @interface VideoState {}
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java
index 7cd1612..cac9f2b 100644
--- a/telephony/java/android/telephony/AccessNetworkConstants.java
+++ b/telephony/java/android/telephony/AccessNetworkConstants.java
@@ -30,6 +30,9 @@
         public static final int EUTRAN = 3;
         public static final int CDMA2000 = 4;
         public static final int IWLAN = 5;
+
+        /** @hide */
+        private AccessNetworkType() {};
     }
 
     /**
@@ -42,6 +45,9 @@
         public static final int WWAN = 1;
         /** Wireless Local Area Networks (i.e. Wifi) */
         public static final int WLAN = 2;
+
+        /** @hide */
+        private TransportType() {};
     }
 
     /**
@@ -63,6 +69,9 @@
         public static final int BAND_DCS1800 = 12;
         public static final int BAND_PCS1900 = 13;
         public static final int BAND_ER900 = 14;
+
+        /** @hide */
+        private GeranBand() {};
     }
 
     /**
@@ -92,6 +101,9 @@
         /** band 23, 24 are reserved */
         public static final int BAND_25 = 25;
         public static final int BAND_26 = 26;
+
+        /** @hide */
+        private UtranBand() {};
     }
 
     /**
@@ -147,6 +159,9 @@
         public static final int BAND_66 = 66;
         public static final int BAND_68 = 68;
         public static final int BAND_70 = 70;
+
+        /** @hide */
+        private EutranBand() {};
     }
 
     /**
@@ -179,5 +194,11 @@
         public static final int BAND_19 = 20;
         public static final int BAND_20 = 21;
         public static final int BAND_21 = 22;
+
+        /** @hide */
+        private CdmaBands() {};
     }
+
+    /** @hide */
+    private AccessNetworkConstants() {};
 }
diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java
new file mode 100644
index 0000000..5d2c225
--- /dev/null
+++ b/telephony/java/android/telephony/AccessNetworkUtils.java
@@ -0,0 +1,167 @@
+package android.telephony;
+
+import static android.telephony.ServiceState.DUPLEX_MODE_FDD;
+import static android.telephony.ServiceState.DUPLEX_MODE_TDD;
+import static android.telephony.ServiceState.DUPLEX_MODE_UNKNOWN;
+
+import android.telephony.AccessNetworkConstants.EutranBand;
+import android.telephony.ServiceState.DuplexMode;
+
+
+/**
+ * Utilities to map between radio constants.
+ *
+ * @hide
+ */
+public class AccessNetworkUtils {
+
+    // do not instantiate
+    private AccessNetworkUtils() {}
+
+    public static final int INVALID_BAND = -1;
+
+    /**
+     * Gets the duplex mode for the given EUTRAN operating band.
+     *
+     * <p>See 3GPP 36.101 sec 5.5-1 for calculation
+     *
+     * @param band The EUTRAN band number
+     * @return The duplex mode of the given EUTRAN band
+     */
+    @DuplexMode
+    public static int getDuplexModeForEutranBand(int band) {
+        if (band == INVALID_BAND) {
+            return DUPLEX_MODE_UNKNOWN;
+        }
+
+        if (band >= EutranBand.BAND_68) {
+            return DUPLEX_MODE_UNKNOWN;
+        } else if (band >= EutranBand.BAND_65) {
+            return DUPLEX_MODE_FDD;
+        } else if (band >= EutranBand.BAND_47) {
+            return DUPLEX_MODE_UNKNOWN;
+        } else if (band >= EutranBand.BAND_33) {
+            return DUPLEX_MODE_TDD;
+        } else if (band >= EutranBand.BAND_1) {
+            return DUPLEX_MODE_FDD;
+        }
+
+        return DUPLEX_MODE_UNKNOWN;
+    }
+
+    /**
+     * Gets the EUTRAN Operating band for a given downlink EARFCN.
+     *
+     * <p>See 3GPP 36.101 sec 5.7.3-1 for calculation.
+     *
+     * @param earfcn The downlink EARFCN
+     * @return Operating band number, or {@link #INVALID_BAND} if no corresponding band exists
+     */
+    public static int getOperatingBandForEarfcn(int earfcn) {
+        if (earfcn > 67535) {
+            return INVALID_BAND;
+        } else if (earfcn >= 67366) {
+            return INVALID_BAND; // band 67 only for CarrierAgg
+        } else if (earfcn >= 66436) {
+            return EutranBand.BAND_66;
+        } else if (earfcn >= 65536) {
+            return EutranBand.BAND_65;
+        } else if (earfcn > 54339) {
+            return INVALID_BAND;
+        } else if (earfcn >= 46790 /* inferred from the end range of BAND_45 */) {
+            return EutranBand.BAND_46;
+        } else if (earfcn >= 46590) {
+            return EutranBand.BAND_45;
+        } else if (earfcn >= 45590) {
+            return EutranBand.BAND_44;
+        } else if (earfcn >= 43590) {
+            return EutranBand.BAND_43;
+        } else if (earfcn >= 41590) {
+            return EutranBand.BAND_42;
+        } else if (earfcn >= 39650) {
+            return EutranBand.BAND_41;
+        } else if (earfcn >= 38650) {
+            return EutranBand.BAND_40;
+        } else if (earfcn >= 38250) {
+            return EutranBand.BAND_39;
+        } else if (earfcn >= 37750) {
+            return EutranBand.BAND_38;
+        } else if (earfcn >= 37550) {
+            return EutranBand.BAND_37;
+        } else if (earfcn >= 36950) {
+            return EutranBand.BAND_36;
+        } else if (earfcn >= 36350) {
+            return EutranBand.BAND_35;
+        } else if (earfcn >= 36200) {
+            return EutranBand.BAND_34;
+        } else if (earfcn >= 36000) {
+            return EutranBand.BAND_33;
+        } else if (earfcn > 10359) {
+            return INVALID_BAND;
+        } else if (earfcn >= 9920) {
+            return INVALID_BAND; // band 32 only for CarrierAgg
+        } else if (earfcn >= 9870) {
+            return EutranBand.BAND_31;
+        } else if (earfcn >= 9770) {
+            return EutranBand.BAND_30;
+        } else if (earfcn >= 9660) {
+            return INVALID_BAND; // band 29 only for CarrierAgg
+        } else if (earfcn >= 9210) {
+            return EutranBand.BAND_28;
+        } else if (earfcn >= 9040) {
+            return EutranBand.BAND_27;
+        } else if (earfcn >= 8690) {
+            return EutranBand.BAND_26;
+        } else if (earfcn >= 8040) {
+            return EutranBand.BAND_25;
+        } else if (earfcn >= 7700) {
+            return EutranBand.BAND_24;
+        } else if (earfcn >= 7500) {
+            return EutranBand.BAND_23;
+        } else if (earfcn >= 6600) {
+            return EutranBand.BAND_22;
+        } else if (earfcn >= 6450) {
+            return EutranBand.BAND_21;
+        } else if (earfcn >= 6150) {
+            return EutranBand.BAND_20;
+        } else if (earfcn >= 6000) {
+            return EutranBand.BAND_19;
+        } else if (earfcn >= 5850) {
+            return EutranBand.BAND_18;
+        } else if (earfcn >= 5730) {
+            return EutranBand.BAND_17;
+        } else if (earfcn > 5379) {
+            return INVALID_BAND;
+        } else if (earfcn >= 5280) {
+            return EutranBand.BAND_14;
+        } else if (earfcn >= 5180) {
+            return EutranBand.BAND_13;
+        } else if (earfcn >= 5010) {
+            return EutranBand.BAND_12;
+        } else if (earfcn >= 4750) {
+            return EutranBand.BAND_11;
+        } else if (earfcn >= 4150) {
+            return EutranBand.BAND_10;
+        } else if (earfcn >= 3800) {
+            return EutranBand.BAND_9;
+        } else if (earfcn >= 3450) {
+            return EutranBand.BAND_8;
+        } else if (earfcn >= 2750) {
+            return EutranBand.BAND_7;
+        } else if (earfcn >= 2650) {
+            return EutranBand.BAND_6;
+        } else if (earfcn >= 2400) {
+            return EutranBand.BAND_5;
+        } else if (earfcn >= 1950) {
+            return EutranBand.BAND_4;
+        } else if (earfcn >= 1200) {
+            return EutranBand.BAND_3;
+        } else if (earfcn >= 600) {
+            return EutranBand.BAND_2;
+        } else if (earfcn >= 0) {
+            return EutranBand.BAND_1;
+        }
+
+        return INVALID_BAND;
+    }
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index e8b2fa7..fa07777 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -991,8 +991,13 @@
             "wfc_emergency_address_carrier_app_string";
 
     /**
-     * Boolean to decide whether to use #KEY_CARRIER_NAME_STRING from CarrierConfig app.
-     * @hide
+     * Unconditionally override the carrier name string using #KEY_CARRIER_NAME_STRING.
+     *
+     * If true, then the carrier display name will be #KEY_CARRIER_NAME_STRING, unconditionally.
+     *
+     * <p>If false, then the override will be performed conditionally and the
+     * #KEY_CARRIER_NAME_STRING will have the lowest-precedence; it will only be used in the event
+     * that the name string would otherwise be empty, allowing it to serve as a last-resort.
      */
     public static final String KEY_CARRIER_NAME_OVERRIDE_BOOL = "carrier_name_override_bool";
 
@@ -1000,7 +1005,6 @@
      * String to identify carrier name in CarrierConfig app. This string overrides SPN if
      * #KEY_CARRIER_NAME_OVERRIDE_BOOL is true; otherwise, it will be used if its value is provided
      * and SPN is unavailable
-     * @hide
      */
     public static final String KEY_CARRIER_NAME_STRING = "carrier_name_string";
 
@@ -1272,13 +1276,38 @@
 
     /**
      * The duration in seconds that platform call and message blocking is disabled after the user
-     * contacts emergency services. Platform considers values in the range 0 to 604800 (one week) as
-     * valid. See {@link android.provider.BlockedNumberContract#isBlocked(Context, String)}).
+     * contacts emergency services. Platform considers values for below cases:
+     *  1) 0 <= VALUE <= 604800(one week): the value will be used as the duration directly.
+     *  2) VALUE > 604800(one week): will use the default value as duration instead.
+     *  3) VALUE < 0: block will be disabled forever until user re-eanble block manually,
+     *     the suggested value to disable forever is -1.
+     * See {@code android.provider.BlockedNumberContract#notifyEmergencyContact(Context)}
+     * See {@code android.provider.BlockedNumberContract#isBlocked(Context, String)}.
      */
     public static final String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT =
             "duration_blocking_disabled_after_emergency_int";
 
     /**
+     * Determines whether to enable enhanced call blocking feature on the device.
+     * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNREGISTERED
+     * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PRIVATE
+     * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_PAYPHONE
+     * @see SystemContract#ENHANCED_SETTING_KEY_BLOCK_UNKNOWN
+     *
+     * <p>
+     * 1. For Single SIM(SS) device, it can be customized in both carrier_config_mccmnc.xml
+     *    and vendor.xml.
+     * <p>
+     * 2. For Dual SIM(DS) device, it should be customized in vendor.xml, since call blocking
+     *    function is used regardless of SIM.
+     * <p>
+     * If {@code true} enable enhanced call blocking feature on the device, {@code false} otherwise.
+     * @hide
+     */
+    public static final String KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL =
+            "support_enhanced_call_blocking_bool";
+
+    /**
      * For carriers which require an empty flash to be sent before sending the normal 3-way calling
      * flash, the duration in milliseconds of the empty flash to send.  When {@code 0}, no empty
      * flash is sent.
@@ -1569,6 +1598,14 @@
             "notify_international_call_on_wfc_bool";
 
     /**
+     * Flag specifying whether to show an alert dialog for video call charges.
+     * By default this value is {@code false}.
+     * @hide
+     */
+    public static final String KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL =
+            "show_video_call_charges_alert_dialog_bool";
+
+    /**
      * An array containing custom call forwarding number prefixes that will be blocked while the
      * device is reporting that it is roaming. By default, there are no custom call
      * forwarding prefixes and none of these numbers will be filtered. If one or more entries are
@@ -1829,6 +1866,33 @@
     public static final String KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING
             = "carrier_network_service_wwan_package_override_string";
 
+    /**
+     * A list of 4 LTE RSCP thresholds above which a signal level is considered POOR,
+     * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+     *
+     * Note that the min and max thresholds are fixed at -120 and -24, as set in 3GPP TS 27.007
+     * section 8.69.
+     * <p>
+     * See SignalStrength#MAX_WCDMA_RSCP and SignalStrength#MIN_WDCMA_RSCP. Any signal level outside
+     * these boundaries is considered invalid.
+     * @hide
+     */
+    public static final String KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY =
+            "wcdma_rscp_thresholds_int_array";
+
+    /**
+     * The default measurement to use for signal strength reporting. If this is not specified, the
+     * RSSI is used.
+     * <p>
+     * e.g.) To use RSCP by default, set the value to "rscp". The signal strength level will
+     * then be determined by #KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY
+     * <p>
+     * Currently this only supports the value "rscp"
+     * @hide
+     */
+    public static final String KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING =
+            "wcdma_default_signal_strength_measurement_string";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -1997,6 +2061,7 @@
         sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
         sDefaults.putBoolean(KEY_SKIP_CF_FAIL_TO_DISABLE_DIALOG_BOOL, false);
+        sDefaults.putBoolean(KEY_SUPPORT_ENHANCED_CALL_BLOCKING_BOOL, false);
 
         // MMS defaults
         sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
@@ -2102,6 +2167,7 @@
         sDefaults.putBoolean(KEY_DISPLAY_VOICEMAIL_NUMBER_AS_DEFAULT_CALL_FORWARDING_NUMBER_BOOL,
                 false);
         sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
+        sDefaults.putBoolean(KEY_SHOW_VIDEO_CALL_CHARGES_ALERT_DIALOG_BOOL, false);
         sDefaults.putStringArray(KEY_CALL_FORWARDING_BLOCKS_WHILE_ROAMING_STRING_ARRAY,
                 null);
         sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
@@ -2130,6 +2196,14 @@
                         -108, /* SIGNAL_STRENGTH_GOOD */
                         -98,  /* SIGNAL_STRENGTH_GREAT */
                 });
+        sDefaults.putIntArray(KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY,
+                new int[] {
+                        -115,  /* SIGNAL_STRENGTH_POOR */
+                        -105, /* SIGNAL_STRENGTH_MODERATE */
+                        -95, /* SIGNAL_STRENGTH_GOOD */
+                        -85  /* SIGNAL_STRENGTH_GREAT */
+                });
+        sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "");
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java
index e092d52..08f8bb6 100644
--- a/telephony/java/android/telephony/CellIdentity.java
+++ b/telephony/java/android/telephony/CellIdentity.java
@@ -68,6 +68,9 @@
      */
     public static final int TYPE_TDSCDMA        = 5;
 
+    /** @hide */
+    public static final int INVALID_CHANNEL_NUMBER = -1;
+
     // Log tag
     /** @hide */
     protected final String mTag;
@@ -125,6 +128,16 @@
     public @Type int getType() { return mType; }
 
     /**
+     * Returns the channel number of the cell identity.
+     *
+     * @hide
+     * @return The channel number, or {@link #INVALID_CHANNEL_NUMBER} if not implemented
+     */
+    public int getChannelNumber() {
+        return INVALID_CHANNEL_NUMBER;
+    }
+
+    /**
      * Used by child classes for parceling.
      *
      * @hide
diff --git a/telephony/java/android/telephony/CellIdentityCdma.java b/telephony/java/android/telephony/CellIdentityCdma.java
index 2e1d1dc..105ddb0 100644
--- a/telephony/java/android/telephony/CellIdentityCdma.java
+++ b/telephony/java/android/telephony/CellIdentityCdma.java
@@ -103,8 +103,12 @@
         mNetworkId = nid;
         mSystemId = sid;
         mBasestationId = bid;
-        mLongitude = lon;
-        mLatitude = lat;
+        if (!isNullIsland(lat, lon)) {
+            mLongitude = lon;
+            mLatitude = lat;
+        } else {
+            mLongitude = mLatitude = Integer.MAX_VALUE;
+        }
         mAlphaLong = alphal;
         mAlphaShort = alphas;
     }
@@ -119,6 +123,18 @@
     }
 
     /**
+     * Take the latitude and longitude in 1/4 seconds and see if
+     * the reported location is on Null Island.
+     *
+     * @return whether the reported Lat/Long are for Null Island
+     *
+     * @hide
+     */
+    private boolean isNullIsland(int lat, int lon) {
+        return Math.abs(lat) <= 1 && Math.abs(lon) <= 1;
+    }
+
+    /**
      * @return Network Id 0..65535, Integer.MAX_VALUE if unknown
      */
     public int getNetworkId() {
diff --git a/telephony/java/android/telephony/CellIdentityGsm.java b/telephony/java/android/telephony/CellIdentityGsm.java
index f948f81..52944a8 100644
--- a/telephony/java/android/telephony/CellIdentityGsm.java
+++ b/telephony/java/android/telephony/CellIdentityGsm.java
@@ -120,7 +120,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -129,7 +129,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -176,14 +176,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
@@ -203,6 +203,11 @@
         return mAlphaShort;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mArfcn;
+    }
 
     /**
      * @deprecated Primary Scrambling Code is not applicable to GSM.
diff --git a/telephony/java/android/telephony/CellIdentityLte.java b/telephony/java/android/telephony/CellIdentityLte.java
index 5f1f448..37fb075 100644
--- a/telephony/java/android/telephony/CellIdentityLte.java
+++ b/telephony/java/android/telephony/CellIdentityLte.java
@@ -125,7 +125,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -134,7 +134,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -179,14 +179,14 @@
     /**
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
@@ -213,6 +213,12 @@
         return mAlphaShort;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mEarfcn;
+    }
+
     @Override
     public int hashCode() {
         return Objects.hash(mMccStr, mMncStr, mCi, mPci, mTac, mAlphaLong, mAlphaShort);
diff --git a/telephony/java/android/telephony/CellIdentityTdscdma.java b/telephony/java/android/telephony/CellIdentityTdscdma.java
index 001d19f..992545d 100644
--- a/telephony/java/android/telephony/CellIdentityTdscdma.java
+++ b/telephony/java/android/telephony/CellIdentityTdscdma.java
@@ -86,7 +86,7 @@
      * Get Mobile Country Code in string format
      * @return Mobile Country Code in string format, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
@@ -94,7 +94,7 @@
      * Get Mobile Network Code in string format
      * @return Mobile Network Code in string format, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
diff --git a/telephony/java/android/telephony/CellIdentityWcdma.java b/telephony/java/android/telephony/CellIdentityWcdma.java
index 1aa1715..affa0c1 100644
--- a/telephony/java/android/telephony/CellIdentityWcdma.java
+++ b/telephony/java/android/telephony/CellIdentityWcdma.java
@@ -118,7 +118,7 @@
 
     /**
      * @return 3-digit Mobile Country Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMccStr} instead.
+     * @deprecated Use {@link #getMccString} instead.
      */
     @Deprecated
     public int getMcc() {
@@ -127,7 +127,7 @@
 
     /**
      * @return 2 or 3-digit Mobile Network Code, 0..999, Integer.MAX_VALUE if unknown
-     * @deprecated Use {@link #getMncStr} instead.
+     * @deprecated Use {@link #getMncString} instead.
      */
     @Deprecated
     public int getMnc() {
@@ -160,14 +160,14 @@
     /**
      * @return Mobile Country Code in string version, null if unknown
      */
-    public String getMccStr() {
+    public String getMccString() {
         return mMccStr;
     }
 
     /**
      * @return Mobile Network Code in string version, null if unknown
      */
-    public String getMncStr() {
+    public String getMncString() {
         return mMncStr;
     }
 
@@ -206,6 +206,12 @@
         return mUarfcn;
     }
 
+    /** @hide */
+    @Override
+    public int getChannelNumber() {
+        return mUarfcn;
+    }
+
     @Override
     public boolean equals(Object other) {
         if (this == other) {
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index ece1ee3..183f96d 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -41,14 +41,36 @@
         setDefaultValues();
     }
 
-    /** @hide */
+    /**
+     * SignalStrength constructor for input from the HAL.
+     *
+     * Note that values received from the HAL require coersion to be compatible here. All values
+     * reported through IRadio are the negative of the actual values (which results in a positive
+     * input to this method.
+     *
+     * <p>Note that this HAL is inconsistent with UMTS-based radio techs as the value indicating
+     * that a field is unreported is negative, rather than a large(r) positive number.
+     * <p>Also note that to keep the public-facing methods of this class consistent with others,
+     * unreported values are coerced to Integer.MAX_VALUE rather than left as -1, which is
+     * a departure from SignalStrength, which is stuck with the values it currently reports.
+     *
+     * @param cdmaDbm negative of the CDMA signal strength value or -1 if invalid.
+     * @param cdmaEcio negative of the CDMA pilot/noise ratio or -1 if invalid.
+     * @param evdoDbm negative of the EvDO signal strength value or -1 if invalid.
+     * @param evdoEcio negative of the EvDO pilot/noise ratio or -1 if invalid.
+     * @param evdoSnr an SNR value 0..8 or -1 if invalid.
+     * @hide
+     */
     public CellSignalStrengthCdma(int cdmaDbm, int cdmaEcio, int evdoDbm, int evdoEcio,
             int evdoSnr) {
-        mCdmaDbm = cdmaDbm;
-        mCdmaEcio = cdmaEcio;
-        mEvdoDbm = evdoDbm;
-        mEvdoEcio = evdoEcio;
-        mEvdoSnr = evdoSnr;
+        // The values here were lifted from SignalStrength.validateInput()
+        // FIXME: Combine all checking and setting logic between this and SignalStrength.
+        mCdmaDbm = ((cdmaDbm > 0) && (cdmaDbm < 120))  ? -cdmaDbm : Integer.MAX_VALUE;
+        mCdmaEcio = ((cdmaEcio > 0) && (cdmaEcio < 160)) ? -cdmaEcio : Integer.MAX_VALUE;
+
+        mEvdoDbm = ((evdoDbm > 0) && (evdoDbm < 120)) ? -evdoDbm : Integer.MAX_VALUE;
+        mEvdoEcio = ((evdoEcio > 0) && (evdoEcio < 160)) ? -evdoEcio : Integer.MAX_VALUE;
+        mEvdoSnr = ((evdoSnr > 0) && (evdoSnr <= 8)) ? evdoSnr : Integer.MAX_VALUE;
     }
 
     /** @hide */
@@ -303,13 +325,10 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         if (DBG) log("writeToParcel(Parcel, int): " + toString());
-        // Need to multiply CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio by -1
-        // to ensure consistency when reading values written here
-        // unless the value is invalid
-        dest.writeInt(mCdmaDbm * (mCdmaDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mCdmaEcio * (mCdmaEcio != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoDbm * (mEvdoDbm != Integer.MAX_VALUE ? -1 : 1));
-        dest.writeInt(mEvdoEcio * (mEvdoEcio != Integer.MAX_VALUE ? -1 : 1));
+        dest.writeInt(mCdmaDbm);
+        dest.writeInt(mCdmaEcio);
+        dest.writeInt(mEvdoDbm);
+        dest.writeInt(mEvdoEcio);
         dest.writeInt(mEvdoSnr);
     }
 
@@ -322,13 +341,9 @@
         // the parcel as positive values.
         // Need to convert into negative values unless the value is invalid
         mCdmaDbm = in.readInt();
-        if (mCdmaDbm != Integer.MAX_VALUE) mCdmaDbm *= -1;
         mCdmaEcio = in.readInt();
-        if (mCdmaEcio != Integer.MAX_VALUE) mCdmaEcio *= -1;
         mEvdoDbm = in.readInt();
-        if (mEvdoDbm != Integer.MAX_VALUE) mEvdoDbm *= -1;
         mEvdoEcio = in.readInt();
-        if (mEvdoEcio != Integer.MAX_VALUE) mEvdoEcio *= -1;
         mEvdoSnr = in.readInt();
         if (DBG) log("CellSignalStrengthCdma(Parcel): " + toString());
     }
diff --git a/telephony/java/android/telephony/LocationAccessPolicy.java b/telephony/java/android/telephony/LocationAccessPolicy.java
index b362df9..26ffe32 100644
--- a/telephony/java/android/telephony/LocationAccessPolicy.java
+++ b/telephony/java/android/telephony/LocationAccessPolicy.java
@@ -82,8 +82,7 @@
                     .noteOpNoThrow(opCode, uid, pkgName) != AppOpsManager.MODE_ALLOWED) {
                 return false;
             }
-            if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))
-                    && !isLegacyForeground(context, pkgName, uid)) {
+            if (!isLocationModeEnabled(context, UserHandle.getUserId(uid))) {
                 return false;
             }
             // If the user or profile is current, permission is granted.
@@ -101,35 +100,6 @@
                 && locationMode != Settings.Secure.LOCATION_MODE_SENSORS_ONLY;
     }
 
-    private static boolean isLegacyForeground(@NonNull Context context, @NonNull String pkgName,
-            int uid) {
-        long token = Binder.clearCallingIdentity();
-        try {
-            return isLegacyVersion(context, pkgName) && isForegroundApp(context, uid);
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-    }
-
-    private static boolean isLegacyVersion(@NonNull Context context, @NonNull String pkgName) {
-        try {
-            if (context.getPackageManager().getApplicationInfo(pkgName, 0)
-                    .targetSdkVersion <= Build.VERSION_CODES.O) {
-                return true;
-            }
-        } catch (PackageManager.NameNotFoundException e) {
-            // In case of exception, assume known app (more strict checking)
-            // Note: This case will never happen since checkPackage is
-            // called to verify validity before checking app's version.
-        }
-        return false;
-    }
-
-    private static boolean isForegroundApp(@NonNull Context context, int uid) {
-        final ActivityManager am = context.getSystemService(ActivityManager.class);
-        return am.getUidImportance(uid) <= ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
-    }
-
     private static boolean checkInteractAcrossUsersFull(@NonNull Context context) {
         return context.checkCallingOrSelfPermission(
                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index ce1b80c..81a966b 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -131,6 +131,14 @@
      */
     public static final String DEFAULT_TOP_LEVEL_TEMP_DIRECTORY = "androidMbmsTempFileRoot";
 
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {RESULT_SUCCESSFUL, RESULT_CANCELLED, RESULT_EXPIRED, RESULT_IO_ERROR,
+            RESULT_SERVICE_ID_NOT_DEFINED, RESULT_DOWNLOAD_FAILURE, RESULT_OUT_OF_STORAGE,
+            RESULT_FILE_ROOT_UNREACHABLE}, prefix = { "RESULT_" })
+    public @interface DownloadResultCode{}
+
     /**
      * Indicates that the download was successful.
      */
diff --git a/telephony/java/android/telephony/NetworkScan.java b/telephony/java/android/telephony/NetworkScan.java
index a277212..073c313 100644
--- a/telephony/java/android/telephony/NetworkScan.java
+++ b/telephony/java/android/telephony/NetworkScan.java
@@ -29,9 +29,9 @@
 
 /**
  * The caller of
- * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)}
+ * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
  * will receive an instance of {@link NetworkScan}, which contains a callback method
- * {@link #stop()} for stopping the in-progress scan.
+ * {@link #stopScan()} for stopping the in-progress scan.
  */
 public class NetworkScan {
 
@@ -106,16 +106,26 @@
      * Use this method to stop an ongoing scan. When user requests a new scan, a {@link NetworkScan}
      * object will be returned, and the user can stop the scan by calling this method.
      */
-    public void stop() throws RemoteException {
+    public void stopScan() {
+        ITelephony telephony = getITelephony();
+        if (telephony == null) {
+            Rlog.e(TAG, "Failed to get the ITelephony instance.");
+        }
         try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null) {
-                telephony.stopNetworkScan(mSubId, mScanId);
-            } else {
-                throw new RemoteException("Failed to get the ITelephony instance.");
-            }
+            telephony.stopNetworkScan(mSubId, mScanId);
         } catch (RemoteException ex) {
             Rlog.e(TAG, "stopNetworkScan  RemoteException", ex);
+        } catch (RuntimeException ex) {
+            Rlog.e(TAG, "stopNetworkScan  RuntimeException", ex);
+        }
+    }
+
+    /** @deprecated Use {@link #stopScan()} */
+    @Deprecated
+    public void stop() throws RemoteException {
+        try {
+            stopScan();
+        } catch (RuntimeException ex) {
             throw new RemoteException("Failed to stop the network scan with id " + mScanId);
         }
     }
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index 0446925..7db83f6 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -20,6 +20,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.telecom.TelecomManager;
 
 import com.android.internal.telephony.IPhoneStateListener;
 
@@ -61,9 +62,6 @@
     /**
      * Listen for changes to the network signal strength (cellular).
      * {@more}
-     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
-     * READ_PHONE_STATE}
-     * <p>
      *
      * @see #onSignalStrengthChanged
      *
@@ -76,7 +74,8 @@
      * Listen for changes to the message-waiting indicator.
      * {@more}
      * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
-     * READ_PHONE_STATE}
+     * READ_PHONE_STATE} or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
      * <p>
      * Example: The status bar uses this to determine when to display the
      * voicemail icon.
@@ -89,7 +88,9 @@
      * Listen for changes to the call-forwarding indicator.
      * {@more}
      * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE
-     * READ_PHONE_STATE}
+     * READ_PHONE_STATE} or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      * @see #onCallForwardingIndicatorChanged
      */
     public static final int LISTEN_CALL_FORWARDING_INDICATOR                = 0x00000008;
@@ -428,16 +429,21 @@
 
     /**
      * Callback invoked when device call state changes.
+     * <p>
+     * Reports the state of Telephony (mobile) calls on the device.
+     * <p>
+     * Note: The state returned here may differ from that returned by
+     * {@link TelephonyManager#getCallState()}. Receivers of this callback should be aware that
+     * calling {@link TelephonyManager#getCallState()} from within this callback may return a
+     * different state than the callback reports.
+     *
      * @param state call state
      * @param phoneNumber call phone number. If application does not have
-     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission, an empty
-     * string will be passed as an argument.
-     *
-     * @see TelephonyManager#CALL_STATE_IDLE
-     * @see TelephonyManager#CALL_STATE_RINGING
-     * @see TelephonyManager#CALL_STATE_OFFHOOK
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} permission or carrier
+     * privileges (see {@link TelephonyManager#hasCarrierPrivileges}), an empty string will be
+     * passed as an argument.
      */
-    public void onCallStateChanged(int state, String phoneNumber) {
+    public void onCallStateChanged(@TelephonyManager.CallState int state, String phoneNumber) {
         // default implementation empty
     }
 
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index b6be3c5..9c831b9 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -19,6 +19,7 @@
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.TestApi;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -220,7 +221,7 @@
     public static final int ROAMING_TYPE_INTERNATIONAL = 3;
 
     /**
-     * Unknown ID. Could be returned by {@link #getNetworkId()} or {@link #getSystemId()}
+     * Unknown ID. Could be returned by {@link #getCdmaNetworkId()} or {@link #getCdmaSystemId()}
      */
     public static final int UNKNOWN_ID = -1;
 
@@ -470,9 +471,13 @@
      */
     @DuplexMode
     public int getDuplexMode() {
-        // TODO(b/72117602) determine duplex mode from channel number, using 3GPP 36.101 sections
-        // 5.7.3-1 and 5.5-1
-        return DUPLEX_MODE_UNKNOWN;
+        // only support LTE duplex mode
+        if (!isLte(mRilDataRadioTechnology)) {
+            return DUPLEX_MODE_UNKNOWN;
+        }
+
+        int band = AccessNetworkUtils.getOperatingBandForEarfcn(mChannelNumber);
+        return AccessNetworkUtils.getDuplexModeForEutranBand(band);
     }
 
     /**
@@ -890,6 +895,7 @@
             .append(", mDataRegState=").append(mDataRegState)
             .append("(" + rilServiceStateToString(mDataRegState) + ")")
             .append(", mChannelNumber=").append(mChannelNumber)
+            .append(", duplexMode()=").append(getDuplexMode())
             .append(", mCellBandwidths=").append(Arrays.toString(mCellBandwidths))
             .append(", mVoiceRoamingType=").append(getRoamingLogString(mVoiceRoamingType))
             .append(", mDataRoamingType=").append(getRoamingLogString(mDataRoamingType))
@@ -1215,7 +1221,8 @@
     }
 
     /** @hide */
-    public void setSystemAndNetworkId(int systemId, int networkId) {
+    @TestApi
+    public void setCdmaSystemAndNetworkId(int systemId, int networkId) {
         this.mSystemId = systemId;
         this.mNetworkId = networkId;
     }
@@ -1381,7 +1388,7 @@
      * within a wireless system. (Defined in 3GPP2 C.S0023 3.4.8)
      * @return The CDMA NID or {@link #UNKNOWN_ID} if not available.
      */
-    public int getNetworkId() {
+    public int getCdmaNetworkId() {
         return this.mNetworkId;
     }
 
@@ -1390,7 +1397,7 @@
      * system. (Defined in 3GPP2 C.S0023 3.4.8)
      * @return The CDMA SID or {@link #UNKNOWN_ID} if not available.
      */
-    public int getSystemId() {
+    public int getCdmaSystemId() {
         return this.mSystemId;
     }
 
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index e508b19..3feec992 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -25,6 +25,7 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * Contains phone signal strength related information.
@@ -61,6 +62,13 @@
     private static final int MAX_LTE_RSRP = -44;
     private static final int MIN_LTE_RSRP = -140;
 
+    private static final int WCDMA_RSCP_THRESHOLDS_NUM = 4;
+    private static final int MAX_WCDMA_RSCP = -24;
+    private static final int MIN_WCDMA_RSCP = -120;
+
+    /* The type of signal measurement */
+    private static final String MEASUMENT_TYPE_RSCP = "rscp";
+
     /** Parameters reported by the Radio */
     private int mGsmSignalStrength; // Valid values are (0-31, 99) as defined in TS 27.007 8.5
     private int mGsmBitErrorRate;   // bit error rate (0-7, 99) as defined in TS 27.007 8.5
@@ -74,7 +82,10 @@
     private int mLteRsrq;
     private int mLteRssnr;
     private int mLteCqi;
-    private int mTdScdmaRscp;
+    private int mTdScdmaRscp; // Valid values are -24...-120dBm or INVALID if unknown
+    private int mWcdmaSignalStrength;
+    private int mWcdmaRscpAsu;  // the WCDMA RSCP in ASU as reported from the HAL
+    private int mWcdmaRscp;     // the WCDMA RSCP in dBm
 
     /** Parameters from the framework */
     private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
@@ -87,6 +98,13 @@
     // min and max are fixed at MIN_LTE_RSRP (-140) and MAX_LTE_RSRP (-44).
     private int mLteRsrpThresholds[] = new int[LTE_RSRP_THRESHOLDS_NUM];
 
+    // The type of default measurement for determining the display level of WCDMA signal bar.
+    private String mWcdmaDefaultSignalMeasurement;
+
+    // The threshold of WCDMA RSCP for determining the display level of WCDMA signal bar. Note that
+    // the min and max are fixed at MIN_WCDMA_RSCP (-120) and MAX_WCDMA_RSCP (-24).
+    private int mWcdmaRscpThresholds[] = new int[WCDMA_RSCP_THRESHOLDS_NUM];
+
     /**
      * Create a new SignalStrength from a intent notifier Bundle
      *
@@ -136,10 +154,15 @@
         mLteRssnr = INVALID;
         mLteCqi = INVALID;
         mTdScdmaRscp = INVALID;
+        mWcdmaSignalStrength = 99;
+        mWcdmaRscp = INVALID;
+        mWcdmaRscpAsu = 255;
         mLteRsrpBoost = 0;
         mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = false;
+        mWcdmaDefaultSignalMeasurement = "";
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
     }
 
     /**
@@ -152,9 +175,10 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            int tdScdmaRscp,
+            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscpAsu,
             // values Added by config
-            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp) {
+            int lteRsrpBoost, boolean gsmFlag, boolean lteLevelBaseOnRsrp,
+            String wcdmaDefaultMeasurement) {
         mGsmSignalStrength = gsmSignalStrength;
         mGsmBitErrorRate = gsmBitErrorRate;
         mCdmaDbm = cdmaDbm;
@@ -168,15 +192,20 @@
         mLteRssnr = lteRssnr;
         mLteCqi = lteCqi;
         mTdScdmaRscp = INVALID;
+        mWcdmaSignalStrength = wcdmaSignalStrength;
+        mWcdmaRscpAsu = wcdmaRscpAsu;
+        mWcdmaRscp = wcdmaRscpAsu - 120;
         mLteRsrpBoost = lteRsrpBoost;
         mIsGsm = gsmFlag;
         mUseOnlyRsrpForLteLevel = lteLevelBaseOnRsrp;
+        mWcdmaDefaultSignalMeasurement = wcdmaDefaultMeasurement;
         setLteRsrpThresholds(getDefaultLteRsrpThresholds());
+        setWcdmaRscpThresholds(getDefaultWcdmaRscpThresholds());
         if (DBG) log("initialize: " + toString());
     }
 
     /**
-     * Constructor for only values provided by Radio HAL
+     * Constructor for only values provided by Radio HAL V1.0
      *
      * @hide
      */
@@ -187,7 +216,23 @@
             int tdScdmaRscp) {
         this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 0, true, false);
+                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, 99, INVALID, 0, true, false, "");
+    }
+
+    /**
+     * Constructor for only values provided by Radio HAL V1.2
+     *
+     * @hide
+     */
+    public SignalStrength(int gsmSignalStrength, int gsmBitErrorRate,
+            int cdmaDbm, int cdmaEcio,
+            int evdoDbm, int evdoEcio, int evdoSnr,
+            int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            int tdScdmaRscp, int wcdmaSignalStrength, int wcdmaRscp) {
+        this(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, tdScdmaRscp, wcdmaSignalStrength, wcdmaRscp, 0, true,
+                false, "");
     }
 
     /**
@@ -218,10 +263,15 @@
         mLteRssnr = s.mLteRssnr;
         mLteCqi = s.mLteCqi;
         mTdScdmaRscp = s.mTdScdmaRscp;
+        mWcdmaSignalStrength = s.mWcdmaSignalStrength;
+        mWcdmaRscpAsu = s.mWcdmaRscpAsu;
+        mWcdmaRscp = s.mWcdmaRscp;
         mLteRsrpBoost = s.mLteRsrpBoost;
         mIsGsm = s.mIsGsm;
         mUseOnlyRsrpForLteLevel = s.mUseOnlyRsrpForLteLevel;
+        mWcdmaDefaultSignalMeasurement = s.mWcdmaDefaultSignalMeasurement;
         setLteRsrpThresholds(s.mLteRsrpThresholds);
+        setWcdmaRscpThresholds(s.mWcdmaRscpThresholds);
     }
 
     /**
@@ -245,10 +295,15 @@
         mLteRssnr = in.readInt();
         mLteCqi = in.readInt();
         mTdScdmaRscp = in.readInt();
+        mWcdmaSignalStrength = in.readInt();
+        mWcdmaRscpAsu = in.readInt();
+        mWcdmaRscp = in.readInt();
         mLteRsrpBoost = in.readInt();
         mIsGsm = in.readBoolean();
         mUseOnlyRsrpForLteLevel = in.readBoolean();
+        mWcdmaDefaultSignalMeasurement = in.readString();
         in.readIntArray(mLteRsrpThresholds);
+        in.readIntArray(mWcdmaRscpThresholds);
     }
 
     /**
@@ -268,10 +323,15 @@
         out.writeInt(mLteRssnr);
         out.writeInt(mLteCqi);
         out.writeInt(mTdScdmaRscp);
+        out.writeInt(mWcdmaSignalStrength);
+        out.writeInt(mWcdmaRscpAsu);
+        out.writeInt(mWcdmaRscp);
         out.writeInt(mLteRsrpBoost);
         out.writeBoolean(mIsGsm);
         out.writeBoolean(mUseOnlyRsrpForLteLevel);
+        out.writeString(mWcdmaDefaultSignalMeasurement);
         out.writeIntArray(mLteRsrpThresholds);
+        out.writeIntArray(mWcdmaRscpThresholds);
     }
 
     /**
@@ -311,25 +371,34 @@
         if (DBG) log("Signal before validate=" + this);
         // TS 27.007 8.5
         mGsmSignalStrength = mGsmSignalStrength >= 0 ? mGsmSignalStrength : 99;
+        mWcdmaSignalStrength = (mWcdmaSignalStrength >= 0) ? mWcdmaSignalStrength : 99;
+        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
         // BER no change;
 
+        // WCDMA RSCP valid values are -120 through -24 as defined in TS 27.007 8.69
+        // but are reported in ASU which is 0 through 96, so we do the conversion here
+        mWcdmaRscpAsu =
+                ((mWcdmaRscpAsu - 120 >= MIN_WCDMA_RSCP) && (mWcdmaRscpAsu - 120 <= MAX_WCDMA_RSCP))
+                ? mWcdmaRscpAsu : 255;
+        mWcdmaRscp = ((mWcdmaRscp >= MIN_WCDMA_RSCP) && (mWcdmaRscp <= MAX_WCDMA_RSCP))
+                ? mWcdmaRscp : INVALID;
+
         mCdmaDbm = mCdmaDbm > 0 ? -mCdmaDbm : -120;
-        mCdmaEcio = (mCdmaEcio > 0) ? -mCdmaEcio : -160;
+        mCdmaEcio = (mCdmaEcio >= 0) ? -mCdmaEcio : -160;
 
         mEvdoDbm = (mEvdoDbm > 0) ? -mEvdoDbm : -120;
-        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -1;
-        mEvdoSnr = ((mEvdoSnr > 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
+        mEvdoEcio = (mEvdoEcio >= 0) ? -mEvdoEcio : -160;
+        mEvdoSnr = ((mEvdoSnr >= 0) && (mEvdoSnr <= 8)) ? mEvdoSnr : -1;
 
         // TS 36.214 Physical Layer Section 5.1.3, TS 36.331 RRC
-        mLteSignalStrength = (mLteSignalStrength >= 0) ? mLteSignalStrength : 99;
         mLteRsrp = ((-mLteRsrp >= MIN_LTE_RSRP) && (-mLteRsrp <= MAX_LTE_RSRP)) ? -mLteRsrp
                 : SignalStrength.INVALID;
         mLteRsrq = ((mLteRsrq >= 3) && (mLteRsrq <= 20)) ? -mLteRsrq : SignalStrength.INVALID;
         mLteRssnr = ((mLteRssnr >= -200) && (mLteRssnr <= 300)) ? mLteRssnr
                 : SignalStrength.INVALID;
 
-        mTdScdmaRscp = ((mTdScdmaRscp >= 25) && (mTdScdmaRscp <= 120))
-                ? -mTdScdmaRscp : SignalStrength.INVALID;
+        mTdScdmaRscp = ((mTdScdmaRscp >= 0) && (mTdScdmaRscp <= 96))
+                ? (mTdScdmaRscp - 120) : SignalStrength.INVALID;
         // Cqi no change
         if (DBG) log("Signal after validate=" + this);
     }
@@ -367,6 +436,16 @@
     }
 
     /**
+     * @param defaultMeasurement sets the type of WCDMA default signal measurement
+     *
+     * Used by phone to determine default measurement type for calculation WCDMA signal level.
+     * @hide
+     */
+    public void setWcdmaDefaultSignalMeasurement(String defaultMeasurement) {
+        mWcdmaDefaultSignalMeasurement = defaultMeasurement;
+    }
+
+    /**
      * @param lteRsrpBoost - signal strength offset
      *
      * Used by phone to set the lte signal strength offset which will be
@@ -410,6 +489,23 @@
     }
 
     /**
+     * Sets the threshold array for determining the display level of WCDMA signal bar.
+     *
+     * @param wcdmaRscpThresholds int array for determining the display level.
+     *
+     * @hide
+     */
+    public void setWcdmaRscpThresholds(int[] wcdmaRscpThresholds) {
+        if ((wcdmaRscpThresholds == null)
+                || (wcdmaRscpThresholds.length != WCDMA_RSCP_THRESHOLDS_NUM)) {
+            Log.wtf(LOG_TAG, "setWcdmaRscpThresholds - wcdmaRscpThresholds is invalid.");
+            return;
+        }
+        System.arraycopy(wcdmaRscpThresholds, 0, mWcdmaRscpThresholds, 0,
+                WCDMA_RSCP_THRESHOLDS_NUM);
+    }
+
+    /**
      * Get the CDMA RSSI value in dBm
      */
     public int getCdmaDbm() {
@@ -500,6 +596,8 @@
                 asuLevel = getLteAsuLevel();
             } else if (mTdScdmaRscp != SignalStrength.INVALID) {
                 asuLevel = getTdScdmaAsuLevel();
+            } else if (mWcdmaRscp != SignalStrength.INVALID) {
+                asuLevel = getWcdmaAsuLevel();
             } else {
                 asuLevel = getGsmAsuLevel();
             }
@@ -533,7 +631,11 @@
             dBm = getLteDbm();
             if (dBm == INVALID) {
                 if (getTdScdmaLevel() == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                    dBm = getGsmDbm();
+                    if (getWcdmaDbm() == INVALID) {
+                        dBm = getGsmDbm();
+                    } else {
+                        dBm = getWcdmaDbm();
+                    }
                 } else {
                     dBm = getTdScdmaDbm();
                 }
@@ -804,18 +906,19 @@
 
         if (rsrpIconLevel != -1) return rsrpIconLevel;
 
-        /* Valid values are (0-63, 99) as defined in TS 36.331 */
-        if (mLteSignalStrength > 63) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        /* Valid values are (0-31, 99) as defined in TS 27.007 8.5 */
+        if (mLteSignalStrength > 31) rssiIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
         else if (mLteSignalStrength >= 12) rssiIconLevel = SIGNAL_STRENGTH_GREAT;
         else if (mLteSignalStrength >= 8) rssiIconLevel = SIGNAL_STRENGTH_GOOD;
         else if (mLteSignalStrength >= 5) rssiIconLevel = SIGNAL_STRENGTH_MODERATE;
         else if (mLteSignalStrength >= 0) rssiIconLevel = SIGNAL_STRENGTH_POOR;
 
-        if (DBG) log("getLTELevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
+        if (DBG) log("getLteLevel - rssi:" + mLteSignalStrength + " rssiIconLevel:"
                 + rssiIconLevel);
         return rssiIconLevel;
 
     }
+
     /**
      * Get the LTE signal level as an asu value between 0..97, 99 is unknown
      * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
@@ -908,6 +1011,105 @@
         return tdScdmaAsuLevel;
     }
 
+    /**
+     * Gets WCDMA RSCP as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+     *
+     * @hide
+     */
+    public int getWcdmaRscp() {
+        return mWcdmaRscp;
+    }
+
+    /**
+     * Get the WCDMA signal level as an ASU value between 0-96, 255 is unknown
+     *
+     * @hide
+     */
+    public int getWcdmaAsuLevel() {
+        /*
+         * 3GPP 27.007 (Ver 10.3.0) Sec 8.69
+         * 0      -120 dBm or less
+         * 1      -119 dBm
+         * 2...95 -118... -25 dBm
+         * 96     -24 dBm or greater
+         * 255    not known or not detectable
+         */
+        final int wcdmaDbm = getWcdmaDbm();
+        int wcdmaAsuLevel = 255;
+        // validateInput will always give a valid range between -120 to -24 as per ril.h. so RSCP
+        // outside range is already set to INVALID
+        if (wcdmaDbm == SignalStrength.INVALID) wcdmaAsuLevel =  255;
+        else wcdmaAsuLevel = wcdmaDbm + 120;
+        if (DBG) log("Wcdma Asu level: " + wcdmaAsuLevel);
+        return wcdmaAsuLevel;
+    }
+
+    /**
+     * Gets WCDMA signal strength as a dbm value between -120 and -24, as defined in TS 27.007 8.69.
+     *
+     * @hide
+     */
+    public int getWcdmaDbm() {
+        return mWcdmaRscp;
+    }
+
+    /**
+     * Get WCDMA as level 0..4
+     *
+     * @hide
+     */
+    public int getWcdmaLevel() {
+        int level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+
+        if (mWcdmaDefaultSignalMeasurement == null) {
+            Log.wtf(LOG_TAG, "getWcdmaLevel - WCDMA default signal measurement is invalid.");
+            return level;
+        }
+
+        switch (mWcdmaDefaultSignalMeasurement) {
+            case MEASUMENT_TYPE_RSCP:
+                // RSCP valid values are (-120 through -24) as defined in TS 27.007 8.69
+                if (mWcdmaRscp < MIN_WCDMA_RSCP || mWcdmaRscp > MAX_WCDMA_RSCP) {
+                    if (mWcdmaRscp != INVALID) {
+                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSCP: mWcdmaRscp="
+                                + mWcdmaRscp);
+                    }
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[3]) {
+                    level = SIGNAL_STRENGTH_GREAT;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[2]) {
+                    level = SIGNAL_STRENGTH_GOOD;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[1]) {
+                    level = SIGNAL_STRENGTH_MODERATE;
+                } else if (mWcdmaRscp >= mWcdmaRscpThresholds[0]) {
+                    level = SIGNAL_STRENGTH_POOR;
+                }
+                if (DBG) log("getWcdmaLevel=" + level + " WcdmaRscp=" + mWcdmaRscp);
+                break;
+
+            default:
+                // RSSI valid values are (0..31) as defined in TS 27.007 8.5
+                if (mWcdmaSignalStrength < 0 || mWcdmaSignalStrength > 31) {
+                    if (mWcdmaSignalStrength != 99) {
+                        Log.wtf(LOG_TAG, "getWcdmaLevel - invalid WCDMA RSSI: mWcdmaSignalStrength="
+                                + mWcdmaSignalStrength);
+                    }
+                } else if (mWcdmaSignalStrength >= 18) {
+                    level = SIGNAL_STRENGTH_GREAT;
+                } else if (mWcdmaSignalStrength >= 13) {
+                    level = SIGNAL_STRENGTH_GOOD;
+                } else if (mWcdmaSignalStrength >= 8) {
+                    level = SIGNAL_STRENGTH_MODERATE;
+                } else if (mWcdmaSignalStrength >= 3) {
+                    level = SIGNAL_STRENGTH_POOR;
+                }
+                if (DBG) log("getWcdmaLevel=" + level + " WcdmaSignalStrength=" +
+                        mWcdmaSignalStrength);
+                break;
+
+        }
+        return level;
+    }
+
    /**
      * @return hash code
      */
@@ -920,8 +1122,11 @@
                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
-                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (mIsGsm ? 1 : 0)
-                + (mUseOnlyRsrpForLteLevel ? 1 : 0) + (Arrays.hashCode(mLteRsrpThresholds)));
+                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum)
+                + (mWcdmaSignalStrength * primeNum) + (mWcdmaRscpAsu * primeNum)
+                + (mWcdmaRscp * primeNum) + (mIsGsm ? 1 : 0) + (mUseOnlyRsrpForLteLevel ? 1 : 0)
+                + (Objects.hashCode(mWcdmaDefaultSignalMeasurement))
+                + (Arrays.hashCode(mLteRsrpThresholds)) + (Arrays.hashCode(mWcdmaRscpThresholds)));
     }
 
     /**
@@ -955,9 +1160,14 @@
                 && mLteCqi == s.mLteCqi
                 && mLteRsrpBoost == s.mLteRsrpBoost
                 && mTdScdmaRscp == s.mTdScdmaRscp
+                && mWcdmaSignalStrength == s.mWcdmaSignalStrength
+                && mWcdmaRscpAsu == s.mWcdmaRscpAsu
+                && mWcdmaRscp == s.mWcdmaRscp
                 && mIsGsm == s.mIsGsm
                 && mUseOnlyRsrpForLteLevel == s.mUseOnlyRsrpForLteLevel
-                && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds));
+                && Objects.equals(mWcdmaDefaultSignalMeasurement, s.mWcdmaDefaultSignalMeasurement)
+                && Arrays.equals(mLteRsrpThresholds, s.mLteRsrpThresholds)
+                && Arrays.equals(mWcdmaRscpThresholds, s.mWcdmaRscpThresholds));
     }
 
     /**
@@ -980,10 +1190,15 @@
                 + " " + mLteCqi
                 + " " + mLteRsrpBoost
                 + " " + mTdScdmaRscp
+                + " " + mWcdmaSignalStrength
+                + " " + mWcdmaRscpAsu
+                + " " + mWcdmaRscp
                 + " " + (mIsGsm ? "gsm|lte" : "cdma")
                 + " " + (mUseOnlyRsrpForLteLevel ? "use_only_rsrp_for_lte_level" :
                          "use_rsrp_and_rssnr_for_lte_level")
-                + " " + (Arrays.toString(mLteRsrpThresholds)));
+                + " " + mWcdmaDefaultSignalMeasurement
+                + " " + (Arrays.toString(mLteRsrpThresholds))
+                + " " + (Arrays.toString(mWcdmaRscpThresholds)));
     }
 
     /** Returns the signal strength related to GSM. */
@@ -992,7 +1207,10 @@
         if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
             level = getTdScdmaLevel();
             if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
-                level = getGsmLevel();
+                level = getWcdmaLevel();
+                if (level == SIGNAL_STRENGTH_NONE_OR_UNKNOWN) {
+                    level = getGsmLevel();
+                }
             }
         }
         return level;
@@ -1037,12 +1255,20 @@
         mLteCqi = m.getInt("LteCqi");
         mLteRsrpBoost = m.getInt("LteRsrpBoost");
         mTdScdmaRscp = m.getInt("TdScdma");
+        mWcdmaSignalStrength = m.getInt("WcdmaSignalStrength");
+        mWcdmaRscpAsu = m.getInt("WcdmaRscpAsu");
+        mWcdmaRscp = m.getInt("WcdmaRscp");
         mIsGsm = m.getBoolean("IsGsm");
         mUseOnlyRsrpForLteLevel = m.getBoolean("UseOnlyRsrpForLteLevel");
+        mWcdmaDefaultSignalMeasurement = m.getString("WcdmaDefaultSignalMeasurement");
         ArrayList<Integer> lteRsrpThresholds = m.getIntegerArrayList("lteRsrpThresholds");
         for (int i = 0; i < lteRsrpThresholds.size(); i++) {
             mLteRsrpThresholds[i] = lteRsrpThresholds.get(i);
         }
+        ArrayList<Integer> wcdmaRscpThresholds = m.getIntegerArrayList("wcdmaRscpThresholds");
+        for (int i = 0; i < wcdmaRscpThresholds.size(); i++) {
+            mWcdmaRscpThresholds[i] = wcdmaRscpThresholds.get(i);
+        }
     }
 
     /**
@@ -1066,13 +1292,22 @@
         m.putInt("LteCqi", mLteCqi);
         m.putInt("LteRsrpBoost", mLteRsrpBoost);
         m.putInt("TdScdma", mTdScdmaRscp);
+        m.putInt("WcdmaSignalStrength", mWcdmaSignalStrength);
+        m.putInt("WcdmaRscpAsu", mWcdmaRscpAsu);
+        m.putInt("WcdmaRscp", mWcdmaRscp);
         m.putBoolean("IsGsm", mIsGsm);
         m.putBoolean("UseOnlyRsrpForLteLevel", mUseOnlyRsrpForLteLevel);
+        m.putString("WcdmaDefaultSignalMeasurement", mWcdmaDefaultSignalMeasurement);
         ArrayList<Integer> lteRsrpThresholds = new ArrayList<Integer>();
         for (int value : mLteRsrpThresholds) {
             lteRsrpThresholds.add(value);
         }
         m.putIntegerArrayList("lteRsrpThresholds", lteRsrpThresholds);
+        ArrayList<Integer> wcdmaRscpThresholds = new ArrayList<Integer>();
+        for (int value : mWcdmaRscpThresholds) {
+            wcdmaRscpThresholds.add(value);
+        }
+        m.putIntegerArrayList("wcdmaRscpThresholds", wcdmaRscpThresholds);
     }
 
     /**
@@ -1086,6 +1321,16 @@
     }
 
     /**
+     * Gets the default threshold array for determining the display level of WCDMA signal bar.
+     *
+     * @return int array for determining the display level.
+     */
+    private int[] getDefaultWcdmaRscpThresholds() {
+        return CarrierConfigManager.getDefaultConfig().getIntArray(
+                CarrierConfigManager.KEY_WCDMA_RSCP_THRESHOLDS_INT_ARRAY);
+    }
+
+    /**
      * log
      */
     private static void log(String s) {
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d09d426..05b8b57 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -17,9 +17,11 @@
 package android.telephony;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
-import android.annotation.SystemApi;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.content.Context;
 import android.content.Intent;
@@ -47,9 +49,6 @@
 /**
  * SubscriptionManager is the application interface to SubscriptionController
  * and provides information about the current Telephony Subscriptions.
- * <p>
- * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE unless otherwise
- * specified.
  */
 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
 public class SubscriptionManager {
@@ -590,9 +589,15 @@
     /**
      * Get the active SubscriptionInfo with the input subId.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      * @param subId The unique SubscriptionInfo key in database.
      * @return SubscriptionInfo, maybe null if its not active.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public SubscriptionInfo getActiveSubscriptionInfo(int subId) {
         if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId);
         if (!isValidSubscriptionId(subId)) {
@@ -646,9 +651,16 @@
 
     /**
      * Get the active SubscriptionInfo associated with the slotIndex
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}).
+     *
      * @param slotIndex the slot which the subscription is inserted
      * @return SubscriptionInfo, maybe null if its not active
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
         if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
         if (!isValidSlotIndex(slotIndex)) {
@@ -700,6 +712,11 @@
      * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted
      * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible
+     * to the calling app are returned.
+     *
      * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device.
      * <ul>
      * <li>
@@ -716,6 +733,8 @@
      * </li>
      * </ul>
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
         List<SubscriptionInfo> result = null;
 
@@ -858,10 +877,18 @@
     }
 
     /**
+     *
+     * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see
+     * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include
+     * only those subscriptions accessible to the caller.
+     *
      * @return the current number of active subscriptions. There is no guarantee the value
      * returned by this method will be the same as the length of the list returned by
      * {@link #getActiveSubscriptionInfoList}.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getActiveSubscriptionInfoCount() {
         int result = 0;
 
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index cb87d1f..f1653ce 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -3165,8 +3165,8 @@
             values.put(RIL_VOICE_RADIO_TECHNOLOGY, state.getRilVoiceRadioTechnology());
             values.put(RIL_DATA_RADIO_TECHNOLOGY, state.getRilDataRadioTechnology());
             values.put(CSS_INDICATOR, state.getCssIndicator());
-            values.put(NETWORK_ID, state.getNetworkId());
-            values.put(SYSTEM_ID, state.getSystemId());
+            values.put(NETWORK_ID, state.getCdmaNetworkId());
+            values.put(SYSTEM_ID, state.getCdmaSystemId());
             values.put(CDMA_ROAMING_INDICATOR, state.getCdmaRoamingIndicator());
             values.put(CDMA_DEFAULT_ROAMING_INDICATOR, state.getCdmaDefaultRoamingIndicator());
             values.put(CDMA_ERI_ICON_INDEX, state.getCdmaEriIconIndex());
@@ -3296,13 +3296,13 @@
         public static final String CSS_INDICATOR = "css_indicator";
 
         /**
-         * This is the same as {@link ServiceState#getNetworkId()}.
+         * This is the same as {@link ServiceState#getCdmaNetworkId()}.
          * @hide
          */
         public static final String NETWORK_ID = "network_id";
 
         /**
-         * This is the same as {@link ServiceState#getSystemId()}.
+         * This is the same as {@link ServiceState#getCdmaSystemId()}.
          * @hide
          */
         public static final String SYSTEM_ID = "system_id";
@@ -3356,23 +3356,23 @@
      * Contains carrier identification information for the current subscriptions.
      * @see SubscriptionManager#getActiveSubscriptionIdList()
      */
-    public static final class CarrierIdentification implements BaseColumns {
+    public static final class CarrierId implements BaseColumns {
         /**
          * Not instantiable.
          * @hide
          */
-        private CarrierIdentification() {}
+        private CarrierId() {}
 
         /**
          * The {@code content://} style URI for this provider.
          */
-        public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification");
+        public static final Uri CONTENT_URI = Uri.parse("content://carrier_id");
 
         /**
-         * The authority string for the CarrierIdentification Provider
+         * The authority string for the CarrierId Provider
          * @hide
          */
-        public static final String AUTHORITY = "carrier_identification";
+        public static final String AUTHORITY = "carrier_id";
 
 
         /**
@@ -3380,7 +3380,7 @@
          * on the given subscriptionId
          * <p>
          * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the
-         * carrier identity {@link TelephonyManager#getAndroidCarrierIdForSubscription()}
+         * carrier identity {@link TelephonyManager#getSimCarrierId()}
          * 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
@@ -3396,17 +3396,17 @@
 
         /**
          * A user facing carrier name.
-         * @see TelephonyManager#getAndroidCarrierNameForSubscription()
+         * @see TelephonyManager#getSimCarrierIdName()
          * <P>Type: TEXT </P>
          */
-        public static final String NAME = "carrier_name";
+        public static final String CARRIER_NAME = "carrier_name";
 
         /**
          * A unique carrier id
-         * @see TelephonyManager#getAndroidCarrierIdForSubscription()
+         * @see TelephonyManager#getSimCarrierId()
          * <P>Type: INTEGER </P>
          */
-        public static final String CID = "carrier_id";
+        public static final String CARRIER_ID = "carrier_id";
 
         /**
          * Contains mappings between matching rules with carrier id for all carriers.
@@ -3464,7 +3464,7 @@
             /**
              * The {@code content://} URI for this table.
              */
-            public static final Uri CONTENT_URI = Uri.parse("content://carrier_identification/all");
+            public static final Uri CONTENT_URI = Uri.parse("content://carrier_id/all");
         }
     }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9f5907b..f4f2b6c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressAutoDoc;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
@@ -34,6 +35,7 @@
 import android.net.ConnectivityManager;
 import android.net.NetworkStats;
 import android.net.Uri;
+import android.os.AsyncTask;
 import android.os.BatteryStats;
 import android.os.Bundle;
 import android.os.Handler;
@@ -46,12 +48,12 @@
 import android.service.carrier.CarrierIdentifier;
 import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
 import android.telephony.VisualVoicemailService.VisualVoicemailTask;
 import android.telephony.ims.aidl.IImsConfig;
 import android.telephony.ims.aidl.IImsMmTelFeature;
 import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
-import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.util.Log;
 
@@ -73,6 +75,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -108,6 +111,13 @@
             BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY;
 
     /**
+     * The process name of the Phone app as well as many other apps that use this process name, such
+     * as settings and vendor components.
+     * @hide
+     */
+    public static final String PHONE_PROCESS_NAME = "com.android.phone";
+
+    /**
      * The allowed states of Wi-Fi calling.
      *
      * @hide
@@ -1047,7 +1057,7 @@
 
     /**
      * An int extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which indicates
-     * the updated carrier id {@link TelephonyManager#getAndroidCarrierIdForSubscription()} of
+     * the updated carrier id {@link TelephonyManager#getSimCarrierId()} of
      * the current subscription.
      * <p>Will be {@link TelephonyManager#UNKNOWN_CARRIER_ID} if the subscription is unavailable or
      * the carrier cannot be identified.
@@ -1057,7 +1067,7 @@
     /**
      * An string extra used with {@link #ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED} which
      * indicates the updated carrier name of the current subscription.
-     * {@see TelephonyManager#getSubscriptionCarrierName()}
+     * {@see TelephonyManager#getSimCarrierIdName()}
      * <p>Carrier name is a user-facing name of the carrier id {@link #EXTRA_CARRIER_ID},
      * usually the brand name of the subsidiary (e.g. T-Mobile).
      */
@@ -1080,7 +1090,11 @@
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceSoftwareVersion() {
         return getDeviceSoftwareVersion(getSlotIndex());
@@ -1112,10 +1126,14 @@
      * Returns the unique device ID, for example, the IMEI for GSM and the MEID
      * or ESN for CDMA phones. Return null if device ID is not available.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
      * MEID for CDMA.
      */
     @Deprecated
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceId() {
         try {
@@ -1134,12 +1152,16 @@
      * Returns the unique device ID of a subscription, for example, the IMEI for
      * GSM and the MEID for CDMA phones. Return null if device ID is not available.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @param slotIndex of which deviceID is returned
      *
      * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
      * MEID for CDMA.
      */
     @Deprecated
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getDeviceId(int slotIndex) {
         // FIXME this assumes phoneId == slotIndex
@@ -1158,7 +1180,11 @@
     /**
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getImei() {
         return getImei(getSlotIndex());
@@ -1168,8 +1194,12 @@
      * Returns the IMEI (International Mobile Equipment Identity). Return null if IMEI is not
      * available.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @param slotIndex of which IMEI is returned
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getImei(int slotIndex) {
         ITelephony telephony = getITelephony();
@@ -1186,7 +1216,11 @@
 
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMeid() {
         return getMeid(getSlotIndex());
@@ -1195,8 +1229,12 @@
     /**
      * Returns the MEID (Mobile Equipment Identifier). Return null if MEID is not available.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @param slotIndex of which MEID is returned
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getMeid(int slotIndex) {
         ITelephony telephony = getITelephony();
@@ -1213,10 +1251,11 @@
 
     /**
      * Returns the Network Access Identifier (NAI). Return null if NAI is not available.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getNai() {
         return getNaiBySubscriberId(getSubId());
@@ -1717,6 +1756,7 @@
      * @see #createForSubscriptionId(int)
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      */
+    // TODO(b/73136824, b/70041899): Permit carrier-privileged callers as well.
     @WorkerThread
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public PersistableBundle getCarrierConfig() {
@@ -1916,6 +1956,9 @@
      * If this object has been created with {@link #createForSubscriptionId}, applies to the given
      * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @return the network type
      *
      * @see #NETWORK_TYPE_UNKNOWN
@@ -1935,6 +1978,7 @@
      * @see #NETWORK_TYPE_EHRPD
      * @see #NETWORK_TYPE_HSPAP
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getDataNetworkType() {
         return getDataNetworkType(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()));
@@ -1969,7 +2013,11 @@
 
     /**
      * Returns the NETWORK_TYPE_xxxx for voice
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public int getVoiceNetworkType() {
         return getVoiceNetworkType(getSubId());
@@ -2555,7 +2603,11 @@
     /**
      * Returns the serial number of the SIM, if applicable. Return null if it is
      * unavailable.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSimSerialNumber() {
          return getSimSerialNumber(getSubId());
@@ -2680,7 +2732,11 @@
     /**
      * Returns the unique subscriber ID, for example, the IMSI for a GSM phone.
      * Return null if it is unavailable.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getSubscriberId() {
         return getSubscriberId(getSubId());
@@ -2821,7 +2877,11 @@
     /**
      * Returns the Group Identifier Level1 for a GSM phone.
      * Return null if it is unavailable.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getGroupIdLevel1() {
         try {
@@ -2862,9 +2922,15 @@
     /**
      * Returns the phone number string for line 1, for example, the MSISDN
      * for a GSM phone. Return null if it is unavailable.
-     * <p>
-     * The default SMS app can also use this.
+     *
+     * <p>Requires Permission:
+     *     {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE},
+     *     {@link android.Manifest.permission#READ_SMS READ_SMS},
+     *     {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS},
+     *     that the caller is the default SMS app,
+     *     or that the caller has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PHONE_STATE,
             android.Manifest.permission.READ_SMS,
@@ -2919,8 +2985,7 @@
      * change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
      * value.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param alphaTag alpha-tagging of the dailing nubmer
      * @param number The dialing number
@@ -2936,8 +3001,7 @@
      * change the actual MSISDN/MDN. To unset alphatag or number, pass in a null
      * value.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId the subscriber that the alphatag and dialing number belongs to.
      * @param alphaTag alpha-tagging of the dailing nubmer
@@ -3056,7 +3120,11 @@
 
     /**
      * Returns the voice mail number. Return null if it is unavailable.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailNumber() {
         return getVoiceMailNumber(getSubId());
@@ -3117,8 +3185,7 @@
     /**
      * Sets the voice mail number.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param alphaTag The alpha tag to display.
      * @param number The voicemail number.
@@ -3130,8 +3197,7 @@
     /**
      * Sets the voicemail number for the given subscriber.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription id.
      * @param alphaTag The alpha tag to display.
@@ -3152,9 +3218,9 @@
     /**
      * Enables or disables the visual voicemail client for a phone account.
      *
-     * <p>Requires that the calling app is the default dialer, or has carrier privileges, or
-     * has permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+     * {@link #hasCarrierPrivileges}), or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      *
      * @param phoneAccountHandle the phone account to change the client state
      * @param enabled the new state of the client
@@ -3217,11 +3283,15 @@
      * to the TelephonyManager. Returns {@code null} when there is no package responsible for
      * processing visual voicemail for the subscription.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @see #createForSubscriptionId(int)
      * @see #createForPhoneAccountHandle(PhoneAccountHandle)
      * @see VisualVoicemailService
      */
     @Nullable
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVisualVoicemailPackageName() {
         try {
@@ -3410,6 +3480,7 @@
      * Initial SIM activation state, unknown. Not set by any carrier apps.
      * @hide
      */
+    @SystemApi
     public static final int SIM_ACTIVATION_STATE_UNKNOWN = 0;
 
     /**
@@ -3420,12 +3491,14 @@
      * @see #SIM_ACTIVATION_STATE_RESTRICTED
      * @hide
      */
+    @SystemApi
     public static final int SIM_ACTIVATION_STATE_ACTIVATING = 1;
 
     /**
      * Indicate SIM has been successfully activated with full service
      * @hide
      */
+    @SystemApi
     public static final int SIM_ACTIVATION_STATE_ACTIVATED = 2;
 
     /**
@@ -3435,6 +3508,7 @@
      * deactivated sim state and set it back to activated after successfully run activation service.
      * @hide
      */
+    @SystemApi
     public static final int SIM_ACTIVATION_STATE_DEACTIVATED = 3;
 
     /**
@@ -3442,14 +3516,46 @@
      * note this is currently available for data activation state. For example out of byte sim.
      * @hide
      */
+    @SystemApi
     public static final int SIM_ACTIVATION_STATE_RESTRICTED = 4;
 
+    /** @hide */
+    @IntDef({
+            SIM_ACTIVATION_STATE_UNKNOWN,
+            SIM_ACTIVATION_STATE_ACTIVATING,
+            SIM_ACTIVATION_STATE_ACTIVATED,
+            SIM_ACTIVATION_STATE_DEACTIVATED,
+            SIM_ACTIVATION_STATE_RESTRICTED
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface SimActivationState{}
+
+     /**
+      * Sets the voice activation state
+      *
+      * <p>Requires Permission:
+      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+      * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+      *
+      * @param activationState The voice activation state
+      * @see #SIM_ACTIVATION_STATE_UNKNOWN
+      * @see #SIM_ACTIVATION_STATE_ACTIVATING
+      * @see #SIM_ACTIVATION_STATE_ACTIVATED
+      * @see #SIM_ACTIVATION_STATE_DEACTIVATED
+      * @hide
+      */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setVoiceActivationState(@SimActivationState int activationState) {
+        setVoiceActivationState(getSubId(), activationState);
+    }
+
     /**
      * Sets the voice activation state for the given subscriber.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription id.
      * @param activationState The voice activation state of the given subscriber.
@@ -3459,22 +3565,44 @@
      * @see #SIM_ACTIVATION_STATE_DEACTIVATED
      * @hide
      */
-    public void setVoiceActivationState(int subId, int activationState) {
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setVoiceActivationState(int subId, @SimActivationState int activationState) {
         try {
-            ITelephony telephony = getITelephony();
-            if (telephony != null)
-                telephony.setVoiceActivationState(subId, activationState);
-        } catch (RemoteException ex) {
-        } catch (NullPointerException ex) {
-        }
+           ITelephony telephony = getITelephony();
+           if (telephony != null)
+               telephony.setVoiceActivationState(subId, activationState);
+       } catch (RemoteException ex) {
+       } catch (NullPointerException ex) {
+       }
+    }
+
+    /**
+     * Sets the data activation state
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @param activationState The data activation state
+     * @see #SIM_ACTIVATION_STATE_UNKNOWN
+     * @see #SIM_ACTIVATION_STATE_ACTIVATING
+     * @see #SIM_ACTIVATION_STATE_ACTIVATED
+     * @see #SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see #SIM_ACTIVATION_STATE_RESTRICTED
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setDataActivationState(@SimActivationState int activationState) {
+        setDataActivationState(getSubId(), activationState);
     }
 
     /**
      * Sets the data activation state for the given subscriber.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription id.
      * @param activationState The data activation state of the given subscriber.
@@ -3485,7 +3613,8 @@
      * @see #SIM_ACTIVATION_STATE_RESTRICTED
      * @hide
      */
-    public void setDataActivationState(int subId, int activationState) {
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setDataActivationState(int subId, @SimActivationState int activationState) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
@@ -3496,8 +3625,32 @@
     }
 
     /**
+     * Returns the voice activation state
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @return voiceActivationState
+     * @see #SIM_ACTIVATION_STATE_UNKNOWN
+     * @see #SIM_ACTIVATION_STATE_ACTIVATING
+     * @see #SIM_ACTIVATION_STATE_ACTIVATED
+     * @see #SIM_ACTIVATION_STATE_DEACTIVATED
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimActivationState int getVoiceActivationState() {
+        return getVoiceActivationState(getSubId());
+    }
+
+    /**
      * Returns the voice activation state for the given subscriber.
      *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @param subId The subscription id.
      *
      * @return voiceActivationState for the given subscriber
@@ -3507,8 +3660,8 @@
      * @see #SIM_ACTIVATION_STATE_DEACTIVATED
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getVoiceActivationState(int subId) {
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimActivationState int getVoiceActivationState(int subId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
@@ -3520,8 +3673,33 @@
     }
 
     /**
+     * Returns the data activation state
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @return dataActivationState for the given subscriber
+     * @see #SIM_ACTIVATION_STATE_UNKNOWN
+     * @see #SIM_ACTIVATION_STATE_ACTIVATING
+     * @see #SIM_ACTIVATION_STATE_ACTIVATED
+     * @see #SIM_ACTIVATION_STATE_DEACTIVATED
+     * @see #SIM_ACTIVATION_STATE_RESTRICTED
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimActivationState int getDataActivationState() {
+        return getDataActivationState(getSubId());
+    }
+
+    /**
      * Returns the data activation state for the given subscriber.
      *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @param subId The subscription id.
      *
      * @return dataActivationState for the given subscriber
@@ -3532,8 +3710,8 @@
      * @see #SIM_ACTIVATION_STATE_RESTRICTED
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    public int getDataActivationState(int subId) {
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimActivationState int getDataActivationState(int subId) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null)
@@ -3577,7 +3755,11 @@
     /**
      * Retrieves the alphabetic identifier associated with the voice
      * mail number.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String getVoiceMailAlphaTag() {
         return getVoiceMailAlphaTag(getSubId());
@@ -3606,9 +3788,8 @@
     }
 
     /**
-     * Send the special dialer code. The IPC caller must be the current default dialer or has
-     * carrier privileges.
-     * @see #hasCarrierPrivileges
+     * Send the special dialer code. The IPC caller must be the current default dialer or have
+     * carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param inputCode The special dialer code to send
      *
@@ -3699,26 +3880,45 @@
         return IPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));
     }
 
-    /** Device call state: No activity. */
+    /**
+     * Device call state: No activity.
+     */
     public static final int CALL_STATE_IDLE = 0;
-    /** Device call state: Ringing. A new call arrived and is
+    /**
+     * Device call state: Ringing. A new call arrived and is
      *  ringing or waiting. In the latter case, another call is
-     *  already active. */
+     *  already active.
+     */
     public static final int CALL_STATE_RINGING = 1;
-    /** Device call state: Off-hook. At least one call exists
-      * that is dialing, active, or on hold, and no calls are ringing
-      * or waiting. */
+    /**
+     * Device call state: Off-hook. At least one call exists
+     * that is dialing, active, or on hold, and no calls are ringing
+     * or waiting.
+     */
     public static final int CALL_STATE_OFFHOOK = 2;
 
+    /** @hide */
+    @IntDef(prefix = { "CALL_STATE_" }, value = {
+            CALL_STATE_IDLE,
+            CALL_STATE_RINGING,
+            CALL_STATE_OFFHOOK
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CallState{}
+
     /**
-     * Returns one of the following constants that represents the current state of all
-     * phone calls.
+     * Returns the state of all calls on the device.
+     * <p>
+     * This method considers not only calls in the Telephony stack, but also calls via other
+     * {@link android.telecom.ConnectionService} implementations.
+     * <p>
+     * Note: The call state returned via this method may differ from what is reported by
+     * {@link PhoneStateListener#onCallStateChanged(int, String)}, as that callback only considers
+     * Telephony (mobile) calls.
      *
-     * {@link TelephonyManager#CALL_STATE_RINGING}
-     * {@link TelephonyManager#CALL_STATE_OFFHOOK}
-     * {@link TelephonyManager#CALL_STATE_IDLE}
+     * @return the current call state.
      */
-    public int getCallState() {
+    public @CallState int getCallState() {
         try {
             ITelecomService telecom = getTelecomService();
             if (telecom != null) {
@@ -3731,23 +3931,31 @@
     }
 
     /**
-     * Returns a constant indicating the call state (cellular) on the device
-     * for a subscription.
+     * Returns the Telephony call state for calls on a specific subscription.
+     * <p>
+     * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
+     * considers the state of calls from other {@link android.telecom.ConnectionService}
+     * implementations.
      *
-     * @param subId whose call state is returned
+     * @param subId the subscription to check call state for.
      * @hide
      */
-    public int getCallState(int subId) {
+    public @CallState int getCallState(int subId) {
         int phoneId = SubscriptionManager.getPhoneId(subId);
         return getCallStateForSlot(phoneId);
     }
 
     /**
-     * See getCallState.
+     * Returns the Telephony call state for calls on a specific SIM slot.
+     * <p>
+     * Note: This method considers ONLY telephony/mobile calls, where {@link #getCallState()}
+     * considers the state of calls from other {@link android.telecom.ConnectionService}
+     * implementations.
      *
+     * @param slotIndex the SIM slot index to check call state for.
      * @hide
      */
-    public int getCallStateForSlot(int slotIndex) {
+    public @CallState int getCallStateForSlot(int slotIndex) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony == null)
@@ -4136,8 +4344,8 @@
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param AID Application id. See ETSI 102.221 and 101.220.
      * @return an IccOpenLogicalChannelResponse object.
@@ -4154,8 +4362,8 @@
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param AID Application id. See ETSI 102.221 and 101.220.
      * @param p2 P2 parameter (described in ISO 7816-4).
@@ -4171,8 +4379,8 @@
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param AID Application id. See ETSI 102.221 and 101.220.
@@ -4197,8 +4405,8 @@
      * Input parameters equivalent to TS 27.007 AT+CCHC command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param channel is the channel id to be closed as retruned by a successful
      *            iccOpenLogicalChannel.
@@ -4214,8 +4422,8 @@
      * Input parameters equivalent to TS 27.007 AT+CCHC command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param channel is the channel id to be closed as retruned by a successful
@@ -4240,8 +4448,8 @@
      * Input parameters equivalent to TS 27.007 AT+CGLA command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
@@ -4267,8 +4475,8 @@
      * Input parameters equivalent to TS 27.007 AT+CGLA command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param channel is the channel id to be closed as returned by a successful
@@ -4303,8 +4511,8 @@
      * Input parameters equivalent to TS 27.007 AT+CSIM command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param cla Class of the APDU command.
      * @param instruction Instruction of the APDU command.
@@ -4328,8 +4536,8 @@
      * Input parameters equivalent to TS 27.007 AT+CSIM command.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param cla Class of the APDU command.
@@ -4360,8 +4568,8 @@
      * Returns the response APDU for a command APDU sent through SIM_IO.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param fileID
      * @param command
@@ -4380,8 +4588,8 @@
      * Returns the response APDU for a command APDU sent through SIM_IO.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param fileID
@@ -4409,8 +4617,8 @@
      * Send ENVELOPE to the SIM and return the response.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param content String containing SAT/USAT response in hexadecimal
      *                format starting with command tag. See TS 102 223 for
@@ -4427,8 +4635,8 @@
      * Send ENVELOPE to the SIM and return the response.
      *
      * <p>Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param content String containing SAT/USAT response in hexadecimal
@@ -4453,10 +4661,10 @@
     /**
      * Read one of the NV items defined in com.android.internal.telephony.RadioNVItems.
      * Used for device configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param itemID the ID of the item to read.
      * @return the NV item as a String, or null on any failure.
@@ -4479,10 +4687,10 @@
     /**
      * Write one of the NV items defined in com.android.internal.telephony.RadioNVItems.
      * Used for device configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param itemID the ID of the item to read.
      * @param itemValue the value to write, as a String.
@@ -4506,10 +4714,10 @@
     /**
      * Update the CDMA Preferred Roaming List (PRL) in the radio NV storage.
      * Used for device configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param preferredRoamingList byte array containing the new PRL.
      * @return true on success; false on any failure.
@@ -4533,10 +4741,10 @@
      * Perform the specified type of NV config reset. The radio will be taken offline
      * and the device must be rebooted after the operation. Used for device
      * configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param resetType reset type: 1: reload NV reset, 2: erase NV reset, 3: factory NV reset
      * @return true on success; false on any failure.
@@ -4884,8 +5092,8 @@
      * Returns the response of authentication for the default subscription.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires that the calling app has carrier privileges or READ_PRIVILEGED_PHONE_STATE
-     * permission.
+     * <p>Requires Permission: READ_PRIVILEGED_PHONE_STATE or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
      * @param authType the authentication type, {@link #AUTHTYPE_EAP_AKA} or
@@ -4893,9 +5101,10 @@
      * @param data authentication challenge data, base64 encoded.
      * See 3GPP TS 31.102 7.1.2 for more details.
      * @return the response of authentication, or null if not available
-     *
-     * @see #hasCarrierPrivileges
      */
+    // TODO(b/73660190): This should probably require MODIFY_PHONE_STATE, not
+    // READ_PRIVILEGED_PHONE_STATE. It certainly shouldn't reference the permission in Javadoc since
+    // it's not public API.
     public String getIccAuthentication(int appType, int authType, String data) {
         return getIccAuthentication(getSubId(), appType, authType, data);
     }
@@ -4904,7 +5113,7 @@
      * Returns the response of USIM Authentication for specified subId.
      * Returns null if the authentication hasn't been successful
      *
-     * <p>Requires that the calling app has carrier privileges.
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId subscription ID used for authentication
      * @param appType the icc application type, like {@link #APPTYPE_USIM}
@@ -4913,8 +5122,6 @@
      * @param data authentication challenge data, base64 encoded.
      * See 3GPP TS 31.102 7.1.2 for more details.
      * @return the response of authentication, or null if not available
-     *
-     * @see #hasCarrierPrivileges
      * @hide
      */
     public String getIccAuthentication(int subId, int appType, int authType, String data) {
@@ -4935,8 +5142,12 @@
      * Returns an array of Forbidden PLMNs from the USIM App
      * Returns null if the query fails.
      *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
      * @return an array of forbidden PLMNs or null if not available
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public String[] getForbiddenPlmns() {
       return getForbiddenPlmns(getSubId(), APPTYPE_USIM);
@@ -5107,19 +5318,18 @@
     }
 
     /**
-     * Determines if emergency calling is allowed for the MMTEL feature on the slot provided.
-     * @param slotIndex The SIM slot of the MMTEL feature
-     * @return true if emergency calling is allowed, false otherwise.
+     * @return true if the IMS resolver is busy resolving a binding and should not be considered
+     * available, false if the IMS resolver is idle.
      * @hide
      */
-    public boolean isEmergencyMmTelAvailable(int slotIndex) {
+    public boolean isResolvingImsBinding() {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.isEmergencyMmTelAvailable(slotIndex);
+                return telephony.isResolvingImsBinding();
             }
         } catch (RemoteException e) {
-            Rlog.e(TAG, "isEmergencyMmTelAvailable, RemoteException: " + e.getMessage());
+            Rlog.e(TAG, "isResolvingImsBinding, RemoteException: " + e.getMessage());
         }
         return false;
     }
@@ -5142,10 +5352,10 @@
     /**
      * Get the preferred network type.
      * Used for device configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @return the preferred network type, defined in RILConstants.java.
      * @hide
@@ -5165,11 +5375,12 @@
 
     /**
      * Sets the network selection mode to automatic.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setNetworkSelectionModeAutomatic() {
         try {
@@ -5185,15 +5396,14 @@
     }
 
     /**
-     * Perform a radio scan and return the list of avialble networks.
+     * Perform a radio scan and return the list of available networks.
      *
      * The return value is a list of the OperatorInfo of the networks found. Note that this
      * scan can take a long time (sometimes minutes) to happen.
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @hide
      * TODO: Add an overload that takes no args.
@@ -5217,33 +5427,49 @@
      * This method is asynchronous, so the network scan results will be returned by callback.
      * The returned NetworkScan will contain a callback method which can be used to stop the scan.
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param request Contains all the RAT with bands/channels that need to be scanned.
+     * @param executor The executor through which the callback should be invoked. Since the scan
+     *        request may trigger multiple callbacks and they must be invoked in the same order as
+     *        they are received by the platform, the user should provide an executor which executes
+     *        tasks one at a time in serial order. For example AsyncTask.SERIAL_EXECUTOR.
      * @param callback Returns network scan results or errors.
      * @return A NetworkScan obj which contains a callback which can be used to stop the scan.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public NetworkScan requestNetworkScan(
-            NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+            NetworkScanRequest request, Executor executor,
+            TelephonyScanManager.NetworkScanCallback callback) {
         synchronized (this) {
             if (mTelephonyScanManager == null) {
                 mTelephonyScanManager = new TelephonyScanManager();
             }
         }
-        return mTelephonyScanManager.requestNetworkScan(getSubId(), request, callback);
+        return mTelephonyScanManager.requestNetworkScan(getSubId(), request, executor, callback);
+    }
+
+    /**
+     * @deprecated
+     * Use {@link
+     * #requestNetworkScan(NetworkScanRequest, Executor, TelephonyScanManager.NetworkScanCallback)}
+     */
+    @Deprecated
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public NetworkScan requestNetworkScan(
+        NetworkScanRequest request, TelephonyScanManager.NetworkScanCallback callback) {
+        return requestNetworkScan(request, AsyncTask.SERIAL_EXECUTOR, callback);
     }
 
     /**
      * Ask the radio to connect to the input network and change selection mode to manual.
      *
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param operatorNumeric the PLMN ID of the network to select.
      * @param persistSelection whether the selection will persist until reboot. If true, only allows
@@ -5251,6 +5477,7 @@
      * normal network selection next time.
      * @return true on success; false on any failure.
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean setNetworkSelectionModeManual(String operatorNumeric, boolean persistSelection) {
         try {
@@ -5270,10 +5497,10 @@
     /**
      * Set the preferred network type.
      * Used for device configuration by some CDMA operators.
-     * <p>
-     * Requires Permission:
-     *   {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}
-     * Or the calling app has carrier privileges. @see #hasCarrierPrivileges
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId the id of the subscription to set the preferred network type for.
      * @param networkType the preferred network type, defined in RILConstants.java.
@@ -5297,9 +5524,7 @@
     /**
      * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
      *
-     * <p>
-     * Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @return true on success; false on any failure.
      */
@@ -5310,9 +5535,7 @@
     /**
      * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA.
      *
-     * <p>
-     * Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @return true on success; false on any failure.
      * @hide
@@ -5402,8 +5625,7 @@
      * brand value input. To unset the value, the same function should be
      * called with a null brand value.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param brand The brand name to display/set.
      * @return true if the operation was executed correctly.
@@ -5420,8 +5642,7 @@
      * brand value input. To unset the value, the same function should be
      * called with a null brand value.
      *
-     * <p>Requires that the calling app has carrier privileges.
-     * @see #hasCarrierPrivileges
+     * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param subId The subscription to use.
      * @param brand The brand name to display/set.
@@ -6075,15 +6296,15 @@
      * subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
      * <p>Requires Permission:
-     *     {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
-     *     calling app has carrier privileges.
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * @param enable Whether to enable mobile data.
      *
-     * @see #hasCarrierPrivileges
      * @deprecated use {@link #setUserMobileDataEnabled(boolean)} instead.
      */
     @Deprecated
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setDataEnabled(boolean enable) {
         setUserMobileDataEnabled(enable);
@@ -6120,7 +6341,7 @@
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
-     * calling app has carrier privileges.
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      *
      * <p>Note that this does not take into account any data restrictions that may be present on the
      * calling app. Such restrictions may be inspected with
@@ -6128,7 +6349,6 @@
      *
      * @return true if mobile data is enabled.
      *
-     * @see #hasCarrierPrivileges
      * @deprecated use {@link #isUserMobileDataEnabled()} instead.
      */
     @Deprecated
@@ -6858,7 +7078,11 @@
 
     /**
      * Returns the current {@link ServiceState} information.
+     *
+     * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
      */
+    @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
     public ServiceState getServiceState() {
         return getServiceStateForSubscriber(getSubId());
@@ -6904,14 +7128,14 @@
     /**
      * Sets the per-account voicemail ringtone.
      *
-     * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
-     * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+     * {@link #hasCarrierPrivileges}, or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      *
      * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
      * voicemail ringtone.
      * @param uri The URI for the ringtone to play when receiving a voicemail from a specific
      * PhoneAccount.
-     * @see #hasCarrierPrivileges
      *
      * @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
      * instead.
@@ -6949,14 +7173,14 @@
     /**
      * Sets the per-account preference whether vibration is enabled for voicemail notifications.
      *
-     * <p>Requires that the calling app is the default dialer, or has carrier privileges, or has
-     * permission {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
+     * <p>Requires that the calling app is the default dialer, or has carrier privileges (see
+     * {@link #hasCarrierPrivileges}, or has permission
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}.
      *
      * @param phoneAccountHandle The handle for the {@link PhoneAccount} for which to set the
      * voicemail vibration setting.
      * @param enabled Whether to enable or disable vibration for voicemail notifications from a
      * specific PhoneAccount.
-     * @see #hasCarrierPrivileges
      *
      * @deprecated Use {@link android.provider.Settings#ACTION_CHANNEL_NOTIFICATION_SETTINGS}
      * instead.
@@ -6977,8 +7201,8 @@
     /**
      * Returns carrier id of the current subscription.
      * <p>To recognize a carrier (including MVNO) as a first-class identity, Android assigns each
-     * carrier with a canonical integer a.k.a. android carrier id. The Android carrier ID is an
-     * Android platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
+     * carrier with a canonical integer a.k.a. carrier id. The carrier ID is an Android
+     * platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in
      * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a>
      *
      * <p>Apps which have carrier-specific configurations or business logic can use the carrier id
@@ -6987,7 +7211,7 @@
      * @return Carrier id of the current subscription. Return {@link #UNKNOWN_CARRIER_ID} if the
      * subscription is unavailable or the carrier cannot be identified.
      */
-    public int getAndroidCarrierIdForSubscription() {
+    public int getSimCarrierId() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
@@ -7001,18 +7225,18 @@
     }
 
     /**
-     * Returns carrier name of the current subscription.
-     * <p>Carrier name is a user-facing name of carrier id
-     * {@link #getAndroidCarrierIdForSubscription()}, usually the brand name of the subsidiary
+     * Returns carrier id name of the current subscription.
+     * <p>Carrier id name is a user-facing name of carrier id
+     * {@link #getSimCarrierId()}, usually the brand name of the subsidiary
      * (e.g. T-Mobile). Each carrier could configure multiple {@link #getSimOperatorName() SPN} but
      * should have a single carrier name. Carrier name is not a canonical identity,
-     * use {@link #getAndroidCarrierIdForSubscription()} instead.
+     * use {@link #getSimCarrierId()} instead.
      * <p>The returned carrier name is unlocalized.
      *
      * @return Carrier name of the current subscription. Return {@code null} if the subscription is
      * unavailable or the carrier cannot be identified.
      */
-    public CharSequence getAndroidCarrierNameForSubscription() {
+    public CharSequence getSimCarrierIdName() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
@@ -7376,12 +7600,10 @@
      * Otherwise, it applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
      *
      * <p>Requires Permission:
-     *     {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
-     *     calling app has carrier privileges.
+     * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
+     * app has carrier privileges (see {@link #hasCarrierPrivileges}.
      *
      * @param enable Whether to enable mobile data.
-     *
-     * @see #hasCarrierPrivileges
      */
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setUserMobileDataEnabled(boolean enable) {
@@ -7399,15 +7621,13 @@
      * <p>Requires one of the following permissions:
      * {@link android.Manifest.permission#ACCESS_NETWORK_STATE ACCESS_NETWORK_STATE},
      * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}, or that the
-     * calling app has carrier privileges.
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}.
      *
      * <p>Note that this does not take into account any data restrictions that may be present on the
      * calling app. Such restrictions may be inspected with
      * {@link ConnectivityManager#getRestrictBackgroundStatus}.
      *
      * @return true if mobile data is enabled.
-     *
-     * @see #hasCarrierPrivileges
      */
     @RequiresPermission(anyOf = {
             android.Manifest.permission.ACCESS_NETWORK_STATE,
diff --git a/telephony/java/android/telephony/TelephonyScanManager.java b/telephony/java/android/telephony/TelephonyScanManager.java
index c182e34..96ff332 100644
--- a/telephony/java/android/telephony/TelephonyScanManager.java
+++ b/telephony/java/android/telephony/TelephonyScanManager.java
@@ -33,6 +33,7 @@
 import android.util.SparseArray;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.Executor;
 
 import com.android.internal.telephony.ITelephony;
 
@@ -55,8 +56,10 @@
 
     /**
      * The caller of
-     * {@link TelephonyManager#requestNetworkScan(NetworkScanRequest, NetworkScanCallback)} should
-     * implement and provide this callback so that the scan results or errors can be returned.
+     * {@link
+     * TelephonyManager#requestNetworkScan(NetworkScanRequest, Executor, NetworkScanCallback)}
+     * should implement and provide this callback so that the scan results or errors can be
+     * returned.
      */
     public static abstract class NetworkScanCallback {
         /** Returns the scan results to the user, this callback will be called multiple times. */
@@ -83,10 +86,13 @@
 
     private static class NetworkScanInfo {
         private final NetworkScanRequest mRequest;
+        private final Executor mExecutor;
         private final NetworkScanCallback mCallback;
 
-        NetworkScanInfo(NetworkScanRequest request, NetworkScanCallback callback) {
+        NetworkScanInfo(
+                NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
             mRequest = request;
+            mExecutor = executor;
             mCallback = callback;
         }
     }
@@ -112,10 +118,15 @@
                         "Failed to find NetworkScanInfo with id " + message.arg2);
                 }
                 NetworkScanCallback callback = nsi.mCallback;
+                Executor executor = nsi.mExecutor;
                 if (callback == null) {
                     throw new RuntimeException(
                         "Failed to find NetworkScanCallback with id " + message.arg2);
                 }
+                if (executor == null) {
+                    throw new RuntimeException(
+                        "Failed to find Executor with id " + message.arg2);
+                }
 
                 switch (message.what) {
                     case CALLBACK_SCAN_RESULTS:
@@ -126,21 +137,31 @@
                             for (int i = 0; i < parcelables.length; i++) {
                                 ci[i] = (CellInfo) parcelables[i];
                             }
-                            callback.onResults((List<CellInfo>) Arrays.asList(ci));
+                            executor.execute(() ->{
+                                Rlog.d(TAG, "onResults: " + ci.toString());
+                                callback.onResults((List<CellInfo>) Arrays.asList(ci));
+                            });
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onResults", e);
                         }
                         break;
                     case CALLBACK_SCAN_ERROR:
                         try {
-                            callback.onError(message.arg1);
+                            final int errorCode = message.arg1;
+                            executor.execute(() -> {
+                                Rlog.d(TAG, "onError: " + errorCode);
+                                callback.onError(errorCode);
+                            });
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onError", e);
                         }
                         break;
                     case CALLBACK_SCAN_COMPLETE:
                         try {
-                            callback.onComplete();
+                            executor.execute(() -> {
+                                Rlog.d(TAG, "onComplete");
+                                callback.onComplete();
+                            });
                             mScanInfo.remove(message.arg2);
                         } catch (Exception e) {
                             Rlog.e(TAG, "Exception in networkscan callback onComplete", e);
@@ -171,12 +192,12 @@
      * @hide
      */
     public NetworkScan requestNetworkScan(int subId,
-            NetworkScanRequest request, NetworkScanCallback callback) {
+            NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
                 int scanId = telephony.requestNetworkScan(subId, request, mMessenger, new Binder());
-                saveScanInfo(scanId, request, callback);
+                saveScanInfo(scanId, request, executor, callback);
                 return new NetworkScan(scanId, subId);
             }
         } catch (RemoteException ex) {
@@ -187,9 +208,10 @@
         return null;
     }
 
-    private void saveScanInfo(int id, NetworkScanRequest request, NetworkScanCallback callback) {
+    private void saveScanInfo(
+            int id, NetworkScanRequest request, Executor executor, NetworkScanCallback callback) {
         synchronized (mScanInfo) {
-            mScanInfo.put(id, new NetworkScanInfo(request, callback));
+            mScanInfo.put(id, new NetworkScanInfo(request, executor, callback));
         }
     }
 
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index 0c17147..125161d 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -60,6 +60,7 @@
     private final String mCardId;
     private final @CardStateInfo int mCardStateInfo;
     private final int mLogicalSlotIdx;
+    private final boolean mIsExtendedApduSupported;
 
     public static final Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
         @Override
@@ -79,6 +80,7 @@
         mCardId = in.readString();
         mCardStateInfo = in.readInt();
         mLogicalSlotIdx = in.readInt();
+        mIsExtendedApduSupported = in.readByte() != 0;
     }
 
     @Override
@@ -88,6 +90,7 @@
         dest.writeString(mCardId);
         dest.writeInt(mCardStateInfo);
         dest.writeInt(mLogicalSlotIdx);
+        dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
     }
 
     @Override
@@ -96,12 +99,13 @@
     }
 
     public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
-            @CardStateInfo int cardStateInfo, int logicalSlotIdx) {
+            @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported) {
         this.mIsActive = isActive;
         this.mIsEuicc = isEuicc;
         this.mCardId = cardId;
         this.mCardStateInfo = cardStateInfo;
         this.mLogicalSlotIdx = logicalSlotIdx;
+        this.mIsExtendedApduSupported = isExtendedApduSupported;
     }
 
     public boolean getIsActive() {
@@ -125,6 +129,13 @@
         return mLogicalSlotIdx;
     }
 
+    /**
+     * @return {@code true} if this slot supports extended APDU from ATR, {@code false} otherwise.
+     */
+    public boolean getIsExtendedApduSupported() {
+        return mIsExtendedApduSupported;
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
@@ -139,7 +150,8 @@
                 && (mIsEuicc == that.mIsEuicc)
                 && (mCardId == that.mCardId)
                 && (mCardStateInfo == that.mCardStateInfo)
-                && (mLogicalSlotIdx == that.mLogicalSlotIdx);
+                && (mLogicalSlotIdx == that.mLogicalSlotIdx)
+                && (mIsExtendedApduSupported == that.mIsExtendedApduSupported);
     }
 
     @Override
@@ -150,6 +162,7 @@
         result = 31 * result + Objects.hashCode(mCardId);
         result = 31 * result + mCardStateInfo;
         result = 31 * result + mLogicalSlotIdx;
+        result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
         return result;
     }
 
@@ -165,6 +178,8 @@
                 + mCardStateInfo
                 + ", phoneId="
                 + mLogicalSlotIdx
+                + ", mIsExtendedApduSupported="
+                + mIsExtendedApduSupported
                 + ")";
     }
 }
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index 6be7725..cc0d1c6 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -115,6 +115,9 @@
     /** Result code of an unknown error. */
     public static final int RESULT_UNKNOWN_ERROR = -1;
 
+    /** Result code when the eUICC card with the given card Id is not found. */
+    public static final int RESULT_EUICC_NOT_FOUND = -2;
+
     /**
      * Callback to receive the result of an eUICC card API.
      *
diff --git a/telephony/java/android/telephony/ims/ImsService.java b/telephony/java/android/telephony/ims/ImsService.java
index 2748cb5..c008711 100644
--- a/telephony/java/android/telephony/ims/ImsService.java
+++ b/telephony/java/android/telephony/ims/ImsService.java
@@ -161,11 +161,6 @@
         }
 
         @Override
-        public void notifyImsFeatureReady(int slotId, int featureType) {
-            ImsService.this.notifyImsFeatureReady(slotId, featureType);
-        }
-
-        @Override
         public IImsConfig getConfig(int slotId) {
             ImsConfigImplBase c = ImsService.this.getConfig(slotId);
             return c != null ? c.getIImsConfig() : null;
@@ -274,25 +269,6 @@
         }
     }
 
-    private void notifyImsFeatureReady(int slotId, int featureType) {
-        synchronized (mFeaturesBySlot) {
-            // get ImsFeature associated with the slot/feature
-            SparseArray<ImsFeature> features = mFeaturesBySlot.get(slotId);
-            if (features == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No ImsFeatures exist on " +
-                        "slot " + slotId);
-                return;
-            }
-            ImsFeature f = features.get(featureType);
-            if (f == null) {
-                Log.w(LOG_TAG, "Can not notify ImsFeature ready. No feature with type "
-                        + featureType + " exists on slot " + slotId);
-                return;
-            }
-            f.onFeatureReady();
-        }
-    }
-
     /**
      * When called, provide the {@link ImsFeatureConfiguration} that this {@link ImsService}
      * currently supports. This will trigger the framework to set up the {@link ImsFeature}s that
diff --git a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
index 86f8606..c7da681 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl
@@ -36,8 +36,6 @@
     ImsFeatureConfiguration querySupportedImsFeatures();
     // Synchronous call to ensure the ImsService is ready before continuing with feature creation.
     void notifyImsServiceReadyForFeatureCreation();
-    // Synchronous call to ensure the new ImsFeature is ready before using the Feature.
-    void notifyImsFeatureReady(int slotId, int featureType);
     void removeImsFeature(int slotId, int featureType, in IImsFeatureStatusCallback c);
     IImsConfig getConfig(int slotId);
     IImsRegistration getRegistration(int slotId);
diff --git a/telephony/java/android/telephony/ims/feature/MmTelFeature.java b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
index 2fffd36..aaf1a1cf8 100644
--- a/telephony/java/android/telephony/ims/feature/MmTelFeature.java
+++ b/telephony/java/android/telephony/ims/feature/MmTelFeature.java
@@ -139,34 +139,44 @@
 
         @Override
         public int queryCapabilityStatus() throws RemoteException {
-            return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            synchronized (mLock) {
+                return MmTelFeature.this.queryCapabilityStatus().mCapabilities;
+            }
         }
 
         @Override
         public void addCapabilityCallback(IImsCapabilityCallback c) {
+            // no need to lock, structure already handles multithreading.
             MmTelFeature.this.addCapabilityCallback(c);
         }
 
         @Override
         public void removeCapabilityCallback(IImsCapabilityCallback c) {
+            // no need to lock, structure already handles multithreading.
             MmTelFeature.this.removeCapabilityCallback(c);
         }
 
         @Override
         public void changeCapabilitiesConfiguration(CapabilityChangeRequest request,
                 IImsCapabilityCallback c) throws RemoteException {
-            MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            synchronized (mLock) {
+                MmTelFeature.this.requestChangeEnabledCapabilities(request, c);
+            }
         }
 
         @Override
         public void queryCapabilityConfiguration(int capability, int radioTech,
                 IImsCapabilityCallback c) {
-            queryCapabilityConfigurationInternal(capability, radioTech, c);
+            synchronized (mLock) {
+                queryCapabilityConfigurationInternal(capability, radioTech, c);
+            }
         }
 
         @Override
         public void setSmsListener(IImsSmsListener l) throws RemoteException {
-            MmTelFeature.this.setSmsListener(l);
+            synchronized (mLock) {
+                MmTelFeature.this.setSmsListener(l);
+            }
         }
 
         @Override
@@ -575,7 +585,7 @@
      */
     public ImsUtImplBase getUt() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsUtImplBase();
     }
 
     /**
@@ -584,7 +594,7 @@
      */
     public ImsEcbmImplBase getEcbm() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsEcbmImplBase();
     }
 
     /**
@@ -593,7 +603,7 @@
      */
     public ImsMultiEndpointImplBase getMultiEndpoint() {
         // Base Implementation - Should be overridden
-        return null;
+        return new ImsMultiEndpointImplBase();
     }
 
     /**
diff --git a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
index 98b67c3..2f52c0a 100644
--- a/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
+++ b/telephony/java/android/telephony/ims/stub/ImsFeatureConfiguration.java
@@ -21,6 +21,7 @@
 import android.os.Parcelable;
 import android.telephony.ims.feature.ImsFeature;
 import android.util.ArraySet;
+import android.util.Pair;
 
 import java.util.Set;
 
@@ -34,14 +35,57 @@
  */
 @SystemApi
 public final class ImsFeatureConfiguration implements Parcelable {
+
+    public static final class FeatureSlotPair {
+        /**
+         * SIM slot that this feature is associated with.
+         */
+        public final int slotId;
+        /**
+         * The feature that this slotId supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
+         */
+        public final @ImsFeature.FeatureType int featureType;
+
+        /**
+         * A mapping from slotId to IMS Feature type.
+         * @param slotId the SIM slot ID associated with this feature.
+         * @param featureType The feature that this slotId supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
+         */
+        public FeatureSlotPair(int slotId, @ImsFeature.FeatureType int featureType) {
+            this.slotId = slotId;
+            this.featureType = featureType;
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+
+            FeatureSlotPair that = (FeatureSlotPair) o;
+
+            if (slotId != that.slotId) return false;
+            return featureType == that.featureType;
+        }
+
+        @Override
+        public int hashCode() {
+            int result = slotId;
+            result = 31 * result + featureType;
+            return result;
+        }
+    }
+
     /**
      * Features that this ImsService supports.
      */
-    private final Set<Integer> mFeatures;
+    private final Set<FeatureSlotPair> mFeatures;
 
     /**
-     * Builder for {@link ImsFeatureConfiguration} that makes adding supported {@link ImsFeature}s
-     * easier.
+     * Builder for {@link ImsFeatureConfiguration}.
      */
     public static class Builder {
             ImsFeatureConfiguration mConfig;
@@ -50,12 +94,15 @@
         }
 
         /**
-         * @param feature A feature defined in {@link ImsFeature.FeatureType} that this service
-         *         supports.
+         * Adds an IMS feature associated with a SIM slot ID.
+         * @param slotId The slot ID associated with the IMS feature.
+         * @param featureType The feature that the slot ID supports. Supported values are
+         * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
+         * {@link ImsFeature#FEATURE_RCS}.
          * @return a {@link Builder} to continue constructing the ImsFeatureConfiguration.
          */
-        public Builder addFeature(@ImsFeature.FeatureType int feature) {
-            mConfig.addFeature(feature);
+        public Builder addFeature(int slotId, @ImsFeature.FeatureType int featureType) {
+            mConfig.addFeature(slotId, featureType);
             return this;
         }
 
@@ -66,8 +113,7 @@
 
     /**
      * Creates with all registration features empty.
-     *
-     * Consider using the provided {@link Builder} to create this configuration instead.
+     * @hide
      */
     public ImsFeatureConfiguration() {
         mFeatures = new ArraySet<>();
@@ -76,45 +122,41 @@
     /**
      * Configuration of the ImsService, which describes which features the ImsService supports
      * (for registration).
-     * @param features an array of feature integers defined in {@link ImsFeature} that describe
-     * which features this ImsService supports. Supported values are
-     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
-     * {@link ImsFeature#FEATURE_RCS}.
+     * @param features a set of {@link FeatureSlotPair}s that describe which features this
+     *         ImsService supports.
      * @hide
      */
-    public ImsFeatureConfiguration(int[] features) {
+    public ImsFeatureConfiguration(Set<FeatureSlotPair> features) {
         mFeatures = new ArraySet<>();
 
         if (features != null) {
-            for (int i : features) {
-                mFeatures.add(i);
-            }
+            mFeatures.addAll(features);
         }
     }
 
     /**
-     * @return an int[] containing the features that this ImsService supports. Supported values are
-     * {@link ImsFeature#FEATURE_EMERGENCY_MMTEL}, {@link ImsFeature#FEATURE_MMTEL}, and
-     * {@link ImsFeature#FEATURE_RCS}.
+     * @return a set of supported slot ID to feature type pairs contained within a
+     * {@link FeatureSlotPair}.
      */
-    public int[] getServiceFeatures() {
-        return mFeatures.stream().mapToInt(i->i).toArray();
+    public Set<FeatureSlotPair> getServiceFeatures() {
+        return new ArraySet<>(mFeatures);
     }
 
-    void addFeature(int feature) {
-        mFeatures.add(feature);
+    /**
+     * @hide
+     */
+    void addFeature(int slotId, int feature) {
+        mFeatures.add(new FeatureSlotPair(slotId, feature));
     }
 
     /** @hide */
     protected ImsFeatureConfiguration(Parcel in) {
-        int[] features = in.createIntArray();
-        if (features != null) {
-            mFeatures = new ArraySet<>(features.length);
-            for(Integer i : features) {
-                mFeatures.add(i);
-            }
-        } else {
-            mFeatures = new ArraySet<>();
+        int featurePairLength = in.readInt();
+        // length
+        mFeatures = new ArraySet<>(featurePairLength);
+        for (int i = 0; i < featurePairLength; i++) {
+            // pair of reads for each entry (slotId->featureType)
+            mFeatures.add(new FeatureSlotPair(in.readInt(), in.readInt()));
         }
     }
 
@@ -138,7 +180,15 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeIntArray(mFeatures.stream().mapToInt(i->i).toArray());
+        FeatureSlotPair[] featureSlotPairs = new FeatureSlotPair[mFeatures.size()];
+        mFeatures.toArray(featureSlotPairs);
+        // length of list
+        dest.writeInt(featureSlotPairs.length);
+        // then pairs of integers for each entry (slotId->featureType).
+        for (FeatureSlotPair featureSlotPair : featureSlotPairs) {
+            dest.writeInt(featureSlotPair.slotId);
+            dest.writeInt(featureSlotPair.featureType);
+        }
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a941a56..1ace032 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -623,12 +623,6 @@
     void setCellInfoListRate(int rateInMillis);
 
     /**
-     * get default sim
-     * @return sim id
-     */
-    int getDefaultSim();
-
-    /**
      * Opens a logical channel to the ICC card.
      *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
@@ -823,10 +817,10 @@
     IImsConfig getImsConfig(int slotId, int feature);
 
     /**
-    * Returns true if emergency calling is available for the MMTEL feature associated with the
-    * slot specified.
-    */
-    boolean isEmergencyMmTelAvailable(int slotId);
+     * @return true if the IMS resolver is busy resolving a binding and should not be considered
+     * available, false if the IMS resolver is idle.
+     */
+    boolean isResolvingImsBinding();
 
     /**
      * Set the network selection mode to automatic.
@@ -1358,10 +1352,10 @@
 
     /**
      * Returns carrier name of the given subscription.
-     * <p>Carrier name is a user-facing name of carrier id {@link #getSubscriptionCarrierId(int)},
+     * <p>Carrier name is a user-facing name of carrier id {@link #getSimCarrierId(int)},
      * usually the brand name of the subsidiary (e.g. T-Mobile). Each carrier could configure
      * multiple {@link #getSimOperatorName() SPN} but should have a single carrier name.
-     * Carrier name is not canonical identity, use {@link #getSubscriptionCarrierId(int)} instead.
+     * Carrier name is not canonical identity, use {@link #getSimCarrierId(int)} instead.
      * <p>Returned carrier name is unlocalized.
      *
      * @return Carrier name of given subscription id. return {@code null} if subscription is
diff --git a/telephony/java/com/android/internal/telephony/RILConstants.java b/telephony/java/com/android/internal/telephony/RILConstants.java
index a3a3080..ee7084a 100644
--- a/telephony/java/com/android/internal/telephony/RILConstants.java
+++ b/telephony/java/com/android/internal/telephony/RILConstants.java
@@ -25,6 +25,7 @@
  */
 
 import android.os.SystemProperties;
+import android.telephony.TelephonyManager;
 
 /**
  * {@hide}
@@ -162,8 +163,8 @@
     int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA   = 20; /* TD-SCDMA, GSM/WCDMA and LTE */
     int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA  = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/
     int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */
-    int PREFERRED_NETWORK_MODE      = SystemProperties.getInt("ro.telephony.default_network",
-            NETWORK_MODE_WCDMA_PREF);
+    int PREFERRED_NETWORK_MODE = Integer.parseInt(TelephonyManager.getTelephonyProperty(0,
+            "ro.telephony.default_network", Integer.toString(NETWORK_MODE_WCDMA_PREF)));
 
     int BAND_MODE_UNSPECIFIED = 0;      //"unspecified" (selected by baseband automatically)
     int BAND_MODE_EURO = 1;             //"EURO band" (GSM-900 / DCS-1800 / WCDMA-IMT-2000)
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index da8471f..a182f2b 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -26,7 +26,8 @@
 import android.telephony.TelephonyManager;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.ITelephony;
+
+import java.util.function.Supplier;
 
 /** Utility class for Telephony permission enforcement. */
 public final class TelephonyPermissions {
@@ -34,6 +35,9 @@
 
     private static final boolean DBG = false;
 
+    private static final Supplier<ITelephony> TELEPHONY_SUPPLIER = () ->
+            ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+
     private TelephonyPermissions() {}
 
     /**
@@ -41,8 +45,8 @@
      *
      * <p>This method behaves in one of the following ways:
      * <ul>
-     *   <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
-     *       READ_PHONE_STATE runtime permission.
+     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+     *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
      *   <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
      *       apps which support runtime permissions, if the caller does not currently have any of
      *       these permissions.
@@ -51,20 +55,30 @@
      *       manually (via AppOps). In this case we can't throw as it would break app compatibility,
      *       so we return false to indicate that the calling function should return dummy data.
      * </ul>
+     *
+     * <p>Note: for simplicity, this method always returns false for callers using legacy
+     * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+     * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+     * devices.
+     *
+     * @param subId the subId of the relevant subscription; used to check carrier privileges. May be
+     *              {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} to skip this check for cases
+     *              where it isn't relevant (hidden APIs, or APIs which are otherwise okay to leave
+     *              inaccesible to carrier-privileged apps).
      */
     public static boolean checkCallingOrSelfReadPhoneState(
-            Context context, String callingPackage, String message) {
-        return checkReadPhoneState(context, Binder.getCallingPid(), Binder.getCallingUid(),
+            Context context, int subId, String callingPackage, String message) {
+        return checkReadPhoneState(context, subId, Binder.getCallingPid(), Binder.getCallingUid(),
                 callingPackage, message);
     }
 
     /**
      * Check whether the app with the given pid/uid can read phone state.
      *
-     * <p>This method behaves in one of the following ways:
+    * <p>This method behaves in one of the following ways:
      * <ul>
-     *   <li>return true: if the caller has either the READ_PRIVILEGED_PHONE_STATE permission or the
-     *       READ_PHONE_STATE runtime permission.
+     *   <li>return true: if the caller has the READ_PRIVILEGED_PHONE_STATE permission, the
+     *       READ_PHONE_STATE runtime permission, or carrier privileges on the given subId.
      *   <li>throw SecurityException: if the caller didn't declare any of these permissions, or, for
      *       apps which support runtime permissions, if the caller does not currently have any of
      *       these permissions.
@@ -73,9 +87,22 @@
      *       manually (via AppOps). In this case we can't throw as it would break app compatibility,
      *       so we return false to indicate that the calling function should return dummy data.
      * </ul>
+     *
+     * <p>Note: for simplicity, this method always returns false for callers using legacy
+     * permissions and who have had READ_PHONE_STATE revoked, even if they are carrier-privileged.
+     * Such apps should migrate to runtime permissions or stop requiring READ_PHONE_STATE on P+
+     * devices.
      */
     public static boolean checkReadPhoneState(
-            Context context, int pid, int uid, String callingPackage, String message) {
+            Context context, int subId, int pid, int uid, String callingPackage, String message) {
+        return checkReadPhoneState(
+                context, TELEPHONY_SUPPLIER, subId, pid, uid, callingPackage, message);
+    }
+
+    @VisibleForTesting
+    public static boolean checkReadPhoneState(
+            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+            String callingPackage, String message) {
         try {
             context.enforcePermission(
                     android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, pid, uid, message);
@@ -83,8 +110,18 @@
             // SKIP checking for run-time permission since caller has PRIVILEGED permission
             return true;
         } catch (SecurityException privilegedPhoneStateException) {
-            context.enforcePermission(
-                    android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+            try {
+                context.enforcePermission(
+                        android.Manifest.permission.READ_PHONE_STATE, pid, uid, message);
+            } catch (SecurityException phoneStateException) {
+                // If we don't have the runtime permission, but do have carrier privileges, that
+                // suffices for reading phone state.
+                if (SubscriptionManager.isValidSubscriptionId(subId)) {
+                    enforceCarrierPrivilege(telephonySupplier, subId, uid, message);
+                    return true;
+                }
+                throw phoneStateException;
+            }
         }
 
         // We have READ_PHONE_STATE permission, so return true as long as the AppOps bit hasn't been
@@ -101,14 +138,16 @@
      * default SMS app and apps with READ_SMS or READ_PHONE_NUMBERS can also read phone numbers.
      */
     public static boolean checkCallingOrSelfReadPhoneNumber(
-            Context context, String callingPackage, String message) {
+            Context context, int subId, String callingPackage, String message) {
         return checkReadPhoneNumber(
-                context, Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, message);
+                context, TELEPHONY_SUPPLIER, subId, Binder.getCallingPid(), Binder.getCallingUid(),
+                callingPackage, message);
     }
 
     @VisibleForTesting
     public static boolean checkReadPhoneNumber(
-            Context context, int pid, int uid, String callingPackage, String message) {
+            Context context, Supplier<ITelephony> telephonySupplier, int subId, int pid, int uid,
+            String callingPackage, String message) {
         // Default SMS app can always read it.
         AppOpsManager appOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
         if (appOps.noteOp(AppOpsManager.OP_WRITE_SMS, uid, callingPackage) ==
@@ -121,7 +160,8 @@
 
         // First, check if we can read the phone state.
         try {
-            return checkReadPhoneState(context, pid, uid, callingPackage, message);
+            return checkReadPhoneState(
+                    context, telephonySupplier, subId, pid, uid, callingPackage, message);
         } catch (SecurityException readPhoneStateSecurityException) {
         }
         // Can be read with READ_SMS too.
@@ -186,16 +226,21 @@
     }
 
     private static void enforceCarrierPrivilege(int subId, int uid, String message) {
-        if (getCarrierPrivilegeStatus(subId, uid) !=
+        enforceCarrierPrivilege(TELEPHONY_SUPPLIER, subId, uid, message);
+    }
+
+    private static void enforceCarrierPrivilege(
+            Supplier<ITelephony> telephonySupplier, int subId, int uid, String message) {
+        if (getCarrierPrivilegeStatus(telephonySupplier, subId, uid) !=
                 TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
             if (DBG) Rlog.e(LOG_TAG, "No Carrier Privilege.");
             throw new SecurityException(message);
         }
     }
 
-    private static int getCarrierPrivilegeStatus(int subId, int uid) {
-        ITelephony telephony =
-                ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));
+    private static int getCarrierPrivilegeStatus(
+            Supplier<ITelephony> telephonySupplier, int subId, int uid) {
+        ITelephony telephony = telephonySupplier.get();
         try {
             if (telephony != null) {
                 return telephony.getCarrierPrivilegeStatusForUid(subId, uid);
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 14c5f4b..964a313 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -470,6 +470,9 @@
         int bearerDataLength;
         SmsEnvelope env = new SmsEnvelope();
         CdmaSmsAddress addr = new CdmaSmsAddress();
+        // We currently do not parse subaddress in PDU, but it is required when determining
+        // fingerprint (see getIncomingSmsFingerprint()).
+        CdmaSmsSubaddress subaddr = new CdmaSmsSubaddress();
 
         try {
             env.messageType = dis.readInt();
@@ -520,6 +523,7 @@
         // link the filled objects to this SMS
         mOriginatingAddress = addr;
         env.origAddress = addr;
+        env.origSubaddress = subaddr;
         mEnvelope = env;
         mPdu = pdu;
 
@@ -1009,8 +1013,11 @@
         output.write(mEnvelope.teleService);
         output.write(mEnvelope.origAddress.origBytes, 0, mEnvelope.origAddress.origBytes.length);
         output.write(mEnvelope.bearerData, 0, mEnvelope.bearerData.length);
-        output.write(mEnvelope.origSubaddress.origBytes, 0,
-                mEnvelope.origSubaddress.origBytes.length);
+        // subaddress is not set when parsing some MT SMS.
+        if (mEnvelope.origSubaddress != null && mEnvelope.origSubaddress.origBytes != null) {
+            output.write(mEnvelope.origSubaddress.origBytes, 0,
+                    mEnvelope.origSubaddress.origBytes.length);
+        }
 
         return output.toByteArray();
     }
diff --git a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
index 55ed277..9a4348e 100644
--- a/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
+++ b/tests/Camera2Tests/SmartCamera/SimpleCamera/src/androidx/media/filterfw/FrameManager.java
@@ -354,7 +354,7 @@
         assertNotRunning();
         FrameSlot slot = getSlot(name);
         slot.releaseFrame();
-        mFrameSlots.remove(slot);
+        mFrameSlots.remove(name);
     }
 
     /**
diff --git a/tests/net/Android.mk b/tests/net/Android.mk
index 4907894..a6559e7 100644
--- a/tests/net/Android.mk
+++ b/tests/net/Android.mk
@@ -24,6 +24,7 @@
     android.test.runner
 
 LOCAL_PACKAGE_NAME := FrameworksNetTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 LOCAL_CERTIFICATE := platform
diff --git a/tests/net/java/android/app/usage/NetworkStatsManagerTest.java b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
new file mode 100644
index 0000000..25e1474
--- /dev/null
+++ b/tests/net/java/android/app/usage/NetworkStatsManagerTest.java
@@ -0,0 +1,213 @@
+/*
+ * 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.app.usage;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.net.ConnectivityManager;
+import android.net.INetworkStatsService;
+import android.net.INetworkStatsSession;
+import android.net.NetworkStats.Entry;
+import android.net.NetworkStatsHistory;
+import android.net.NetworkTemplate;
+import android.os.RemoteException;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NetworkStatsManagerTest {
+
+    private @Mock INetworkStatsService mService;
+    private @Mock INetworkStatsSession mStatsSession;
+
+    private NetworkStatsManager mManager;
+
+    // TODO: change to NetworkTemplate.MATCH_MOBILE once internal constant rename is merged to aosp.
+    private static final int MATCH_MOBILE_ALL = 1;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mManager = new NetworkStatsManager(InstrumentationRegistry.getContext(), mService);
+    }
+
+    @Test
+    public void testQueryDetails() throws RemoteException {
+        final String subscriberId = "subid";
+        final long startTime = 1;
+        final long endTime = 100;
+        final int uid1 = 10001;
+        final int uid2 = 10002;
+        final int uid3 = 10003;
+
+        Entry uid1Entry1 = new Entry("if1", uid1,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                100, 10, 200, 20, 0);
+
+        Entry uid1Entry2 = new Entry(
+                "if2", uid1,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                100, 10, 200, 20, 0);
+
+        Entry uid2Entry1 = new Entry("if1", uid2,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                150, 10, 250, 20, 0);
+
+        Entry uid2Entry2 = new Entry(
+                "if2", uid2,
+                android.net.NetworkStats.SET_DEFAULT, android.net.NetworkStats.TAG_NONE,
+                150, 10, 250, 20, 0);
+
+        NetworkStatsHistory history1 = new NetworkStatsHistory(10, 2);
+        history1.recordData(10, 20, uid1Entry1);
+        history1.recordData(20, 30, uid1Entry2);
+
+        NetworkStatsHistory history2 = new NetworkStatsHistory(10, 2);
+        history1.recordData(30, 40, uid2Entry1);
+        history1.recordData(35, 45, uid2Entry2);
+
+
+        when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
+        when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2, uid3 });
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                eq(uid1), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
+                .then((InvocationOnMock inv) -> {
+                    NetworkTemplate template = inv.getArgument(0);
+                    assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
+                    assertEquals(subscriberId, template.getSubscriberId());
+                    return history1;
+                });
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                eq(uid2), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime)))
+                .then((InvocationOnMock inv) -> {
+                    NetworkTemplate template = inv.getArgument(0);
+                    assertEquals(MATCH_MOBILE_ALL, template.getMatchRule());
+                    assertEquals(subscriberId, template.getSubscriberId());
+                    return history2;
+                });
+
+
+        NetworkStats stats = mManager.queryDetails(
+                ConnectivityManager.TYPE_MOBILE, subscriberId, startTime, endTime);
+
+        NetworkStats.Bucket bucket = new NetworkStats.Bucket();
+
+        // First 2 buckets exactly match entry timings
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(10, bucket.getStartTimeStamp());
+        assertEquals(20, bucket.getEndTimeStamp());
+        assertBucketMatches(uid1Entry1, bucket);
+
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(20, bucket.getStartTimeStamp());
+        assertEquals(30, bucket.getEndTimeStamp());
+        assertBucketMatches(uid1Entry2, bucket);
+
+        // 30 -> 40: contains uid2Entry1 and half of uid2Entry2
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(30, bucket.getStartTimeStamp());
+        assertEquals(40, bucket.getEndTimeStamp());
+        assertEquals(225, bucket.getRxBytes());
+        assertEquals(15, bucket.getRxPackets());
+        assertEquals(375, bucket.getTxBytes());
+        assertEquals(30, bucket.getTxPackets());
+
+        // 40 -> 50: contains half of uid2Entry2
+        assertTrue(stats.getNextBucket(bucket));
+        assertEquals(40, bucket.getStartTimeStamp());
+        assertEquals(50, bucket.getEndTimeStamp());
+        assertEquals(75, bucket.getRxBytes());
+        assertEquals(5, bucket.getRxPackets());
+        assertEquals(125, bucket.getTxBytes());
+        assertEquals(10, bucket.getTxPackets());
+
+        assertFalse(stats.hasNextBucket());
+    }
+
+    @Test
+    public void testQueryDetails_NoSubscriberId() throws RemoteException {
+        final long startTime = 1;
+        final long endTime = 100;
+        final int uid1 = 10001;
+        final int uid2 = 10002;
+
+        when(mService.openSessionForUsageStats(anyInt(), anyString())).thenReturn(mStatsSession);
+        when(mStatsSession.getRelevantUids()).thenReturn(new int[] { uid1, uid2 });
+
+        NetworkStats stats = mManager.queryDetails(
+                ConnectivityManager.TYPE_MOBILE, null, startTime, endTime);
+
+        when(mStatsSession.getHistoryIntervalForUid(any(NetworkTemplate.class),
+                anyInt(), anyInt(), anyInt(), anyInt(), anyLong(), anyLong()))
+                .thenReturn(new NetworkStatsHistory(10, 0));
+
+        verify(mStatsSession, times(1)).getHistoryIntervalForUid(
+                argThat((NetworkTemplate t) ->
+                        // No subscriberId: MATCH_MOBILE_WILDCARD template
+                        t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
+                eq(uid1), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
+
+        verify(mStatsSession, times(1)).getHistoryIntervalForUid(
+                argThat((NetworkTemplate t) ->
+                        // No subscriberId: MATCH_MOBILE_WILDCARD template
+                        t.getMatchRule() == NetworkTemplate.MATCH_MOBILE_WILDCARD),
+                eq(uid2), eq(android.net.NetworkStats.SET_ALL),
+                eq(android.net.NetworkStats.TAG_NONE),
+                eq(NetworkStatsHistory.FIELD_ALL), eq(startTime), eq(endTime));
+
+        assertFalse(stats.hasNextBucket());
+    }
+
+    private void assertBucketMatches(Entry expected,
+            NetworkStats.Bucket actual) {
+        assertEquals(expected.uid, actual.getUid());
+        assertEquals(expected.rxBytes, actual.getRxBytes());
+        assertEquals(expected.rxPackets, actual.getRxPackets());
+        assertEquals(expected.txBytes, actual.getTxBytes());
+        assertEquals(expected.txPackets, actual.getTxPackets());
+    }
+}
diff --git a/tests/net/java/android/net/IpPrefixTest.java b/tests/net/java/android/net/IpPrefixTest.java
index b5b2c07..1f1ba2e 100644
--- a/tests/net/java/android/net/IpPrefixTest.java
+++ b/tests/net/java/android/net/IpPrefixTest.java
@@ -223,14 +223,14 @@
     }
 
     @Test
-    public void testContains() {
+    public void testContainsInetAddress() {
         IpPrefix p = new IpPrefix("2001:db8:f00::ace:d00d/127");
         assertTrue(p.contains(Address("2001:db8:f00::ace:d00c")));
         assertTrue(p.contains(Address("2001:db8:f00::ace:d00d")));
         assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
         assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
         assertFalse(p.contains(Address("2001:4868:4860::8888")));
-        assertFalse(p.contains(null));
+        assertFalse(p.contains((InetAddress)null));
         assertFalse(p.contains(Address("8.8.8.8")));
 
         p = new IpPrefix("192.0.2.0/23");
@@ -251,6 +251,53 @@
     }
 
     @Test
+    public void testContainsIpPrefix() {
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("0.0.0.0/0")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/0")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/8")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/24")));
+        assertTrue(new IpPrefix("0.0.0.0/0").containsPrefix(new IpPrefix("1.2.3.4/23")));
+
+        assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.2.3.4/8")));
+        assertTrue(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("1.254.12.9/8")));
+        assertTrue(new IpPrefix("1.2.3.4/21").containsPrefix(new IpPrefix("1.2.3.4/21")));
+        assertTrue(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.4/32")));
+
+        assertTrue(new IpPrefix("1.2.3.4/20").containsPrefix(new IpPrefix("1.2.3.0/24")));
+
+        assertFalse(new IpPrefix("1.2.3.4/32").containsPrefix(new IpPrefix("1.2.3.5/32")));
+        assertFalse(new IpPrefix("1.2.3.4/8").containsPrefix(new IpPrefix("2.2.3.4/8")));
+        assertFalse(new IpPrefix("0.0.0.0/16").containsPrefix(new IpPrefix("0.0.0.0/15")));
+        assertFalse(new IpPrefix("100.0.0.0/8").containsPrefix(new IpPrefix("99.0.0.0/8")));
+
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("::/0")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/1")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("3d8a:661:a0::770/8")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/8")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/64")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/113")));
+        assertTrue(new IpPrefix("::/0").containsPrefix(new IpPrefix("2001:db8::f00/128")));
+
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/64")));
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/120")));
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/32")));
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/64").containsPrefix(
+                new IpPrefix("2006:db8:f00::ace:d00d/96")));
+
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00d/128")));
+        assertTrue(new IpPrefix("2001:db8:f00::ace:d00d/100").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:ccaf/110")));
+
+        assertFalse(new IpPrefix("2001:db8:f00::ace:d00d/128").containsPrefix(
+                new IpPrefix("2001:db8:f00::ace:d00e/128")));
+        assertFalse(new IpPrefix("::/30").containsPrefix(new IpPrefix("::/29")));
+    }
+
+    @Test
     public void testHashCode() {
         IpPrefix p = new IpPrefix(new byte[4], 0);
         Random random = new Random();
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 2414a8e..69edc0c 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -17,19 +17,25 @@
 package android.net;
 
 import static android.net.NetworkCapabilities.LINK_BANDWIDTH_UNSPECIFIED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_CBS;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_DUN;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_EIMS;
 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;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
 import static android.net.NetworkCapabilities.NET_CAPABILITY_OEM_PAID;
+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_VALIDATED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_WIFI_P2P;
 import static android.net.NetworkCapabilities.RESTRICTED_CAPABILITIES;
 import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
 import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -223,7 +229,9 @@
         assertFalse(netCap.appliesToUidRange(new UidRange(60, 3400)));
 
         NetworkCapabilities netCap2 = new NetworkCapabilities();
-        assertFalse(netCap2.satisfiedByUids(netCap));
+        // A new netcap object has null UIDs, so anything will satisfy it.
+        assertTrue(netCap2.satisfiedByUids(netCap));
+        // Still not equal though.
         assertFalse(netCap2.equalsUids(netCap));
         netCap2.setUids(uids);
         assertTrue(netCap2.satisfiedByUids(netCap));
@@ -240,7 +248,7 @@
         assertTrue(netCap.appliesToUid(650));
         assertFalse(netCap.appliesToUid(500));
 
-        assertFalse(new NetworkCapabilities().satisfiedByUids(netCap));
+        assertTrue(new NetworkCapabilities().satisfiedByUids(netCap));
         netCap.combineCapabilities(new NetworkCapabilities());
         assertTrue(netCap.appliesToUid(500));
         assertTrue(netCap.appliesToUidRange(new UidRange(1, 100000)));
@@ -275,6 +283,117 @@
         assertFalse(nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
     }
 
+    @Test
+    public void testUnwantedCapabilities() {
+        NetworkCapabilities network = new NetworkCapabilities();
+
+        NetworkCapabilities request = new NetworkCapabilities();
+        assertTrue("Request: " + request + ", Network:" + network,
+                request.satisfiedByNetworkCapabilities(network));
+
+        // Requesting absence of capabilities that network doesn't have. Request should satisfy.
+        request.addUnwantedCapability(NET_CAPABILITY_WIFI_P2P);
+        request.addUnwantedCapability(NET_CAPABILITY_NOT_METERED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+        assertArrayEquals(new int[] {NET_CAPABILITY_WIFI_P2P, NET_CAPABILITY_NOT_METERED},
+                request.getUnwantedCapabilities());
+
+        // This is a default capability, just want to make sure its there because we use it below.
+        assertTrue(network.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // Verify that adding unwanted capability will effectively remove it from capability list.
+        request.addUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        assertFalse(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        // Now this request won't be satisfied because network contains NOT_RESTRICTED.
+        assertFalse(request.satisfiedByNetworkCapabilities(network));
+        network.removeCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+
+        // Verify that adding capability will effectively remove it from unwanted list
+        request.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.hasCapability(NET_CAPABILITY_NOT_RESTRICTED));
+        assertFalse(request.hasUnwantedCapability(NET_CAPABILITY_NOT_RESTRICTED));
+
+        assertFalse(request.satisfiedByNetworkCapabilities(network));
+        network.addCapability(NET_CAPABILITY_NOT_RESTRICTED);
+        assertTrue(request.satisfiedByNetworkCapabilities(network));
+    }
+
+    @Test
+    public void testEqualsNetCapabilities() {
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+        assertEquals(nc1, nc2);
+
+        nc1.addCapability(NET_CAPABILITY_MMS);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        assertNotEquals(nc1, nc2);
+        nc2.addCapability(NET_CAPABILITY_MMS);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+        assertEquals(nc1, nc2);
+
+        nc1.addUnwantedCapability(NET_CAPABILITY_INTERNET);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        nc2.addUnwantedCapability(NET_CAPABILITY_INTERNET);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+
+        nc1.removeCapability(NET_CAPABILITY_INTERNET);
+        assertFalse(nc1.equalsNetCapabilities(nc2));
+        nc2.removeCapability(NET_CAPABILITY_INTERNET);
+        assertTrue(nc1.equalsNetCapabilities(nc2));
+    }
+
+    @Test
+    public void testCombineCapabilities() {
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+
+        nc1.addUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL);
+        nc1.addCapability(NET_CAPABILITY_NOT_ROAMING);
+        assertNotEquals(nc1, nc2);
+        nc2.combineCapabilities(nc1);
+        assertEquals(nc1, nc2);
+        assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_CAPTIVE_PORTAL));
+
+        // This will effectively move NOT_ROAMING capability from required to unwanted for nc1.
+        nc1.addUnwantedCapability(NET_CAPABILITY_NOT_ROAMING);
+
+        nc2.combineCapabilities(nc1);
+        // We will get this capability in both requested and unwanted lists thus this request
+        // will never be satisfied.
+        assertTrue(nc2.hasCapability(NET_CAPABILITY_NOT_ROAMING));
+        assertTrue(nc2.hasUnwantedCapability(NET_CAPABILITY_NOT_ROAMING));
+    }
+
+    @Test
+    public void testSetCapabilities() {
+        final int[] REQUIRED_CAPABILITIES = new int[] {
+                NET_CAPABILITY_INTERNET, NET_CAPABILITY_NOT_VPN };
+        final int[] UNWANTED_CAPABILITIES = new int[] {
+                NET_CAPABILITY_NOT_RESTRICTED, NET_CAPABILITY_NOT_METERED
+        };
+
+        NetworkCapabilities nc1 = new NetworkCapabilities();
+        NetworkCapabilities nc2 = new NetworkCapabilities();
+
+        nc1.setCapabilities(REQUIRED_CAPABILITIES, UNWANTED_CAPABILITIES);
+        assertArrayEquals(REQUIRED_CAPABILITIES, nc1.getCapabilities());
+
+        // Verify that setting and adding capabilities leads to the same object state.
+        nc2.clearAll();
+        for (int cap : REQUIRED_CAPABILITIES) {
+            nc2.addCapability(cap);
+        }
+        for (int cap : UNWANTED_CAPABILITIES) {
+            nc2.addUnwantedCapability(cap);
+        }
+        assertEquals(nc1, nc2);
+    }
+
     private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) {
         Parcel p = Parcel.obtain();
         netCap.writeToParcel(p, /* flags */ 0);
diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java
index 8d51c3b..a5ee8e3 100644
--- a/tests/net/java/android/net/NetworkUtilsTest.java
+++ b/tests/net/java/android/net/NetworkUtilsTest.java
@@ -19,8 +19,10 @@
 import android.net.NetworkUtils;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import java.math.BigInteger;
 import java.net.Inet4Address;
 import java.net.InetAddress;
+import java.util.TreeSet;
 
 import junit.framework.TestCase;
 
@@ -67,4 +69,101 @@
         assertInvalidNetworkMask(IPv4Address("255.255.255.253"));
         assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
     }
+
+    @SmallTest
+    public void testRoutedIPv4AddressCount() {
+        final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
+        // No routes routes to no addresses.
+        assertEquals(0, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("0.0.0.0/0"));
+        assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("20.18.0.0/16"));
+        set.add(new IpPrefix("20.18.0.0/24"));
+        set.add(new IpPrefix("20.18.0.0/8"));
+        // There is a default route, still covers everything
+        assertEquals(1l << 32, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("20.18.0.0/24"));
+        set.add(new IpPrefix("20.18.0.0/8"));
+        // The 8-length includes the 24-length prefix
+        assertEquals(1l << 24, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("10.10.10.126/25"));
+        // The 8-length does not include this 25-length prefix
+        assertEquals((1l << 24) + (1 << 7), NetworkUtils.routedIPv4AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        set.add(new IpPrefix("1.2.3.4/32"));
+        assertEquals(1l, NetworkUtils.routedIPv4AddressCount(set));
+
+        set.add(new IpPrefix("1.2.3.5/32"));
+        set.add(new IpPrefix("1.2.3.6/32"));
+
+        set.add(new IpPrefix("1.2.3.7/32"));
+        set.add(new IpPrefix("1.2.3.8/32"));
+        set.add(new IpPrefix("1.2.3.9/32"));
+        set.add(new IpPrefix("1.2.3.0/32"));
+        assertEquals(7l, NetworkUtils.routedIPv4AddressCount(set));
+
+        // 1.2.3.4/30 eats 1.2.3.{4-7}/32
+        set.add(new IpPrefix("1.2.3.4/30"));
+        set.add(new IpPrefix("6.2.3.4/28"));
+        set.add(new IpPrefix("120.2.3.4/16"));
+        assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set));
+    }
+
+    @SmallTest
+    public void testRoutedIPv6AddressCount() {
+        final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator());
+        // No routes routes to no addresses.
+        assertEquals(BigInteger.ZERO, NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("::/0"));
+        assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("1234:622a::18/64"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
+        // There is a default route, still covers everything
+        assertEquals(BigInteger.ONE.shiftLeft(128), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/96"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6adb/8"));
+        // The 8-length includes the 96-length prefix
+        assertEquals(BigInteger.ONE.shiftLeft(120), NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("10::26/64"));
+        // The 8-length does not include this 64-length prefix
+        assertEquals(BigInteger.ONE.shiftLeft(120).add(BigInteger.ONE.shiftLeft(64)),
+                NetworkUtils.routedIPv6AddressCount(set));
+
+        set.clear();
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/128"));
+        assertEquals(BigInteger.ONE, NetworkUtils.routedIPv6AddressCount(set));
+
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad5/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad6/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad7/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad8/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad9/128"));
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad0/128"));
+        assertEquals(BigInteger.valueOf(7), NetworkUtils.routedIPv6AddressCount(set));
+
+        // add4:f00:80:f7:1111::6ad4/126 eats add4:f00:8[:f7:1111::6ad{4-7}/128
+        set.add(new IpPrefix("add4:f00:80:f7:1111::6ad4/126"));
+        set.add(new IpPrefix("d00d:f00:80:f7:1111::6ade/124"));
+        set.add(new IpPrefix("f00b:a33::/112"));
+        assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
+                NetworkUtils.routedIPv6AddressCount(set));
+    }
 }
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpClientTest.java
similarity index 80%
rename from tests/net/java/android/net/ip/IpManagerTest.java
rename to tests/net/java/android/net/ip/IpClientTest.java
index 22d88fb..e9e880d 100644
--- a/tests/net/java/android/net/ip/IpManagerTest.java
+++ b/tests/net/java/android/net/ip/IpClientTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyString;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -38,10 +39,12 @@
 import android.net.IpPrefix;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
+import android.net.MacAddress;
 import android.net.RouteInfo;
-import android.net.ip.IpManager.Callback;
-import android.net.ip.IpManager.InitialConfiguration;
-import android.net.ip.IpManager.ProvisioningConfiguration;
+import android.net.ip.IpClient.Callback;
+import android.net.ip.IpClient.InitialConfiguration;
+import android.net.ip.IpClient.ProvisioningConfiguration;
+import android.net.util.InterfaceParams;
 import android.os.INetworkManagementService;
 import android.provider.Settings;
 import android.support.test.filters.SmallTest;
@@ -68,15 +71,19 @@
 import java.util.Set;
 
 /**
- * Tests for IpManager.
+ * Tests for IpClient.
  */
 @RunWith(AndroidJUnit4.class)
 @SmallTest
-public class IpManagerTest {
+public class IpClientTest {
     private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
 
     private static final String VALID = "VALID";
     private static final String INVALID = "INVALID";
+    private static final String TEST_IFNAME = "test_wlan0";
+    private static final int TEST_IFINDEX = 1001;
+    // See RFC 7042#section-2.1.2 for EUI-48 documentation values.
+    private static final MacAddress TEST_MAC = MacAddress.fromString("00:00:5E:00:53:01");
 
     @Mock private Context mContext;
     @Mock private INetworkManagementService mNMService;
@@ -84,9 +91,11 @@
     @Mock private Resources mResources;
     @Mock private Callback mCb;
     @Mock private AlarmManager mAlarm;
+    @Mock private IpClient.Dependencies mDependecies;
     private MockContentResolver mContentResolver;
 
-    BaseNetworkObserver mObserver;
+    private BaseNetworkObserver mObserver;
+    private InterfaceParams mIfParams;
 
     @Before
     public void setUp() throws Exception {
@@ -100,10 +109,23 @@
         mContentResolver = new MockContentResolver();
         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
         when(mContext.getContentResolver()).thenReturn(mContentResolver);
+
+        mIfParams = null;
+
+        when(mDependecies.getNMS()).thenReturn(mNMService);
+        when(mDependecies.getNetd()).thenReturn(mNetd);
     }
 
-    private IpManager makeIpManager(String ifname) throws Exception {
-        final IpManager ipm = new IpManager(mContext, ifname, mCb, mNMService, mNetd);
+    private void setTestInterfaceParams(String ifname) {
+        mIfParams = (ifname != null)
+                ? new InterfaceParams(ifname, TEST_IFINDEX, TEST_MAC)
+                : null;
+        when(mDependecies.getInterfaceParams(anyString())).thenReturn(mIfParams);
+    }
+
+    private IpClient makeIpClient(String ifname) throws Exception {
+        setTestInterfaceParams(ifname);
+        final IpClient ipc = new IpClient(mContext, ifname, mCb, mDependecies);
         verify(mNMService, timeout(100).times(1)).disableIpv6(ifname);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(ifname);
         ArgumentCaptor<BaseNetworkObserver> arg =
@@ -111,23 +133,54 @@
         verify(mNMService, times(1)).registerObserver(arg.capture());
         mObserver = arg.getValue();
         reset(mNMService);
-        return ipm;
+        return ipc;
     }
 
     @Test
-    public void testNullCallbackDoesNotThrow() throws Exception {
-        final IpManager ipm = new IpManager(mContext, "lo", null, mNMService);
+    public void testNullInterfaceNameMostDefinitelyThrows() throws Exception {
+        setTestInterfaceParams(null);
+        try {
+            final IpClient ipc = new IpClient(mContext, null, mCb, mDependecies);
+            ipc.shutdown();
+            fail();
+        } catch (NullPointerException npe) {
+            // Phew; null interface names not allowed.
+        }
+    }
+
+    @Test
+    public void testNullCallbackMostDefinitelyThrows() throws Exception {
+        final String ifname = "lo";
+        setTestInterfaceParams(ifname);
+        try {
+            final IpClient ipc = new IpClient(mContext, ifname, null, mDependecies);
+            ipc.shutdown();
+            fail();
+        } catch (NullPointerException npe) {
+            // Phew; null callbacks not allowed.
+        }
     }
 
     @Test
     public void testInvalidInterfaceDoesNotThrow() throws Exception {
-        final IpManager ipm = new IpManager(mContext, "test_wlan0", mCb, mNMService);
+        setTestInterfaceParams(TEST_IFNAME);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+        ipc.shutdown();
+    }
+
+    @Test
+    public void testInterfaceNotFoundFailsImmediately() throws Exception {
+        setTestInterfaceParams(null);
+        final IpClient ipc = new IpClient(mContext, TEST_IFNAME, mCb, mDependecies);
+        ipc.startProvisioning(new IpClient.ProvisioningConfiguration());
+        verify(mCb, times(1)).onProvisioningFailure(any());
+        ipc.shutdown();
     }
 
     @Test
     public void testDefaultProvisioningConfiguration() throws Exception {
-        final String iface = "test_wlan0";
-        final IpManager ipm = makeIpManager(iface);
+        final String iface = TEST_IFNAME;
+        final IpClient ipc = makeIpClient(iface);
 
         ProvisioningConfiguration config = new ProvisioningConfiguration.Builder()
                 .withoutIPv4()
@@ -136,20 +189,20 @@
                 .withoutIpReachabilityMonitor()
                 .build();
 
-        ipm.startProvisioning(config);
+        ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
         verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
 
-        ipm.stop();
+        ipc.shutdown();
         verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
     }
 
     @Test
     public void testProvisioningWithInitialConfiguration() throws Exception {
-        final String iface = "test_wlan0";
-        final IpManager ipm = makeIpManager(iface);
+        final String iface = TEST_IFNAME;
+        final IpClient ipc = makeIpClient(iface);
 
         String[] addresses = {
             "fe80::a4be:f92:e1f7:22d1/64",
@@ -164,7 +217,7 @@
                 .withInitialConfiguration(conf(links(addresses), prefixes(prefixes), ips()))
                 .build();
 
-        ipm.startProvisioning(config);
+        ipc.startProvisioning(config);
         verify(mCb, times(1)).setNeighborDiscoveryOffload(true);
         verify(mCb, timeout(100).times(1)).setFallbackMulticastFilter(false);
         verify(mCb, never()).onProvisioningFailure(any());
@@ -190,7 +243,7 @@
         want.setInterfaceName(iface);
         verify(mCb, timeout(100).times(1)).onProvisioningSuccess(eq(want));
 
-        ipm.stop();
+        ipc.shutdown();
         verify(mNMService, timeout(100).times(1)).disableIpv6(iface);
         verify(mNMService, timeout(100).times(1)).clearInterfaceAddresses(iface);
     }
@@ -228,7 +281,7 @@
         };
 
         for (IsProvisionedTestCase testcase : testcases) {
-            if (IpManager.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
+            if (IpClient.isProvisioned(testcase.lp, testcase.config) != testcase.isProvisioned) {
                 fail(testcase.errorMessage());
             }
         }
@@ -424,11 +477,11 @@
         List<String> list3 = Arrays.asList("bar", "baz");
         List<String> list4 = Arrays.asList("foo", "bar", "baz");
 
-        assertTrue(IpManager.all(list1, (x) -> false));
-        assertFalse(IpManager.all(list2, (x) -> false));
-        assertTrue(IpManager.all(list3, (x) -> true));
-        assertTrue(IpManager.all(list2, (x) -> x.charAt(0) == 'f'));
-        assertFalse(IpManager.all(list4, (x) -> x.charAt(0) == 'f'));
+        assertTrue(IpClient.all(list1, (x) -> false));
+        assertFalse(IpClient.all(list2, (x) -> false));
+        assertTrue(IpClient.all(list3, (x) -> true));
+        assertTrue(IpClient.all(list2, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.all(list4, (x) -> x.charAt(0) == 'f'));
     }
 
     @Test
@@ -438,11 +491,11 @@
         List<String> list3 = Arrays.asList("bar", "baz");
         List<String> list4 = Arrays.asList("foo", "bar", "baz");
 
-        assertFalse(IpManager.any(list1, (x) -> true));
-        assertTrue(IpManager.any(list2, (x) -> true));
-        assertTrue(IpManager.any(list2, (x) -> x.charAt(0) == 'f'));
-        assertFalse(IpManager.any(list3, (x) -> x.charAt(0) == 'f'));
-        assertTrue(IpManager.any(list4, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.any(list1, (x) -> true));
+        assertTrue(IpClient.any(list2, (x) -> true));
+        assertTrue(IpClient.any(list2, (x) -> x.charAt(0) == 'f'));
+        assertFalse(IpClient.any(list3, (x) -> x.charAt(0) == 'f'));
+        assertTrue(IpClient.any(list4, (x) -> x.charAt(0) == 'f'));
     }
 
     @Test
@@ -451,9 +504,9 @@
         List<String> list2 = Arrays.asList("foo");
         List<String> list3 = Arrays.asList("foo", "bar", "baz");
 
-        assertEquals(list1, IpManager.findAll(list1, (x) -> true));
-        assertEquals(list1, IpManager.findAll(list3, (x) -> false));
-        assertEquals(list3, IpManager.findAll(list3, (x) -> true));
-        assertEquals(list2, IpManager.findAll(list3, (x) -> x.charAt(0) == 'f'));
+        assertEquals(list1, IpClient.findAll(list1, (x) -> true));
+        assertEquals(list1, IpClient.findAll(list3, (x) -> false));
+        assertEquals(list3, IpClient.findAll(list3, (x) -> true));
+        assertEquals(list2, IpClient.findAll(list3, (x) -> x.charAt(0) == 'f'));
     }
 }
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 28f8122..5ea21ea 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -387,6 +387,7 @@
                     mScore = 20;
                     break;
                 case TRANSPORT_VPN:
+                    mNetworkCapabilities.removeCapability(NET_CAPABILITY_NOT_VPN);
                     mScore = ConnectivityConstants.VPN_DEFAULT_SCORE;
                     break;
                 default:
@@ -3744,14 +3745,19 @@
         final int uid = Process.myUid();
 
         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
+        final TestNetworkCallback genericNotVpnNetworkCallback = new TestNetworkCallback();
         final TestNetworkCallback wifiNetworkCallback = new TestNetworkCallback();
         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
-        final NetworkRequest genericRequest = new NetworkRequest.Builder().build();
+        final NetworkRequest genericNotVpnRequest = new NetworkRequest.Builder().build();
+        final NetworkRequest genericRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN).build();
         final NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         final NetworkRequest vpnNetworkRequest = new NetworkRequest.Builder()
+                .removeCapability(NET_CAPABILITY_NOT_VPN)
                 .addTransportType(TRANSPORT_VPN).build();
         mCm.registerNetworkCallback(genericRequest, genericNetworkCallback);
+        mCm.registerNetworkCallback(genericNotVpnRequest, genericNotVpnNetworkCallback);
         mCm.registerNetworkCallback(wifiRequest, wifiNetworkCallback);
         mCm.registerNetworkCallback(vpnNetworkRequest, vpnNetworkCallback);
 
@@ -3759,6 +3765,7 @@
         mWiFiNetworkAgent.connect(false);
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        genericNotVpnNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         wifiNetworkCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         vpnNetworkCallback.assertNoCallback();
 
@@ -3773,16 +3780,19 @@
         vpnNetworkAgent.connect(false);
 
         genericNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectAvailableCallbacksUnvalidated(vpnNetworkAgent);
 
         genericNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCapabilitiesLike(nc -> null == nc.getUids(), vpnNetworkAgent);
 
         ranges.clear();
         vpnNetworkAgent.setUids(ranges);
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
 
@@ -3790,18 +3800,21 @@
         vpnNetworkAgent.setUids(ranges);
 
         genericNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectAvailableCallbacksValidated(vpnNetworkAgent);
 
         mWiFiNetworkAgent.disconnect();
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        genericNotVpnNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         wifiNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         vpnNetworkCallback.assertNoCallback();
 
         vpnNetworkAgent.disconnect();
 
         genericNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
+        genericNotVpnNetworkCallback.assertNoCallback();
         wifiNetworkCallback.assertNoCallback();
         vpnNetworkCallback.expectCallback(CallbackState.LOST, vpnNetworkAgent);
 
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 1dbf9b2..f59850d 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -57,9 +57,13 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.IConnectivityManager;
+import android.net.IpPrefix;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.VpnService;
 import android.os.Build.VERSION_CODES;
@@ -90,7 +94,8 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
-
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Tests for {@link Vpn}.
@@ -563,4 +568,75 @@
             return networks.get(network);
         }).when(mConnectivityManager).getNetworkCapabilities(any());
     }
+
+    // Need multiple copies of this, but Java's Stream objects can't be reused or
+    // duplicated.
+    private Stream<String> publicIpV4Routes() {
+        return Stream.of(
+                "0.0.0.0/5", "8.0.0.0/7", "11.0.0.0/8", "12.0.0.0/6", "16.0.0.0/4",
+                "32.0.0.0/3", "64.0.0.0/2", "128.0.0.0/3", "160.0.0.0/5", "168.0.0.0/6",
+                "172.0.0.0/12", "172.32.0.0/11", "172.64.0.0/10", "172.128.0.0/9",
+                "173.0.0.0/8", "174.0.0.0/7", "176.0.0.0/4", "192.0.0.0/9", "192.128.0.0/11",
+                "192.160.0.0/13", "192.169.0.0/16", "192.170.0.0/15", "192.172.0.0/14",
+                "192.176.0.0/12", "192.192.0.0/10", "193.0.0.0/8", "194.0.0.0/7",
+                "196.0.0.0/6", "200.0.0.0/5", "208.0.0.0/4");
+    }
+
+    private Stream<String> publicIpV6Routes() {
+        return Stream.of(
+                "::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6",
+                "fe00::/8", "2605:ef80:e:af1d::/64");
+    }
+
+    @Test
+    public void testProvidesRoutesToMostDestinations() {
+        final LinkProperties lp = new LinkProperties();
+
+        // Default route provides routes to all IPv4 destinations.
+        lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Empty LP provides routes to no destination
+        lp.clear();
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // All IPv4 routes except for local networks. This is the case most relevant
+        // to this function. It provides routes to almost the entire space.
+        // (clone the stream so that we can reuse it later)
+        publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to
+        // provide routes to "most" destinations.
+        lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // Remove the /2 route, which represent a quarter of the available routing space.
+        // This LP does not provides routes to "most" destinations any more.
+        lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        lp.clear();
+        publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        lp.removeRoute(new RouteInfo(new IpPrefix("::/1")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V6 does not provide sufficient coverage but v4 does
+        publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 still does
+        lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 does not any more
+        lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
+        assertFalse(Vpn.providesRoutesToMostDestinations(lp));
+
+        // V4 does not, but V6 has sufficient coverage again
+        lp.addRoute(new RouteInfo(new IpPrefix("::/1")));
+        assertTrue(Vpn.providesRoutesToMostDestinations(lp));
+    }
 }
diff --git a/tools/aapt2/integration-tests/AppOne/Android.mk b/tools/aapt2/integration-tests/AppOne/Android.mk
index 38bd5b5..7b30c4e 100644
--- a/tools/aapt2/integration-tests/AppOne/Android.mk
+++ b/tools/aapt2/integration-tests/AppOne/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptTestAppOne
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets $(LOCAL_PATH)/assets2
diff --git a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
index 012728f..03cce35 100644
--- a/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
+++ b/tools/aapt2/integration-tests/AutoVersionTest/Android.mk
@@ -19,5 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptAutoVersionTest
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/StaticLibOne/Android.mk b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
index 0b7129a..ec4f052 100644
--- a/tools/aapt2/integration-tests/StaticLibOne/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibOne/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := AaptTestStaticLibOne
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
index 8b6eb41..40f91af 100644
--- a/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
+++ b/tools/aapt2/integration-tests/StaticLibTwo/Android.mk
@@ -19,6 +19,7 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_MODULE := AaptTestStaticLibTwo
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 LOCAL_SRC_FILES := $(call all-java-files-under,src)
 LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
index 902fc65..8da1141 100644
--- a/tools/aapt2/integration-tests/SymlinkTest/Android.mk
+++ b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
@@ -19,5 +19,6 @@
 include $(CLEAR_VARS)
 LOCAL_USE_AAPT2 := true
 LOCAL_PACKAGE_NAME := AaptSymlinkTest
+LOCAL_SDK_VERSION := current
 LOCAL_MODULE_TAGS := tests
 include $(BUILD_PACKAGE)
diff --git a/wifi/tests/Android.mk b/wifi/tests/Android.mk
index c98e40a..8804c8a 100644
--- a/wifi/tests/Android.mk
+++ b/wifi/tests/Android.mk
@@ -60,6 +60,7 @@
     android.test.runner \
 
 LOCAL_PACKAGE_NAME := FrameworksWifiApiTests
+LOCAL_PRIVATE_PLATFORM_APIS := true
 LOCAL_COMPATIBILITY_SUITE := device-tests
 
 include $(BUILD_PACKAGE)