Merge "make carrier default app direct boot aware"
diff --git a/api/current.txt b/api/current.txt
index b5a99ca..db44f3b 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6694,6 +6694,7 @@
     method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+    method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
     method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
@@ -7076,9 +7077,7 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7174,12 +7173,8 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+  public abstract class BluetoothGattCallback {
     ctor public BluetoothGattCallback();
-  }
-
-  public abstract class BluetoothGattCallbackExt {
-    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7288,12 +7283,8 @@
     method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+  public abstract class BluetoothGattServerCallback {
     ctor public BluetoothGattServerCallback();
-  }
-
-  public abstract class BluetoothGattServerCallbackExt {
-    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7505,11 +7496,11 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean);
-    method public void periodicAdvertisingEnable(boolean);
+    method public void enableAdvertising(boolean, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingEnable(boolean);
     method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
     method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
   }
@@ -7518,11 +7509,11 @@
     ctor public AdvertisingSetCallback();
     method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
     method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
-    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
     method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
     method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
     method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
     method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
     field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7538,12 +7529,12 @@
     method public int getInterval();
     method public int getPrimaryPhy();
     method public int getSecondaryPhy();
-    method public int getTimeout();
     method public int getTxPowerLevel();
     method public boolean includeTxPower();
     method public boolean isAnonymous();
     method public boolean isConnectable();
     method public boolean isLegacy();
+    method public boolean isScannable();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
     field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7565,14 +7556,14 @@
   public static final class AdvertisingSetParameters.Builder {
     ctor public AdvertisingSetParameters.Builder();
     method public android.bluetooth.le.AdvertisingSetParameters build();
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
   }
 
@@ -7581,6 +7572,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -23812,7 +23805,9 @@
     method public boolean isDefaultNetworkActive();
     method public static deprecated boolean isNetworkTypeValid(int);
     method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
     method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -23821,6 +23816,8 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
@@ -25011,7 +25008,7 @@
 
   public class WifiManager {
     method public int addNetwork(android.net.wifi.WifiConfiguration);
-    method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+    method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method public static int calculateSignalLevel(int, int);
     method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
@@ -25040,7 +25037,7 @@
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
-    method public boolean removePasspointConfiguration(java.lang.String);
+    method public void removePasspointConfiguration(java.lang.String);
     method public deprecated boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -25055,26 +25052,22 @@
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
+    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
+    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -25293,7 +25286,6 @@
     method public void setUsageLimitStartTimeInMs(long);
     method public void setUsageLimitTimeLimitInMinutes(long);
     method public void setUsageLimitUsageTimePeriodInMinutes(long);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
   }
@@ -25334,7 +25326,6 @@
     method public void setRealm(java.lang.String);
     method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
     method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
   }
@@ -25347,7 +25338,6 @@
     method public java.lang.String getCertType();
     method public void setCertSha256Fingerprint(byte[]);
     method public void setCertType(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
   }
@@ -25360,7 +25350,6 @@
     method public java.lang.String getImsi();
     method public void setEapType(int);
     method public void setImsi(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
   }
@@ -25383,7 +25372,6 @@
     method public void setPassword(java.lang.String);
     method public void setSoftTokenApp(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
   }
@@ -25408,7 +25396,6 @@
     method public void setMatchAnyOis(long[]);
     method public void setOtherHomePartners(java.lang.String[]);
     method public void setRoamingConsortiumOis(long[]);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
   }
@@ -25435,7 +25422,6 @@
     method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
     method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
     method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
   }
@@ -25452,7 +25438,6 @@
     method public void setFqdn(java.lang.String);
     method public void setFqdnExactMatch(boolean);
     method public void setPriority(int);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
   }
@@ -25477,7 +25462,6 @@
     method public void setUpdateIntervalInMinutes(long);
     method public void setUpdateMethod(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
     field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -38207,13 +38191,17 @@
     method public boolean getDataEnabled();
     method public int getDataNetworkType();
     method public int getDataState();
-    method public java.lang.String getDeviceId();
-    method public java.lang.String getDeviceId(int);
+    method public deprecated java.lang.String getDeviceId();
+    method public deprecated java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+    method public java.lang.String getImei();
+    method public java.lang.String getImei(int);
     method public java.lang.String getLine1Number();
+    method public java.lang.String getMeid();
+    method public java.lang.String getMeid(int);
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
     method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -53163,6 +53151,7 @@
 
   public class GenericSignatureFormatError extends java.lang.ClassFormatError {
     ctor public GenericSignatureFormatError();
+    ctor public GenericSignatureFormatError(java.lang.String);
   }
 
   public abstract interface InvocationHandler {
diff --git a/api/system-current.txt b/api/system-current.txt
index c2338d8..20697d4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -87,6 +87,7 @@
     field public static final java.lang.String CLEAR_APP_CACHE = "android.permission.CLEAR_APP_CACHE";
     field public static final java.lang.String CLEAR_APP_USER_DATA = "android.permission.CLEAR_APP_USER_DATA";
     field public static final java.lang.String CONNECTIVITY_INTERNAL = "android.permission.CONNECTIVITY_INTERNAL";
+    field public static final java.lang.String CONNECTIVITY_USE_RESTRICTED_NETWORKS = "android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS";
     field public static final java.lang.String CONTROL_INCALL_EXPERIENCE = "android.permission.CONTROL_INCALL_EXPERIENCE";
     field public static final java.lang.String CONTROL_LOCATION_UPDATES = "android.permission.CONTROL_LOCATION_UPDATES";
     field public static final java.lang.String CONTROL_VPN = "android.permission.CONTROL_VPN";
@@ -6992,6 +6993,7 @@
     method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+    method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
     method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
@@ -7378,9 +7380,7 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7478,12 +7478,8 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+  public abstract class BluetoothGattCallback {
     ctor public BluetoothGattCallback();
-  }
-
-  public abstract class BluetoothGattCallbackExt {
-    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7592,12 +7588,8 @@
     method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+  public abstract class BluetoothGattServerCallback {
     ctor public BluetoothGattServerCallback();
-  }
-
-  public abstract class BluetoothGattServerCallbackExt {
-    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7809,11 +7801,11 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean);
-    method public void periodicAdvertisingEnable(boolean);
+    method public void enableAdvertising(boolean, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingEnable(boolean);
     method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
     method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
   }
@@ -7822,11 +7814,11 @@
     ctor public AdvertisingSetCallback();
     method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
     method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
-    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
     method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
     method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
     method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
     method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
     field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7842,12 +7834,12 @@
     method public int getInterval();
     method public int getPrimaryPhy();
     method public int getSecondaryPhy();
-    method public int getTimeout();
     method public int getTxPowerLevel();
     method public boolean includeTxPower();
     method public boolean isAnonymous();
     method public boolean isConnectable();
     method public boolean isLegacy();
+    method public boolean isScannable();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
     field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7869,14 +7861,14 @@
   public static final class AdvertisingSetParameters.Builder {
     ctor public AdvertisingSetParameters.Builder();
     method public android.bluetooth.le.AdvertisingSetParameters build();
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
   }
 
@@ -7885,6 +7877,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -25599,7 +25593,9 @@
     method public static deprecated boolean isNetworkTypeValid(int);
     method public boolean isTetheringSupported();
     method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
     method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -25608,6 +25604,8 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
@@ -27389,7 +27387,7 @@
 
   public class WifiManager {
     method public int addNetwork(android.net.wifi.WifiConfiguration);
-    method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+    method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method public static int calculateSignalLevel(int, int);
     method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
@@ -27429,7 +27427,7 @@
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
-    method public boolean removePasspointConfiguration(java.lang.String);
+    method public void removePasspointConfiguration(java.lang.String);
     method public deprecated boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -27452,29 +27450,25 @@
     field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
     field public static final java.lang.String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
+    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
     field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason";
+    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_AP_STATE = "wifi_state";
     field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
     field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
@@ -27853,7 +27847,6 @@
     method public void setUsageLimitStartTimeInMs(long);
     method public void setUsageLimitTimeLimitInMinutes(long);
     method public void setUsageLimitUsageTimePeriodInMinutes(long);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
   }
@@ -27894,7 +27887,6 @@
     method public void setRealm(java.lang.String);
     method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
     method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
   }
@@ -27907,7 +27899,6 @@
     method public java.lang.String getCertType();
     method public void setCertSha256Fingerprint(byte[]);
     method public void setCertType(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
   }
@@ -27920,7 +27911,6 @@
     method public java.lang.String getImsi();
     method public void setEapType(int);
     method public void setImsi(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
   }
@@ -27943,7 +27933,6 @@
     method public void setPassword(java.lang.String);
     method public void setSoftTokenApp(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
   }
@@ -27968,7 +27957,6 @@
     method public void setMatchAnyOis(long[]);
     method public void setOtherHomePartners(java.lang.String[]);
     method public void setRoamingConsortiumOis(long[]);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
   }
@@ -27995,7 +27983,6 @@
     method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
     method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
     method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
   }
@@ -28012,7 +27999,6 @@
     method public void setFqdn(java.lang.String);
     method public void setFqdnExactMatch(boolean);
     method public void setPriority(int);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
   }
@@ -28037,7 +28023,6 @@
     method public void setUpdateIntervalInMinutes(long);
     method public void setUpdateMethod(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
     field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -41425,8 +41410,8 @@
     method public boolean getDataEnabled(int);
     method public int getDataNetworkType();
     method public int getDataState();
-    method public java.lang.String getDeviceId();
-    method public java.lang.String getDeviceId(int);
+    method public deprecated java.lang.String getDeviceId();
+    method public deprecated java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
@@ -41434,6 +41419,8 @@
     method public java.lang.String getImei();
     method public java.lang.String getImei(int);
     method public java.lang.String getLine1Number();
+    method public java.lang.String getMeid();
+    method public java.lang.String getMeid(int);
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
     method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -56793,6 +56780,7 @@
 
   public class GenericSignatureFormatError extends java.lang.ClassFormatError {
     ctor public GenericSignatureFormatError();
+    ctor public GenericSignatureFormatError(java.lang.String);
   }
 
   public abstract interface InvocationHandler {
diff --git a/api/test-current.txt b/api/test-current.txt
index bc0b5b0..8b29697 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -6703,6 +6703,7 @@
     method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
     method public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method public static synchronized android.bluetooth.BluetoothAdapter getDefaultAdapter();
+    method public int getLeMaximumAdvertisingDataLength();
     method public java.lang.String getName();
     method public android.bluetooth.le.PeriodicAdvertisingManager getPeriodicAdvertisingManager();
     method public int getProfileConnectionState(int);
@@ -7085,9 +7086,7 @@
   public final class BluetoothDevice implements android.os.Parcelable {
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback);
     method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int);
-    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallbackExt, int, int);
+    method public android.bluetooth.BluetoothGatt connectGatt(android.content.Context, boolean, android.bluetooth.BluetoothGattCallback, int, int);
     method public boolean createBond();
     method public android.bluetooth.BluetoothSocket createInsecureRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
     method public android.bluetooth.BluetoothSocket createRfcommSocketToServiceRecord(java.util.UUID) throws java.io.IOException;
@@ -7183,12 +7182,8 @@
     field public static final int GATT_WRITE_NOT_PERMITTED = 3; // 0x3
   }
 
-  public abstract deprecated class BluetoothGattCallback extends android.bluetooth.BluetoothGattCallbackExt {
+  public abstract class BluetoothGattCallback {
     ctor public BluetoothGattCallback();
-  }
-
-  public abstract class BluetoothGattCallbackExt {
-    ctor public BluetoothGattCallbackExt();
     method public void onCharacteristicChanged(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
     method public void onCharacteristicWrite(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int);
@@ -7297,12 +7292,8 @@
     method public void setPreferredPhy(android.bluetooth.BluetoothDevice, int, int, int);
   }
 
-  public abstract deprecated class BluetoothGattServerCallback extends android.bluetooth.BluetoothGattServerCallbackExt {
+  public abstract class BluetoothGattServerCallback {
     ctor public BluetoothGattServerCallback();
-  }
-
-  public abstract class BluetoothGattServerCallbackExt {
-    ctor public BluetoothGattServerCallbackExt();
     method public void onCharacteristicReadRequest(android.bluetooth.BluetoothDevice, int, int, android.bluetooth.BluetoothGattCharacteristic);
     method public void onCharacteristicWriteRequest(android.bluetooth.BluetoothDevice, int, android.bluetooth.BluetoothGattCharacteristic, boolean, boolean, int, byte[]);
     method public void onConnectionStateChange(android.bluetooth.BluetoothDevice, int, int);
@@ -7514,11 +7505,11 @@
   }
 
   public final class AdvertisingSet {
-    method public void enableAdvertising(boolean);
-    method public void periodicAdvertisingEnable(boolean);
+    method public void enableAdvertising(boolean, int);
     method public void setAdvertisingData(android.bluetooth.le.AdvertiseData);
     method public void setAdvertisingParameters(android.bluetooth.le.AdvertisingSetParameters);
     method public void setPeriodicAdvertisingData(android.bluetooth.le.AdvertiseData);
+    method public void setPeriodicAdvertisingEnable(boolean);
     method public void setPeriodicAdvertisingParameters(android.bluetooth.le.PeriodicAdvertisingParameters);
     method public void setScanResponseData(android.bluetooth.le.AdvertiseData);
   }
@@ -7527,11 +7518,11 @@
     ctor public AdvertisingSetCallback();
     method public void onAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
     method public void onAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
-    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
-    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int);
+    method public void onAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int, int);
+    method public void onAdvertisingSetStarted(android.bluetooth.le.AdvertisingSet, int, int);
     method public void onAdvertisingSetStopped(android.bluetooth.le.AdvertisingSet);
     method public void onPeriodicAdvertisingDataSet(android.bluetooth.le.AdvertisingSet, int);
-    method public void onPeriodicAdvertisingEnable(android.bluetooth.le.AdvertisingSet, boolean, int);
+    method public void onPeriodicAdvertisingEnabled(android.bluetooth.le.AdvertisingSet, boolean, int);
     method public void onPeriodicAdvertisingParametersUpdated(android.bluetooth.le.AdvertisingSet, int);
     method public void onScanResponseDataSet(android.bluetooth.le.AdvertisingSet, int);
     field public static final int ADVERTISE_FAILED_ALREADY_STARTED = 3; // 0x3
@@ -7547,12 +7538,12 @@
     method public int getInterval();
     method public int getPrimaryPhy();
     method public int getSecondaryPhy();
-    method public int getTimeout();
     method public int getTxPowerLevel();
     method public boolean includeTxPower();
     method public boolean isAnonymous();
     method public boolean isConnectable();
     method public boolean isLegacy();
+    method public boolean isScannable();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertisingSetParameters> CREATOR;
     field public static final int INTERVAL_HIGH = 160; // 0xa0
@@ -7574,14 +7565,14 @@
   public static final class AdvertisingSetParameters.Builder {
     ctor public AdvertisingSetParameters.Builder();
     method public android.bluetooth.le.AdvertisingSetParameters build();
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymouus(boolean);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setAnonymous(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setConnectable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setIncludeTxPower(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setInterval(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setLegacyMode(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setPrimaryPhy(int);
+    method public android.bluetooth.le.AdvertisingSetParameters.Builder setScannable(boolean);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setSecondaryPhy(int);
-    method public android.bluetooth.le.AdvertisingSetParameters.Builder setTimeout(int);
     method public android.bluetooth.le.AdvertisingSetParameters.Builder setTxPowerLevel(int);
   }
 
@@ -7590,6 +7581,8 @@
     method public void startAdvertising(android.bluetooth.le.AdvertiseSettings, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback);
     method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback);
+    method public void startAdvertisingSet(android.bluetooth.le.AdvertisingSetParameters, android.bluetooth.le.AdvertiseData, android.bluetooth.le.AdvertiseData, android.bluetooth.le.PeriodicAdvertisingParameters, android.bluetooth.le.AdvertiseData, int, android.bluetooth.le.AdvertisingSetCallback, android.os.Handler);
     method public void stopAdvertising(android.bluetooth.le.AdvertiseCallback);
     method public void stopAdvertisingSet(android.bluetooth.le.AdvertisingSetCallback);
   }
@@ -23885,7 +23878,9 @@
     method public boolean isDefaultNetworkActive();
     method public static deprecated boolean isNetworkTypeValid(int);
     method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback);
+    method public void registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
+    method public void registerNetworkCallback(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void registerNetworkCallback(android.net.NetworkRequest, android.app.PendingIntent);
     method public void releaseNetworkRequest(android.app.PendingIntent);
     method public void removeDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
@@ -23894,6 +23889,8 @@
     method public boolean requestBandwidthUpdate(android.net.Network);
     method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback);
     method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback);
+    method public void requestNetwork(android.net.NetworkRequest, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
+    method public void requestNetwork(android.net.NetworkRequest, int, android.net.ConnectivityManager.NetworkCallback, android.os.Handler);
     method public void requestNetwork(android.net.NetworkRequest, android.app.PendingIntent);
     method public deprecated boolean requestRouteToHost(int, int);
     method public deprecated void setNetworkPreference(int);
@@ -25084,7 +25081,7 @@
 
   public class WifiManager {
     method public int addNetwork(android.net.wifi.WifiConfiguration);
-    method public boolean addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
+    method public void addOrUpdatePasspointConfiguration(android.net.wifi.hotspot2.PasspointConfiguration);
     method public static int calculateSignalLevel(int, int);
     method public void cancelWps(android.net.wifi.WifiManager.WpsCallback);
     method public static int compareSignalLevel(int, int);
@@ -25113,7 +25110,7 @@
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
-    method public boolean removePasspointConfiguration(java.lang.String);
+    method public void removePasspointConfiguration(java.lang.String);
     method public deprecated boolean saveConfiguration();
     method public void setTdlsEnabled(java.net.InetAddress, boolean);
     method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
@@ -25128,26 +25125,22 @@
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
+    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
+    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
+    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
+    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
+    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
+    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
-    field public static final java.lang.String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY = "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_BSSID = "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_DATA = "android.net.wifi.extra.PASSPOINT_ICON_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_ICON_FILENAME = "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA = "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
-    field public static final java.lang.String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL = "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
+    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -25366,7 +25359,6 @@
     method public void setUsageLimitStartTimeInMs(long);
     method public void setUsageLimitTimeLimitInMinutes(long);
     method public void setUsageLimitUsageTimePeriodInMinutes(long);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.PasspointConfiguration> CREATOR;
   }
@@ -25407,7 +25399,6 @@
     method public void setRealm(java.lang.String);
     method public void setSimCredential(android.net.wifi.hotspot2.pps.Credential.SimCredential);
     method public void setUserCredential(android.net.wifi.hotspot2.pps.Credential.UserCredential);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential> CREATOR;
   }
@@ -25420,7 +25411,6 @@
     method public java.lang.String getCertType();
     method public void setCertSha256Fingerprint(byte[]);
     method public void setCertType(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.CertificateCredential> CREATOR;
   }
@@ -25433,7 +25423,6 @@
     method public java.lang.String getImsi();
     method public void setEapType(int);
     method public void setImsi(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.SimCredential> CREATOR;
   }
@@ -25456,7 +25445,6 @@
     method public void setPassword(java.lang.String);
     method public void setSoftTokenApp(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Credential.UserCredential> CREATOR;
   }
@@ -25481,7 +25469,6 @@
     method public void setMatchAnyOis(long[]);
     method public void setOtherHomePartners(java.lang.String[]);
     method public void setRoamingConsortiumOis(long[]);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.HomeSp> CREATOR;
   }
@@ -25508,7 +25495,6 @@
     method public void setPolicyUpdate(android.net.wifi.hotspot2.pps.UpdateParameter);
     method public void setPreferredRoamingPartnerList(java.util.List<android.net.wifi.hotspot2.pps.Policy.RoamingPartner>);
     method public void setRequiredProtoPortMap(java.util.Map<java.lang.Integer, java.lang.String>);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy> CREATOR;
   }
@@ -25525,7 +25511,6 @@
     method public void setFqdn(java.lang.String);
     method public void setFqdnExactMatch(boolean);
     method public void setPriority(int);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.Policy.RoamingPartner> CREATOR;
   }
@@ -25550,7 +25535,6 @@
     method public void setUpdateIntervalInMinutes(long);
     method public void setUpdateMethod(java.lang.String);
     method public void setUsername(java.lang.String);
-    method public boolean validate();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.hotspot2.pps.UpdateParameter> CREATOR;
     field public static final long UPDATE_CHECK_INTERVAL_NEVER = 4294967295L; // 0xffffffffL
@@ -38289,13 +38273,17 @@
     method public boolean getDataEnabled();
     method public int getDataNetworkType();
     method public int getDataState();
-    method public java.lang.String getDeviceId();
-    method public java.lang.String getDeviceId(int);
+    method public deprecated java.lang.String getDeviceId();
+    method public deprecated java.lang.String getDeviceId(int);
     method public java.lang.String getDeviceSoftwareVersion();
     method public java.lang.String[] getForbiddenPlmns();
     method public java.lang.String getGroupIdLevel1();
     method public java.lang.String getIccAuthentication(int, int, java.lang.String);
+    method public java.lang.String getImei();
+    method public java.lang.String getImei(int);
     method public java.lang.String getLine1Number();
+    method public java.lang.String getMeid();
+    method public java.lang.String getMeid(int);
     method public java.lang.String getMmsUAProfUrl();
     method public java.lang.String getMmsUserAgent();
     method public deprecated java.util.List<android.telephony.NeighboringCellInfo> getNeighboringCellInfo();
@@ -53254,6 +53242,7 @@
 
   public class GenericSignatureFormatError extends java.lang.ClassFormatError {
     ctor public GenericSignatureFormatError();
+    ctor public GenericSignatureFormatError(java.lang.String);
   }
 
   public abstract interface InvocationHandler {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0dd9c63..bcdf3f4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1761,7 +1761,9 @@
         if (this.actions != null) {
             that.actions = new Action[this.actions.length];
             for(int i=0; i<this.actions.length; i++) {
-                that.actions[i] = this.actions[i].clone();
+                if ( this.actions[i] != null) {
+                    that.actions[i] = this.actions[i].clone();
+                }
             }
         }
 
@@ -3108,7 +3110,9 @@
          * @param action The action to add.
          */
         public Builder addAction(Action action) {
-            mActions.add(action);
+            if (action != null) {
+                mActions.add(action);
+            }
             return this;
         }
 
@@ -3122,7 +3126,9 @@
         public Builder setActions(Action... actions) {
             mActions.clear();
             for (int i = 0; i < actions.length; i++) {
-                mActions.add(actions[i]);
+                if (actions[i] != null) {
+                    mActions.add(actions[i]);
+                }
             }
             return this;
         }
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8186937..27640e7 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -1447,9 +1447,9 @@
     }
 
     /**
-     * Return true if LE Periodic Advertising feature is supported.
+     * Return true if LE Extended Advertising feature is supported.
      *
-     * @return true if chipset supports LE Periodic Advertising feature
+     * @return true if chipset supports LE Extended Advertising feature
      */
     public boolean isLeExtendedAdvertisingSupported() {
         if (!getLeAccess()) return false;
@@ -1483,6 +1483,25 @@
     }
 
     /**
+     * Return the maximum LE advertising data length,
+     * if LE Extended Advertising feature is supported.
+     *
+     * @return the maximum LE advertising data length.
+     */
+    public int getLeMaximumAdvertisingDataLength() {
+        if (!getLeAccess()) return 0;
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) return mService.getLeMaximumAdvertisingDataLength();
+        } catch (RemoteException e) {
+            Log.e(TAG, "failed to get getLeMaximumAdvertisingDataLength, error: ", e);
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return 0;
+    }
+
+    /**
      * Return true if hardware has entries available for matching beacons
      *
      * @return true if there are hw entries available for matching beacons
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 31fc294..cb6fa05 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -1664,43 +1664,6 @@
      * @param autoConnect Whether to directly connect to the remote device (false)
      *                    or to automatically connect as soon as the remote
      *                    device becomes available (true).
-     * @throws IllegalArgumentException if callback is null
-     */
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-                                     BluetoothGattCallbackExt callback) {
-        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO));
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false)
-     *                    or to automatically connect as soon as the remote
-     *                    device becomes available (true).
-     * @param transport preferred transport for GATT connections to remote dual-mode devices
-     *             {@link BluetoothDevice#TRANSPORT_AUTO} or
-     *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
-     * @throws IllegalArgumentException if callback is null
-     */
-    public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-                                     BluetoothGattCallbackExt callback, int transport) {
-        return (connectGatt(context, autoConnect,callback, TRANSPORT_AUTO, PHY_LE_1M));
-    }
-
-    /**
-     * Connect to GATT Server hosted by this device. Caller acts as GATT client.
-     * The callback is used to deliver results to Caller, such as connection status as well
-     * as any further GATT client operations.
-     * The method returns a BluetoothGatt instance. You can use BluetoothGatt to conduct
-     * GATT client operations.
-     * @param callback GATT callback handler that will receive asynchronous callbacks.
-     * @param autoConnect Whether to directly connect to the remote device (false)
-     *                    or to automatically connect as soon as the remote
-     *                    device becomes available (true).
      * @param transport preferred transport for GATT connections to remote dual-mode devices
      *             {@link BluetoothDevice#TRANSPORT_AUTO} or
      *             {@link BluetoothDevice#TRANSPORT_BREDR} or {@link BluetoothDevice#TRANSPORT_LE}
@@ -1711,7 +1674,7 @@
      * @throws IllegalArgumentException if callback is null
      */
     public BluetoothGatt connectGatt(Context context, boolean autoConnect,
-                                     BluetoothGattCallbackExt callback, int transport, int phy) {
+                                     BluetoothGattCallback callback, int transport, int phy) {
         // TODO(Bluetooth) check whether platform support BLE
         //     Do the check here or in GattServer?
         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 0cb69ae..a314aaf 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -31,7 +31,7 @@
  * <p>This class provides Bluetooth GATT functionality to enable communication
  * with Bluetooth Smart or Smart Ready devices.
  *
- * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallbackExt}
+ * <p>To connect to a remote peripheral device, create a {@link BluetoothGattCallback}
  * and call {@link BluetoothDevice#connectGatt} to get a instance of this class.
  * GATT capable devices can be discovered using the Bluetooth device discovery or BLE
  * scan process.
@@ -42,7 +42,7 @@
     private static final boolean VDBG = false;
 
     private IBluetoothGatt mService;
-    private BluetoothGattCallbackExt mCallback;
+    private BluetoothGattCallback mCallback;
     private int mClientIf;
     private BluetoothDevice mDevice;
     private boolean mAutoConnect;
@@ -133,14 +133,15 @@
     /*package*/ static final int AUTHENTICATION_MITM = 2;
 
     /**
-     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallbackExt implementation.
+     * Bluetooth GATT callbacks. Overrides the default BluetoothGattCallback implementation.
      */
-    private final IBluetoothGattCallbackExt mBluetoothGattCallbackExt =
+    private final IBluetoothGattCallbackExt mBluetoothGattCallback =
         new IBluetoothGattCallbackExt.Stub() {
             /**
              * Application interface registered - app is ready to go
              * @hide
              */
+            @Override
             public void onClientRegistered(int status, int clientIf) {
                 if (DBG) Log.d(TAG, "onClientRegistered() - status=" + status
                     + " clientIf=" + clientIf);
@@ -210,6 +211,7 @@
              * Client connection state changed
              * @hide
              */
+            @Override
             public void onClientConnectionState(int status, int clientIf,
                                                 boolean connected, String address) {
                 if (DBG) Log.d(TAG, "onClientConnectionState() - status=" + status
@@ -245,6 +247,7 @@
              * we are done at this point.
              * @hide
              */
+            @Override
             public void onSearchComplete(String address, List<BluetoothGattService> services,
                                          int status) {
                 if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
@@ -288,6 +291,7 @@
              * Updates the internal value.
              * @hide
              */
+            @Override
             public void onCharacteristicRead(String address, int status, int handle, byte[] value) {
                 if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
                             + " handle=" + handle + " Status=" + status);
@@ -336,6 +340,7 @@
              * Let the app know how we did...
              * @hide
              */
+            @Override
             public void onCharacteristicWrite(String address, int status, int handle) {
                 if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
                             + " handle=" + handle + " Status=" + status);
@@ -380,6 +385,7 @@
              * Updates the internal value.
              * @hide
              */
+            @Override
             public void onNotify(String address, int handle, byte[] value) {
                 if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
 
@@ -403,6 +409,7 @@
              * Descriptor has been read.
              * @hide
              */
+            @Override
             public void onDescriptorRead(String address, int status, int handle, byte[] value) {
                 if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle);
 
@@ -446,6 +453,7 @@
              * Descriptor write operation complete.
              * @hide
              */
+            @Override
             public void onDescriptorWrite(String address, int status, int handle) {
                 if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle);
 
@@ -488,6 +496,7 @@
              * Prepared write transaction completed (or aborted)
              * @hide
              */
+            @Override
             public void onExecuteWrite(String address, int status) {
                 if (VDBG) Log.d(TAG, "onExecuteWrite() - Device=" + address
                     + " status=" + status);
@@ -510,6 +519,7 @@
              * Remote device RSSI has been read
              * @hide
              */
+            @Override
             public void onReadRemoteRssi(String address, int rssi, int status) {
                 if (VDBG) Log.d(TAG, "onReadRemoteRssi() - Device=" + address +
                             " rssi=" + rssi + " status=" + status);
@@ -527,6 +537,7 @@
              * Callback invoked when the MTU for a given connection changes
              * @hide
              */
+            @Override
             public void onConfigureMTU(String address, int mtu, int status) {
                 if (DBG) Log.d(TAG, "onConfigureMTU() - Device=" + address +
                             " mtu=" + mtu + " status=" + status);
@@ -539,6 +550,27 @@
                     Log.w(TAG, "Unhandled exception in callback", ex);
                 }
             }
+
+            /**
+             * Callback invoked when the given connection is updated
+             * @hide
+             */
+            @Override
+            public void onConnectionUpdated(String address, int interval, int latency,
+                                            int timeout, int status) {
+                if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address +
+                            " interval=" + interval + " latency=" + latency +
+                            " timeout=" + timeout + " status=" + status);
+                if (!address.equals(mDevice.getAddress())) {
+                    return;
+                }
+                try {
+                    mCallback.onConnectionUpdated(BluetoothGatt.this, interval, latency,
+                                                  timeout, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception in callback", ex);
+                }
+            }
         };
 
     /*package*/ BluetoothGatt(IBluetoothGatt iGatt, BluetoothDevice device,
@@ -618,7 +650,7 @@
     /**
      * Register an application callback to start using GATT.
      *
-     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallbackExt#onAppRegistered}
+     * <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
      * is used to notify success or failure if the function returns true.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -627,7 +659,7 @@
      * @return If true, the callback will be called to notify success or failure,
      *         false on immediate error
      */
-    private boolean registerApp(BluetoothGattCallbackExt callback) {
+    private boolean registerApp(BluetoothGattCallback callback) {
         if (DBG) Log.d(TAG, "registerApp()");
         if (mService == null) return false;
 
@@ -636,7 +668,7 @@
         if (DBG) Log.d(TAG, "registerApp() - UUID=" + uuid);
 
         try {
-            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallbackExt);
+            mService.registerClient(new ParcelUuid(uuid), mBluetoothGattCallback);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
             return false;
@@ -666,7 +698,7 @@
      *
      * <p>The connection may not be established right away, but will be
      * completed when the remote device is available. A
-     * {@link BluetoothGattCallbackExt#onConnectionStateChange} callback will be
+     * {@link BluetoothGattCallback#onConnectionStateChange} callback will be
      * invoked when the connection state changes as a result of this function.
      *
      * <p>The autoConnect parameter determines whether to actively connect to
@@ -684,7 +716,7 @@
      *                    device becomes available (true).
      * @return true, if the connection attempt was initiated successfully
      */
-    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallbackExt callback) {
+    /*package*/ boolean connect(Boolean autoConnect, BluetoothGattCallback callback) {
         if (DBG) Log.d(TAG, "connect() - device: " + mDevice.getAddress() + ", auto: " + autoConnect);
         synchronized(mStateLock) {
             if (mConnState != CONN_STATE_IDLE) {
@@ -749,7 +781,7 @@
      * recommendation, wether the PHY change will happen depends on other applications peferences,
      * local and remote controller capabilities. Controller can override these settings.
      * <p>
-     * {@link BluetoothGattCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+     * {@link BluetoothGattCallback#onPhyUpdate} will be triggered as a result of this call, even
      * if no PHY change happens. It is also triggered when remote device updates the PHY.
      *
      * @param txPhy preferred transmitter PHY. Bitwise OR of any of
@@ -773,7 +805,7 @@
 
     /**
      * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
-     * in {@link BluetoothGattCallbackExt#onPhyRead}
+     * in {@link BluetoothGattCallback#onPhyRead}
      */
     public void readPhy() {
         try {
@@ -797,7 +829,7 @@
      * characteristics and descriptors.
      *
      * <p>This is an asynchronous operation. Once service discovery is completed,
-     * the {@link BluetoothGattCallbackExt#onServicesDiscovered} callback is
+     * the {@link BluetoothGattCallback#onServicesDiscovered} callback is
      * triggered. If the discovery was successful, the remote services can be
      * retrieved using the {@link #getServices} function.
      *
@@ -876,7 +908,7 @@
      * Reads the requested characteristic from the associated remote device.
      *
      * <p>This is an asynchronous operation. The result of the read operation
-     * is reported by the {@link BluetoothGattCallbackExt#onCharacteristicRead}
+     * is reported by the {@link BluetoothGattCallback#onCharacteristicRead}
      * callback.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -918,7 +950,7 @@
      * Writes a given characteristic and its values to the associated remote device.
      *
      * <p>Once the write operation has been completed, the
-     * {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback is invoked,
+     * {@link BluetoothGattCallback#onCharacteristicWrite} callback is invoked,
      * reporting the result of the operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -962,7 +994,7 @@
      * Reads the value for a given descriptor from the associated remote device.
      *
      * <p>Once the read operation has been completed, the
-     * {@link BluetoothGattCallbackExt#onDescriptorRead} callback is
+     * {@link BluetoothGattCallback#onDescriptorRead} callback is
      * triggered, signaling the result of the operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1003,7 +1035,7 @@
     /**
      * Write the value of a given descriptor to the associated remote device.
      *
-     * <p>A {@link BluetoothGattCallbackExt#onDescriptorWrite} callback is
+     * <p>A {@link BluetoothGattCallback#onDescriptorWrite} callback is
      * triggered to report the result of the write operation.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1047,7 +1079,7 @@
      * <p>Once a reliable write transaction has been initiated, all calls
      * to {@link #writeCharacteristic} are sent to the remote device for
      * verification and queued up for atomic execution. The application will
-     * receive an {@link BluetoothGattCallbackExt#onCharacteristicWrite} callback
+     * receive an {@link BluetoothGattCallback#onCharacteristicWrite} callback
      * in response to every {@link #writeCharacteristic} call and is responsible
      * for verifying if the value has been transmitted accurately.
      *
@@ -1081,7 +1113,7 @@
      * <p>This function will commit all queued up characteristic write
      * operations for a given remote device.
      *
-     * <p>A {@link BluetoothGattCallbackExt#onReliableWriteCompleted} callback is
+     * <p>A {@link BluetoothGattCallback#onReliableWriteCompleted} callback is
      * invoked to indicate whether the transaction has been executed correctly.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1138,7 +1170,7 @@
      * Enable or disable notifications/indications for a given characteristic.
      *
      * <p>Once notifications are enabled for a characteristic, a
-     * {@link BluetoothGattCallbackExt#onCharacteristicChanged} callback will be
+     * {@link BluetoothGattCallback#onCharacteristicChanged} callback will be
      * triggered if the remote device indicates that the given characteristic
      * has changed.
      *
@@ -1193,7 +1225,7 @@
     /**
      * Read the RSSI for a connected remote device.
      *
-     * <p>The {@link BluetoothGattCallbackExt#onReadRemoteRssi} callback will be
+     * <p>The {@link BluetoothGattCallback#onReadRemoteRssi} callback will be
      * invoked when the RSSI value has been read.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
@@ -1221,7 +1253,7 @@
      * the data sent is truncated to the MTU size. This function may be used
      * to request a larger MTU size to be able to send more data at once.
      *
-     * <p>A {@link BluetoothGattCallbackExt#onMtuChanged} callback will indicate
+     * <p>A {@link BluetoothGattCallback#onMtuChanged} callback will indicate
      * whether this operation was successful.
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattCallback.java b/core/java/android/bluetooth/BluetoothGattCallback.java
index 4da106d..11a15c6 100644
--- a/core/java/android/bluetooth/BluetoothGattCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattCallback.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -18,22 +18,183 @@
 
 /**
  * This abstract class is used to implement {@link BluetoothGatt} callbacks.
- * @deprecated use {@link BluetoothGattCallbackExt}
  */
-public abstract class BluetoothGattCallback extends BluetoothGattCallbackExt {
+public abstract class BluetoothGattCallback{
 
     /**
-     * @hide
+     * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
+     * remote device changing the PHY.
+     *
+     * @param gatt GATT client
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param status status of the operation
      */
-    @Override
     public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
 
     /**
-     * @hide
+     * Callback triggered as result of {@link BluetoothGatt#readPhy}
+     *
+     * @param gatt GATT client
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
+     * @param status status of the operation
      */
-    @Override
     public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
     }
 
+    /**
+     * Callback indicating when GATT client has connected/disconnected to/from a remote
+     * GATT server.
+     *
+     * @param gatt GATT client
+     * @param status Status of the connect or disconnect operation.
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     * @param newState Returns the new connection state. Can be one of
+     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
+     *                  {@link BluetoothProfile#STATE_CONNECTED}
+     */
+    public void onConnectionStateChange(BluetoothGatt gatt, int status,
+                                        int newState) {
+    }
+
+    /**
+     * Callback invoked when the list of remote services, characteristics and descriptors
+     * for the remote device have been updated, ie new services have been discovered.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
+     *               has been explored successfully.
+     */
+    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
+    }
+
+    /**
+     * Callback reporting the result of a characteristic read operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
+     * @param characteristic Characteristic that was read from the associated
+     *                       remote device.
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+     *               was completed successfully.
+     */
+    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
+                                     int status) {
+    }
+
+    /**
+     * Callback indicating the result of a characteristic write operation.
+     *
+     * <p>If this callback is invoked while a reliable write transaction is
+     * in progress, the value of the characteristic represents the value
+     * reported by the remote device. An application should compare this
+     * value to the desired value to be written. If the values don't match,
+     * the application must abort the reliable write transaction.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
+     * @param characteristic Characteristic that was written to the associated
+     *                       remote device.
+     * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     */
+    public void onCharacteristicWrite(BluetoothGatt gatt,
+                                      BluetoothGattCharacteristic characteristic, int status) {
+    }
+
+    /**
+     * Callback triggered as a result of a remote characteristic notification.
+     *
+     * @param gatt GATT client the characteristic is associated with
+     * @param characteristic Characteristic that has been updated as a result
+     *                       of a remote notification event.
+     */
+    public void onCharacteristicChanged(BluetoothGatt gatt,
+                                        BluetoothGattCharacteristic characteristic) {
+    }
+
+    /**
+     * Callback reporting the result of a descriptor read operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
+     * @param descriptor Descriptor that was read from the associated
+     *                   remote device.
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
+     *               was completed successfully
+     */
+    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+                                 int status) {
+    }
+
+    /**
+     * Callback indicating the result of a descriptor write operation.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
+     * @param descriptor Descriptor that was writte to the associated
+     *                   remote device.
+     * @param status The result of the write operation
+     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
+     */
+    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
+                                  int status) {
+    }
+
+    /**
+     * Callback invoked when a reliable write transaction has been completed.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
+     *               transaction was executed successfully
+     */
+    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
+    }
+
+    /**
+     * Callback reporting the RSSI for a remote device connection.
+     *
+     * This callback is triggered in response to the
+     * {@link BluetoothGatt#readRemoteRssi} function.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
+     * @param rssi The RSSI value for the remote device
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
+     */
+    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
+    }
+
+    /**
+     * Callback indicating the MTU for a given device connection has changed.
+     *
+     * This callback is triggered in response to the
+     * {@link BluetoothGatt#requestMtu} function, or in response to a connection
+     * event.
+     *
+     * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
+     * @param mtu The new MTU size
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
+     */
+    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
+    }
+
+    /**
+     * Callback indicating the connection parameters were updated.
+     *
+     * @param gatt GATT client involved
+     * @param interval Connection interval used on this connection, 1.25ms unit. Valid
+     *            range is from 6 (7.5ms) to 3200 (4000ms).
+     * @param latency Slave latency for the connection in number of connection events. Valid
+     *            range is from 0 to 499
+     * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is
+     *            from 10 (0.1s) to 3200 (32s)
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
+     *                successfully
+     * @hide
+     */
+    public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,
+                                    int status) {
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackExt.java b/core/java/android/bluetooth/BluetoothGattCallbackExt.java
deleted file mode 100644
index 63774c8..0000000
--- a/core/java/android/bluetooth/BluetoothGattCallbackExt.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-/**
- * This abstract class is used to implement {@link BluetoothGatt} callbacks.
- */
-public abstract class BluetoothGattCallbackExt {
-
-    /**
-     * Callback triggered as result of {@link BluetoothGatt#setPreferredPhy}, or as a result of
-     * remote device changing the PHY.
-     *
-     * @param gatt GATT client
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status status of the operation
-     */
-    public void onPhyUpdate(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGatt#readPhy}
-     *
-     * @param gatt GATT client
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}.
-     * @param status status of the operation
-     */
-    public void onPhyRead(BluetoothGatt gatt, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback indicating when GATT client has connected/disconnected to/from a remote
-     * GATT server.
-     *
-     * @param gatt GATT client
-     * @param status Status of the connect or disconnect operation.
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     * @param newState Returns the new connection state. Can be one of
-     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
-     *                  {@link BluetoothProfile#STATE_CONNECTED}
-     */
-    public void onConnectionStateChange(BluetoothGatt gatt, int status,
-                                        int newState) {
-    }
-
-    /**
-     * Callback invoked when the list of remote services, characteristics and descriptors
-     * for the remote device have been updated, ie new services have been discovered.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#discoverServices}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the remote device
-     *               has been explored successfully.
-     */
-    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
-    }
-
-    /**
-     * Callback reporting the result of a characteristic read operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readCharacteristic}
-     * @param characteristic Characteristic that was read from the associated
-     *                       remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
-     *               was completed successfully.
-     */
-    public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic,
-                                     int status) {
-    }
-
-    /**
-     * Callback indicating the result of a characteristic write operation.
-     *
-     * <p>If this callback is invoked while a reliable write transaction is
-     * in progress, the value of the characteristic represents the value
-     * reported by the remote device. An application should compare this
-     * value to the desired value to be written. If the values don't match,
-     * the application must abort the reliable write transaction.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeCharacteristic}
-     * @param characteristic Characteristic that was written to the associated
-     *                       remote device.
-     * @param status The result of the write operation
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     */
-    public void onCharacteristicWrite(BluetoothGatt gatt,
-                                      BluetoothGattCharacteristic characteristic, int status) {
-    }
-
-    /**
-     * Callback triggered as a result of a remote characteristic notification.
-     *
-     * @param gatt GATT client the characteristic is associated with
-     * @param characteristic Characteristic that has been updated as a result
-     *                       of a remote notification event.
-     */
-    public void onCharacteristicChanged(BluetoothGatt gatt,
-                                        BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * Callback reporting the result of a descriptor read operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readDescriptor}
-     * @param descriptor Descriptor that was read from the associated
-     *                   remote device.
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the read operation
-     *               was completed successfully
-     */
-    public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-                                 int status) {
-    }
-
-    /**
-     * Callback indicating the result of a descriptor write operation.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#writeDescriptor}
-     * @param descriptor Descriptor that was writte to the associated
-     *                   remote device.
-     * @param status The result of the write operation
-     *               {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
-     */
-    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor,
-                                  int status) {
-    }
-
-    /**
-     * Callback invoked when a reliable write transaction has been completed.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#executeReliableWrite}
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the reliable write
-     *               transaction was executed successfully
-     */
-    public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
-    }
-
-    /**
-     * Callback reporting the RSSI for a remote device connection.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#readRemoteRssi} function.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#readRemoteRssi}
-     * @param rssi The RSSI value for the remote device
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the RSSI was read successfully
-     */
-    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * This callback is triggered in response to the
-     * {@link BluetoothGatt#requestMtu} function, or in response to a connection
-     * event.
-     *
-     * @param gatt GATT client invoked {@link BluetoothGatt#requestMtu}
-     * @param mtu The new MTU size
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the MTU has been changed successfully
-     */
-    public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
-    }
-}
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 9ee739f..c991e2f 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -46,7 +46,7 @@
 
     private BluetoothAdapter mAdapter;
     private IBluetoothGatt mService;
-    private BluetoothGattServerCallbackExt mCallback;
+    private BluetoothGattServerCallback mCallback;
 
     private Object mServerIfLock = new Object();
     private int mServerIf;
@@ -65,6 +65,7 @@
              * Application interface registered - app is ready to go
              * @hide
              */
+            @Override
             public void onServerRegistered(int status, int serverIf) {
                 if (DBG) Log.d(TAG, "onServerRegistered() - status=" + status
                     + " serverIf=" + serverIf);
@@ -80,18 +81,10 @@
             }
 
             /**
-             * Callback reporting an LE scan result.
-             * @hide
-             */
-            public void onScanResult(String address, int rssi, byte[] advData) {
-                if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
-                // no op
-            }
-
-            /**
              * Server connection state changed
              * @hide
              */
+            @Override
             public void onServerConnectionState(int status, int serverIf,
                                                 boolean connected, String address) {
                 if (DBG) Log.d(TAG, "onServerConnectionState() - status=" + status
@@ -109,6 +102,7 @@
              * Service has been added
              * @hide
              */
+            @Override
             public void onServiceAdded(int status, BluetoothGattService service) {
                 if (DBG) Log.d(TAG, "onServiceAdded() - handle=" + service.getInstanceId()
                     + " uuid=" + service.getUuid() + " status=" + status);
@@ -149,6 +143,7 @@
              * Remote client characteristic read request.
              * @hide
              */
+            @Override
             public void onCharacteristicReadRequest(String address, int transId,
                             int offset, boolean isLong, int handle) {
                 if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
@@ -171,6 +166,7 @@
              * Remote client descriptor read request.
              * @hide
              */
+            @Override
             public void onDescriptorReadRequest(String address, int transId,
                             int offset, boolean isLong, int handle) {
                 if (VDBG) Log.d(TAG, "onCharacteristicReadRequest() - handle=" + handle);
@@ -193,6 +189,7 @@
              * Remote client characteristic write request.
              * @hide
              */
+            @Override
             public void onCharacteristicWriteRequest(String address, int transId,
                             int offset, int length, boolean isPrep, boolean needRsp,
                             int handle, byte[] value) {
@@ -218,6 +215,7 @@
              * Remote client descriptor write request.
              * @hide
              */
+            @Override
             public void onDescriptorWriteRequest(String address, int transId, int offset,
                             int length, boolean isPrep, boolean needRsp, int handle, byte[] value) {
                 if (VDBG) Log.d(TAG, "onDescriptorWriteRequest() - handle=" + handle);
@@ -241,6 +239,7 @@
              * Execute pending writes.
              * @hide
              */
+            @Override
             public void onExecuteWrite(String address, int transId,
                                        boolean execWrite) {
                 if (DBG) Log.d(TAG, "onExecuteWrite() - "
@@ -261,6 +260,7 @@
              * A notification/indication has been sent.
              * @hide
              */
+            @Override
             public void onNotificationSent(String address, int status) {
                 if (VDBG) Log.d(TAG, "onNotificationSent() - "
                     + "device=" + address + ", status=" + status);
@@ -279,6 +279,7 @@
              * The MTU for a connection has changed
              * @hide
              */
+            @Override
             public void onMtuChanged(String address, int mtu) {
                 if (DBG) Log.d(TAG, "onMtuChanged() - "
                     + "device=" + address + ", mtu=" + mtu);
@@ -297,6 +298,7 @@
              * The PHY for a connection was updated
              * @hide
              */
+            @Override
             public void onPhyUpdate(String address, int txPhy, int rxPhy, int status) {
                 if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
                     + ", rxPHy=" + rxPhy);
@@ -315,6 +317,7 @@
              * The PHY for a connection was read
              * @hide
              */
+            @Override
             public void onPhyRead(String address, int txPhy, int rxPhy, int status) {
                 if (DBG) Log.d(TAG, "onPhyUpdate() - " + "device=" + address + ", txPHy=" + txPhy
                     + ", rxPHy=" + rxPhy);
@@ -328,6 +331,28 @@
                     Log.w(TAG, "Unhandled exception: " + ex);
                 }
             }
+
+            /**
+             * Callback invoked when the given connection is updated
+             * @hide
+             */
+            @Override
+            public void onConnectionUpdated(String address, int interval, int latency,
+                                            int timeout, int status) {
+                if (DBG) Log.d(TAG, "onConnectionUpdated() - Device=" + address +
+                            " interval=" + interval + " latency=" + latency +
+                            " timeout=" + timeout + " status=" + status);
+                BluetoothDevice device = mAdapter.getRemoteDevice(address);
+                if (device == null) return;
+
+                try {
+                    mCallback.onConnectionUpdated(device, interval, latency,
+                                                  timeout, status);
+                } catch (Exception ex) {
+                    Log.w(TAG, "Unhandled exception: " + ex);
+                }
+            }
+
         };
 
     /**
@@ -396,7 +421,7 @@
      * @return true, the callback will be called to notify success or failure,
      *         false on immediate error
      */
-    /*package*/ boolean registerCallback(BluetoothGattServerCallbackExt callback) {
+    /*package*/ boolean registerCallback(BluetoothGattServerCallback callback) {
         if (DBG) Log.d(TAG, "registerCallback()");
         if (mService == null) {
             Log.e(TAG, "GATT service not available");
@@ -472,7 +497,7 @@
      *
      * <p>The connection may not be established right away, but will be
      * completed when the remote device is available. A
-     * {@link BluetoothGattServerCallbackExt#onConnectionStateChange} callback will be
+     * {@link BluetoothGattServerCallback#onConnectionStateChange} callback will be
      * invoked when the connection state changes as a result of this function.
      *
      * <p>The autoConnect paramter determines whether to actively connect to
@@ -528,7 +553,7 @@
      * recommendation, wether the PHY change will happen depends on other applications peferences,
      * local and remote controller capabilities. Controller can override these settings.
      * <p>
-     * {@link BluetoothGattServerCallbackExt#onPhyUpdate} will be triggered as a result of this call, even
+     * {@link BluetoothGattServerCallback#onPhyUpdate} will be triggered as a result of this call, even
      * if no PHY change happens. It is also triggered when remote device updates the PHY.
      *
      * @param device The remote device to send this response to
@@ -553,7 +578,7 @@
 
     /**
      * Read the current transmitter PHY and receiver PHY of the connection. The values are returned
-     * in {@link BluetoothGattServerCallbackExt#onPhyRead}
+     * in {@link BluetoothGattServerCallback#onPhyRead}
      *
      * @param device The remote device to send this response to
      */
@@ -572,10 +597,10 @@
      * is received by one of these callback methods:
      *
      * <ul>
-     *      <li>{@link BluetoothGattServerCallbackExt#onCharacteristicReadRequest}
-     *      <li>{@link BluetoothGattServerCallbackExt#onCharacteristicWriteRequest}
-     *      <li>{@link BluetoothGattServerCallbackExt#onDescriptorReadRequest}
-     *      <li>{@link BluetoothGattServerCallbackExt#onDescriptorWriteRequest}
+     *      <li>{@link BluetoothGattServerCallback#onCharacteristicReadRequest}
+     *      <li>{@link BluetoothGattServerCallback#onCharacteristicWriteRequest}
+     *      <li>{@link BluetoothGattServerCallback#onDescriptorReadRequest}
+     *      <li>{@link BluetoothGattServerCallback#onDescriptorWriteRequest}
      * </ul>
      *
      * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallback.java b/core/java/android/bluetooth/BluetoothGattServerCallback.java
index 75ceb52..3b8f962 100644
--- a/core/java/android/bluetooth/BluetoothGattServerCallback.java
+++ b/core/java/android/bluetooth/BluetoothGattServerCallback.java
@@ -20,21 +20,187 @@
 
 /**
  * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- * @deprecated please use {@link BluetoothGattServerCallbackExt}
  */
-public abstract class BluetoothGattServerCallback extends BluetoothGattServerCallbackExt {
+public abstract class BluetoothGattServerCallback {
 
     /**
-     * @hide
+     * Callback indicating when a remote device has been connected or disconnected.
+     *
+     * @param device Remote device that has been connected or disconnected.
+     * @param status Status of the connect or disconnect operation.
+     * @param newState Returns the new connection state. Can be one of
+     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
+     *                  {@link BluetoothProfile#STATE_CONNECTED}
      */
-    @Override
+    public void onConnectionStateChange(BluetoothDevice device, int status,
+                                        int newState) {
+    }
+
+    /**
+     * Indicates whether a local service has been added successfully.
+     *
+     * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
+     *               was added successfully.
+     * @param service The service that has been added
+     */
+    public void onServiceAdded(int status, BluetoothGattService service) {
+    }
+
+    /**
+     * A remote client has requested to read a local characteristic.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the read operation
+     * @param requestId The Id of the request
+     * @param offset Offset into the value of the characteristic
+     * @param characteristic Characteristic to be read
+     */
+    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
+                        int offset, BluetoothGattCharacteristic characteristic) {
+    }
+
+    /**
+     * A remote client has requested to write to a local characteristic.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operation
+     * @param requestId The Id of the request
+     * @param characteristic Characteristic to be written to.
+     * @param preparedWrite true, if this write operation should be queued for
+     *                      later execution.
+     * @param responseNeeded true, if the remote device requires a response
+     * @param offset The offset given for the value
+     * @param value The value the client wants to assign to the characteristic
+     */
+    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
+                                             BluetoothGattCharacteristic characteristic,
+                                             boolean preparedWrite, boolean responseNeeded,
+                                             int offset, byte[] value) {
+    }
+
+    /**
+     * A remote client has requested to read a local descriptor.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the read operation
+     * @param requestId The Id of the request
+     * @param offset Offset into the value of the characteristic
+     * @param descriptor Descriptor to be read
+     */
+    public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
+                                        int offset, BluetoothGattDescriptor descriptor) {
+    }
+
+    /**
+     * A remote client has requested to write to a local descriptor.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operation
+     * @param requestId The Id of the request
+     * @param descriptor Descriptor to be written to.
+     * @param preparedWrite true, if this write operation should be queued for
+     *                      later execution.
+     * @param responseNeeded true, if the remote device requires a response
+     * @param offset The offset given for the value
+     * @param value The value the client wants to assign to the descriptor
+     */
+    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
+                                         BluetoothGattDescriptor descriptor,
+                                         boolean preparedWrite, boolean responseNeeded,
+                                         int offset,  byte[] value) {
+    }
+
+    /**
+     * Execute all pending write operations for this device.
+     *
+     * <p>An application must call {@link BluetoothGattServer#sendResponse}
+     * to complete the request.
+     *
+     * @param device The remote device that has requested the write operations
+     * @param requestId The Id of the request
+     * @param execute Whether the pending writes should be executed (true) or
+     *                cancelled (false)
+     */
+    public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
+    }
+
+    /**
+     * Callback invoked when a notification or indication has been sent to
+     * a remote device.
+     *
+     * <p>When multiple notifications are to be sent, an application must
+     * wait for this callback to be received before sending additional
+     * notifications.
+     *
+     * @param device The remote device the notification has been sent to
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
+     */
+    public void onNotificationSent(BluetoothDevice device, int status) {
+    }
+
+    /**
+     * Callback indicating the MTU for a given device connection has changed.
+     *
+     * <p>This callback will be invoked if a remote client has requested to change
+     * the MTU for a given connection.
+     *
+     * @param device The remote device that requested the MTU change
+     * @param mtu The new MTU size
+     */
+    public void onMtuChanged(BluetoothDevice device, int mtu) {
+    }
+
+    /**
+     * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
+     * of remote device changing the PHY.
+     *
+     * @param device The remote device
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param status status of the operation
+     */
     public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
 
     /**
-     * @hide
+     * Callback triggered as result of {@link BluetoothGattServer#readPhy}
+     *
+     * @param device The remote device that requested the PHY read
+     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
+     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
+     * @param status status of the operation
      */
-    @Override
     public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
     }
+
+    /**
+     * Callback indicating the connection parameters were updated.
+     *
+     * @param device The remote device involved
+     * @param interval Connection interval used on this connection, 1.25ms unit. Valid
+     *            range is from 6 (7.5ms) to 3200 (4000ms).
+     * @param latency Slave latency for the connection in number of connection events. Valid
+     *            range is from 0 to 499
+     * @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is
+     *            from 10 (0.1s) to 3200 (32s)
+     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
+     *                successfully
+     * @hide
+     */
+    public void onConnectionUpdated(BluetoothDevice gatt, int interval, int latency, int timeout,
+                                    int status) {
+    }
+
 }
diff --git a/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java b/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
deleted file mode 100644
index 455cce0..0000000
--- a/core/java/android/bluetooth/BluetoothGattServerCallbackExt.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.BluetoothDevice;
-
-/**
- * This abstract class is used to implement {@link BluetoothGattServer} callbacks.
- */
-public abstract class BluetoothGattServerCallbackExt {
-
-    /**
-     * Callback indicating when a remote device has been connected or disconnected.
-     *
-     * @param device Remote device that has been connected or disconnected.
-     * @param status Status of the connect or disconnect operation.
-     * @param newState Returns the new connection state. Can be one of
-     *                  {@link BluetoothProfile#STATE_DISCONNECTED} or
-     *                  {@link BluetoothProfile#STATE_CONNECTED}
-     */
-    public void onConnectionStateChange(BluetoothDevice device, int status,
-                                        int newState) {
-    }
-
-    /**
-     * Indicates whether a local service has been added successfully.
-     *
-     * @param status Returns {@link BluetoothGatt#GATT_SUCCESS} if the service
-     *               was added successfully.
-     * @param service The service that has been added
-     */
-    public void onServiceAdded(int status, BluetoothGattService service) {
-    }
-
-    /**
-     * A remote client has requested to read a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param characteristic Characteristic to be read
-     */
-    public void onCharacteristicReadRequest(BluetoothDevice device, int requestId,
-                        int offset, BluetoothGattCharacteristic characteristic) {
-    }
-
-    /**
-     * A remote client has requested to write to a local characteristic.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param characteristic Characteristic to be written to.
-     * @param preparedWrite true, if this write operation should be queued for
-     *                      later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the characteristic
-     */
-    public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId,
-                                             BluetoothGattCharacteristic characteristic,
-                                             boolean preparedWrite, boolean responseNeeded,
-                                             int offset, byte[] value) {
-    }
-
-    /**
-     * A remote client has requested to read a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the read operation
-     * @param requestId The Id of the request
-     * @param offset Offset into the value of the characteristic
-     * @param descriptor Descriptor to be read
-     */
-    public void onDescriptorReadRequest(BluetoothDevice device, int requestId,
-                                        int offset, BluetoothGattDescriptor descriptor) {
-    }
-
-    /**
-     * A remote client has requested to write to a local descriptor.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operation
-     * @param requestId The Id of the request
-     * @param descriptor Descriptor to be written to.
-     * @param preparedWrite true, if this write operation should be queued for
-     *                      later execution.
-     * @param responseNeeded true, if the remote device requires a response
-     * @param offset The offset given for the value
-     * @param value The value the client wants to assign to the descriptor
-     */
-    public void onDescriptorWriteRequest(BluetoothDevice device, int requestId,
-                                         BluetoothGattDescriptor descriptor,
-                                         boolean preparedWrite, boolean responseNeeded,
-                                         int offset,  byte[] value) {
-    }
-
-    /**
-     * Execute all pending write operations for this device.
-     *
-     * <p>An application must call {@link BluetoothGattServer#sendResponse}
-     * to complete the request.
-     *
-     * @param device The remote device that has requested the write operations
-     * @param requestId The Id of the request
-     * @param execute Whether the pending writes should be executed (true) or
-     *                cancelled (false)
-     */
-    public void onExecuteWrite(BluetoothDevice device, int requestId, boolean execute) {
-    }
-
-    /**
-     * Callback invoked when a notification or indication has been sent to
-     * a remote device.
-     *
-     * <p>When multiple notifications are to be sent, an application must
-     * wait for this callback to be received before sending additional
-     * notifications.
-     *
-     * @param device The remote device the notification has been sent to
-     * @param status {@link BluetoothGatt#GATT_SUCCESS} if the operation was successful
-     */
-    public void onNotificationSent(BluetoothDevice device, int status) {
-    }
-
-    /**
-     * Callback indicating the MTU for a given device connection has changed.
-     *
-     * <p>This callback will be invoked if a remote client has requested to change
-     * the MTU for a given connection.
-     *
-     * @param device The remote device that requested the MTU change
-     * @param mtu The new MTU size
-     */
-    public void onMtuChanged(BluetoothDevice device, int mtu) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGattServer#setPreferredPhy}, or as a result
-     * of remote device changing the PHY.
-     *
-     * @param device The remote device
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status status of the operation
-     */
-    public void onPhyUpdate(BluetoothDevice device, int txPhy, int rxPhy, int status) {
-    }
-
-    /**
-     * Callback triggered as result of {@link BluetoothGattServer#readPhy}
-     *
-     * @param device The remote device that requested the PHY read
-     * @param txPhy the transmitter PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param rxPhy the receiver PHY in use. One of {@link BluetoothDevice#PHY_LE_1M},
-     *             {@link BluetoothDevice#PHY_LE_2M}, and {@link BluetoothDevice#PHY_LE_CODED}
-     * @param status status of the operation
-     */
-    public void onPhyRead(BluetoothDevice device, int txPhy, int rxPhy, int status) {
-    }
-}
diff --git a/core/java/android/bluetooth/IBluetooth.aidl b/core/java/android/bluetooth/IBluetooth.aidl
index 76ca554..b337817 100644
--- a/core/java/android/bluetooth/IBluetooth.aidl
+++ b/core/java/android/bluetooth/IBluetooth.aidl
@@ -108,6 +108,7 @@
     boolean isLeCodedPhySupported();
     boolean isLeExtendedAdvertisingSupported();
     boolean isLePeriodicAdvertisingSupported();
+    int getLeMaximumAdvertisingDataLength();
     BluetoothActivityEnergyInfo reportActivityInfo();
 
     /**
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 33fedc7..652a1c60 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -50,26 +50,18 @@
     void stopScan(in int scannerId);
     void flushPendingBatchResults(in int scannerId);
 
-    void registerAdvertiser(in IAdvertiserCallback callback);
-    void unregisterAdvertiser(in int advertiserId);
-    void startMultiAdvertising(in int advertiserId,
-                               in AdvertiseData advertiseData,
-                               in AdvertiseData scanResponse,
-                               in AdvertiseSettings settings);
-    void stopMultiAdvertising(in int advertiserId);
-
     void startAdvertisingSet(in AdvertisingSetParameters parameters, in AdvertiseData advertiseData,
                                 in AdvertiseData scanResponse, in PeriodicAdvertisingParameters periodicParameters,
-                                in AdvertiseData periodicData, in IAdvertisingSetCallback callback);
+                                in AdvertiseData periodicData, in int timeout, in IAdvertisingSetCallback callback);
     void stopAdvertisingSet(in IAdvertisingSetCallback callback);
 
-    void enableAdverisingSet(in int advertiserId, in boolean enable);
+    void enableAdvertisingSet(in int advertiserId, in boolean enable, in int timeout);
     void setAdvertisingData(in int advertiserId, in AdvertiseData data);
     void setScanResponseData(in int advertiserId, in AdvertiseData data);
     void setAdvertisingParameters(in int advertiserId, in AdvertisingSetParameters parameters);
     void setPeriodicAdvertisingParameters(in int advertiserId, in PeriodicAdvertisingParameters parameters);
     void setPeriodicAdvertisingData(in int advertiserId, in AdvertiseData data);
-    void periodicAdvertisingEnable(in int advertiserId, in boolean enable);
+    void setPeriodicAdvertisingEnable(in int advertiserId, in boolean enable);
 
     void registerSync(in ScanResult scanResult, in int skip, in int timeout, in IPeriodicAdvertisingCallback callback);
     void unregisterSync(in IPeriodicAdvertisingCallback callback);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl b/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
index 736f4b2..ed69e54 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallbackExt.aidl
@@ -37,4 +37,6 @@
     void onNotify(in String address, in int handle, in byte[] value);
     void onReadRemoteRssi(in String address, in int rssi, in int status);
     void onConfigureMTU(in String address, in int mtu, in int status);
+    void onConnectionUpdated(in String address, in int interval, in int latency,
+                             in int timeout, in int status);
 }
diff --git a/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl b/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
index 091ffb3..267e882 100644
--- a/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattServerCallbackExt.aidl
@@ -42,4 +42,6 @@
     void onMtuChanged(in String address, in int mtu);
     void onPhyUpdate(in String address, in int txPhy, in int rxPhy, in int status);
     void onPhyRead(in String address, in int txPhy, in int rxPhy, in int status);
+    void onConnectionUpdated(in String address, in int interval, in int latency,
+                             in int timeout, in int status);
 }
diff --git a/core/java/android/bluetooth/le/AdvertisingSet.java b/core/java/android/bluetooth/le/AdvertisingSet.java
index 1524022..7355b0d 100644
--- a/core/java/android/bluetooth/le/AdvertisingSet.java
+++ b/core/java/android/bluetooth/le/AdvertisingSet.java
@@ -63,9 +63,9 @@
      * Requires {@link android.Manifest.permission#BLUETOOTH_ADMIN}
      *
      */
-    public void enableAdvertising(boolean enable) {
+    public void enableAdvertising(boolean enable, int timeout) {
         try {
-            gatt.enableAdverisingSet(this.advertiserId, enable);
+            gatt.enableAdvertisingSet(this.advertiserId, enable, timeout);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
@@ -143,9 +143,9 @@
      * Used to enable/disable periodic advertising. This method returns immediately, the operation
      * status is delivered through {@code callback.onPeriodicAdvertisingEnable()}.
      */
-    public void periodicAdvertisingEnable(boolean enable) {
+    public void setPeriodicAdvertisingEnable(boolean enable) {
         try {
-            gatt.periodicAdvertisingEnable(this.advertiserId, enable);
+            gatt.setPeriodicAdvertisingEnable(this.advertiserId, enable);
         } catch (RemoteException e) {
             Log.e(TAG, "remote exception - ", e);
         }
diff --git a/core/java/android/bluetooth/le/AdvertisingSetCallback.java b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
index ceed8d9..fe3b1cd 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetCallback.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetCallback.java
@@ -62,9 +62,10 @@
      * null, and status will be set to proper error code.
      *
      * @param advertisingSet The advertising set that was started or null if error.
+     * @param txPower tx power that will be used for this set.
      * @param status Status of the operation.
      */
-    public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int status) {}
+    public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {}
 
     /**
      * Callback triggered in response to {@link BluetoothLeAdvertiser#stopAdvertisingSet}
@@ -106,10 +107,11 @@
      * indicating result of the operation.
      *
      * @param advertisingSet The advertising set.
+     * @param txPower tx power that will be used for this set.
      * @param status Status of the operation.
      */
     public void onAdvertisingParametersUpdated(AdvertisingSet advertisingSet,
-                                               int status) {}
+                                               int txPower, int status) {}
 
     /**
      * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingParameters}
@@ -133,12 +135,12 @@
                                              int status) {}
 
     /**
-     * Callback triggered in response to {@link AdvertisingSet#periodicAdvertisingEnable}
+     * Callback triggered in response to {@link AdvertisingSet#setPeriodicAdvertisingEnable}
      * indicating result of the operation.
      *
      * @param advertisingSet The advertising set.
      * @param status Status of the operation.
      */
-    public void onPeriodicAdvertisingEnable(AdvertisingSet advertisingSet, boolean enable,
+    public void onPeriodicAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enable,
                                             int status) {}
 }
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/AdvertisingSetParameters.java b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
index 03a01e1..fe1f425 100644
--- a/core/java/android/bluetooth/le/AdvertisingSetParameters.java
+++ b/core/java/android/bluetooth/le/AdvertisingSetParameters.java
@@ -116,16 +116,16 @@
     private final int primaryPhy;
     private final int secondaryPhy;
     private final boolean connectable;
+    private final boolean scannable;
     private final int interval;
     private final int txPowerLevel;
-    private final int timeoutMillis;
 
-    private AdvertisingSetParameters(boolean connectable, boolean isLegacy,
+    private AdvertisingSetParameters(boolean connectable, boolean scannable, boolean isLegacy,
                                      boolean isAnonymous, boolean includeTxPower,
                                      int primaryPhy, int secondaryPhy,
-                                     int interval, int txPowerLevel,
-                                     int timeoutMillis) {
+                                     int interval, int txPowerLevel) {
         this.connectable = connectable;
+        this.scannable = scannable;
         this.isLegacy = isLegacy;
         this.isAnonymous = isAnonymous;
         this.includeTxPower = includeTxPower;
@@ -133,11 +133,11 @@
         this.secondaryPhy = secondaryPhy;
         this.interval = interval;
         this.txPowerLevel = txPowerLevel;
-        this.timeoutMillis = timeoutMillis;
     }
 
     private AdvertisingSetParameters(Parcel in) {
         connectable = in.readInt() != 0 ? true : false;
+        scannable = in.readInt() != 0 ? true : false;
         isLegacy = in.readInt() != 0 ? true : false;
         isAnonymous = in.readInt() != 0 ? true : false;
         includeTxPower = in.readInt() != 0 ? true : false;
@@ -145,7 +145,6 @@
         secondaryPhy = in.readInt();
         interval = in.readInt();
         txPowerLevel = in.readInt();
-        timeoutMillis = in.readInt();
     }
 
     /**
@@ -154,6 +153,11 @@
     public boolean isConnectable() { return connectable; }
 
     /**
+     * Returns whether the advertisement will be scannable.
+     */
+    public boolean isScannable() { return scannable; }
+
+    /**
      * Returns whether the legacy advertisement will be used.
      */
     public boolean isLegacy() { return isLegacy; }
@@ -188,11 +192,6 @@
      */
     public int getTxPowerLevel() { return txPowerLevel; }
 
-    /**
-     * Returns the advertising time limit in milliseconds.
-     */
-    public int getTimeout() { return timeoutMillis; }
-
     @Override
     public String toString() {
         return "AdvertisingSetParameters [connectable=" + connectable
@@ -202,8 +201,7 @@
              + ", primaryPhy=" + primaryPhy
              + ", secondaryPhy=" + secondaryPhy
              + ", interval=" + interval
-             + ", txPowerLevel=" + txPowerLevel
-             + ", timeoutMillis=" + timeoutMillis + "]";
+             + ", txPowerLevel=" + txPowerLevel + "]";
     }
 
     @Override
@@ -214,6 +212,7 @@
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(connectable ? 1 : 0);
+        dest.writeInt(scannable ? 1 : 0);
         dest.writeInt(isLegacy ? 1 : 0);
         dest.writeInt(isAnonymous ? 1 : 0);
         dest.writeInt(includeTxPower ? 1 : 0);
@@ -221,7 +220,6 @@
         dest.writeInt(secondaryPhy);
         dest.writeInt(interval);
         dest.writeInt(txPowerLevel);
-        dest.writeInt(timeoutMillis);
     }
 
     public static final Parcelable.Creator<AdvertisingSetParameters> CREATOR =
@@ -243,6 +241,7 @@
     public static final class Builder {
 
         private boolean connectable = true;
+        private boolean scannable = true;
         private boolean isLegacy = false;
         private boolean isAnonymous = false;
         private boolean includeTxPower = false;
@@ -250,7 +249,6 @@
         private int secondaryPhy = PHY_LE_1M;
         private int interval = INTERVAL_LOW;
         private int txPowerLevel = TX_POWER_MEDIUM;
-        private int timeoutMillis = 0;
 
         /**
          * Set whether the advertisement type should be connectable or
@@ -266,6 +264,18 @@
         }
 
         /**
+         * Set whether the advertisement type should be scannable
+         * Legacy advertisements can be both connectable and scannable. Other
+         * advertisements can be scannable only if not connectable.
+         * @param scannable Controls whether the advertisment type will be
+         * scannable (true) or non-scannable (false).
+         */
+        public Builder setScannable(boolean scannable) {
+            this.scannable = scannable;
+            return this;
+        }
+
+        /**
          * When set to true, advertising set will advertise 4.x Spec compliant
          * advertisements.
          *
@@ -284,7 +294,7 @@
          *
          * @param isAnonymous wether anonymous advertising should be used.
          */
-        public Builder setAnonymouus(boolean isAnonymous) {
+        public Builder setAnonymous(boolean isAnonymous) {
             this.isAnonymous = isAnonymous;
             return this;
         }
@@ -380,30 +390,12 @@
         }
 
         /**
-         * Limit advertising to a given amount of time.
-         * @param timeoutMillis Advertising time limit. May not exceed 180000
-         * milliseconds. A value of 0 will disable the time limit.
-         * @throws IllegalArgumentException If the provided timeout is over 180000
-         * ms.
-         */
-        public Builder setTimeout(int timeoutMillis) {
-            if (timeoutMillis < 0 || timeoutMillis > LIMITED_ADVERTISING_MAX_MILLIS) {
-                throw new IllegalArgumentException("timeoutMillis invalid (must be 0-" +
-                                                   LIMITED_ADVERTISING_MAX_MILLIS +
-                                                   " milliseconds)");
-            }
-            this.timeoutMillis = timeoutMillis;
-            return this;
-        }
-
-        /**
          * Build the {@link AdvertisingSetParameters} object.
          */
         public AdvertisingSetParameters build() {
-            return new AdvertisingSetParameters(connectable, isLegacy, isAnonymous,
+            return new AdvertisingSetParameters(connectable, scannable, isLegacy, isAnonymous,
                                                 includeTxPower, primaryPhy,
-                                                secondaryPhy, interval, txPowerLevel,
-                                                timeoutMillis);
+                                                secondaryPhy, interval, txPowerLevel);
         }
     }
 }
\ No newline at end of file
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index e03c947..242ee77 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -28,6 +28,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
@@ -60,11 +61,12 @@
     private final IBluetoothManager mBluetoothManager;
     private final Handler mHandler;
     private BluetoothAdapter mBluetoothAdapter;
-    private final Map<AdvertiseCallback, AdvertiseCallbackWrapper>
-            mLeAdvertisers = new HashMap<AdvertiseCallback, AdvertiseCallbackWrapper>();
+    private final Map<AdvertiseCallback, AdvertisingSetCallback>
+            mLegacyAdvertisers = new HashMap<>();
     private final Map<AdvertisingSetCallback, IAdvertisingSetCallback>
-            advertisingSetCallbackWrappers = new HashMap<>();
-    private final Map<Integer, AdvertisingSet> advertisingSets = new HashMap<>();
+            mCallbackWrappers = Collections.synchronizedMap(new HashMap<>());
+    private final Map<Integer, AdvertisingSet>
+            mAdvertisingSets = Collections.synchronizedMap(new HashMap<>());
 
     /**
      * Use BluetoothAdapter.getLeAdvertiser() instead.
@@ -109,7 +111,7 @@
     public void startAdvertising(AdvertiseSettings settings,
             AdvertiseData advertiseData, AdvertiseData scanResponse,
             final AdvertiseCallback callback) {
-        synchronized (mLeAdvertisers) {
+        synchronized (mLegacyAdvertisers) {
             BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
             if (callback == null) {
                 throw new IllegalArgumentException("callback cannot be null");
@@ -120,25 +122,69 @@
                 postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
                 return;
             }
-            if (mLeAdvertisers.containsKey(callback)) {
+            if (mLegacyAdvertisers.containsKey(callback)) {
                 postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_ALREADY_STARTED);
                 return;
             }
 
-            IBluetoothGatt gatt;
-            try {
-                gatt = mBluetoothManager.getBluetoothGatt();
-            } catch (RemoteException e) {
-                Log.e(TAG, "Failed to get Bluetooth gatt - ", e);
-                postStartFailure(callback, AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR);
-                return;
+            AdvertisingSetParameters.Builder parameters = new AdvertisingSetParameters.Builder();
+            parameters.setLegacyMode(true);
+            parameters.setConnectable(isConnectable);
+            parameters.setScannable(true); // legacy advertisements we support are always scannable
+            if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_POWER) {
+                parameters.setInterval(1600); // 1s
+            } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_BALANCED) {
+                parameters.setInterval(400); // 250ms
+            } else if (settings.getMode() == AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY) {
+                parameters.setInterval(160); // 100ms
             }
-            AdvertiseCallbackWrapper wrapper = new AdvertiseCallbackWrapper(callback, advertiseData,
-                    scanResponse, settings, gatt);
-            wrapper.startRegisteration();
+
+            if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_ULTRA_LOW) {
+                parameters.setTxPowerLevel(-21);
+            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_LOW) {
+                parameters.setTxPowerLevel(-15);
+            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_MEDIUM) {
+                parameters.setTxPowerLevel(-7);
+            } else if (settings.getTxPowerLevel() == AdvertiseSettings.ADVERTISE_TX_POWER_HIGH) {
+                parameters.setTxPowerLevel(1);
+            }
+
+            AdvertisingSetCallback wrapped = wrapOldCallback(callback, settings);
+            mLegacyAdvertisers.put(callback, wrapped);
+            startAdvertisingSet(parameters.build(), advertiseData, scanResponse, null, null,
+                                settings.getTimeout(), wrapped);
         }
     }
 
+    AdvertisingSetCallback wrapOldCallback(AdvertiseCallback callback, AdvertiseSettings settings) {
+        return new AdvertisingSetCallback() {
+            @Override
+            public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower,
+                        int status) {
+                if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
+                    postStartFailure(callback, status);
+                    return;
+                }
+
+                postStartSuccess(callback, settings);
+            }
+
+            /* Legacy advertiser is disabled on timeout */
+            @Override
+            public void onAdvertisingEnabled(AdvertisingSet advertisingSet, boolean enabled,
+                        int status) {
+                if (enabled == true) {
+                    Log.e(TAG, "Legacy advertiser should be only disabled on timeout," +
+                        " but was enabled!");
+                    return;
+                }
+
+                stopAdvertising(callback);
+            }
+
+        };
+    }
+
     /**
      * Stop Bluetooth LE advertising. The {@code callback} must be the same one use in
      * {@link BluetoothLeAdvertiser#startAdvertising}.
@@ -148,20 +194,21 @@
      * @param callback {@link AdvertiseCallback} identifies the advertising instance to stop.
      */
     public void stopAdvertising(final AdvertiseCallback callback) {
-        synchronized (mLeAdvertisers) {
+        synchronized (mLegacyAdvertisers) {
             if (callback == null) {
                 throw new IllegalArgumentException("callback cannot be null");
             }
-            AdvertiseCallbackWrapper wrapper = mLeAdvertisers.get(callback);
+            AdvertisingSetCallback wrapper = mLegacyAdvertisers.get(callback);
             if (wrapper == null) return;
-            wrapper.stopAdvertising();
+
+            stopAdvertisingSet(wrapper);
         }
     }
 
     /**
     * Creates a new advertising set. If operation succeed, device will start advertising. This
     * method returns immediately, the operation status is delivered through
-    * {@code callback.onNewAdvertisingSet()}.
+    * {@code callback.onAdvertisingSetStarted()}.
     * <p>
     * @param parameters advertising set parameters.
     * @param advertiseData Advertisement data to be broadcasted.
@@ -173,14 +220,14 @@
                                     AdvertiseData advertiseData, AdvertiseData scanResponse,
                                     PeriodicAdvertisingParameters periodicParameters,
                                     AdvertiseData periodicData, AdvertisingSetCallback callback) {
-        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                            periodicData, callback, new Handler(Looper.getMainLooper()));
+            startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+                            periodicData, 0, callback, new Handler(Looper.getMainLooper()));
     }
 
     /**
     * Creates a new advertising set. If operation succeed, device will start advertising. This
     * method returns immediately, the operation status is delivered through
-    * {@code callback.onNewAdvertisingSet()}.
+    * {@code callback.onAdvertisingSetStarted()}.
     * <p>
     * @param parameters advertising set parameters.
     * @param advertiseData Advertisement data to be broadcasted.
@@ -194,6 +241,49 @@
                                     PeriodicAdvertisingParameters periodicParameters,
                                     AdvertiseData periodicData, AdvertisingSetCallback callback,
                                     Handler handler) {
+        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+                            periodicData, 0, callback, handler);
+    }
+
+    /**
+    * Creates a new advertising set. If operation succeed, device will start advertising. This
+    * method returns immediately, the operation status is delivered through
+    * {@code callback.onAdvertisingSetStarted()}.
+    * <p>
+    * @param parameters advertising set parameters.
+    * @param advertiseData Advertisement data to be broadcasted.
+    * @param scanResponse Scan response associated with the advertisement data.
+    * @param periodicData Periodic advertising data.
+    * @param timeoutMillis Advertising time limit. May not exceed 180000
+    * @param callback Callback for advertising set.
+    */
+    public void startAdvertisingSet(AdvertisingSetParameters parameters,
+                                    AdvertiseData advertiseData, AdvertiseData scanResponse,
+                                    PeriodicAdvertisingParameters periodicParameters,
+                                    AdvertiseData periodicData, int timeoutMillis,
+                                    AdvertisingSetCallback callback) {
+        startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
+                            periodicData, timeoutMillis, callback, new Handler(Looper.getMainLooper()));
+    }
+
+    /**
+    * Creates a new advertising set. If operation succeed, device will start advertising. This
+    * method returns immediately, the operation status is delivered through
+    * {@code callback.onAdvertisingSetStarted()}.
+    * <p>
+    * @param parameters advertising set parameters.
+    * @param advertiseData Advertisement data to be broadcasted.
+    * @param scanResponse Scan response associated with the advertisement data.
+    * @param periodicData Periodic advertising data.
+    * @param timeoutMillis Advertising time limit. May not exceed 180000
+    * @param callback Callback for advertising set.
+    * @param handler thread upon which the callbacks will be invoked.
+    */
+    public void startAdvertisingSet(AdvertisingSetParameters parameters,
+                                    AdvertiseData advertiseData, AdvertiseData scanResponse,
+                                    PeriodicAdvertisingParameters periodicParameters,
+                                    AdvertiseData periodicData, int timeoutMillis,
+                                    AdvertisingSetCallback callback, Handler handler) {
         BluetoothLeUtils.checkAdapterStateOn(mBluetoothAdapter);
 
         if (callback == null) {
@@ -209,11 +299,14 @@
         }
 
         IAdvertisingSetCallback wrapped = wrap(callback, handler);
-        advertisingSetCallbackWrappers.put(callback, wrapped);
+        if (mCallbackWrappers.putIfAbsent(callback, wrapped) != null) {
+            throw new IllegalArgumentException(
+                "callback instance already associated with advertising");
+        }
 
         try {
             gatt.startAdvertisingSet(parameters, advertiseData, scanResponse, periodicParameters,
-                                     periodicData, wrapped);
+                                     periodicData, timeoutMillis, wrapped);
         } catch (RemoteException e) {
           Log.e(TAG, "Failed to start advertising set - ", e);
           throw new IllegalStateException("Failed to start advertising set");
@@ -229,10 +322,9 @@
           throw new IllegalArgumentException("callback cannot be null");
         }
 
-        IAdvertisingSetCallback wrapped = advertisingSetCallbackWrappers.remove(callback);
+        IAdvertisingSetCallback wrapped = mCallbackWrappers.remove(callback);
         if (wrapped == null) {
-            throw new IllegalArgumentException(
-                "callback does not represent valid registered callback.");
+            return;
         }
 
         IBluetoothGatt gatt;
@@ -251,7 +343,9 @@
      * @hide
      */
     public void cleanup() {
-        mLeAdvertisers.clear();
+        mLegacyAdvertisers.clear();
+        mCallbackWrappers.clear();
+        mAdvertisingSets.clear();
     }
 
     // Compute the size of advertisement data or scan resp
@@ -311,246 +405,117 @@
 
     IAdvertisingSetCallback wrap(AdvertisingSetCallback callback, Handler handler) {
         return new IAdvertisingSetCallback.Stub() {
-            public void onAdvertisingSetStarted(int advertiserId, int status) {
+            @Override
+            public void onAdvertisingSetStarted(int advertiserId, int txPower, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
                         if (status != AdvertisingSetCallback.ADVERTISE_SUCCESS) {
-                            callback.onAdvertisingSetStarted(null, status);
-                            advertisingSetCallbackWrappers.remove(callback);
+                            callback.onAdvertisingSetStarted(null, 0, status);
+                            mCallbackWrappers.remove(callback);
                             return;
                         }
 
                         AdvertisingSet advertisingSet =
                             new AdvertisingSet(advertiserId, mBluetoothManager);
-                        advertisingSets.put(advertiserId, advertisingSet);
-                        callback.onAdvertisingSetStarted(advertisingSet, status);
+                        mAdvertisingSets.put(advertiserId, advertisingSet);
+                        callback.onAdvertisingSetStarted(advertisingSet, txPower, status);
                     }
                 });
             }
 
+            @Override
             public void onAdvertisingSetStopped(int advertiserId) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onAdvertisingSetStopped(advertisingSet);
-                        advertisingSets.remove(advertiserId);
-                        advertisingSetCallbackWrappers.remove(callback);
+                        mAdvertisingSets.remove(advertiserId);
+                        mCallbackWrappers.remove(callback);
                     }
                 });
             }
 
+            @Override
             public void onAdvertisingEnabled(int advertiserId, boolean enabled, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onAdvertisingEnabled(advertisingSet, enabled, status);
                     }
                 });
             }
 
+            @Override
             public void onAdvertisingDataSet(int advertiserId, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onAdvertisingDataSet(advertisingSet, status);
                     }
                 });
             }
 
+            @Override
             public void onScanResponseDataSet(int advertiserId, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onScanResponseDataSet(advertisingSet, status);
                     }
                 });
             }
 
-            public void onAdvertisingParametersUpdated(int advertiserId, int status) {
+            @Override
+            public void onAdvertisingParametersUpdated(int advertiserId, int txPower, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
-                        callback.onAdvertisingParametersUpdated(advertisingSet, status);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+                        callback.onAdvertisingParametersUpdated(advertisingSet, txPower, status);
                     }
                 });
             }
 
+            @Override
             public void onPeriodicAdvertisingParametersUpdated(int advertiserId, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onPeriodicAdvertisingParametersUpdated(advertisingSet, status);
                     }
                 });
             }
 
+            @Override
             public void onPeriodicAdvertisingDataSet(int advertiserId, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
                         callback.onPeriodicAdvertisingDataSet(advertisingSet, status);
                     }
                 });
             }
 
-            public void onPeriodicAdvertisingEnable(int advertiserId, boolean enable, int status) {
+            @Override
+            public void onPeriodicAdvertisingEnabled(int advertiserId, boolean enable, int status) {
                 handler.post(new Runnable() {
                     @Override
                     public void run() {
-                        AdvertisingSet advertisingSet = advertisingSets.get(advertiserId);
-                        callback.onPeriodicAdvertisingEnable(advertisingSet, enable, status);
+                        AdvertisingSet advertisingSet = mAdvertisingSets.get(advertiserId);
+                        callback.onPeriodicAdvertisingEnabled(advertisingSet, enable, status);
                     }
                 });
             }
         };
     }
 
-    /**
-     * Bluetooth GATT interface callbacks for advertising.
-     */
-    private class AdvertiseCallbackWrapper extends IAdvertiserCallback.Stub {
-        private static final int LE_CALLBACK_TIMEOUT_MILLIS = 2000;
-        private final AdvertiseCallback mAdvertiseCallback;
-        private final AdvertiseData mAdvertisement;
-        private final AdvertiseData mScanResponse;
-        private final AdvertiseSettings mSettings;
-        private final IBluetoothGatt mBluetoothGatt;
-
-        // mAdvertiserId -1: not registered
-        // -2: advertise stopped or registration timeout
-        // >=0: registered and advertising started
-        private int mAdvertiserId;
-        private boolean mIsAdvertising = false;
-        private int registrationError = AdvertiseCallback.ADVERTISE_FAILED_INTERNAL_ERROR;
-
-        public AdvertiseCallbackWrapper(AdvertiseCallback advertiseCallback,
-                AdvertiseData advertiseData, AdvertiseData scanResponse,
-                AdvertiseSettings settings,
-                IBluetoothGatt bluetoothGatt) {
-            mAdvertiseCallback = advertiseCallback;
-            mAdvertisement = advertiseData;
-            mScanResponse = scanResponse;
-            mSettings = settings;
-            mBluetoothGatt = bluetoothGatt;
-            mAdvertiserId = -1;
-        }
-
-        public void startRegisteration() {
-            synchronized (this) {
-                if (mAdvertiserId == -2) return;
-
-                try {
-                    mBluetoothGatt.registerAdvertiser(this);
-                    wait(LE_CALLBACK_TIMEOUT_MILLIS);
-                } catch (InterruptedException | RemoteException e) {
-                    Log.e(TAG, "Failed to start registeration", e);
-                }
-                if (mAdvertiserId >= 0 && mIsAdvertising) {
-                    mLeAdvertisers.put(mAdvertiseCallback, this);
-                } else if (mAdvertiserId < 0) {
-
-                    // Registration timeout, reset mClientIf to -2 so no subsequent operations can
-                    // proceed.
-                    if (mAdvertiserId == -1) mAdvertiserId = -2;
-                    // Post internal error if registration failed.
-                    postStartFailure(mAdvertiseCallback, registrationError);
-                } else {
-                    // Unregister application if it's already registered but advertise failed.
-                    try {
-                        mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
-                        mAdvertiserId = -2;
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "remote exception when unregistering", e);
-                    }
-                }
-            }
-        }
-
-        public void stopAdvertising() {
-            synchronized (this) {
-                try {
-                    mBluetoothGatt.stopMultiAdvertising(mAdvertiserId);
-                    wait(LE_CALLBACK_TIMEOUT_MILLIS);
-                } catch (InterruptedException | RemoteException e) {
-                    Log.e(TAG, "Failed to stop advertising", e);
-                }
-                // Advertise callback should have been removed from LeAdvertisers when
-                // onMultiAdvertiseCallback was called. In case onMultiAdvertiseCallback is never
-                // invoked and wait timeout expires, remove callback here.
-                if (mLeAdvertisers.containsKey(mAdvertiseCallback)) {
-                    mLeAdvertisers.remove(mAdvertiseCallback);
-                }
-            }
-        }
-
-        /**
-         * Advertiser interface registered - app is ready to go
-         */
-        @Override
-        public void onAdvertiserRegistered(int status, int advertiserId) {
-            Log.d(TAG, "onAdvertiserRegistered() - status=" + status + " advertiserId=" + advertiserId);
-            synchronized (this) {
-                if (status == BluetoothGatt.GATT_SUCCESS) {
-                    try {
-                        if (mAdvertiserId == -2) {
-                            // Registration succeeds after timeout, unregister advertiser.
-                            mBluetoothGatt.unregisterAdvertiser(advertiserId);
-                        } else {
-                            mAdvertiserId = advertiserId;
-                            mBluetoothGatt.startMultiAdvertising(mAdvertiserId, mAdvertisement,
-                                    mScanResponse, mSettings);
-                        }
-                        return;
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "failed to start advertising", e);
-                    }
-                } else if (status == AdvertiseCallback.ADVERTISE_FAILED_TOO_MANY_ADVERTISERS) {
-                    registrationError = status;
-                }
-                // Registration failed.
-                mAdvertiserId = -2;
-                notifyAll();
-            }
-        }
-
-        @Override
-        public void onMultiAdvertiseCallback(int status, boolean isStart,
-                AdvertiseSettings settings) {
-            synchronized (this) {
-                if (isStart) {
-                    if (status == AdvertiseCallback.ADVERTISE_SUCCESS) {
-                        // Start success
-                        mIsAdvertising = true;
-                        postStartSuccess(mAdvertiseCallback, settings);
-                    } else {
-                        // Start failure.
-                        postStartFailure(mAdvertiseCallback, status);
-                    }
-                } else {
-                    // unregister advertiser for stop.
-                    try {
-                        mBluetoothGatt.unregisterAdvertiser(mAdvertiserId);
-                        mAdvertiserId = -2;
-                        mIsAdvertising = false;
-                        mLeAdvertisers.remove(mAdvertiseCallback);
-                    } catch (RemoteException e) {
-                        Log.e(TAG, "remote exception when unregistering", e);
-                    }
-                }
-                notifyAll();
-            }
-
-        }
-    }
-
     private void postStartFailure(final AdvertiseCallback callback, final int error) {
         mHandler.post(new Runnable() {
             @Override
diff --git a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
index 4b0a111..2c9f4ba 100644
--- a/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
+++ b/core/java/android/bluetooth/le/IAdvertisingSetCallback.aidl
@@ -20,13 +20,13 @@
  * @hide
  */
 oneway interface IAdvertisingSetCallback {
-  void onAdvertisingSetStarted(in int advertiserId, in int status);
+  void onAdvertisingSetStarted(in int advertiserId, in int tx_power, in int status);
   void onAdvertisingSetStopped(in int advertiserId);
   void onAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
   void onAdvertisingDataSet(in int advertiserId, in int status);
   void onScanResponseDataSet(in int advertiserId, in int status);
-  void onAdvertisingParametersUpdated(in int advertiserId, in int status);
+  void onAdvertisingParametersUpdated(in int advertiserId, in int tx_power, in int status);
   void onPeriodicAdvertisingParametersUpdated(in int advertiserId, in int status);
   void onPeriodicAdvertisingDataSet(in int advertiserId, in int status);
-  void onPeriodicAdvertisingEnable(in int advertiserId, in boolean enable, in int status);
+  void onPeriodicAdvertisingEnabled(in int advertiserId, in boolean enable, in int status);
 }
diff --git a/core/java/android/bluetooth/le/ScanResult.java b/core/java/android/bluetooth/le/ScanResult.java
index 583ddd2..745cd16 100644
--- a/core/java/android/bluetooth/le/ScanResult.java
+++ b/core/java/android/bluetooth/le/ScanResult.java
@@ -67,12 +67,12 @@
     public static final int SID_NOT_PRESENT = 0xFF;
 
     /**
-     * Mask for checking wether event type represents legacy advertisement.
+     * Mask for checking whether event type represents legacy advertisement.
      */
     private static final int ET_LEGACY_MASK = 0x10;
 
     /**
-     * Mask for checking wether event type represents connectable advertisement.
+     * Mask for checking whether event type represents connectable advertisement.
      */
     private static final int ET_CONNECTABLE_MASK = 0x01;
 
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b7876d9..2ce22b4 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1083,18 +1083,7 @@
      * @hide
      */
     public static final String ACTION_CALL_PRIVILEGED = "android.intent.action.CALL_PRIVILEGED";
-    /**
-     * Activity action: Activate the current SIM card.  If SIM cards do not require activation,
-     * sending this intent is a no-op.
-     * <p>Input: No data should be specified.  get*Extra may have an optional
-     * {@link #EXTRA_SIM_ACTIVATION_RESPONSE} field containing a PendingIntent through which to
-     * send the activation result.
-     * <p>Output: nothing.
-     * @hide
-     */
-    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
-    public static final String ACTION_SIM_ACTIVATION_REQUEST =
-            "android.intent.action.SIM_ACTIVATION_REQUEST";
+
     /**
      * Activity Action: Main entry point for carrier setup apps.
      * <p>Carrier apps that provide an implementation for this action may be invoked to configure
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 11d247b..e163365 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2956,7 +2956,6 @@
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
      * @throws IllegalArgumentException if {@code request} specifies any mutable
      *         {@code NetworkCapabilities}.
-     * @hide
      */
     public void requestNetwork(
             NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
@@ -3073,8 +3072,6 @@
      * @param networkCallback The {@link NetworkCallback} to be utilized for this request. Note
      *                        the callback must not be shared - it uniquely specifies this request.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
-     *
-     * @hide
      */
     public void requestNetwork(NetworkRequest request, int timeoutMs,
             NetworkCallback networkCallback, Handler handler) {
@@ -3214,7 +3211,6 @@
      * @param networkCallback The {@link NetworkCallback} that the system will call as suitable
      *                        networks change state.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
-     * @hide
      */
     public void registerNetworkCallback(
             NetworkRequest request, NetworkCallback networkCallback, Handler handler) {
@@ -3288,7 +3284,6 @@
      * @param networkCallback The {@link NetworkCallback} that the system will call as the
      *                        system default network changes.
      * @param handler {@link Handler} to specify the thread upon which the callback will be invoked.
-     * @hide
      */
     public void registerDefaultNetworkCallback(NetworkCallback networkCallback, Handler handler) {
         // This works because if the NetworkCapabilities are null,
diff --git a/core/java/android/os/HwParcel.java b/core/java/android/os/HwParcel.java
index a265dd0..94fd5b0 100644
--- a/core/java/android/os/HwParcel.java
+++ b/core/java/android/os/HwParcel.java
@@ -219,6 +219,7 @@
     public native final void writeStatus(int status);
     public native final void verifySuccess();
     public native final void releaseTemporaryStorage();
+    public native final void release();
 
     public native final void send();
 
diff --git a/core/java/android/os/IBatteryPropertiesRegistrar.aidl b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
index fd01802..468b58b 100644
--- a/core/java/android/os/IBatteryPropertiesRegistrar.aidl
+++ b/core/java/android/os/IBatteryPropertiesRegistrar.aidl
@@ -27,4 +27,5 @@
     void registerListener(IBatteryPropertiesListener listener);
     void unregisterListener(IBatteryPropertiesListener listener);
     int getProperty(in int id, out BatteryProperty prop);
+    oneway void scheduleUpdate();
 }
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index 2bf3c2c..c520917 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -35,6 +35,12 @@
     private static final String TAG = "SystemProperties";
     private static final boolean TRACK_KEY_ACCESS = false;
 
+    /**
+     * Android O removed the property name length limit, but com.amazon.kindle 7.8.1.5
+     * uses reflection to read this whenever text is selected (http://b/36095274).
+     */
+    public static final int PROP_NAME_MAX = Integer.MAX_VALUE;
+
     public static final int PROP_VALUE_MAX = 91;
 
     private static final ArrayList<Runnable> sChangeCallbacks = new ArrayList<Runnable>();
diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java
index 6a10743..203b8dd 100644
--- a/core/java/android/widget/ListPopupWindow.java
+++ b/core/java/android/widget/ListPopupWindow.java
@@ -600,6 +600,10 @@
         mPopup.setWindowLayoutType(mDropDownWindowLayoutType);
 
         if (mPopup.isShowing()) {
+            if (!getAnchorView().isAttachedToWindow()) {
+                //Don't update position if the anchor view is detached from window.
+                return;
+            }
             final int widthSpec;
             if (mDropDownWidth == ViewGroup.LayoutParams.MATCH_PARENT) {
                 // The call to PopupWindow's update method below can accept -1 for any
diff --git a/core/java/com/android/internal/os/WrapperInit.java b/core/java/com/android/internal/os/WrapperInit.java
index dbbebbe7..aced75d 100644
--- a/core/java/com/android/internal/os/WrapperInit.java
+++ b/core/java/com/android/internal/os/WrapperInit.java
@@ -17,6 +17,11 @@
 package com.android.internal.os;
 
 import android.os.Process;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructCapUserData;
+import android.system.StructCapUserHeader;
 import android.util.Slog;
 import com.android.internal.os.Zygote.MethodAndArgsCaller;
 import dalvik.system.VMRuntime;
@@ -119,6 +124,7 @@
         command.append(' ');
         command.append(targetSdkVersion);
         Zygote.appendQuotedShellArgs(command, args);
+        preserveCapabilities();
         Zygote.execShell(command.toString());
     }
 
@@ -139,6 +145,74 @@
             Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from wrapper");
         }
 
-        RuntimeInit.applicationInit(targetSdkVersion, argv, null);
+        // Check whether the first argument is a "-cp" in argv, and assume the next argument is the
+        // classpath. If found, create a PathClassLoader and use it for applicationInit.
+        ClassLoader classLoader = null;
+        if (argv != null && argv.length > 2 && argv[0].equals("-cp")) {
+            classLoader = ZygoteInit.createPathClassLoader(argv[1], targetSdkVersion);
+
+            // Install this classloader as the context classloader, too.
+            Thread.currentThread().setContextClassLoader(classLoader);
+
+            // Remove the classpath from the arguments.
+            String removedArgs[] = new String[argv.length - 2];
+            System.arraycopy(argv, 2, removedArgs, 0, argv.length - 2);
+            argv = removedArgs;
+        }
+
+        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
+    }
+
+    /**
+     * Copy current capabilities to ambient capabilities. This is required for apps using
+     * capabilities, as execv will re-evaluate the capability set, and the set of sh is
+     * empty. Ambient capabilities have to be set to inherit them effectively.
+     *
+     * Note: This is BEST EFFORT ONLY. In case capabilities can't be raised, this function
+     *       will silently return. In THIS CASE ONLY, as this is a development feature, it
+     *       is better to return and try to run anyways, instead of blocking the wrapped app.
+     *       This is acceptable here as failure will leave the wrapped app with strictly less
+     *       capabilities, which may make it crash, but not exceed its allowances.
+     */
+    private static void preserveCapabilities() {
+        StructCapUserHeader header = new StructCapUserHeader(
+                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
+        StructCapUserData[] data;
+        try {
+            data = Os.capget(header);
+        } catch (ErrnoException e) {
+            Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capget", e);
+            return;
+        }
+
+        if (data[0].permitted != data[0].inheritable ||
+                data[1].permitted != data[1].inheritable) {
+            data[0] = new StructCapUserData(data[0].effective, data[0].permitted,
+                    data[0].permitted);
+            data[1] = new StructCapUserData(data[1].effective, data[1].permitted,
+                    data[1].permitted);
+            try {
+                Os.capset(header, data);
+            } catch (ErrnoException e) {
+                Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capset", e);
+                return;
+            }
+        }
+
+        for (int i = 0; i < 64; i++) {
+            int dataIndex = OsConstants.CAP_TO_INDEX(i);
+            int capMask = OsConstants.CAP_TO_MASK(i);
+            if ((data[dataIndex].inheritable & capMask) != 0) {
+                try {
+                    Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, i, 0,
+                            0);
+                } catch (ErrnoException ex) {
+                    // Only log here. Try to run the wrapped application even without this
+                    // ambient capability. It may crash after fork, but at least we'll try.
+                    Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed to raise ambient capability "
+                            + i, ex);
+                }
+            }
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 59416dd..e065843 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -100,6 +100,8 @@
           int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
           int[] fdsToIgnore, String instructionSet, String appDataDir) {
         VM_HOOKS.preFork();
+        // Resets nice priority for zygote process.
+        resetNicePriority();
         int pid = nativeForkAndSpecialize(
                   uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                   fdsToIgnore, instructionSet, appDataDir);
@@ -144,6 +146,8 @@
     public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
         VM_HOOKS.preFork();
+        // Resets nice priority for zygote process.
+        resetNicePriority();
         int pid = nativeForkSystemServer(
                 uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
         // Enable tracing as soon as we enter the system_server.
@@ -173,6 +177,14 @@
         VM_HOOKS.postForkChild(debugFlags, isSystemServer, instructionSet);
     }
 
+    /**
+     * Resets the calling thread priority to the default value (Thread.NORM_PRIORITY
+     * or nice value 0). This updates both the priority value in java.lang.Thread and
+     * the nice value (setpriority).
+     */
+    static void resetNicePriority() {
+        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
+    }
 
     /**
      * Executes "/system/bin/sh -c &lt;command&gt;" using the exec() system call.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 1e0a998..e560c0c7 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -449,7 +449,8 @@
                 String[] amendedArgs = new String[args.length + 2];
                 amendedArgs[0] = "-cp";
                 amendedArgs[1] = systemServerClasspath;
-                System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
+                System.arraycopy(args, 0, amendedArgs, 2, args.length);
+                args = amendedArgs;
             }
 
             WrapperInit.execApplication(parsedArgs.invokeWith,
@@ -458,8 +459,7 @@
         } else {
             ClassLoader cl = null;
             if (systemServerClasspath != null) {
-                cl = createSystemServerClassLoader(systemServerClasspath,
-                                                   parsedArgs.targetSdkVersion);
+                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
 
                 Thread.currentThread().setContextClassLoader(cl);
             }
@@ -474,15 +474,14 @@
     }
 
     /**
-     * Creates a PathClassLoader for the system server. It also creates
-     * a shared namespace associated with the classloader to let it access
-     * platform-private native libraries.
+     * Creates a PathClassLoader for the given class path that is associated with a shared
+     * namespace, i.e., this classloader can access platform-private native libraries. The
+     * classloader will use java.library.path as the native library path.
      */
-    private static PathClassLoader createSystemServerClassLoader(String systemServerClasspath,
-                                                                 int targetSdkVersion) {
+    static PathClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
       String libraryPath = System.getProperty("java.library.path");
 
-      return PathClassLoaderFactory.createClassLoader(systemServerClasspath,
+      return PathClassLoaderFactory.createClassLoader(classPath,
                                                       libraryPath,
                                                       libraryPath,
                                                       ClassLoader.getSystemClassLoader(),
diff --git a/core/jni/android_os_HwParcel.cpp b/core/jni/android_os_HwParcel.cpp
index 1bd2333..678041f 100644
--- a/core/jni/android_os_HwParcel.cpp
+++ b/core/jni/android_os_HwParcel.cpp
@@ -404,6 +404,11 @@
     signalExceptionForError(env, err);
 }
 
+static void JHwParcel_native_release(
+        JNIEnv *env, jobject thiz) {
+    JHwParcel::GetNativeContext(env, thiz)->setParcel(NULL, false /* assumeOwnership */);
+}
+
 static void JHwParcel_native_releaseTemporaryStorage(
         JNIEnv *env, jobject thiz) {
     JHwParcel::GetNativeContext(env, thiz)->getStorage()->release(env);
@@ -955,6 +960,10 @@
 
     { "writeBuffer", "(L" PACKAGE_PATH "/HwBlob;)V",
         (void *)JHwParcel_native_writeBuffer },
+
+    { "release", "()V",
+        (void *)JHwParcel_native_release },
+
 };
 
 namespace android {
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 3498108..90ad2da 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -155,24 +155,6 @@
   }
 }
 
-// Resets nice priority for zygote process. Zygote priority can be set
-// to high value during boot phase to speed it up. We want to ensure
-// zygote is running at normal priority before childs are forked from it.
-//
-// This ends up being called repeatedly before each fork(), but there's
-// no real harm in that.
-static void ResetNicePriority(JNIEnv* env) {
-  errno = 0;
-  int prio = getpriority(PRIO_PROCESS, 0);
-  if (prio == -1 && errno != 0) {
-    ALOGW("getpriority failed: %s\n", strerror(errno));
-  }
-  if (prio != 0 && setpriority(PRIO_PROCESS, 0, 0) != 0) {
-    ALOGE("setpriority(%d, 0, 0) failed: %s", PRIO_PROCESS, strerror(errno));
-    RuntimeAbort(env, __LINE__, "setpriority failed");
-  }
-}
-
 // Sets the SIGCHLD handler back to default behavior in zygote children.
 static void UnsetSigChldHandler() {
   struct sigaction sa;
@@ -512,8 +494,6 @@
     RuntimeAbort(env, __LINE__, "Unable to restat file descriptor table.");
   }
 
-  ResetNicePriority(env);
-
   pid_t pid = fork();
 
   if (pid == 0) {
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 9660de4..956b724 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -26,7 +26,9 @@
 #include <sys/un.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 #include <android-base/strings.h>
 
 // Static whitelist of open paths that the zygote is allowed to keep open.
@@ -65,9 +67,10 @@
       return true;
   }
 
-  static const std::string kFrameworksPrefix = "/system/framework/";
-  static const std::string kJarSuffix = ".jar";
-  if (StartsWith(path, kFrameworksPrefix) && EndsWith(path, kJarSuffix)) {
+  static const char* kFrameworksPrefix = "/system/framework/";
+  static const char* kJarSuffix = ".jar";
+  if (android::base::StartsWith(path, kFrameworksPrefix)
+      && android::base::EndsWith(path, kJarSuffix)) {
     return true;
   }
 
@@ -79,28 +82,31 @@
   // /data/resource-cache/system@vendor@overlay@framework-res.apk@idmap
   // /data/resource-cache/system@vendor@overlay-subdir@pg@framework-res.apk@idmap
   // See AssetManager.cpp for more details on overlay-subdir.
-  static const std::string kOverlayDir = "/system/vendor/overlay/";
-  static const std::string kVendorOverlayDir = "/vendor/overlay";
-  static const std::string kOverlaySubdir = "/system/vendor/overlay-subdir/";
-  static const std::string kApkSuffix = ".apk";
+  static const char* kOverlayDir = "/system/vendor/overlay/";
+  static const char* kVendorOverlayDir = "/vendor/overlay";
+  static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
+  static const char* kApkSuffix = ".apk";
 
-  if ((StartsWith(path, kOverlayDir) || StartsWith(path, kOverlaySubdir)
-       || StartsWith(path, kVendorOverlayDir))
-      && EndsWith(path, kApkSuffix)
+  if ((android::base::StartsWith(path, kOverlayDir)
+       || android::base::StartsWith(path, kOverlaySubdir)
+       || android::base::StartsWith(path, kVendorOverlayDir))
+      && android::base::EndsWith(path, kApkSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
   }
 
-  static const std::string kOverlayIdmapPrefix = "/data/resource-cache/";
-  static const std::string kOverlayIdmapSuffix = ".apk@idmap";
-  if (StartsWith(path, kOverlayIdmapPrefix) && EndsWith(path, kOverlayIdmapSuffix)
+  static const char* kOverlayIdmapPrefix = "/data/resource-cache/";
+  static const char* kOverlayIdmapSuffix = ".apk@idmap";
+  if (android::base::StartsWith(path, kOverlayIdmapPrefix)
+      && android::base::EndsWith(path, kOverlayIdmapSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
   }
 
   // All regular files that are placed under this path are whitelisted automatically.
-  static const std::string kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
-  if (StartsWith(path, kZygoteWhitelistPath) && path.find("/../") == std::string::npos) {
+  static const char* kZygoteWhitelistPath = "/vendor/zygote_whitelist/";
+  if (android::base::StartsWith(path, kZygoteWhitelistPath)
+      && path.find("/../") == std::string::npos) {
     return true;
   }
 
@@ -111,24 +117,6 @@
     : whitelist_() {
 }
 
-// TODO: Call android::base::StartsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::StartsWith(const std::string& str,
-                                         const std::string& prefix) {
-  return str.compare(0, prefix.size(), prefix) == 0;
-}
-
-// TODO: Call android::base::EndsWith instead of copying the code here.
-// static
-bool FileDescriptorWhitelist::EndsWith(const std::string& str,
-                                       const std::string& suffix) {
-  if (suffix.size() > str.size()) {
-    return false;
-  }
-
-  return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
-}
-
 FileDescriptorWhitelist* FileDescriptorWhitelist::instance_ = nullptr;
 
 // static
@@ -174,7 +162,8 @@
   }
 
   std::string file_path;
-  if (!Readlink(fd, &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;
   }
 
@@ -299,30 +288,6 @@
   is_sock(false) {
 }
 
-// TODO: Call android::base::Readlink instead of copying the code here.
-// static
-bool FileDescriptorInfo::Readlink(const int fd, std::string* result) {
-  char path[64];
-  snprintf(path, sizeof(path), "/proc/self/fd/%d", fd);
-
-  // Code copied from android::base::Readlink starts here :
-
-  // Annoyingly, the readlink system call returns EINVAL for a zero-sized buffer,
-  // and truncates to whatever size you do supply, so it can't be used to query.
-  // We could call lstat first, but that would introduce a race condition that
-  // we couldn't detect.
-  // ext2 and ext4 both have PAGE_SIZE limitations, so we assume that here.
-  char buf[4096];
-  ssize_t len = readlink(path, buf, sizeof(buf));
-  if (len == -1) {
-    PLOG(ERROR) << "Readlink on " << fd << " failed.";
-    return false;
-  }
-
-  result->assign(buf, len);
-  return true;
-}
-
 // static
 bool FileDescriptorInfo::GetSocketName(const int fd, std::string* result) {
   sockaddr_storage ss;
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index 03298c3..a39e387 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -59,10 +59,6 @@
  private:
   FileDescriptorWhitelist();
 
-  static bool StartsWith(const std::string& str, const std::string& prefix);
-
-  static bool EndsWith(const std::string& str, const std::string& suffix);
-
   static FileDescriptorWhitelist* instance_;
 
   std::vector<std::string> whitelist_;
@@ -99,8 +95,6 @@
   FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
                      int fd_flags, int fs_flags, off_t offset);
 
-  static bool Readlink(const int fd, std::string* result);
-
   // Returns the locally-bound name of the socket |fd|. Returns true
   // iff. all of the following hold :
   //
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 7d4f99d..c3b2aa1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1300,7 +1300,7 @@
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows an internal user to use restricted Networks.
+    <!-- @SystemApi Allows an internal user to use restricted Networks.
          @hide -->
     <permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
         android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..d704951
--- /dev/null
+++ b/core/res/res/drawable-hdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..5dfc89e
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
new file mode 100644
index 0000000..a648b0b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/stat_notify_mmcc_indication_icn.png
Binary files differ
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2b2e18b..beb495de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -462,6 +462,8 @@
     <integer translatable="false" name="config_wifi_framework_LAST_SELECTION_AWARD">480</integer>
     <integer translatable="false" name="config_wifi_framework_PASSPOINT_SECURITY_AWARD">40</integer>
     <integer translatable="false" name="config_wifi_framework_SECURITY_AWARD">80</integer>
+    <!-- Integer specifying the base interval in seconds for the exponential backoff scan for autojoin -->
+    <integer translatable="false" name="config_wifi_framework_exponential_backoff_scan_base_interval">20</integer>
     <!-- Integer parameters of the wifi to cellular handover feature
          wifi should not stick to bad networks -->
     <integer translatable="false" name="config_wifi_framework_wifi_score_bad_rssi_threshold_5GHz">-82</integer>
@@ -1391,6 +1393,9 @@
     <!-- Boolean indicating if current platform supports BLE peripheral mode -->
     <bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
 
+    <!-- Boolean indicating if current platform supports HFP inband ringing -->
+    <bool name="config_bluetooth_hfp_inband_ringing_support">false</bool>
+
     <!-- Max number of scan filters supported by blutooth controller. 0 if the
          device does not support hardware scan filters-->
     <integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index f07fe70..513bdd1 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -75,7 +75,7 @@
         <item>ce-RU</item> <!-- Chechen (Russia) -->
         <item>cgg-UG</item> <!-- Chiga (Uganda) -->
         <item>chr-US</item> <!-- Cherokee (United States) -->
-        <item>cs-CZ</item> <!-- Czech (Czech Republic) -->
+        <item>cs-CZ</item> <!-- Czech (Czechia) -->
         <item>cy-GB</item> <!-- Welsh (United Kingdom) -->
         <item>da-DK</item> <!-- Danish (Denmark) -->
         <item>da-GL</item> <!-- Danish (Greenland) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4231698..5450e98 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4441,4 +4441,25 @@
 
     <!-- Label used by Telephony code, assigned as the display name for conference calls [CHAR LIMIT=60] -->
     <string name="conference_call">Conference Call</string>
+
+    <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for earthquake -->
+    <string name="etws_primary_default_message_earthquake">Stay calm and seek shelter nearby.</string>
+
+    <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for Tsunami -->
+    <string name="etws_primary_default_message_tsunami">Evacuate immediately from coastal regions and riverside areas to a safer place such as high ground.</string>
+
+    <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for earthquake and Tsunami -->
+    <string name="etws_primary_default_message_earthquake_and_tsunami">Stay calm and seek shelter nearby.</string>
+
+    <!-- Primary ETWS (Earthquake and Tsunami Warning System) default message for test -->
+    <string name="etws_primary_default_message_test">Emergency messages test</string>
+
+    <!-- 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>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index dbeda0b..a539af2 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -240,6 +240,7 @@
   <java-symbol type="bool" name="config_bluetooth_address_validation" />
   <java-symbol type="bool" name="config_bluetooth_sco_off_call" />
   <java-symbol type="bool" name="config_bluetooth_le_peripheral_mode_supported" />
+  <java-symbol type="bool" name="config_bluetooth_hfp_inband_ringing_support" />
   <java-symbol type="bool" name="config_cellBroadcastAppLinks" />
   <java-symbol type="bool" name="config_duplicate_port_omadm_wappush" />
   <java-symbol type="bool" name="config_enableAutoPowerModes" />
@@ -1290,6 +1291,8 @@
   <java-symbol type="drawable" name="ic_sim_card_multi_24px_clr" />
   <java-symbol type="drawable" name="ic_sim_card_multi_48px_clr" />
 
+  <java-symbol type="drawable" name="stat_notify_mmcc_indication_icn" />
+
   <java-symbol type="drawable" name="ic_account_circle" />
   <java-symbol type="color" name="user_icon_1" />
   <java-symbol type="color" name="user_icon_2" />
@@ -1862,6 +1865,10 @@
   <java-symbol type="string" name="low_internal_storage_view_text" />
   <java-symbol type="string" name="low_internal_storage_view_text_no_boot" />
   <java-symbol type="string" name="low_internal_storage_view_title" />
+  <java-symbol type="string" name="mmcc_authentication_reject" />
+  <java-symbol type="string" name="mmcc_imsi_unknown_in_hlr" />
+  <java-symbol type="string" name="mmcc_illegal_ms" />
+  <java-symbol type="string" name="mmcc_illegal_me" />
   <java-symbol type="string" name="notification_listener_binding_label" />
   <java-symbol type="string" name="vr_listener_binding_label" />
   <java-symbol type="string" name="condition_provider_service_binding_label" />
@@ -2742,4 +2749,15 @@
   <java-symbol type="array" name="config_networkRecommendationPackageNames" />
 
   <java-symbol type="string" name="config_defaultCellBroadcastReceiverPkg" />
+
+  <!-- ETWS primary messages -->
+  <java-symbol type="string" name="etws_primary_default_message_earthquake" />
+
+  <java-symbol type="string" name="etws_primary_default_message_tsunami" />
+
+  <java-symbol type="string" name="etws_primary_default_message_earthquake_and_tsunami" />
+
+  <java-symbol type="string" name="etws_primary_default_message_test" />
+
+  <java-symbol type="string" name="etws_primary_default_message_others" />
 </resources>
diff --git a/core/res/res/xml/sms_short_codes.xml b/core/res/res/xml/sms_short_codes.xml
index 29c6b79..1ae922a 100644
--- a/core/res/res/xml/sms_short_codes.xml
+++ b/core/res/res/xml/sms_short_codes.xml
@@ -79,7 +79,7 @@
     <!-- Cyprus: 4-6 digits (not confirmed), known premium codes listed, plus EU -->
     <shortcode country="cy" pattern="\\d{4,6}" premium="7510" free="116\\d{3}" />
 
-    <!-- Czech Republic: 7-8 digits, starting with 9, plus EU:
+    <!-- Czechia: 7-8 digits, starting with 9, plus EU:
          http://www.o2.cz/osobni/en/services-by-alphabet/91670-premium_sms.html -->
     <shortcode country="cz" premium="9\\d{6,7}" free="116\\d{3}" />
 
diff --git a/core/res/res/xml/time_zones_by_country.xml b/core/res/res/xml/time_zones_by_country.xml
index a685e2b..6c1ce44 100644
--- a/core/res/res/xml/time_zones_by_country.xml
+++ b/core/res/res/xml/time_zones_by_country.xml
@@ -336,6 +336,10 @@
 
     <timezone code="ck">Pacific/Rarotonga</timezone>
 
+    <!-- CHILE, -3:00 -->
+
+    <timezone code="cl">America/Punta_Arenas</timezone>
+
     <!-- CHILE, -4:00 -->
 
     <timezone code="cl">America/Santiago</timezone>
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
index 29020ba..48f2935 100644
--- a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -32,10 +32,10 @@
 import android.test.InstrumentationTestCase;
 import com.android.internal.R;
 import java.util.List;
-import org.mockito.ArgumentMatcher;
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.mockito.compat.ArgumentMatcher;
 
 public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
     @Mock private Context mMockContext;
@@ -218,7 +218,7 @@
         when(mMockPm.resolveService(
                 Mockito.argThat(new ArgumentMatcher<Intent>() {
                     @Override
-                    public boolean matches(Object object) {
+                    public boolean matchesObject(Object object) {
                         Intent intent = (Intent) object;
                         return NetworkScoreManager.ACTION_RECOMMEND_NETWORKS
                                 .equals(intent.getAction())
diff --git a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
index 7a4980a..56e977c 100644
--- a/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
+++ b/core/tests/coretests/src/android/os/BinderThreadPriorityTest.java
@@ -109,7 +109,7 @@
     }
 
     public static String expectedSchedulerGroup(int prio) {
-        return prio < Process.THREAD_PRIORITY_BACKGROUND ? "/" : "/bg_non_interactive";
+        return "/";
     }
 
     public void testPassPriorityToService() throws Exception {
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index e10db05..38d2a58 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -4320,6 +4320,7 @@
         if (curOff > (dtohl(entry.type->header.size)-sizeof(ResTable_map))) {
             ALOGW("ResTable_map at %d is beyond type chunk data %d",
                  (int)curOff, dtohl(entry.type->header.size));
+            free(set);
             return BAD_TYPE;
         }
         map = (const ResTable_map*)(((const uint8_t*)entry.type) + curOff);
@@ -4332,6 +4333,7 @@
             if (grp->dynamicRefTable.lookupResourceId(&newName) != NO_ERROR) {
                 ALOGE("Failed resolving ResTable_map name at %d with ident 0x%08x",
                         (int) curOff, (int) newName);
+                free(set);
                 return UNKNOWN_ERROR;
             }
         }
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 760a2d1..56a5737 100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.os.BatteryManager;
 import android.os.RemoteException;
+import android.os.SystemProperties;
 import android.provider.MediaStore;
 import android.provider.MediaStore.Audio;
 import android.provider.MediaStore.Files;
@@ -133,6 +134,8 @@
     private int mBatteryLevel;
     private int mBatteryScale;
 
+    private int mDeviceType;
+
     static {
         System.loadLibrary("media_jni");
     }
@@ -195,6 +198,7 @@
         }
 
         initDeviceProperties(context);
+        mDeviceType = SystemProperties.getInt("sys.usb.mtp.device_type", 0);
 
         mCloseGuard.open("close");
     }
@@ -710,6 +714,7 @@
             MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
             MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
             MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL,
+            MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE,
         };
     }
 
@@ -869,6 +874,10 @@
                 outStringValue[imageSize.length()] = 0;
                 return MtpConstants.RESPONSE_OK;
 
+            case MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
+                outIntValue[0] = mDeviceType;
+                return MtpConstants.RESPONSE_OK;
+
             // DEVICE_PROPERTY_BATTERY_LEVEL is implemented in the JNI code
 
             default:
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 34a7f7c..f7f79169 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -76,6 +76,7 @@
 static jfieldID field_context;
 static jfieldID field_batteryLevel;
 static jfieldID field_batteryScale;
+static jfieldID field_deviceType;
 
 // MtpPropertyList fields
 static jfieldID field_mCount;
@@ -1030,6 +1031,7 @@
     {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
     {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
     {   MTP_DEVICE_PROPERTY_BATTERY_LEVEL,              MTP_TYPE_UINT8 },
+    {   MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE,      MTP_TYPE_UINT32 },
 };
 
 bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
@@ -1209,6 +1211,10 @@
             result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
             result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
             break;
+        case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
+            result = new MtpProperty(property, MTP_TYPE_UINT32);
+            result->mCurrentValue.u.u32 = (uint32_t)env->GetIntField(mDatabase, field_deviceType);
+            break;
     }
 
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
@@ -1388,6 +1394,11 @@
         ALOGE("Can't find MtpDatabase.mBatteryScale");
         return -1;
     }
+    field_deviceType = env->GetFieldID(clazz, "mDeviceType", "I");
+    if (field_deviceType == NULL) {
+        ALOGE("Can't find MtpDatabase.mDeviceType");
+        return -1;
+    }
 
     // now set up fields for MtpPropertyList class
     clazz = env->FindClass("android/mtp/MtpPropertyList");
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 6c879b9..a519f74 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -45,8 +45,8 @@
 
 import com.android.mediaframeworktest.MediaFrameworkIntegrationTestRunner;
 
-import org.mockito.ArgumentMatcher;
 import org.mockito.ArgumentCaptor;
+import org.mockito.compat.ArgumentMatcher;
 import static org.mockito.Mockito.*;
 
 public class CameraDeviceBinderTest extends AndroidTestCase {
@@ -158,7 +158,7 @@
 
     class IsMetadataNotEmpty extends ArgumentMatcher<CameraMetadataNative> {
         @Override
-        public boolean matches(Object obj) {
+        public boolean matchesObject(Object obj) {
             return !((CameraMetadataNative) obj).isEmpty();
         }
     }
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index 13e7e0d1..e450283 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -25,7 +25,6 @@
     <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
     <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" />
     <uses-permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS" />
-    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
     <uses-permission android:name="android.permission.SUBSTITUTE_NOTIFICATION_APP_NAME" />
 
     <application
@@ -36,10 +35,16 @@
                 <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
             </intent-filter>
         </receiver>
-        <activity android:name="com.android.carrierdefaultapp.CaptivePortalLaunchActivity"
-            android:theme="@android:style/Theme.Translucent.NoTitleBar"
-            android:excludeFromRecents="true"/>
         <service android:name="com.android.carrierdefaultapp.ProvisionObserver"
                  android:permission="android.permission.BIND_JOB_SERVICE"/>
+        <activity
+            android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+            android:label="@string/action_bar_label"
+            android:theme="@style/AppTheme"
+            android:configChanges="keyboardHidden|orientation|screenSize" >
+            <intent-filter>
+                <category android:name="android.intent.category.DEFAULT"/>
+            </intent-filter>
+        </activity>
     </application>
 </manifest>
diff --git a/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png b/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png
new file mode 100644
index 0000000..08294ce
--- /dev/null
+++ b/packages/CarrierDefaultApp/assets/quantum_ic_warning_amber_96.png
Binary files differ
diff --git a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
index dc54fe2..75aa405 100644
--- a/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
+++ b/packages/CarrierDefaultApp/res/drawable/ic_sim_card.xml
@@ -22,4 +22,4 @@
 <path
     android:fillColor="#757575"
     android:pathData="M18,2h-8L4.02,8 4,20c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,4c0,-1.1 -0.9,-2 -2,-2zM13,17h-2v-2h2v2zM13,13h-2L11,8h2v5z"/>
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml b/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml
new file mode 100644
index 0000000..528576b
--- /dev/null
+++ b/packages/CarrierDefaultApp/res/layout/activity_captive_portal_login.xml
@@ -0,0 +1,34 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+    tools:ignore="MergeRootFrame">
+    <LinearLayout
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/url_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textSize="20sp"
+        android:singleLine="true" />
+
+    <ProgressBar
+        android:id="@+id/progress_bar"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="?android:attr/progressBarStyleHorizontal" />
+
+    <WebView
+        android:id="@+id/webview"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentBottom="false"
+        android:layout_alignParentRight="false" />
+
+</LinearLayout>
+</FrameLayout>
diff --git a/packages/CarrierDefaultApp/res/values/dimens.xml b/packages/CarrierDefaultApp/res/values/dimens.xml
index a3c5049..1ea8c35 100644
--- a/packages/CarrierDefaultApp/res/values/dimens.xml
+++ b/packages/CarrierDefaultApp/res/values/dimens.xml
@@ -1,3 +1,6 @@
 <resources>
     <dimen name="glif_icon_size">32dp</dimen>
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
 </resources>
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index fe5669d..f9342b7 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -1,14 +1,13 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="app_name">CarrierDefaultApp</string>
-    <string name="android_system_label">Android System</string>
+    <string name="android_system_label">Mobile Carrier</string>
     <string name="portal_notification_id">Mobile data has run out</string>
-    <string name="no_data_notification_id">No Mobile data service</string>
-    <string name="portal_notification_detail">Tap to add funds to your %s SIM</string>
+    <string name="no_data_notification_id">Your mobile data has been deactivated</string>
+    <string name="portal_notification_detail">Tap to visit the %s website</string>
     <string name="no_data_notification_detail">Please contact your service provider %s</string>
-    <string name="progress_dialogue_network_connection">Connecting to captive portal...</string>
-    <string name="alert_dialogue_network_timeout">Network timeout, would you like to retry?</string>
-    <string name="alert_dialogue_network_timeout_title">Network unavailable</string>
-    <string name="quit">Quit</string>
-    <string name="wait">Wait</string>
+    <string name="action_bar_label">Sign in to mobile network</string>
+    <string name="ssl_error_warning">The network you&#8217;re trying to join has security issues.</string>
+    <string name="ssl_error_example">For example, the login page may not belong to the organization shown.</string>
+    <string name="ssl_error_continue">Continue anyway via browser</string>
 </resources>
diff --git a/packages/CarrierDefaultApp/res/values/styles.xml b/packages/CarrierDefaultApp/res/values/styles.xml
index 3d26915..939c1aa 100644
--- a/packages/CarrierDefaultApp/res/values/styles.xml
+++ b/packages/CarrierDefaultApp/res/values/styles.xml
@@ -1,3 +1,16 @@
 <resources>
-    <style name="AlertDialog" parent="android:Theme.Material.Light.Dialog.Alert"/>
+    <style name="AppBaseTheme" parent="@android:style/Theme.Material.Settings">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+        <!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
+        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
+    </style>
 </resources>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
deleted file mode 100644
index b7fde12..0000000
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLaunchActivity.java
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.carrierdefaultapp;
-
-import android.app.Activity;
-import android.app.AlertDialog;
-import android.app.ProgressDialog;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.net.CaptivePortal;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkRequest;
-import android.os.Bundle;
-import android.telephony.CarrierConfigManager;
-import android.telephony.Rlog;
-import android.telephony.SubscriptionManager;
-import android.text.TextUtils;
-import android.net.ICaptivePortal;
-import android.view.ContextThemeWrapper;
-import android.view.WindowManager;
-import com.android.carrierdefaultapp.R;
-import com.android.internal.telephony.PhoneConstants;
-import com.android.internal.telephony.TelephonyIntents;
-import com.android.internal.util.ArrayUtils;
-
-import static android.net.CaptivePortal.APP_RETURN_DISMISSED;
-
-/**
- * Activity that launches in response to the captive portal notification
- * @see com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
- * This activity requests network connection if there is no available one, launches the
- * {@link com.android.captiveportallogin portalApp} and keeps track of the portal activation result.
- */
-public class CaptivePortalLaunchActivity extends Activity {
-    private static final String TAG = CaptivePortalLaunchActivity.class.getSimpleName();
-    private static final boolean DBG = true;
-    public static final int NETWORK_REQUEST_TIMEOUT_IN_MS = 5 * 1000;
-
-    private ConnectivityManager mCm = null;
-    private ConnectivityManager.NetworkCallback mCb = null;
-    /* Progress dialogue when request network connection for captive portal */
-    private AlertDialog mProgressDialog = null;
-    /* Alert dialogue when network request is timeout */
-    private AlertDialog mAlertDialog = null;
-
-
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mCm = ConnectivityManager.from(this);
-        // Check network connection before loading portal
-        Network network = getNetworkForCaptivePortal();
-        NetworkInfo nwInfo = mCm.getNetworkInfo(network);
-        if (nwInfo == null || !nwInfo.isConnected()) {
-            if (DBG) logd("Network unavailable, request restricted connection");
-            requestNetwork(getIntent());
-        } else {
-            launchCaptivePortal(getIntent(), network);
-        }
-    }
-
-    // show progress dialog during network connecting
-    private void showConnectingProgressDialog() {
-        mProgressDialog = new ProgressDialog(getApplicationContext());
-        mProgressDialog.setMessage(getString(R.string.progress_dialogue_network_connection));
-        mProgressDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
-        mProgressDialog.show();
-    }
-
-    // if network request is timeout, show alert dialog with two option: cancel & wait
-    private void showConnectionTimeoutAlertDialog() {
-        mAlertDialog = new AlertDialog.Builder(new ContextThemeWrapper(this, R.style.AlertDialog))
-                .setMessage(getString(R.string.alert_dialogue_network_timeout))
-                .setTitle(getString(R.string.alert_dialogue_network_timeout_title))
-                .setNegativeButton(getString(R.string.quit),
-                        new DialogInterface.OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                // cancel
-                                dismissDialog(mAlertDialog);
-                                finish();
-                            }
-                        })
-                .setPositiveButton(getString(R.string.wait),
-                        new DialogInterface.OnClickListener() {
-                            @Override
-                            public void onClick(DialogInterface dialog, int which) {
-                                // wait, request network again
-                                dismissDialog(mAlertDialog);
-                                requestNetwork(getIntent());
-                            }
-                        })
-                .create();
-        mAlertDialog.show();
-    }
-
-    private void requestNetwork(final Intent intent) {
-        NetworkRequest request = new NetworkRequest.Builder()
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
-                .build();
-
-        mCb = new ConnectivityManager.NetworkCallback() {
-            @Override
-            public void onAvailable(Network network) {
-                if (DBG) logd("Network available: " + network);
-                dismissDialog(mProgressDialog);
-                mCm.bindProcessToNetwork(network);
-                launchCaptivePortal(intent, network);
-            }
-
-            @Override
-            public void onUnavailable() {
-                if (DBG) logd("Network unavailable");
-                dismissDialog(mProgressDialog);
-                showConnectionTimeoutAlertDialog();
-            }
-        };
-        showConnectingProgressDialog();
-        mCm.requestNetwork(request, mCb, NETWORK_REQUEST_TIMEOUT_IN_MS);
-    }
-
-    private void releaseNetworkRequest() {
-        logd("release Network Request");
-        if (mCb != null) {
-            mCm.unregisterNetworkCallback(mCb);
-            mCb = null;
-        }
-    }
-
-    private void dismissDialog(AlertDialog dialog) {
-        if (dialog != null) {
-            dialog.dismiss();
-        }
-    }
-
-    private Network getNetworkForCaptivePortal() {
-        Network[] info = mCm.getAllNetworks();
-        if (!ArrayUtils.isEmpty(info)) {
-            for (Network nw : info) {
-                final NetworkCapabilities nc = mCm.getNetworkCapabilities(nw);
-                if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
-                        && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
-                    return nw;
-                }
-            }
-        }
-        return null;
-    }
-
-    private void launchCaptivePortal(final Intent intent, Network network) {
-        String redirectUrl = intent.getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
-        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
-                SubscriptionManager.getDefaultVoiceSubscriptionId());
-        if (TextUtils.isEmpty(redirectUrl) || !matchUrl(redirectUrl, subId)) {
-            loge("Launch portal fails due to incorrect redirection URL: " +
-                    Rlog.pii(TAG, redirectUrl));
-            return;
-        }
-        final Intent portalIntent = new Intent(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN);
-        portalIntent.putExtra(ConnectivityManager.EXTRA_NETWORK, network);
-        portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL,
-                new CaptivePortal(new ICaptivePortal.Stub() {
-                    @Override
-                    public void appResponse(int response) {
-                        logd("portal response code: " + response);
-                        releaseNetworkRequest();
-                        if (response == APP_RETURN_DISMISSED) {
-                            // Upon success http response code, trigger re-evaluation
-                            CarrierActionUtils.applyCarrierAction(
-                                    CarrierActionUtils.CARRIER_ACTION_ENABLE_RADIO, intent,
-                                    getApplicationContext());
-                            CarrierActionUtils.applyCarrierAction(
-                                    CarrierActionUtils.CARRIER_ACTION_ENABLE_METERED_APNS, intent,
-                                    getApplicationContext());
-                            CarrierActionUtils.applyCarrierAction(
-                                    CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS,
-                                    intent, getApplicationContext());
-                        }
-                    }
-                }));
-        portalIntent.putExtra(ConnectivityManager.EXTRA_CAPTIVE_PORTAL_URL, redirectUrl);
-        portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT | Intent.FLAG_ACTIVITY_NEW_TASK
-                        | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-        if (DBG) logd("launching portal");
-        startActivity(portalIntent);
-        finish();
-    }
-
-    // match configured redirection url
-    private boolean matchUrl(String url, int subId) {
-        CarrierConfigManager configManager = getApplicationContext()
-                .getSystemService(CarrierConfigManager.class);
-        String[] redirectURLs = configManager.getConfigForSubId(subId).getStringArray(
-                CarrierConfigManager.KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY);
-        if (ArrayUtils.isEmpty(redirectURLs)) {
-            if (DBG) logd("match is unnecessary without any configured redirection url");
-            return true;
-        }
-        for (String redirectURL : redirectURLs) {
-            if (url.startsWith(redirectURL)) {
-                return true;
-            }
-        }
-        if (DBG) loge("no match found for configured redirection url");
-        return false;
-    }
-
-    private static void logd(String s) {
-        Rlog.d(TAG, s);
-    }
-
-    private static void loge(String s) {
-        Rlog.d(TAG, s);
-    }
-}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
new file mode 100644
index 0000000..ec4c00e
--- /dev/null
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -0,0 +1,433 @@
+/*
+ * 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 com.android.carrierdefaultapp;
+
+import android.app.Activity;
+import android.app.LoadedApk;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.net.ConnectivityManager;
+import android.net.ConnectivityManager.NetworkCallback;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.NetworkRequest;
+import android.net.Proxy;
+import android.net.TrafficStats;
+import android.net.Uri;
+import android.net.http.SslError;
+import android.os.Bundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.Rlog;
+import android.telephony.SubscriptionManager;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.TypedValue;
+import android.webkit.SslErrorHandler;
+import android.webkit.WebChromeClient;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.telephony.PhoneConstants;
+import com.android.internal.telephony.TelephonyIntents;
+import com.android.internal.util.ArrayUtils;
+
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Random;
+
+/**
+ * Activity that launches in response to the captive portal notification
+ * @see com.android.carrierdefaultapp.CarrierActionUtils#CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
+ * This activity requests network connection if there is no available one before loading the real
+ * portal page and apply carrier actions on the portal activation result.
+ */
+public class CaptivePortalLoginActivity extends Activity {
+    private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
+    private static final boolean DBG = true;
+
+    private static final int SOCKET_TIMEOUT_MS = 10 * 1000;
+    private static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
+
+    private URL mUrl;
+    private Network mNetwork;
+    private NetworkCallback mNetworkCallback;
+    private ConnectivityManager mCm;
+    private WebView mWebView;
+    private MyWebViewClient mWebViewClient;
+    private boolean mLaunchBrowser = false;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mCm = ConnectivityManager.from(this);
+        mUrl = getUrlForCaptivePortal();
+        if (mUrl == null) {
+            done(false);
+            return;
+        }
+        if (DBG) logd(String.format("onCreate for %s", mUrl.toString()));
+        setContentView(R.layout.activity_captive_portal_login);
+        getActionBar().setDisplayShowHomeEnabled(false);
+
+        mWebView = (WebView) findViewById(R.id.webview);
+        mWebView.clearCache(true);
+        WebSettings webSettings = mWebView.getSettings();
+        webSettings.setJavaScriptEnabled(true);
+        webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
+        mWebViewClient = new MyWebViewClient();
+        mWebView.setWebViewClient(mWebViewClient);
+        mWebView.setWebChromeClient(new MyWebChromeClient());
+
+        mNetwork = getNetworkForCaptivePortal();
+        if (mNetwork == null) {
+            requestNetworkForCaptivePortal();
+        } else {
+            mCm.bindProcessToNetwork(mNetwork);
+            // Start initial page load so WebView finishes loading proxy settings.
+            // Actual load of mUrl is initiated by MyWebViewClient.
+            mWebView.loadData("", "text/html", null);
+        }
+    }
+
+    @Override
+    public void onBackPressed() {
+        WebView myWebView = (WebView) findViewById(R.id.webview);
+        if (myWebView.canGoBack() && mWebViewClient.allowBack()) {
+            myWebView.goBack();
+        } else {
+            super.onBackPressed();
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        releaseNetworkRequest();
+        if (mLaunchBrowser) {
+            // Give time for this network to become default. After 500ms just proceed.
+            for (int i = 0; i < 5; i++) {
+                // TODO: This misses when mNetwork underlies a VPN.
+                if (mNetwork.equals(mCm.getActiveNetwork())) break;
+                try {
+                    Thread.sleep(100);
+                } catch (InterruptedException e) {
+                }
+            }
+            final String url = mUrl.toString();
+            if (DBG) logd("starting activity with intent ACTION_VIEW for " + url);
+            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
+        }
+    }
+
+    // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
+    private void setWebViewProxy() {
+        LoadedApk loadedApk = getApplication().mLoadedApk;
+        try {
+            Field receiversField = LoadedApk.class.getDeclaredField("mReceivers");
+            receiversField.setAccessible(true);
+            ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
+            for (Object receiverMap : receivers.values()) {
+                for (Object rec : ((ArrayMap) receiverMap).keySet()) {
+                    Class clazz = rec.getClass();
+                    if (clazz.getName().contains("ProxyChangeListener")) {
+                        Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class,
+                                Intent.class);
+                        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+                        onReceiveMethod.invoke(rec, getApplicationContext(), intent);
+                        Log.v(TAG, "Prompting WebView proxy reload.");
+                    }
+                }
+            }
+        } catch (Exception e) {
+            loge("Exception while setting WebView proxy: " + e);
+        }
+    }
+
+    private void done(boolean success) {
+        if (DBG) logd(String.format("Result success %b for %s", success, mUrl.toString()));
+        if (success) {
+            // Trigger re-evaluation upon success http response code
+            CarrierActionUtils.applyCarrierAction(
+                    CarrierActionUtils.CARRIER_ACTION_ENABLE_RADIO, getIntent(),
+                    getApplicationContext());
+            CarrierActionUtils.applyCarrierAction(
+                    CarrierActionUtils.CARRIER_ACTION_ENABLE_METERED_APNS, getIntent(),
+                    getApplicationContext());
+            CarrierActionUtils.applyCarrierAction(
+                    CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS, getIntent(),
+                    getApplicationContext());
+
+        }
+        finishAndRemoveTask();
+    }
+
+    private URL getUrlForCaptivePortal() {
+        String url = getIntent().getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
+        if (url.isEmpty()) {
+            url = mCm.getCaptivePortalServerUrl();
+        }
+        final CarrierConfigManager configManager = getApplicationContext()
+                .getSystemService(CarrierConfigManager.class);
+        final int subId = getIntent().getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+                SubscriptionManager.getDefaultVoiceSubscriptionId());
+        final String[] portalURLs = configManager.getConfigForSubId(subId).getStringArray(
+                CarrierConfigManager.KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY);
+        if (!ArrayUtils.isEmpty(portalURLs)) {
+            for (String portalUrl : portalURLs) {
+                if (url.startsWith(portalUrl)) {
+                    break;
+                }
+            }
+            url = null;
+        }
+        try {
+            return new URL(url);
+        } catch (MalformedURLException e) {
+            loge("Invalid captive portal URL " + url);
+        }
+        return null;
+    }
+
+    private void testForCaptivePortal() {
+        new Thread(new Runnable() {
+            public void run() {
+                // Give time for captive portal to open.
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                }
+                HttpURLConnection urlConnection = null;
+                int httpResponseCode = 500;
+                TrafficStats.setThreadStatsTag(TrafficStats.TAG_SYSTEM_PROBE);
+                try {
+                    urlConnection = (HttpURLConnection) mNetwork.openConnection(mUrl);
+                    urlConnection.setInstanceFollowRedirects(false);
+                    urlConnection.setConnectTimeout(SOCKET_TIMEOUT_MS);
+                    urlConnection.setReadTimeout(SOCKET_TIMEOUT_MS);
+                    urlConnection.setUseCaches(false);
+                    urlConnection.getInputStream();
+                    httpResponseCode = urlConnection.getResponseCode();
+                } catch (IOException e) {
+                } finally {
+                    if (urlConnection != null) urlConnection.disconnect();
+                }
+                if (httpResponseCode == 204) {
+                    done(true);
+                }
+            }
+        }).start();
+    }
+
+    private Network getNetworkForCaptivePortal() {
+        Network[] info = mCm.getAllNetworks();
+        if (!ArrayUtils.isEmpty(info)) {
+            for (Network nw : info) {
+                final NetworkCapabilities nc = mCm.getNetworkCapabilities(nw);
+                if (nc.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+                        && nc.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+                    return nw;
+                }
+            }
+        }
+        return null;
+    }
+
+    private void requestNetworkForCaptivePortal() {
+        NetworkRequest request = new NetworkRequest.Builder()
+                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
+                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
+                .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
+                .build();
+
+        mNetworkCallback = new ConnectivityManager.NetworkCallback() {
+            @Override
+            public void onAvailable(Network network) {
+                if (DBG) logd("Network available: " + network);
+                mCm.bindProcessToNetwork(network);
+                mNetwork = network;
+                runOnUiThreadIfNotFinishing(() -> {
+                    // Start initial page load so WebView finishes loading proxy settings.
+                    // Actual load of mUrl is initiated by MyWebViewClient.
+                    mWebView.loadData("", "text/html", null);
+                });
+            }
+
+            @Override
+            public void onUnavailable() {
+                if (DBG) logd("Network unavailable");
+                runOnUiThreadIfNotFinishing(() -> {
+                    // Instead of not loading anything in webview, simply load the page and return
+                    // HTTP error page in the absence of network connection.
+                    mWebView.loadUrl(mUrl.toString());
+                });
+            }
+        };
+        logd("request Network for captive portal");
+        mCm.requestNetwork(request, mNetworkCallback, NETWORK_REQUEST_TIMEOUT_MS);
+    }
+
+    private void releaseNetworkRequest() {
+        logd("release Network for captive portal");
+        if (mNetworkCallback != null) {
+            mCm.unregisterNetworkCallback(mNetworkCallback);
+            mNetworkCallback = null;
+            mNetwork = null;
+        }
+    }
+
+    private class MyWebViewClient extends WebViewClient {
+        private static final String INTERNAL_ASSETS = "file:///android_asset/";
+        private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
+        // How many Android device-independent-pixels per scaled-pixel
+        // dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
+        private final float mDpPerSp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 1,
+                    getResources().getDisplayMetrics())
+                / TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1,
+                    getResources().getDisplayMetrics());
+        private int mPagesLoaded;
+
+        // If we haven't finished cleaning up the history, don't allow going back.
+        public boolean allowBack() {
+            return mPagesLoaded > 1;
+        }
+
+        @Override
+        public void onPageStarted(WebView view, String url, Bitmap favicon) {
+            if (url.contains(mBrowserBailOutToken)) {
+                mLaunchBrowser = true;
+                done(false);
+                return;
+            }
+            // The first page load is used only to cause the WebView to
+            // fetch the proxy settings.  Don't update the URL bar, and
+            // don't check if the captive portal is still there.
+            if (mPagesLoaded == 0) return;
+            // For internally generated pages, leave URL bar listing prior URL as this is the URL
+            // the page refers to.
+            if (!url.startsWith(INTERNAL_ASSETS)) {
+                final TextView myUrlBar = (TextView) findViewById(R.id.url_bar);
+                myUrlBar.setText(url);
+            }
+            if (mNetwork != null) {
+                testForCaptivePortal();
+            }
+        }
+
+        @Override
+        public void onPageFinished(WebView view, String url) {
+            mPagesLoaded++;
+            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.
+                setWebViewProxy();
+                // Load the real page.
+                view.loadUrl(mUrl.toString());
+                return;
+            } else if (mPagesLoaded == 2) {
+                // Prevent going back to empty first page.
+                view.clearHistory();
+            }
+            if (mNetwork != null) {
+                testForCaptivePortal();
+            }
+        }
+
+        // Convert Android device-independent-pixels (dp) to HTML size.
+        private String dp(int dp) {
+            // HTML px's are scaled just like dp's, so just add "px" suffix.
+            return Integer.toString(dp) + "px";
+        }
+
+        // Convert Android scaled-pixels (sp) to HTML size.
+        private String sp(int sp) {
+            // Convert sp to dp's.
+            float dp = sp * mDpPerSp;
+            // Apply a scale factor to make things look right.
+            dp *= 1.3;
+            // Convert dp's to HTML size.
+            return dp((int) dp);
+        }
+
+        // A web page consisting of a large broken lock icon to indicate SSL failure.
+        private final String SSL_ERROR_HTML = "<html><head><style>"
+                + "body { margin-left:" + dp(48) + "; margin-right:" + dp(48) + "; "
+                + "margin-top:" + dp(96) + "; background-color:#fafafa; }"
+                + "img { width:" + dp(48) + "; height:" + dp(48) + "; }"
+                + "div.warn { font-size:" + sp(16) + "; margin-top:" + dp(16) + "; "
+                + "           opacity:0.87; line-height:1.28; }"
+                + "div.example { font-size:" + sp(14) + "; margin-top:" + dp(16) + "; "
+                + "              opacity:0.54; line-height:1.21905; }"
+                + "a { font-size:" + sp(14) + "; text-decoration:none; text-transform:uppercase; "
+                + "    margin-top:" + dp(24) + "; display:inline-block; color:#4285F4; "
+                + "    height:" + dp(48) + "; font-weight:bold; }"
+                + "</style></head><body><p><img src=quantum_ic_warning_amber_96.png><br>"
+                + "<div class=warn>%s</div>"
+                + "<div class=example>%s</div>" + "<a href=%s>%s</a></body></html>";
+
+        @Override
+        public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
+            Log.w(TAG, "SSL error (error: " + error.getPrimaryError() + " host: "
+                    // Only show host to avoid leaking private info.
+                    + Uri.parse(error.getUrl()).getHost() + " certificate: "
+                    + error.getCertificate() + "); displaying SSL warning.");
+            final String html = String.format(SSL_ERROR_HTML, getString(R.string.ssl_error_warning),
+                    getString(R.string.ssl_error_example), mBrowserBailOutToken,
+                    getString(R.string.ssl_error_continue));
+            view.loadDataWithBaseURL(INTERNAL_ASSETS, html, "text/HTML", "UTF-8", null);
+        }
+
+        @Override
+        public boolean shouldOverrideUrlLoading(WebView view, String url) {
+            if (url.startsWith("tel:")) {
+                startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
+                return true;
+            }
+            return false;
+        }
+    }
+
+    private class MyWebChromeClient extends WebChromeClient {
+        @Override
+        public void onProgressChanged(WebView view, int newProgress) {
+            final ProgressBar myProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
+            myProgressBar.setProgress(newProgress);
+        }
+    }
+
+    private void runOnUiThreadIfNotFinishing(Runnable r) {
+        if (!isFinishing()) {
+            runOnUiThread(r);
+        }
+    }
+
+    private static void logd(String s) {
+        Rlog.d(TAG, s);
+    }
+
+    private static void loge(String s) {
+        Rlog.d(TAG, s);
+    }
+
+}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index d9bd2fc..73ff3a9 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -112,8 +112,10 @@
         logd("onShowCaptivePortalNotification");
         final NotificationManager notificationMgr = context.getSystemService(
                 NotificationManager.class);
-        Intent portalIntent = new Intent(context, CaptivePortalLaunchActivity.class);
+        Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
         portalIntent.putExtras(intent);
+        portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
+                | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
                 PendingIntent.FLAG_UPDATE_CURRENT);
         Notification notification = getNotification(context, R.string.portal_notification_id,
diff --git a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java b/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
deleted file mode 100644
index 8a18d72..0000000
--- a/packages/CarrierDefaultApp/tests/unit/src/com/android/carrierdefaultapp/LaunchCaptivePortalActivityTest.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.android.carrierdefaultapp;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.net.ConnectivityManager;
-import android.net.Network;
-import android.net.NetworkCapabilities;
-import android.net.NetworkInfo;
-import android.net.NetworkRequest;
-
-import com.android.internal.telephony.TelephonyIntents;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
-public class LaunchCaptivePortalActivityTest extends
-        CarrierDefaultActivityTestCase<CaptivePortalLaunchActivity> {
-
-    @Mock
-    private ConnectivityManager mCm;
-    @Mock
-    private NetworkInfo mNetworkInfo;
-    @Mock
-    private Network mNetwork;
-
-    @Captor
-    private ArgumentCaptor<Integer> mInt;
-    @Captor
-    private ArgumentCaptor<NetworkRequest> mNetworkReq;
-
-    private NetworkCapabilities mNetworkCapabilities;
-
-    public LaunchCaptivePortalActivityTest() {
-        super(CaptivePortalLaunchActivity.class);
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        super.setUp();
-        injectSystemService(ConnectivityManager.class, mCm);
-    }
-
-    @After
-    public void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    @Override
-    protected Intent createActivityIntent() {
-        Intent intent = new Intent(getInstrumentation().getTargetContext(),
-                CaptivePortalLaunchActivity.class);
-        intent.putExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY, "url");
-        return intent;
-    }
-
-    @Test
-    public void testWithoutInternetConnection() throws Throwable {
-        startActivity();
-        TestContext.waitForMs(100);
-        verify(mCm, atLeast(1)).requestNetwork(mNetworkReq.capture(), any(), mInt.capture());
-        // verify network request
-        assert(mNetworkReq.getValue().networkCapabilities.hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_INTERNET));
-        assert(mNetworkReq.getValue().networkCapabilities.hasTransport(
-                NetworkCapabilities.TRANSPORT_CELLULAR));
-        assertFalse(mNetworkReq.getValue().networkCapabilities.hasCapability(
-                NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED));
-        assertEquals(CaptivePortalLaunchActivity.NETWORK_REQUEST_TIMEOUT_IN_MS,
-                (int) mInt.getValue());
-        // verify captive portal app is not launched due to unavailable network
-        assertNull(getStartedActivityIntent());
-        stopActivity();
-    }
-
-    @Test
-    public void testWithInternetConnection() throws Throwable {
-        // Mock internet connection
-        mNetworkCapabilities = new NetworkCapabilities()
-                .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
-                .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
-        doReturn(new Network[]{mNetwork}).when(mCm).getAllNetworks();
-        doReturn(mNetworkCapabilities).when(mCm).getNetworkCapabilities(eq(mNetwork));
-        doReturn(mNetworkInfo).when(mCm).getNetworkInfo(eq(mNetwork));
-        doReturn(true).when(mNetworkInfo).isConnected();
-
-        startActivity();
-        TestContext.waitForMs(100);
-        // verify there is no network request with internet connection
-        verify(mCm, times(0)).requestNetwork(any(), any(), anyInt());
-        // verify captive portal app is launched
-        assertNotNull(getStartedActivityIntent());
-        assertEquals(ConnectivityManager.ACTION_CAPTIVE_PORTAL_SIGN_IN,
-                getStartedActivityIntent().getAction());
-        stopActivity();
-    }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a9f6dc9..4c8c036 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1625,7 +1625,7 @@
      */
     public void reportSimUnlocked(int subId) {
         if (DEBUG_SIM_STATES) Log.v(TAG, "reportSimUnlocked(subId=" + subId + ")");
-        int slotId = SubscriptionManager.getSlotId(subId);
+        int slotId = SubscriptionManager.getSlotIndex(subId);
         handleSimStateChange(subId, slotId, State.READY);
     }
 
@@ -1794,7 +1794,7 @@
         for (int i = 0; i < list.size(); i++) {
             final SubscriptionInfo info = list.get(i);
             final int id = info.getSubscriptionId();
-            int slotId = SubscriptionManager.getSlotId(id);
+            int slotId = SubscriptionManager.getSlotIndex(id);
             if (state == getSimState(id) && bestSlotId > slotId ) {
                 resultId = id;
                 bestSlotId = slotId;
diff --git a/packages/Osu/src/com/android/MainActivity.java b/packages/Osu/src/com/android/MainActivity.java
index 7e7d49a..9bcc390 100644
--- a/packages/Osu/src/com/android/MainActivity.java
+++ b/packages/Osu/src/com/android/MainActivity.java
@@ -246,6 +246,8 @@
                 case WifiManager.SCAN_RESULTS_AVAILABLE_ACTION:
                     mOsuManager.pushScanResults(wifiManager.getScanResults());
                     break;
+                // TODO(b/32883320): use updated intent.
+                /*
                 case WifiManager.PASSPOINT_WNM_FRAME_RECEIVED_ACTION:
                     long bssid = bundle.getLong(WifiManager.EXTRA_PASSPOINT_WNM_BSSID);
                     String url = bundle.getString(WifiManager.EXTRA_PASSPOINT_WNM_URL);
@@ -282,6 +284,7 @@
                             bundle.getString(WifiManager.EXTRA_PASSPOINT_ICON_FILE),
                             bundle.getByteArray(WifiManager.EXTRA_PASSPOINT_ICON_DATA));
                     break;
+                */
                 case WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION:
                     mOsuManager.networkConfigChange((WifiConfiguration)
                             intent.getParcelableExtra(WifiManager.EXTRA_WIFI_CONFIGURATION));
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 1f432de..dbfb118 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -102,6 +102,19 @@
 
 
     <!-- Bluetooth settings -->
+    <!-- Titles for Bluetooth AVRCP Versions -->
+    <string-array name="bluetooth_avrcp_versions">
+        <item>AVRCP 1.4 (Default)</item>
+        <item>AVRCP 1.5</item>
+        <item>AVRCP 1.6</item>
+    </string-array>
+
+    <!-- Values for Bluetooth AVRCP Versions -->
+    <string-array name="bluetooth_avrcp_version_values">
+        <item>avrcp14</item>
+        <item>avrcp15</item>
+        <item>avrcp16</item>
+    </string-array>
 
     <!-- Titles for Bluetooth Audio Codec selection preference. [CHAR LIMIT=50] -->
     <string-array name="bluetooth_a2dp_codec_titles">
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 064059b..3973a43 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -430,6 +430,11 @@
     <!-- Setting Checkbox title for disabling Bluetooth absolute volume -->
     <string name="bluetooth_disable_absolute_volume">Disable absolute volume</string>
 
+    <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+    <string name="bluetooth_select_avrcp_version_string">Bluetooth AVRCP Version</string>
+    <!-- UI debug setting: Select Bluetooth AVRCP Version -->
+    <string name="bluetooth_select_avrcp_version_dialog_title">Select Bluetooth AVRCP Version</string>
+
     <!-- UI debug setting: Select Bluetooth Audio Codec -->
     <string name="bluetooth_select_a2dp_codec_type">Bluetooth Audio Codec</string>
     <!-- UI debug setting: Select Bluetooth Audio Codec -->
diff --git a/packages/SettingsLib/res/xml/timezones.xml b/packages/SettingsLib/res/xml/timezones.xml
index 4426495..12d31cf 100644
--- a/packages/SettingsLib/res/xml/timezones.xml
+++ b/packages/SettingsLib/res/xml/timezones.xml
@@ -21,7 +21,7 @@
     <timezone id="America/St_Johns"></timezone>
     <timezone id="America/Recife"></timezone>
     <timezone id="America/Sao_Paulo"></timezone>
-    <timezone id="America/Buenos_Aires"></timezone>
+    <timezone id="America/Argentina/Buenos_Aires"></timezone>
     <timezone id="America/Godthab"></timezone>
     <timezone id="America/Montevideo"></timezone>
     <timezone id="Atlantic/South_Georgia"></timezone>
@@ -58,11 +58,11 @@
     <timezone id="Asia/Karachi"></timezone>
     <timezone id="Asia/Oral"></timezone>
     <timezone id="Asia/Yekaterinburg"></timezone>
-    <timezone id="Asia/Calcutta"></timezone>
+    <timezone id="Asia/Kolkata"></timezone>
     <timezone id="Asia/Colombo"></timezone>
-    <timezone id="Asia/Katmandu"></timezone>
+    <timezone id="Asia/Kathmandu"></timezone>
     <timezone id="Asia/Almaty"></timezone>
-    <timezone id="Asia/Rangoon"></timezone>
+    <timezone id="Asia/Yangon"></timezone>
     <timezone id="Asia/Krasnoyarsk"></timezone>
     <timezone id="Asia/Bangkok"></timezone>
     <timezone id="Asia/Jakarta"></timezone>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
index f0ec1078..a803e60 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/ApplicationsState.java
@@ -649,7 +649,11 @@
             }
 
             if (comparator != null) {
-                Collections.sort(filteredApps, comparator);
+                synchronized (mEntriesMap) {
+                    // Locking to ensure that the background handler does not mutate
+                    // the size of AppEntries used for ordering while sorting.
+                    Collections.sort(filteredApps, comparator);
+                }
             }
 
             synchronized (mRebuildSync) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index e00178f..144d439 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -398,10 +398,12 @@
                     removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
                 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
                     // We will update when the automation service dies.
-                    UserState userState = getCurrentUserStateLocked();
-                    if (!userState.isUiAutomationSuppressingOtherServices()) {
-                        if (readConfigurationForUserStateLocked(userState)) {
-                            onUserStateChangedLocked(userState);
+                    synchronized (mLock) {
+                        UserState userState = getCurrentUserStateLocked();
+                        if (!userState.isUiAutomationSuppressingOtherServices()) {
+                            if (readConfigurationForUserStateLocked(userState)) {
+                                onUserStateChangedLocked(userState);
+                            }
                         }
                     }
                 } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
diff --git a/services/core/Android.mk b/services/core/Android.mk
index a61743d..898eb7e 100644
--- a/services/core/Android.mk
+++ b/services/core/Android.mk
@@ -19,7 +19,7 @@
     system/netd/server/binder
 
 LOCAL_JAVA_LIBRARIES := services.net telephony-common
-LOCAL_STATIC_JAVA_LIBRARIES := tzdata_update2
+LOCAL_STATIC_JAVA_LIBRARIES := tzdata_shared2 tzdata_update2
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 
 ifneq ($(INCREMENTAL_BUILDS),)
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 5e9cf74..c7c133d 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -76,15 +76,21 @@
 
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
-    private static final String ACTION_SERVICE_STATE_CHANGED="com.android.bluetooth.btservice.action.STATE_CHANGED";
-    private static final String EXTRA_ACTION="action";
+
     private static final String SECURE_SETTINGS_BLUETOOTH_ADDR_VALID="bluetooth_addr_valid";
     private static final String SECURE_SETTINGS_BLUETOOTH_ADDRESS="bluetooth_address";
     private static final String SECURE_SETTINGS_BLUETOOTH_NAME="bluetooth_name";
+
+    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_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 int TIMEOUT_BIND_MS = 3000; //Maximum msec to wait for a bind
-    private static final int TIMEOUT_SAVE_MS = 500; //Maximum msec to wait for a save
     //Maximum msec to wait for service restart
     private static final int SERVICE_RESTART_TIME_MS = 200;
     //Maximum msec to wait for restart due to error
@@ -149,6 +155,10 @@
     private boolean mQuietEnable = false;
     private boolean mEnable;
 
+    private CharSequence timeToLog(long timestamp) {
+        return android.text.format.DateFormat.format("MM-dd HH:mm:ss", timestamp);
+    }
+
     /**
      * Used for tracking apps that enabled / disabled Bluetooth.
      */
@@ -168,13 +178,15 @@
         }
 
         public String toString() {
-            return android.text.format.DateFormat.format("MM-dd HH:mm:ss ", mTimestamp) +
-                    (mEnable ? "  Enabled " : " Disabled ") + " by " + mPackageName;
+            return  timeToLog(mTimestamp) + (mEnable ? "  Enabled " : " Disabled ") + " by "
+                + mPackageName;
         }
 
     }
 
     private LinkedList<ActiveLog> mActiveLogs;
+    private LinkedList<Long> mCrashTimestamps;
+    private int mCrashes;
 
     // configuration from external IBinder call which is used to
     // synchronize with broadcast receiver.
@@ -308,6 +320,8 @@
                 com.android.internal.R.bool.config_permissionReviewRequired);
 
         mActiveLogs = new LinkedList<ActiveLog>();
+        mCrashTimestamps = new LinkedList<Long>();
+        mCrashes = 0;
         mBluetooth = null;
         mBluetoothBinder = null;
         mBluetoothGatt = null;
@@ -1565,6 +1579,9 @@
                         mBluetoothLock.writeLock().unlock();
                     }
 
+                    // log the unexpected crash
+                    addCrashLog();
+                    addActiveLog(REASON_UNEXPECTED, false);
                     if (mEnable) {
                         mEnable = false;
                         // Send a Bluetooth Restart message
@@ -1600,6 +1617,7 @@
                      it doesnt change when IBluetooth
                      service restarts */
                     mEnable = true;
+                    addActiveLog(REASON_RESTARTED, true);
                     handleEnable(mQuietEnable);
                     break;
                 }
@@ -1654,6 +1672,7 @@
 
                         unbindAllBluetoothProfileServices();
                         // disable
+                        addActiveLog(REASON_USER_SWITCH, false);
                         handleDisable();
                         // Pbap service need receive STATE_TURNING_OFF intent to close
                         bluetoothStateChangeHandler(BluetoothAdapter.STATE_ON,
@@ -1691,6 +1710,7 @@
                         mHandler.removeMessages(MESSAGE_BLUETOOTH_STATE_CHANGE);
                         mState = BluetoothAdapter.STATE_OFF;
                         // enable
+                        addActiveLog(REASON_USER_SWITCH, true);
                         handleEnable(mQuietEnable);
                     } else if (mBinding || mBluetooth != null) {
                         Message userMsg = mHandler.obtainMessage(MESSAGE_USER_SWITCHED);
@@ -1945,13 +1965,21 @@
 
     private void addActiveLog(String packageName, boolean enable) {
         synchronized (mActiveLogs) {
-            if (mActiveLogs.size() > 10) {
+            if (mActiveLogs.size() > ACTIVE_LOG_MAX_SIZE) {
                 mActiveLogs.remove();
             }
             mActiveLogs.add(new ActiveLog(packageName, enable, System.currentTimeMillis()));
         }
     }
 
+    private void addCrashLog() {
+      synchronized (mCrashTimestamps) {
+        if (mCrashTimestamps.size() == CRASH_LOG_MAX_SIZE) mCrashTimestamps.removeFirst();
+        mCrashTimestamps.add(System.currentTimeMillis());
+        mCrashes++;
+      }
+    }
+
     private void recoverBluetoothServiceFromError(boolean clearBle) {
         Slog.e(TAG,"recoverBluetoothServiceFromError");
         try {
@@ -1969,6 +1997,7 @@
         SystemClock.sleep(500);
 
         // disable
+        addActiveLog(REASON_START_CRASH, false);
         handleDisable();
 
         waitForOnOff(false, true);
@@ -2070,6 +2099,12 @@
                 }
             }
 
+            writer.println("Bluetooth crashed " + mCrashes + " time" + (mCrashes == 1 ? "" : "s"));
+            if (mCrashes == CRASH_LOG_MAX_SIZE) writer.println("(last " + CRASH_LOG_MAX_SIZE + ")");
+            for (Long time : mCrashTimestamps) {
+              writer.println("  " + timeToLog(time.longValue()));
+            }
+
             String bleAppString = "No BLE Apps registered.";
             if (mBleApps.size() == 1) {
                 bleAppString = "1 BLE App registered:";
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f58cdba..d23347f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3082,13 +3082,22 @@
         boolean tetherEnabledInSettings = (Settings.Global.getInt(mContext.getContentResolver(),
                 Settings.Global.TETHER_SUPPORTED, defaultVal) != 0)
                 && !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING);
-        return tetherEnabledInSettings && mUserManager.isAdminUser() &&
+
+        // Elevate to system UID to avoid caller requiring MANAGE_USERS permission.
+        boolean adminUser = false;
+        final long token = Binder.clearCallingIdentity();
+        try {
+            adminUser = mUserManager.isAdminUser();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+
+        return tetherEnabledInSettings && adminUser &&
                mTethering.hasTetherableConfiguration();
     }
 
     @Override
-    public void startTethering(int type, ResultReceiver receiver,
-            boolean showProvisioningUi) {
+    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
         ConnectivityManager.enforceTetherChangePermission(mContext);
         if (!isTetheringSupported()) {
             receiver.send(ConnectivityManager.TETHER_ERROR_UNSUPPORTED, null);
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index 58c76ec..46f76b1 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.connectivity;
 
+import android.annotation.WorkerThread;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
@@ -73,7 +74,7 @@
     public static final String KEY_PROXY = "keyProxy";
     private String mCurrentPac;
     @GuardedBy("mProxyLock")
-    private Uri mPacUrl = Uri.EMPTY;
+    private volatile Uri mPacUrl = Uri.EMPTY;
 
     private AlarmManager mAlarmManager;
     @GuardedBy("mProxyLock")
@@ -86,29 +87,34 @@
     private int mCurrentDelay;
     private int mLastPort;
 
-    private boolean mHasSentBroadcast;
-    private boolean mHasDownloaded;
+    private volatile boolean mHasSentBroadcast;
+    private volatile boolean mHasDownloaded;
 
     private Handler mConnectivityHandler;
     private int mProxyMessage;
 
     /**
-     * Used for locking when setting mProxyService and all references to mPacUrl or mCurrentPac.
+     * Used for locking when setting mProxyService and all references to mCurrentPac.
      */
     private final Object mProxyLock = new Object();
 
+    /**
+     * Runnable to download PAC script.
+     * The behavior relies on the assamption it always run on mNetThread to guarantee that the
+     * latest data fetched from mPacUrl is stored in mProxyService.
+     */
     private Runnable mPacDownloader = new Runnable() {
         @Override
+        @WorkerThread
         public void run() {
             String file;
-            synchronized (mProxyLock) {
-                if (Uri.EMPTY.equals(mPacUrl)) return;
-                try {
-                    file = get(mPacUrl);
-                } catch (IOException ioe) {
-                    file = null;
-                    Log.w(TAG, "Failed to load PAC file: " + ioe);
-                }
+            final Uri pacUrl = mPacUrl;
+            if (Uri.EMPTY.equals(pacUrl)) return;
+            try {
+                file = get(pacUrl);
+            } catch (IOException ioe) {
+                file = null;
+                Log.w(TAG, "Failed to load PAC file: " + ioe);
             }
             if (file != null) {
                 synchronized (mProxyLock) {
@@ -171,9 +177,7 @@
                 // Allow to send broadcast, nothing to do.
                 return false;
             }
-            synchronized (mProxyLock) {
-                mPacUrl = proxy.getPacFileUrl();
-            }
+            mPacUrl = proxy.getPacFileUrl();
             mCurrentDelay = DELAY_1;
             mHasSentBroadcast = false;
             mHasDownloaded = false;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index dfd647c..693292a 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -77,8 +77,8 @@
 import com.android.server.connectivity.tethering.IPv6TetheringCoordinator;
 import com.android.server.connectivity.tethering.IPv6TetheringInterfaceServices;
 import com.android.server.connectivity.tethering.OffloadController;
-import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.TetherInterfaceStateMachine;
+import com.android.server.connectivity.tethering.TetheringConfiguration;
 import com.android.server.connectivity.tethering.UpstreamNetworkMonitor;
 import com.android.server.net.BaseNetworkObserver;
 
@@ -102,8 +102,7 @@
  */
 public class Tethering extends BaseNetworkObserver implements IControlsTethering {
 
-    private final Context mContext;
-    private final static String TAG = "Tethering";
+    private final static String TAG = Tethering.class.getSimpleName();
     private final static boolean DBG = false;
     private final static boolean VDBG = false;
 
@@ -115,48 +114,43 @@
     private static final SparseArray<String> sMagicDecoderRing =
             MessageUtils.findMessageNames(messageClasses);
 
-    private volatile TetheringConfiguration mConfig;
+    // {@link ComponentName} of the Service used to run tether provisioning.
+    private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
+            .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
+
+    private static class TetherState {
+        public final TetherInterfaceStateMachine stateMachine;
+        public int lastState;
+        public int lastError;
+        public TetherState(TetherInterfaceStateMachine sm) {
+            stateMachine = sm;
+            // Assume all state machines start out available and with no errors.
+            lastState = IControlsTethering.STATE_AVAILABLE;
+            lastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
+        }
+    }
 
     // used to synchronize public access to members
     private final Object mPublicSync;
-
+    private final Context mContext;
+    private final ArrayMap<String, TetherState> mTetherStates;
+    private final BroadcastReceiver mStateReceiver;
     private final INetworkManagementService mNMService;
     private final INetworkStatsService mStatsService;
     private final INetworkPolicyManager mPolicyManager;
     private final Looper mLooper;
     private final MockableSystemProperties mSystemProperties;
-
-    private static class TetherState {
-        public final TetherInterfaceStateMachine mStateMachine;
-        public int mLastState;
-        public int mLastError;
-        public TetherState(TetherInterfaceStateMachine sm) {
-            mStateMachine = sm;
-            // Assume all state machines start out available and with no errors.
-            mLastState = IControlsTethering.STATE_AVAILABLE;
-            mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
-        }
-    }
-    private final ArrayMap<String, TetherState> mTetherStates;
-
-    private final BroadcastReceiver mStateReceiver;
-
-    // {@link ComponentName} of the Service used to run tether provisioning.
-    private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
-            .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
-
     private final StateMachine mTetherMasterSM;
     private final OffloadController mOffloadController;
     private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
-    private String mCurrentUpstreamIface;
 
+    private volatile TetheringConfiguration mConfig;
+    private String mCurrentUpstreamIface;
     private Notification.Builder mTetheredNotificationBuilder;
     private int mLastNotificationId;
-
     private boolean mRndisEnabled;       // track the RNDIS function enabled state
     private boolean mUsbTetherRequested; // true if USB tethering should be started
                                          // when RNDIS is enabled
-
     // True iff WiFi tethering should be started when soft AP is ready.
     private boolean mWifiTetherRequested;
 
@@ -227,7 +221,7 @@
                 }
             } else {
                 if (interfaceType == ConnectivityManager.TETHERING_BLUETOOTH) {
-                    tetherState.mStateMachine.sendMessage(
+                    tetherState.stateMachine.sendMessage(
                             TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
                     mTetherStates.remove(iface);
                 } else {
@@ -289,13 +283,12 @@
                 }
                 return;
             }
-            tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
+            tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_INTERFACE_DOWN);
             mTetherStates.remove(iface);
         }
     }
 
-    public void startTethering(int type, ResultReceiver receiver,
-            boolean showProvisioningUi) {
+    public void startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi) {
         if (!isTetherProvisioningRequired()) {
             enableTetheringInternal(type, true, receiver);
             return;
@@ -527,11 +520,11 @@
             }
             // Ignore the error status of the interface.  If the interface is available,
             // the errors are referring to past tethering attempts anyway.
-            if (tetherState.mLastState != IControlsTethering.STATE_AVAILABLE) {
+            if (tetherState.lastState != IControlsTethering.STATE_AVAILABLE) {
                 Log.e(TAG, "Tried to Tether an unavailable iface: " + iface + ", ignoring");
                 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
             }
-            tetherState.mStateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
+            tetherState.stateMachine.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_REQUESTED);
             return ConnectivityManager.TETHER_ERROR_NO_ERROR;
         }
     }
@@ -544,11 +537,11 @@
                 Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
                 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
             }
-            if (tetherState.mLastState != IControlsTethering.STATE_TETHERED) {
+            if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
                 Log.e(TAG, "Tried to untether an untethered iface :" + iface + ", ignoring");
                 return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
             }
-            tetherState.mStateMachine.sendMessage(
+            tetherState.stateMachine.sendMessage(
                     TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
             return ConnectivityManager.TETHER_ERROR_NO_ERROR;
         }
@@ -568,7 +561,7 @@
                         ", ignoring");
                 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
             }
-            return tetherState.mLastError;
+            return tetherState.lastError;
         }
     }
 
@@ -589,11 +582,11 @@
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
                 String iface = mTetherStates.keyAt(i);
-                if (tetherState.mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                     erroredList.add(iface);
-                } else if (tetherState.mLastState == IControlsTethering.STATE_AVAILABLE) {
+                } else if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
                     availableList.add(iface);
-                } else if (tetherState.mLastState == IControlsTethering.STATE_TETHERED) {
+                } else if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
                     if (cfg.isUsb(iface)) {
                         usbTethered = true;
                     } else if (cfg.isWifi(iface)) {
@@ -766,7 +759,7 @@
                         // themselves down.
                         for (int i = 0; i < mTetherStates.size(); i++) {
                             TetherInterfaceStateMachine tism =
-                                    mTetherStates.valueAt(i).mStateMachine;
+                                    mTetherStates.valueAt(i).stateMachine;
                             if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
                                 tism.sendMessage(
                                         TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
@@ -881,7 +874,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.mLastState == IControlsTethering.STATE_TETHERED) {
+                if (tetherState.lastState == IControlsTethering.STATE_TETHERED) {
                     list.add(mTetherStates.keyAt(i));
                 }
             }
@@ -894,7 +887,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.mLastState == IControlsTethering.STATE_AVAILABLE) {
+                if (tetherState.lastState == IControlsTethering.STATE_AVAILABLE) {
                     list.add(mTetherStates.keyAt(i));
                 }
             }
@@ -911,7 +904,7 @@
         synchronized (mPublicSync) {
             for (int i = 0; i < mTetherStates.size(); i++) {
                 TetherState tetherState = mTetherStates.valueAt(i);
-                if (tetherState.mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
+                if (tetherState.lastError != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                     list.add(mTetherStates.keyAt(i));
                 }
             }
@@ -1318,7 +1311,7 @@
                         synchronized (mPublicSync) {
                             for (int i = 0; i < mTetherStates.size(); i++) {
                                 TetherState tetherState = mTetherStates.valueAt(i);
-                                if (tetherState.mLastState != IControlsTethering.STATE_TETHERED) {
+                                if (tetherState.lastState != IControlsTethering.STATE_TETHERED) {
                                     continue;  // Skip interfaces that aren't tethered.
                                 }
                                 String iface = mTetherStates.keyAt(i);
@@ -1591,14 +1584,14 @@
 
         pw.println("Tethering:");
         pw.increaseIndent();
-        final TetheringConfiguration cfg = mConfig;
-        pw.print("preferredUpstreamIfaceTypes:");
-        synchronized (mPublicSync) {
-            for (Integer netType : cfg.preferredUpstreamIfaceTypes) {
-                pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
-            }
-            pw.println();
 
+        pw.println("Configuration:");
+        pw.increaseIndent();
+        final TetheringConfiguration cfg = mConfig;
+        cfg.dump(pw);
+        pw.decreaseIndent();
+
+        synchronized (mPublicSync) {
             pw.println("Tether state:");
             pw.increaseIndent();
             for (int i = 0; i < mTetherStates.size(); i++) {
@@ -1606,7 +1599,7 @@
                 final TetherState tetherState = mTetherStates.valueAt(i);
                 pw.print(iface + " - ");
 
-                switch (tetherState.mLastState) {
+                switch (tetherState.lastState) {
                     case IControlsTethering.STATE_UNAVAILABLE:
                         pw.print("UnavailableState");
                         break;
@@ -1620,7 +1613,7 @@
                         pw.print("UnknownState");
                         break;
                 }
-                pw.println(" - lastError = " + tetherState.mLastError);
+                pw.println(" - lastError = " + tetherState.lastError);
             }
             pw.decreaseIndent();
         }
@@ -1632,9 +1625,9 @@
                                            int state, int error) {
         synchronized (mPublicSync) {
             TetherState tetherState = mTetherStates.get(iface);
-            if (tetherState != null && tetherState.mStateMachine.equals(who)) {
-                tetherState.mLastState = state;
-                tetherState.mLastError = error;
+            if (tetherState != null && tetherState.stateMachine.equals(who)) {
+                tetherState.lastState = state;
+                tetherState.lastError = error;
             } else {
                 if (DBG) Log.d(TAG, "got notification from stale iface " + iface);
             }
@@ -1678,7 +1671,7 @@
                 interfaceType, mNMService, mStatsService, this,
                 new IPv6TetheringInterfaceServices(iface, mNMService)));
         mTetherStates.put(iface, tetherState);
-        tetherState.mStateMachine.start();
+        tetherState.stateMachine.start();
     }
 
     private static String[] copy(String[] strarray) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
index dec2f77..8c6430c 100644
--- a/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
+++ b/services/core/java/com/android/server/connectivity/tethering/IPv6TetheringInterfaceServices.java
@@ -16,6 +16,8 @@
 
 package com.android.server.connectivity.tethering;
 
+import static android.net.util.NetworkConstants.RFC7421_PREFIX_LENGTH;
+
 import android.net.INetd;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
@@ -48,7 +50,6 @@
 public class IPv6TetheringInterfaceServices {
     private static final String TAG = IPv6TetheringInterfaceServices.class.getSimpleName();
     private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64");
-    private static final int RFC7421_IP_PREFIX_LENGTH = 64;
 
     private final String mIfName;
     private final INetworkManagementService mNMService;
@@ -124,7 +125,7 @@
             params.hasDefaultRoute = v6only.hasIPv6DefaultRoute();
 
             for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
-                if (linkAddr.getPrefixLength() != RFC7421_IP_PREFIX_LENGTH) continue;
+                if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
 
                 final IpPrefix prefix = new IpPrefix(
                         linkAddr.getAddress(), linkAddr.getPrefixLength());
@@ -206,7 +207,7 @@
             for (Inet6Address dns : deprecatedDnses) {
                 final String dnsString = dns.getHostAddress();
                 try {
-                    netd.interfaceDelAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+                    netd.interfaceDelAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
                 } catch (ServiceSpecificException | RemoteException e) {
                     Log.e(TAG, "Failed to remove local dns IP: " + dnsString, e);
                 }
@@ -223,7 +224,7 @@
             for (Inet6Address dns : addedDnses) {
                 final String dnsString = dns.getHostAddress();
                 try {
-                    netd.interfaceAddAddress(mIfName, dnsString, RFC7421_IP_PREFIX_LENGTH);
+                    netd.interfaceAddAddress(mIfName, dnsString, RFC7421_PREFIX_LENGTH);
                 } catch (ServiceSpecificException | RemoteException e) {
                     Log.e(TAG, "Failed to add local dns IP: " + dnsString, e);
                     newDnses.remove(dns);
diff --git a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
index 14d06cc..d38beb3 100644
--- a/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
+++ b/services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
@@ -22,12 +22,15 @@
 
 import android.content.Context;
 import android.content.res.Resources;
+import android.net.ConnectivityManager;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.StringJoiner;
 
 
 /**
@@ -97,6 +100,44 @@
         return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs);
     }
 
+    public void dump(PrintWriter pw) {
+        dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs);
+        dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs);
+        dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs);
+
+        pw.print("isDunRequired: ");
+        pw.println(isDunRequired);
+
+        String[] upstreamTypes = null;
+        if (preferredUpstreamIfaceTypes != null) {
+            upstreamTypes = new String[preferredUpstreamIfaceTypes.size()];
+            int i = 0;
+            for (Integer netType : preferredUpstreamIfaceTypes) {
+                upstreamTypes[i] = ConnectivityManager.getNetworkTypeName(netType);
+                i++;
+            }
+        }
+        dumpStringArray(pw, "preferredUpstreamIfaceTypes", upstreamTypes);
+
+        dumpStringArray(pw, "dhcpRanges", dhcpRanges);
+        dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS);
+    }
+
+    private static void dumpStringArray(PrintWriter pw, String label, String[] values) {
+        pw.print(label);
+        pw.print(": ");
+
+        if (values != null) {
+            final StringJoiner sj = new StringJoiner(", ", "[", "]");
+            for (String value : values) { sj.add(value); }
+            pw.print(sj.toString());
+        } else {
+            pw.print("null");
+        }
+
+        pw.println();
+    }
+
     private static boolean checkDunRequired(Context ctx) {
         final TelephonyManager tm = ctx.getSystemService(TelephonyManager.class);
         final int secureSetting =
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 4658c046..060dd73 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -381,6 +381,7 @@
         mContext.unregisterReceiver(mTetherReceiver);
         mContext.unregisterReceiver(mPollReceiver);
         mContext.unregisterReceiver(mRemovedReceiver);
+        mContext.unregisterReceiver(mUserReceiver);
         mContext.unregisterReceiver(mShutdownReceiver);
 
         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9418e74..1498693 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -213,6 +213,7 @@
         if (getAvailableSpace() > 0) {
             dexoptCommandCountExecuted++;
 
+            Log.d(TAG, "Next command: " + next);
             return next;
         } else {
             if (DEBUG_DEXOPT) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9452219..42f6502 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -9234,9 +9234,9 @@
                         ps.pkg.applicationInfo.primaryCpuAbi = adjustedAbi;
                         Slog.i(TAG, "Adjusting ABI for " + ps.name + " to " + adjustedAbi
                                 + " (requirer="
-                                + (requirer == null ? "null" : requirer.pkg.packageName)
+                                + (requirer != null ? requirer.pkg : "null")
                                 + ", scannedPackage="
-                                + (scannedPackage != null ? scannedPackage.packageName : "null")
+                                + (scannedPackage != null ? scannedPackage : "null")
                                 + ")");
                         try {
                             mInstaller.rmdex(ps.codePathString,
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 522c2e8..9a559ee 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -60,8 +60,8 @@
 
     /** Path to MAC permissions on system image */
     private static final File[] MAC_PERMISSIONS =
-    { new File(Environment.getRootDirectory(), "/etc/security/plat_mac_permissions.xml"),
-      new File(Environment.getRootDirectory(), "/etc/security/nonplat_mac_permissions.xml") };
+    { new File(Environment.getRootDirectory(), "/etc/selinux/plat_mac_permissions.xml"),
+      new File(Environment.getVendorDirectory(), "/etc/selinux/nonplat_mac_permissions.xml") };
 
     // Append privapp to existing seinfo label
     private static final String PRIVILEGED_APP_STR = ":privapp";
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index de4a55b..c907cf3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -235,6 +235,15 @@
                 SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
             }
 
+            //
+            // Default the timezone property to GMT if not set.
+            //
+            String timezoneProperty =  SystemProperties.get("persist.sys.timezone");
+            if (timezoneProperty == null || timezoneProperty.isEmpty()) {
+                Slog.w(TAG, "Timezone not set; setting to GMT.");
+                SystemProperties.set("persist.sys.timezone", "GMT");
+            }
+
             // If the system has "persist.sys.language" and friends set, replace them with
             // "persist.sys.locale". Note that the default locale at this point is calculated
             // using the "-Duser.locale" command line flag. That flag is usually populated by
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 76b1c90..3e3a19b 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -23,6 +23,7 @@
 import android.net.apf.ApfCapabilities;
 import android.net.apf.ApfFilter;
 import android.net.DhcpResults;
+import android.net.INetd;
 import android.net.InterfaceConfiguration;
 import android.net.LinkAddress;
 import android.net.LinkProperties;
@@ -34,10 +35,12 @@
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.IpManagerEvent;
 import android.net.util.MultinetworkPolicyTracker;
+import android.net.util.NetdService;
 import android.os.INetworkManagementService;
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.LocalLog;
@@ -631,6 +634,13 @@
 
         pw.println();
         pw.println(mTag + " connectivity packet log:");
+        pw.println();
+        pw.println("Debug with python and scapy via:");
+        pw.println("shell$ python");
+        pw.println(">>> from scapy import all as scapy");
+        pw.println(">>> scapy.Ether(\"<paste_hex_string>\".decode(\"hex\")).show2()");
+        pw.println();
+
         pw.increaseIndent();
         mConnectivityPacketLog.readOnlyLocalLog().dump(fd, pw, args);
         pw.decreaseIndent();
@@ -1020,14 +1030,16 @@
 
     private boolean startIPv6() {
         // Set privacy extensions.
+        final String PREFER_TEMPADDRS = "2";
         try {
-            mNwService.setInterfaceIpv6PrivacyExtensions(mInterfaceName, true);
+            NetdService.run((INetd netd) -> {
+                netd.setProcSysNet(
+                        INetd.IPV6, INetd.CONF, mInterfaceName, "use_tempaddr",
+                        PREFER_TEMPADDRS);
+            });
             mNwService.enableIpv6(mInterfaceName);
-        } catch (RemoteException re) {
-            logError("Unable to change interface settings: %s", re);
-            return false;
-        } catch (IllegalStateException ie) {
-            logError("Unable to change interface settings: %s", ie);
+        } catch (IllegalStateException|RemoteException|ServiceSpecificException e) {
+            logError("Unable to change interface settings: %s", e);
             return false;
         }
 
diff --git a/services/net/java/android/net/util/NetdService.java b/services/net/java/android/net/util/NetdService.java
index 153cb50..6e69ff5 100644
--- a/services/net/java/android/net/util/NetdService.java
+++ b/services/net/java/android/net/util/NetdService.java
@@ -17,7 +17,10 @@
 package android.net.util;
 
 import android.net.INetd;
+import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.SystemClock;
 import android.util.Log;
 
 
@@ -27,15 +30,24 @@
 public class NetdService {
     private static final String TAG = NetdService.class.getSimpleName();
     private static final String NETD_SERVICE_NAME = "netd";
+    private static final long BASE_TIMEOUT_MS = 100;
+    private static final long MAX_TIMEOUT_MS = 1000;
+
 
     /**
+     * Return an INetd instance, or null if not available.
+     *
      * It is the caller's responsibility to check for a null return value
      * and to handle RemoteException errors from invocations on the returned
      * interface if, for example, netd dies and is restarted.
      *
+     * Returned instances of INetd should not be cached.
+     *
      * @return an INetd instance or null.
      */
     public static INetd getInstance() {
+        // NOTE: ServiceManager does no caching for the netd service,
+        // because netd is not one of the defined common services.
         final INetd netdInstance = INetd.Stub.asInterface(
                 ServiceManager.getService(NETD_SERVICE_NAME));
         if (netdInstance == null) {
@@ -43,4 +55,82 @@
         }
         return netdInstance;
     }
+
+    /**
+     * Blocks for a specified time until an INetd instance is available.
+     *
+     * It is the caller's responsibility to handle RemoteException errors
+     * from invocations on the returned interface if, for example, netd
+     * dies after this interface was returned.
+     *
+     * Returned instances of INetd should not be cached.
+     *
+     * Special values of maxTimeoutMs include: 0, meaning try to obtain an
+     * INetd instance only once, and -1 (or any value less than 0), meaning
+     * try to obtain an INetd instance indefinitely.
+     *
+     * @param maxTimeoutMs the maximum time to spend getting an INetd instance
+     * @return an INetd instance or null if no instance is available
+     * within |maxTimeoutMs| milliseconds.
+     */
+    public static INetd get(long maxTimeoutMs) {
+        if (maxTimeoutMs == 0) return getInstance();
+
+        final long stop = (maxTimeoutMs > 0)
+                ? SystemClock.elapsedRealtime() + maxTimeoutMs
+                : Long.MAX_VALUE;
+
+        long timeoutMs = 0;
+        while (true) {
+            final INetd netdInstance = getInstance();
+            if (netdInstance != null) {
+                return netdInstance;
+            }
+
+            final long remaining = stop - SystemClock.elapsedRealtime();
+            if (remaining <= 0) break;
+
+            // No netdInstance was received; sleep and retry.
+            timeoutMs = Math.min(timeoutMs + BASE_TIMEOUT_MS, MAX_TIMEOUT_MS);
+            timeoutMs = Math.min(timeoutMs, remaining);
+            try {
+                Thread.sleep(timeoutMs);
+            } catch (InterruptedException e) {}
+        }
+        return null;
+    }
+
+    /**
+     * Blocks until an INetd instance is available.
+     *
+     * It is the caller's responsibility to handle RemoteException errors
+     * from invocations on the returned interface if, for example, netd
+     * dies after this interface was returned.
+     *
+     * Returned instances of INetd should not be cached.
+     *
+     * @return an INetd instance.
+     */
+    public static INetd get() {
+        return get(-1);
+    }
+
+    public static interface NetdCommand {
+        void run(INetd netd) throws RemoteException;
+    }
+
+    /**
+     * Blocks until an INetd instance is availabe, and retries until either
+     * the command succeeds or a runtime exception is thrown.
+     */
+    public static void run(NetdCommand cmd) {
+        while (true) {
+            try {
+                cmd.run(get());
+                return;
+            } catch (RemoteException re) {
+                Log.e(TAG, "error communicating with netd: " + re);
+            }
+        }
+    }
 }
diff --git a/services/net/java/android/net/util/NetworkConstants.java b/services/net/java/android/net/util/NetworkConstants.java
index 362f757..26f3050 100644
--- a/services/net/java/android/net/util/NetworkConstants.java
+++ b/services/net/java/android/net/util/NetworkConstants.java
@@ -97,6 +97,7 @@
     public static final int IPV6_SRC_ADDR_OFFSET = 8;
     public static final int IPV6_DST_ADDR_OFFSET = 24;
     public static final int IPV6_ADDR_LEN = 16;
+    public static final int RFC7421_PREFIX_LENGTH = 64;
 
     /**
      * ICMPv6 constants.
diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
index 43c8957..5553fd6 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java
@@ -271,8 +271,8 @@
         final Bundle bundle = new Bundle();
         bundle.putParcelable(EXTRA_RECOMMENDATION_RESULT, providerResult);
         doAnswer(invocation -> {
-            bundle.putInt(EXTRA_SEQUENCE, invocation.getArgumentAt(2, int.class));
-            invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
+            bundle.putInt(EXTRA_SEQUENCE, invocation.getArgument(2));
+            invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
             return null;
         }).when(mRecommendationProvider)
                 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
@@ -336,7 +336,7 @@
         injectProvider();
         final Bundle bundle = new Bundle();
         doAnswer(invocation -> {
-            invocation.getArgumentAt(1, IRemoteCallback.class).sendResult(bundle);
+            invocation.<IRemoteCallback>getArgument(1).sendResult(bundle);
             return null;
         }).when(mRecommendationProvider)
                 .requestRecommendation(eq(mRecommendationRequest), isA(IRemoteCallback.class),
@@ -634,7 +634,7 @@
                 IBinder mockBinder = mock(IBinder.class);
                 when(mockBinder.queryLocalInterface(anyString()))
                         .thenReturn(mRecommendationProvider);
-                invocation.getArgumentAt(1, ServiceConnection.class)
+                invocation.<ServiceConnection>getArgument(1)
                         .onServiceConnected(componentName, mockBinder);
                 return true;
             }
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 3806da6..e43786c 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -29,6 +29,7 @@
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.mockito.Mockito;
+import org.mockito.hamcrest.MockitoHamcrest;
 
 public class MockUtils {
     private MockUtils() {
@@ -47,7 +48,7 @@
                 description.appendText("UserHandle: user-id= \"" + userId + "\"");
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     public static Intent checkIntentComponent(final ComponentName component) {
@@ -63,7 +64,7 @@
                 description.appendText("Intent: component=\"" + component + "\"");
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     public static Intent checkIntentAction(final String action) {
@@ -79,7 +80,7 @@
                 description.appendText("Intent: action=\"" + action + "\"");
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     public static Intent checkIntent(final Intent intent) {
@@ -94,7 +95,7 @@
                 description.appendText(intent.toString());
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     public static Bundle checkUserRestrictions(String... keys) {
@@ -111,7 +112,7 @@
                 description.appendText("User restrictions=" + getRestrictionsAsString(expected));
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     private static String getRestrictionsAsString(Bundle b) {
diff --git a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
index 82c7bdb..1192901 100644
--- a/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/webkit/WebViewUpdateServiceTest.java
@@ -32,14 +32,12 @@
 import android.webkit.WebViewProviderInfo;
 import android.webkit.WebViewProviderResponse;
 
-import org.hamcrest.Description;
-
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.mockito.Mockito;
 import org.mockito.Matchers;
-import org.mockito.ArgumentMatcher;
+import org.mockito.compat.ArgumentMatcher;
 
 import java.util.concurrent.CountDownLatch;
 
@@ -131,14 +129,13 @@
         }
 
         @Override
-        public boolean matches(Object p) {
+        public boolean matchesObject(Object p) {
             return ((PackageInfo) p).packageName.equals(mPackageName);
         }
 
-        // Provide a more useful description in case of mismatch
         @Override
-        public void describeTo (Description description) {
-            description.appendText(String.format("PackageInfo with name '%s'", mPackageName));
+        public String toString() {
+            return String.format("PackageInfo with name '%s'", mPackageName);
         }
     }
 
diff --git a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
index 1fe5cb7..29d58ce 100644
--- a/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
+++ b/services/tests/shortcutmanagerutils/src/com/android/server/pm/shortcutmanagertest/ShortcutManagerTestUtils.java
@@ -59,6 +59,7 @@
 import org.json.JSONObject;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
+import org.mockito.hamcrest.MockitoHamcrest;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -665,7 +666,7 @@
                 d.appendText(description);
             }
         };
-        return Mockito.argThat(m);
+        return MockitoHamcrest.argThat(m);
     }
 
     public static List<ShortcutInfo> checkShortcutIds(String... ids) {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 99eb3d2..39da224 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -743,7 +743,8 @@
                 }
                 mMidiEnabled = enabled;
             }
-            mUsbAlsaManager.setPeripheralMidiState(mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
+            mUsbAlsaManager.setPeripheralMidiState(
+                    mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
         }
 
         @Override
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 1076afc..ce1c3c3 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -315,6 +315,14 @@
     public static final String KEY_DEFAULT_VM_NUMBER_STRING = "default_vm_number_string";
 
     /**
+     * Flag indicating whether we should downgrade/terminate VT calls and disable VT when
+     * data enabled changed (e.g. reach data limit or turn off data).
+     * @hide
+     */
+    public static final String KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS =
+            "ignore_data_enabled_changed_for_video_calls";
+
+    /**
      * Flag specifying whether WFC over IMS should be available for carrier: independent of
      * carrier provisioning. If false: hard disabled. If true: then depends on carrier
      * provisioning, availability etc.
@@ -1135,6 +1143,22 @@
     public static final String KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL =
             "notify_international_call_on_wfc_bool";
 
+    /**
+     * Offset to be reduced from rsrp threshold while calculating signal strength level.
+     * @hide
+     */
+    public static final String KEY_LTE_EARFCNS_RSRP_BOOST_INT = "lte_earfcns_rsrp_boost_int";
+
+    /**
+     * List of EARFCN (E-UTRA Absolute Radio Frequency Channel Number,
+     * Reference: 3GPP TS 36.104 5.4.3) inclusive ranges on which lte_rsrp_boost_int
+     * will be applied. Format of the String array is expected to be {"erafcn1_start-earfcn1_end",
+     * "earfcn2_start-earfcn2_end" ... }
+     * @hide
+     */
+    public static final String KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY =
+            "boosted_lte_earfcns_string_array";
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -1152,6 +1176,7 @@
         sDefaults.putBoolean(KEY_NOTIFY_HANDOVER_VIDEO_FROM_WIFI_TO_LTE_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_DOWNGRADE_VT_TO_AUDIO_BOOL, true);
         sDefaults.putString(KEY_DEFAULT_VM_NUMBER_STRING, "");
+        sDefaults.putBoolean(KEY_IGNORE_DATA_ENABLED_CHANGED_FOR_VIDEO_CALLS, false);
         sDefaults.putBoolean(KEY_CARRIER_WFC_IMS_AVAILABLE_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_WFC_SUPPORTS_WIFI_ONLY_BOOL, false);
         sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
@@ -1341,6 +1366,8 @@
         sDefaults.putBoolean(KEY_EDITABLE_WFC_ROAMING_MODE_BOOL, false);
         sDefaults.putBoolean(KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
         sDefaults.putBoolean(KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL, false);
+        sDefaults.putInt(KEY_LTE_EARFCNS_RSRP_BOOST_INT, 0);
+        sDefaults.putStringArray(KEY_BOOSTED_LTE_EARFCNS_STRING_ARRAY, null);
     }
 
     /**
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 2eba402..0b80d06 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -1619,7 +1619,7 @@
     //
     // Australia: Short codes are six or eight digits in length, starting with the prefix "19"
     //            followed by an additional four or six digits and two.
-    // Czech Republic: Codes are seven digits in length for MO and five (not billed) or
+    // Czechia: Codes are seven digits in length for MO and five (not billed) or
     //            eight (billed) for MT direction
     //
     // see http://en.wikipedia.org/wiki/Short_code#Regional_differences for reference
@@ -1896,7 +1896,7 @@
         number = extractNetworkPortionAlt(number);
 
         String emergencyNumbers = "";
-        int slotId = SubscriptionManager.getSlotId(subId);
+        int slotId = SubscriptionManager.getSlotIndex(subId);
 
         // retrieve the list of emergency numbers
         // check read-write ecclist property first
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index 54ab19d..2516d51 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -25,75 +25,480 @@
 public class PreciseDisconnectCause {
 
     /** The disconnect cause is not valid (Not received a disconnect cause)*/
-    public static final int NOT_VALID                      = -1;
+    public static final int NOT_VALID                                        = -1;
     /** No disconnect cause provided. Generally a local disconnect or an incoming missed call */
-    public static final int NO_DISCONNECT_CAUSE_AVAILABLE  = 0;
+    public static final int NO_DISCONNECT_CAUSE_AVAILABLE                    = 0;
     /**
      * The destination cannot be reached because the number, although valid,
      * is not currently assigned
      */
-    public static final int UNOBTAINABLE_NUMBER            = 1;
+    public static final int UNOBTAINABLE_NUMBER                              = 1;
+    /** The user cannot be reached because the network through which the call has been
+     *  routed does not serve the destination desired
+     */
+    public static final int NO_ROUTE_TO_DESTINATION                          = 3;
+    /** The channel most recently identified is not acceptable to the sending entity for
+     *  use in this call
+     */
+    public static final int CHANNEL_UNACCEPTABLE                             = 6;
+    /** The MS has tried to access a service that the MS's network operator or service
+     *  provider is not prepared to allow
+     */
+    public static final int OPERATOR_DETERMINED_BARRING                      = 8;
     /** One of the users involved in the call has requested that the call is cleared */
-    public static final int NORMAL                         = 16;
+    public static final int NORMAL                                           = 16;
     /** The called user is unable to accept another call */
-    public static final int BUSY                           = 17;
+    public static final int BUSY                                             = 17;
+    /** The user does not respond to a call establishment message with either an alerting
+     *  or connect indication within the prescribed period of time allocated
+     */
+    public static final int NO_USER_RESPONDING                               = 18;
+    /** The user has provided an alerting indication but has not provided a connect
+     *  indication within a prescribed period of time
+     */
+    public static final int NO_ANSWER_FROM_USER                              = 19;
+    /** The equipment sending this cause does not wish to accept this call */
+    public static final int CALL_REJECTED                                    = 21;
     /** The called number is no longer assigned */
-    public static final int NUMBER_CHANGED                 = 22;
+    public static final int NUMBER_CHANGED                                   = 22;
+    /** This cause is returned to the network when a mobile station clears an active
+     *  call which is being pre-empted by another call with higher precedence
+     */
+    public static final int PREEMPTION                                       = 25;
+    /** The destination indicated by the mobile station cannot be reached because
+     *  the interface to the destination is not functioning correctly
+     */
+    public static final int DESTINATION_OUT_OF_ORDER                         = 27;
+    /** The called party number is not a valid format or is not complete */
+    public static final int INVALID_NUMBER_FORMAT                            = 28;
+    /** The facility requested by user can not be provided by the network */
+    public static final int FACILITY_REJECTED                                = 29;
     /** Provided in response to a STATUS ENQUIRY message */
-    public static final int STATUS_ENQUIRY                 = 30;
+    public static final int STATUS_ENQUIRY                                   = 30;
     /** Reports a normal disconnect only when no other normal cause applies */
-    public static final int NORMAL_UNSPECIFIED             = 31;
+    public static final int NORMAL_UNSPECIFIED                               = 31;
     /** There is no channel presently available to handle the call */
-    public static final int NO_CIRCUIT_AVAIL               = 34;
+    public static final int NO_CIRCUIT_AVAIL                                 = 34;
+    /** The network is not functioning correctly and that the condition is likely
+     *  to last a relatively long period of time
+     */
+    public static final int NETWORK_OUT_OF_ORDER                             = 38;
     /**
      * The network is not functioning correctly and the condition is not likely to last
      * a long period of time
      */
-    public static final int TEMPORARY_FAILURE              = 41;
+    public static final int TEMPORARY_FAILURE                                = 41;
     /** The switching equipment is experiencing a period of high traffic */
-    public static final int SWITCHING_CONGESTION           = 42;
+    public static final int SWITCHING_CONGESTION                             = 42;
+    /** The network could not deliver access information to the remote user as requested */
+    public static final int ACCESS_INFORMATION_DISCARDED                     = 43;
     /** The channel cannot be provided */
-    public static final int CHANNEL_NOT_AVAIL              = 44;
+    public static final int CHANNEL_NOT_AVAIL                                = 44;
+    /** This cause is used to report a resource unavailable event only when no other
+     *  cause in the resource unavailable class applies
+     */
+    public static final int RESOURCES_UNAVAILABLE_OR_UNSPECIFIED             = 44;
     /** The requested quality of service (ITU-T X.213) cannot be provided */
-    public static final int QOS_NOT_AVAIL                  = 49;
+    public static final int QOS_NOT_AVAIL                                    = 49;
+    /** The facility could not be provided by the network because the user has no
+     *  complete subscription
+     */
+    public static final int REQUESTED_FACILITY_NOT_SUBSCRIBED                = 50;
+    /** Incoming calls are not allowed within this CUG */
+    public static final int INCOMING_CALLS_BARRED_WITHIN_CUG                 = 55;
+    /** The mobile station is not authorized to use bearer capability requested */
+    public static final int BEARER_CAPABILITY_NOT_AUTHORIZED                 = 57;
     /** The requested bearer capability is not available at this time */
-    public static final int BEARER_NOT_AVAIL               = 58;
+    public static final int BEARER_NOT_AVAIL                                 = 58;
+    /** The service option is not availble at this time */
+    public static final int SERVICE_OPTION_NOT_AVAILABLE                     = 63;
+    /** The equipment sending this cause does not support the bearer capability requested */
+    public static final int BEARER_SERVICE_NOT_IMPLEMENTED                   = 65;
     /** The call clearing is due to ACM being greater than or equal to ACMmax */
-    public static final int ACM_LIMIT_EXCEEDED             = 68;
+    public static final int ACM_LIMIT_EXCEEDED                               = 68;
+    /** The equipment sending this cause does not support the requested facility */
+    public static final int REQUESTED_FACILITY_NOT_IMPLEMENTED               = 69;
+    /** The equipment sending this cause only supports the restricted version of
+     *  the requested bearer capability
+     */
+    public static final int ONLY_DIGITAL_INFORMATION_BEARER_AVAILABLE        = 70;
+    /** The service requested is not implemented at network */
+    public static final int SERVICE_OR_OPTION_NOT_IMPLEMENTED                = 79;
+    /** The equipment sending this cause has received a message with a transaction identifier
+     *  which is not currently in use on the MS-network interface
+     */
+    public static final int INVALID_TRANSACTION_IDENTIFIER                   = 81;
+    /** The called user for the incoming CUG call is not a member of the specified CUG */
+    public static final int USER_NOT_MEMBER_OF_CUG                           = 87;
+    /** The equipment sending this cause has received a request which can't be accomodated */
+    public static final int INCOMPATIBLE_DESTINATION                         = 88;
+    /** This cause is used to report receipt of a message with semantically incorrect contents */
+    public static final int SEMANTICALLY_INCORRECT_MESSAGE                   = 95;
+    /** The equipment sending this cause has received a message with a non-semantical
+     *  mandatory IE error
+     */
+    public static final int INVALID_MANDATORY_INFORMATION                    = 96;
+    /** This is sent in response to a message which is not defined, or defined but not
+     *  implemented by the equipment sending this cause
+     */
+    public static final int MESSAGE_TYPE_NON_IMPLEMENTED                     = 97;
+    /** The equipment sending this cause has received a message not compatible with the
+     *  protocol state
+     */
+    public static final int MESSAGE_TYPE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE  = 98;
+    /** The equipment sending this cause has received a message which includes information
+     *  elements not recognized because its identifier is not defined or it is defined but not
+     *  implemented by the equipment sending the cause
+     */
+    public static final int INFORMATION_ELEMENT_NON_EXISTENT                 = 99;
+    /** The equipment sending this cause has received a message with conditional IE errors */
+    public static final int CONDITIONAL_IE_ERROR                             = 100;
+    /** The message has been received which is incompatible with the protocol state */
+    public static final int MESSAGE_NOT_COMPATIBLE_WITH_PROTOCOL_STATE       = 101;
+    /** The  procedure has been initiated by the expiry of a timer in association with
+     *  3GPP TS 24.008 error handling procedures
+     */
+    public static final int RECOVERY_ON_TIMER_EXPIRED                        = 102;
+    /** This protocol error event is reported only when no other cause in the protocol
+     *  error class applies
+     */
+    public static final int PROTOCOL_ERROR_UNSPECIFIED                       = 111;
+    /** interworking with a network which does not provide causes for actions it takes
+     *  thus, the precise cause for a message which is being sent cannot be ascertained
+     */
+    public static final int INTERWORKING_UNSPECIFIED                         = 127;
     /** The call is restricted */
-    public static final int CALL_BARRED                    = 240;
+    public static final int CALL_BARRED                                      = 240;
     /** The call is blocked by the Fixed Dialing Number list */
-    public static final int FDN_BLOCKED                    = 241;
+    public static final int FDN_BLOCKED                                      = 241;
     /** The given IMSI is not known at the VLR */
     /** TS 24.008 cause 4 */
-    public static final int IMSI_UNKNOWN_IN_VLR            = 242;
+    public static final int IMSI_UNKNOWN_IN_VLR                              = 242;
     /**
      * The network does not accept emergency call establishment using an IMEI or not accept attach
      * procedure for emergency services using an IMEI
      */
-    public static final int IMEI_NOT_ACCEPTED              = 243;
+    public static final int IMEI_NOT_ACCEPTED                                = 243;
+    /** The call cannot be established because RADIO is OFF */
+    public static final int RADIO_OFF                                        = 247;
+    /** The call cannot be established because of no cell coverage */
+    public static final int OUT_OF_SRV                                       = 248;
+    /** The call cannot be established because of no valid SIM */
+    public static final int NO_VALID_SIM                                     = 249;
+    /** The call is dropped or failed internally by modem */
+    public static final int RADIO_INTERNAL_ERROR                             = 250;
+    /** Call failed because of UE timer expired while waiting for a response from network */
+    public static final int NETWORK_RESP_TIMEOUT                             = 251;
+    /** Call failed because of a network reject */
+    public static final int NETWORK_REJECT                                   = 252;
+    /** Call failed because of radio access failure. ex. RACH failure */
+    public static final int RADIO_ACCESS_FAILURE                             = 253;
+    /** Call failed/dropped because of a RLF */
+    public static final int RADIO_LINK_FAILURE                               = 254;
+    /** Call failed/dropped because of radio link lost */
+    public static final int RADIO_LINK_LOST                                  = 255;
+    /** Call failed because of a radio uplink issue */
+    public static final int RADIO_UPLINK_FAILURE                             = 256;
+    /** Call failed because of a RRC connection setup failure */
+    public static final int RADIO_SETUP_FAILURE                              = 257;
+    /** Call failed/dropped because of RRC connection release from NW */
+    public static final int RADIO_RELEASE_NORMAL                             = 258;
+    /** Call failed/dropped because of RRC abnormally released by modem/network */
+    public static final int RADIO_RELEASE_ABNORMAL                           = 259;
+    /** Call setup failed because of access class barring */
+    public static final int ACCESS_CLASS_BLOCKED                             = 260;
+    /** Call failed/dropped because of a network detach */
+    public static final int NETWORK_DETACH                                   = 261;
+
     /** MS is locked until next power cycle */
-    public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE  = 1000;
+    public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE                    = 1000;
     /** Drop call*/
-    public static final int CDMA_DROP                      = 1001;
+    public static final int CDMA_DROP                                        = 1001;
     /** INTERCEPT order received, MS state idle entered */
-    public static final int CDMA_INTERCEPT                 = 1002;
+    public static final int CDMA_INTERCEPT                                   = 1002;
     /** MS has been redirected, call is cancelled */
-    public static final int CDMA_REORDER                   = 1003;
+    public static final int CDMA_REORDER                                     = 1003;
     /** Service option rejection */
-    public static final int CDMA_SO_REJECT                 = 1004;
+    public static final int CDMA_SO_REJECT                                   = 1004;
     /** Requested service is rejected, retry delay is set */
-    public static final int CDMA_RETRY_ORDER               = 1005;
+    public static final int CDMA_RETRY_ORDER                                 = 1005;
     /** Unable to obtain access to the CDMA system */
-    public static final int CDMA_ACCESS_FAILURE            = 1006;
+    public static final int CDMA_ACCESS_FAILURE                              = 1006;
     /** Not a preempted call */
-    public static final int CDMA_PREEMPTED                 = 1007;
+    public static final int CDMA_PREEMPTED                                   = 1007;
     /** Not an emergency call */
-    public static final int CDMA_NOT_EMERGENCY             = 1008;
+    public static final int CDMA_NOT_EMERGENCY                               = 1008;
     /** Access Blocked by CDMA network */
-    public static final int CDMA_ACCESS_BLOCKED            = 1009;
+    public static final int CDMA_ACCESS_BLOCKED                              = 1009;
+
+    /** Mapped from ImsReasonInfo */
+    /* The passed argument is an invalid */
+    public static final int LOCAL_ILLEGAL_ARGUMENT                           = 1200;
+    // The operation is invoked in invalid call state
+    public static final int LOCAL_ILLEGAL_STATE                              = 1201;
+    // IMS service internal error
+    public static final int LOCAL_INTERNAL_ERROR                             = 1202;
+    // IMS service goes down (service connection is lost)
+    public static final int LOCAL_IMS_SERVICE_DOWN                           = 1203;
+    // No pending incoming call exists
+    public static final int LOCAL_NO_PENDING_CALL                            = 1204;
+    // Service unavailable; by power off
+    public static final int LOCAL_POWER_OFF                                  = 1205;
+    // Service unavailable; by low battery
+    public static final int LOCAL_LOW_BATTERY                                = 1206;
+    // Service unavailable; by out of service (data service state)
+    public static final int LOCAL_NETWORK_NO_SERVICE                         = 1207;
+    /* Service unavailable; by no LTE coverage
+     * (VoLTE is not supported even though IMS is registered)
+     */
+    public static final int LOCAL_NETWORK_NO_LTE_COVERAGE                    = 1208;
+    /** Service unavailable; by located in roaming area */
+    public static final int LOCAL_NETWORK_ROAMING                            = 1209;
+    /** Service unavailable; by IP changed */
+    public static final int LOCAL_NETWORK_IP_CHANGED                         = 1210;
+    /** Service unavailable; other */
+    public static final int LOCAL_SERVICE_UNAVAILABLE                        = 1211;
+    /* Service unavailable; IMS connection is lost (IMS is not registered) */
+    public static final int LOCAL_NOT_REGISTERED                             = 1212;
+    /** Max call exceeded */
+    public static final int LOCAL_MAX_CALL_EXCEEDED                          = 1213;
+    /** Call decline */
+    public static final int LOCAL_CALL_DECLINE                               = 1214;
+    /** SRVCC is in progress */
+    public static final int LOCAL_CALL_VCC_ON_PROGRESSING                    = 1215;
+    /** Resource reservation is failed (QoS precondition) */
+    public static final int LOCAL_CALL_RESOURCE_RESERVATION_FAILED           = 1216;
+    /** Retry CS call; VoLTE service can't be provided by the network or remote end
+     *  Resolve the extra code(EXTRA_CODE_CALL_RETRY_*) if the below code is set
+     */
+    public static final int LOCAL_CALL_CS_RETRY_REQUIRED                     = 1217;
+    /** Retry VoLTE call; VoLTE service can't be provided by the network temporarily */
+    public static final int LOCAL_CALL_VOLTE_RETRY_REQUIRED                  = 1218;
+    /** IMS call is already terminated (in TERMINATED state) */
+    public static final int LOCAL_CALL_TERMINATED                            = 1219;
+    /** Handover not feasible */
+    public static final int LOCAL_HO_NOT_FEASIBLE                            = 1220;
+
+    /** 1xx waiting timer is expired after sending INVITE request (MO only) */
+    public static final int TIMEOUT_1XX_WAITING                              = 1221;
+    /** User no answer during call setup operation (MO/MT)
+     *  MO : 200 OK to INVITE request is not received,
+     *  MT : No action from user after alerting the call
+     */
+    public static final int TIMEOUT_NO_ANSWER                                = 1222;
+    /** User no answer during call update operation (MO/MT)
+     *  MO : 200 OK to re-INVITE request is not received,
+     *  MT : No action from user after alerting the call
+     */
+    public static final int TIMEOUT_NO_ANSWER_CALL_UPDATE                    = 1223;
+
+    /**
+     * STATUSCODE (SIP response code) (IMS -> Telephony)
+     */
+    /** SIP request is redirected */
+    public static final int SIP_REDIRECTED                                   = 1300;
+    /** 4xx responses */
+    /** 400 : Bad Request */
+    public static final int SIP_BAD_REQUEST                                  = 1310;
+    /** 403 : Forbidden */
+    public static final int SIP_FORBIDDEN                                    = 1311;
+    /** 404 : Not Found */
+    public static final int SIP_NOT_FOUND                                    = 1312;
+    /** 415 : Unsupported Media Type
+     *  416 : Unsupported URI Scheme
+     *  420 : Bad Extension
+     */
+    public static final int SIP_NOT_SUPPORTED                                = 1313;
+    /** 408 : Request Timeout */
+    public static final int SIP_REQUEST_TIMEOUT                              = 1314;
+    /** 480 : Temporarily Unavailable */
+    public static final int SIP_TEMPRARILY_UNAVAILABLE                       = 1315;
+    /** 484 : Address Incomplete */
+    public static final int SIP_BAD_ADDRESS                                  = 1316;
+    /** 486 : Busy Here
+     *  600 : Busy Everywhere
+     */
+    public static final int SIP_BUSY                                         = 1317;
+    /** 487 : Request Terminated */
+    public static final int SIP_REQUEST_CANCELLED                            = 1318;
+    /** 406 : Not Acceptable
+     *  488 : Not Acceptable Here
+     *  606 : Not Acceptable
+     */
+    public static final int SIP_NOT_ACCEPTABLE                               = 1319;
+    /** 410 : Gone
+     *  604 : Does Not Exist Anywhere
+     */
+    public static final int SIP_NOT_REACHABLE                                = 1320;
+    /** Others */
+    public static final int SIP_CLIENT_ERROR                                 = 1321;
+    /** 5xx responses
+     *  501 : Server Internal Error
+     */
+    public static final int SIP_SERVER_INTERNAL_ERROR                        = 1330;
+    /** 503 : Service Unavailable */
+    public static final int SIP_SERVICE_UNAVAILABLE                          = 1331;
+    /** 504 : Server Time-out */
+    public static final int SIP_SERVER_TIMEOUT                               = 1332;
+    /** Others */
+    public static final int SIP_SERVER_ERROR                                 = 1333;
+    /** 6xx responses
+     *  603 : Decline
+     */
+    public static final int SIP_USER_REJECTED                                = 1340;
+    /** Others */
+    public static final int SIP_GLOBAL_ERROR                                 = 1341;
+    /** Emergency failure */
+    public static final int EMERGENCY_TEMP_FAILURE                           = 1342;
+    public static final int EMERGENCY_PERM_FAILURE                           = 1343;
+    /** Media resource initialization failed */
+    public static final int MEDIA_INIT_FAILED                                = 1400;
+    /** RTP timeout (no audio / video traffic in the session) */
+    public static final int MEDIA_NO_DATA                                    = 1401;
+    /** Media is not supported; so dropped the call */
+    public static final int MEDIA_NOT_ACCEPTABLE                             = 1402;
+    /** Unknown media related errors */
+    public static final int MEDIA_UNSPECIFIED                                = 1403;
+    /** User triggers the call end */
+    public static final int USER_TERMINATED                                  = 1500;
+    /** No action while an incoming call is ringing */
+    public static final int USER_NOANSWER                                    = 1501;
+    /** User ignores an incoming call */
+    public static final int USER_IGNORE                                      = 1502;
+    /** User declines an incoming call */
+    public static final int USER_DECLINE                                     = 1503;
+    /** Device declines/ends a call due to low battery */
+    public static final int LOW_BATTERY                                      = 1504;
+    /** Device declines call due to blacklisted call ID */
+    public static final int BLACKLISTED_CALL_ID                              = 1505;
+    /** The call is terminated by the network or remote user */
+    public static final int USER_TERMINATED_BY_REMOTE                        = 1510;
+
+    /**
+     * UT
+     */
+    public static final int UT_NOT_SUPPORTED                                 = 1800;
+    public static final int UT_SERVICE_UNAVAILABLE                           = 1801;
+    public static final int UT_OPERATION_NOT_ALLOWED                         = 1802;
+    public static final int UT_NETWORK_ERROR                                 = 1803;
+    public static final int UT_CB_PASSWORD_MISMATCH                          = 1804;
+
+    /**
+     * ECBM
+     */
+    public static final int ECBM_NOT_SUPPORTED                               = 1900;
+
+    /**
+     * Fail code used to indicate that Multi-endpoint is not supported by the Ims framework.
+     */
+    public static final int MULTIENDPOINT_NOT_SUPPORTED                      = 1901;
+
+    /**
+     * CALL DROP error codes (Call could drop because of many reasons like Network not available,
+     *  handover, failed, etc)
+     */
+
+    /**
+     * CALL DROP error code for the case when a device is ePDG capable and when the user is on an
+     * active wifi call and at the edge of coverage and there is no qualified LTE network available
+     * to handover the call to. We get a handover NOT_TRIGERRED message from the modem. This error
+     * code is received as part of the handover message.
+     */
+    public static final int CALL_DROP_IWLAN_TO_LTE_UNAVAILABLE               = 2000;
+
+    /**
+     * MT call has ended due to a release from the network
+     * because the call was answered elsewhere
+     */
+    public static final int ANSWERED_ELSEWHERE                               = 2100;
+
+    /**
+     * For MultiEndpoint - Call Pull request has failed
+     */
+    public static final int CALL_PULL_OUT_OF_SYNC                            = 2101;
+
+    /**
+     * For MultiEndpoint - Call has been pulled from primary to secondary
+     */
+    public static final int CALL_PULLED                                      = 2102;
+
+    /**
+     * Supplementary services (HOLD/RESUME) failure error codes.
+     * Values for Supplemetary services failure - Failed, Cancelled and Re-Invite collision.
+     */
+    public static final int SUPP_SVC_FAILED                                  = 2300;
+    public static final int SUPP_SVC_CANCELLED                               = 2301;
+    public static final int SUPP_SVC_REINVITE_COLLISION                      = 2302;
+
+    /**
+     * DPD Procedure received no response or send failed
+     */
+    public static final int IWLAN_DPD_FAILURE                                = 2400;
+
+    /**
+     * Establishment of the ePDG Tunnel Failed
+     */
+    public static final int EPDG_TUNNEL_ESTABLISH_FAILURE                    = 2500;
+
+    /**
+     * Re-keying of the ePDG Tunnel Failed; may not always result in teardown
+     */
+    public static final int EPDG_TUNNEL_REKEY_FAILURE                        = 2501;
+
+    /**
+     * Connection to the packet gateway is lost
+     */
+    public static final int EPDG_TUNNEL_LOST_CONNECTION                      = 2502;
+
+    /**
+     * The maximum number of calls allowed has been reached.  Used in a multi-endpoint scenario
+     * where the number of calls across all connected devices has reached the maximum.
+     */
+    public static final int MAXIMUM_NUMBER_OF_CALLS_REACHED                  = 2503;
+
+    /**
+     * Similar to {@link #CODE_LOCAL_CALL_DECLINE}, except indicates that a remote device has
+     * declined the call.  Used in a multi-endpoint scenario where a remote device declined an
+     * incoming call.
+     */
+    public static final int REMOTE_CALL_DECLINE                              = 2504;
+
+    /**
+     * Indicates the call was disconnected due to the user reaching their data limit.
+     */
+    public static final int DATA_LIMIT_REACHED                               = 2505;
+
+    /**
+     * Indicates the call was disconnected due to the user disabling cellular data.
+     */
+    public static final int DATA_DISABLED                                    = 2506;
+
+    /**
+     * Indicates a call was disconnected due to loss of wifi signal.
+     */
+    public static final int WIFI_LOST                                        = 2507;
+
+
+    /* OEM specific error codes. To be used by OEMs when they don't want to
+       reveal error code which would be replaced by ERROR_UNSPECIFIED */
+    public static final int OEM_CAUSE_1                                      = 0xf001;
+    public static final int OEM_CAUSE_2                                      = 0xf002;
+    public static final int OEM_CAUSE_3                                      = 0xf003;
+    public static final int OEM_CAUSE_4                                      = 0xf004;
+    public static final int OEM_CAUSE_5                                      = 0xf005;
+    public static final int OEM_CAUSE_6                                      = 0xf006;
+    public static final int OEM_CAUSE_7                                      = 0xf007;
+    public static final int OEM_CAUSE_8                                      = 0xf008;
+    public static final int OEM_CAUSE_9                                      = 0xf009;
+    public static final int OEM_CAUSE_10                                     = 0xf00a;
+    public static final int OEM_CAUSE_11                                     = 0xf00b;
+    public static final int OEM_CAUSE_12                                     = 0xf00c;
+    public static final int OEM_CAUSE_13                                     = 0xf00d;
+    public static final int OEM_CAUSE_14                                     = 0xf00e;
+    public static final int OEM_CAUSE_15                                     = 0xf00f;
+
     /** Disconnected due to unspecified reasons */
-    public static final int ERROR_UNSPECIFIED              = 0xffff;
+    public static final int ERROR_UNSPECIFIED                                = 0xffff;
 
     /** Private constructor to avoid class instantiation. */
     private PreciseDisconnectCause() {
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 7a83979..5fb83ab 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -243,6 +243,10 @@
 
     private boolean mIsUsingCarrierAggregation;
 
+    /* EARFCN stands for E-UTRA Absolute Radio Frequency Channel Number,
+     * Reference: 3GPP TS 36.104 5.4.3 */
+    private int mLteEarfcnRsrpBoost = 0;
+
     /**
      * get String description of roaming type
      * @hide
@@ -322,6 +326,7 @@
         mIsEmergencyOnly = s.mIsEmergencyOnly;
         mIsDataRoamingFromRegistration = s.mIsDataRoamingFromRegistration;
         mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
+        mLteEarfcnRsrpBoost = s.mLteEarfcnRsrpBoost;
     }
 
     /**
@@ -351,6 +356,7 @@
         mIsEmergencyOnly = in.readInt() != 0;
         mIsDataRoamingFromRegistration = in.readInt() != 0;
         mIsUsingCarrierAggregation = in.readInt() != 0;
+        mLteEarfcnRsrpBoost = in.readInt();
     }
 
     public void writeToParcel(Parcel out, int flags) {
@@ -377,6 +383,7 @@
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
         out.writeInt(mIsDataRoamingFromRegistration ? 1 : 0);
         out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
+        out.writeInt(mLteEarfcnRsrpBoost);
     }
 
     public int describeContents() {
@@ -814,7 +821,8 @@
                 + " DefRoamInd=" + mCdmaDefaultRoamingIndicator
                 + " EmergOnly=" + mIsEmergencyOnly
                 + " IsDataRoamingFromRegistration=" + mIsDataRoamingFromRegistration
-                + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation);
+                + " IsUsingCarrierAggregation=" + mIsUsingCarrierAggregation
+                + " mLteEarfcnRsrpBoost=" + mLteEarfcnRsrpBoost);
     }
 
     private void setNullState(int state) {
@@ -842,6 +850,7 @@
         mIsEmergencyOnly = false;
         mIsDataRoamingFromRegistration = false;
         mIsUsingCarrierAggregation = false;
+        mLteEarfcnRsrpBoost = 0;
     }
 
     public void setStateOutOfService() {
@@ -1016,6 +1025,7 @@
         mIsEmergencyOnly = m.getBoolean("emergencyOnly");
         mIsDataRoamingFromRegistration = m.getBoolean("isDataRoamingFromRegistration");
         mIsUsingCarrierAggregation = m.getBoolean("isUsingCarrierAggregation");
+        mLteEarfcnRsrpBoost = m.getInt("LteEarfcnRsrpBoost");
     }
 
     /**
@@ -1046,6 +1056,7 @@
         m.putBoolean("emergencyOnly", mIsEmergencyOnly);
         m.putBoolean("isDataRoamingFromRegistration", mIsDataRoamingFromRegistration);
         m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
+        m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
     }
 
     /** @hide */
@@ -1081,6 +1092,16 @@
     }
 
     /** @hide */
+    public int getLteEarfcnRsrpBoost() {
+        return mLteEarfcnRsrpBoost;
+    }
+
+    /** @hide */
+    public void setLteEarfcnRsrpBoost(int LteEarfcnRsrpBoost) {
+        mLteEarfcnRsrpBoost = LteEarfcnRsrpBoost;
+    }
+
+    /** @hide */
     public void setCssIndicator(int css) {
         this.mCssIndicator = (css != 0);
     }
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index c484fd3..9e02399 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -64,6 +64,8 @@
     private int mLteRsrq;
     private int mLteRssnr;
     private int mLteCqi;
+    private int mLteRsrpBoost; // offset to be reduced from the rsrp threshold while calculating
+                                // signal strength level
     private int mTdScdmaRscp;
 
     private boolean isGsm; // This value is set by the ServiceStateTracker onSignalStrengthResult
@@ -104,6 +106,7 @@
         mLteRsrq = INVALID;
         mLteRssnr = INVALID;
         mLteCqi = INVALID;
+        mLteRsrpBoost = 0;
         mTdScdmaRscp = INVALID;
         isGsm = true;
     }
@@ -129,6 +132,7 @@
         mLteRsrq = INVALID;
         mLteRssnr = INVALID;
         mLteCqi = INVALID;
+        mLteRsrpBoost = 0;
         mTdScdmaRscp = INVALID;
         isGsm = gsmFlag;
     }
@@ -142,10 +146,26 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
+            int lteRsrpBoost, int tdScdmaRscp, boolean gsmFlag) {
+        initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
+                evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
+                lteRsrq, lteRssnr, lteCqi, lteRsrpBoost, gsmFlag);
+        mTdScdmaRscp = tdScdmaRscp;
+    }
+
+    /**
+     * Constructor
+     *
+     * @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, boolean gsmFlag) {
         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, gsmFlag);
+                lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
         mTdScdmaRscp = tdScdmaRscp;
     }
 
@@ -161,7 +181,7 @@
             boolean gsmFlag) {
         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, lteSignalStrength, lteRsrp,
-                lteRsrq, lteRssnr, lteCqi, gsmFlag);
+                lteRsrq, lteRssnr, lteCqi, 0, gsmFlag);
     }
 
     /**
@@ -175,7 +195,7 @@
             boolean gsmFlag) {
         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
-                INVALID, INVALID, INVALID, gsmFlag);
+                INVALID, INVALID, INVALID, 0, gsmFlag);
     }
 
     /**
@@ -209,7 +229,7 @@
             boolean gsm) {
         initialize(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio,
                 evdoDbm, evdoEcio, evdoSnr, 99, INVALID,
-                INVALID, INVALID, INVALID, gsm);
+                INVALID, INVALID, INVALID, 0, gsm);
     }
 
     /**
@@ -227,6 +247,7 @@
      * @param lteRsrq
      * @param lteRssnr
      * @param lteCqi
+     * @param lteRsrpBoost
      * @param gsm
      *
      * @hide
@@ -235,7 +256,7 @@
             int cdmaDbm, int cdmaEcio,
             int evdoDbm, int evdoEcio, int evdoSnr,
             int lteSignalStrength, int lteRsrp, int lteRsrq, int lteRssnr, int lteCqi,
-            boolean gsm) {
+            int lteRsrpBoost, boolean gsm) {
         mGsmSignalStrength = gsmSignalStrength;
         mGsmBitErrorRate = gsmBitErrorRate;
         mCdmaDbm = cdmaDbm;
@@ -248,6 +269,7 @@
         mLteRsrq = lteRsrq;
         mLteRssnr = lteRssnr;
         mLteCqi = lteCqi;
+        mLteRsrpBoost = lteRsrpBoost;
         mTdScdmaRscp = INVALID;
         isGsm = gsm;
         if (DBG) log("initialize: " + toString());
@@ -269,6 +291,7 @@
         mLteRsrq = s.mLteRsrq;
         mLteRssnr = s.mLteRssnr;
         mLteCqi = s.mLteCqi;
+        mLteRsrpBoost = s.mLteRsrpBoost;
         mTdScdmaRscp = s.mTdScdmaRscp;
         isGsm = s.isGsm;
     }
@@ -293,6 +316,7 @@
         mLteRsrq = in.readInt();
         mLteRssnr = in.readInt();
         mLteCqi = in.readInt();
+        mLteRsrpBoost = in.readInt();
         mTdScdmaRscp = in.readInt();
         isGsm = (in.readInt() != 0);
     }
@@ -340,6 +364,7 @@
         out.writeInt(mLteRsrq);
         out.writeInt(mLteRssnr);
         out.writeInt(mLteCqi);
+        out.writeInt(mLteRsrpBoost);
         out.writeInt(mTdScdmaRscp);
         out.writeInt(isGsm ? 1 : 0);
     }
@@ -416,6 +441,18 @@
     }
 
     /**
+     * @param lteRsrpBoost - signal strength offset
+     *
+     * Used by phone to set the lte signal strength offset which will be
+     * reduced from rsrp threshold while calculating signal strength level
+     *
+     * @hide
+     */
+    public void setLteRsrpBoost(int lteRsrpBoost) {
+        mLteRsrpBoost = lteRsrpBoost;
+    }
+
+    /**
      * Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS
      * 27.007 8.5
      */
@@ -490,6 +527,11 @@
         return mLteCqi;
     }
 
+    /** @hide */
+    public int getLteRsrpBoost() {
+        return mLteRsrpBoost;
+    }
+
     /**
      * Retrieve an abstract level value for the overall signal strength.
      *
@@ -793,12 +835,19 @@
             Log.wtf(LOG_TAG, "getLteLevel - config_lteDbmThresholds has invalid num of elements."
                     + " Cannot evaluate RSRP signal.");
         } else {
-            if (mLteRsrp > threshRsrp[5]) rsrpIconLevel = -1;
-            else if (mLteRsrp >= threshRsrp[4]) rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
-            else if (mLteRsrp >= threshRsrp[3]) rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
-            else if (mLteRsrp >= threshRsrp[2]) rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
-            else if (mLteRsrp >= threshRsrp[1]) rsrpIconLevel = SIGNAL_STRENGTH_POOR;
-            else if (mLteRsrp >= threshRsrp[0]) rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            if (mLteRsrp > threshRsrp[5]) {
+                rsrpIconLevel = -1;
+            } else if (mLteRsrp >= (threshRsrp[4] - mLteRsrpBoost)) {
+                rsrpIconLevel = SIGNAL_STRENGTH_GREAT;
+            } else if (mLteRsrp >= (threshRsrp[3] - mLteRsrpBoost)) {
+                rsrpIconLevel = SIGNAL_STRENGTH_GOOD;
+            } else if (mLteRsrp >= (threshRsrp[2] - mLteRsrpBoost)) {
+                rsrpIconLevel = SIGNAL_STRENGTH_MODERATE;
+            } else if (mLteRsrp >= (threshRsrp[1] - mLteRsrpBoost)) {
+                rsrpIconLevel = SIGNAL_STRENGTH_POOR;
+            } else if (mLteRsrp >= threshRsrp[0]) {
+                rsrpIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            }
         }
 
         /*
@@ -816,7 +865,8 @@
             snrIconLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
         if (DBG) log("getLTELevel - rsrp:" + mLteRsrp + " snr:" + mLteRssnr + " rsrpIconLevel:"
-                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel);
+                + rsrpIconLevel + " snrIconLevel:" + snrIconLevel
+                + " lteRsrpBoost:" + mLteRsrpBoost);
 
         /* Choose a measurement type to use for notification */
         if (snrIconLevel != -1 && rsrpIconLevel != -1) {
@@ -939,7 +989,7 @@
                 + (mEvdoDbm * primeNum) + (mEvdoEcio * primeNum) + (mEvdoSnr * primeNum)
                 + (mLteSignalStrength * primeNum) + (mLteRsrp * primeNum)
                 + (mLteRsrq * primeNum) + (mLteRssnr * primeNum) + (mLteCqi * primeNum)
-                + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
+                + (mLteRsrpBoost * primeNum) + (mTdScdmaRscp * primeNum) + (isGsm ? 1 : 0));
     }
 
     /**
@@ -971,6 +1021,7 @@
                 && mLteRsrq == s.mLteRsrq
                 && mLteRssnr == s.mLteRssnr
                 && mLteCqi == s.mLteCqi
+                && mLteRsrpBoost == s.mLteRsrpBoost
                 && mTdScdmaRscp == s.mTdScdmaRscp
                 && isGsm == s.isGsm);
     }
@@ -993,6 +1044,7 @@
                 + " " + mLteRsrq
                 + " " + mLteRssnr
                 + " " + mLteCqi
+                + " " + mLteRsrpBoost
                 + " " + mTdScdmaRscp
                 + " " + (isGsm ? "gsm|lte" : "cdma"));
     }
@@ -1016,6 +1068,7 @@
         mLteRsrq = m.getInt("LteRsrq");
         mLteRssnr = m.getInt("LteRssnr");
         mLteCqi = m.getInt("LteCqi");
+        mLteRsrpBoost = m.getInt("lteRsrpBoost");
         mTdScdmaRscp = m.getInt("TdScdma");
         isGsm = m.getBoolean("isGsm");
     }
@@ -1039,6 +1092,7 @@
         m.putInt("LteRsrq", mLteRsrq);
         m.putInt("LteRssnr", mLteRssnr);
         m.putInt("LteCqi", mLteCqi);
+        m.putInt("lteRsrpBoost", mLteRsrpBoost);
         m.putInt("TdScdma", mTdScdmaRscp);
         m.putBoolean("isGsm", isGsm);
     }
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index dd6f9cb..201f3ad 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -521,14 +521,14 @@
     }
 
     /**
-     * Get the active SubscriptionInfo associated with the slotIdx
-     * @param slotIdx the slot which the subscription is inserted
+     * Get the active SubscriptionInfo associated with the slotIndex
+     * @param slotIndex the slot which the subscription is inserted
      * @return SubscriptionInfo, maybe null if its not active
      */
-    public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx) {
-        if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIdx=" + slotIdx);
-        if (!isValidSlotId(slotIdx)) {
-            logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIdx");
+    public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) {
+        if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex);
+        if (!isValidSlotIndex(slotIndex)) {
+            logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex");
             return null;
         }
 
@@ -537,7 +537,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIdx,
+                result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex,
                         mContext.getOpPackageName());
             }
         } catch (RemoteException ex) {
@@ -671,24 +671,24 @@
     /**
      * Add a new SubscriptionInfo to SubscriptionInfo database if needed
      * @param iccId the IccId of the SIM card
-     * @param slotId the slot which the SIM is inserted
+     * @param slotIndex the slot which the SIM is inserted
      * @return the URL of the newly created row or the updated row
      * @hide
      */
-    public Uri addSubscriptionInfoRecord(String iccId, int slotId) {
-        if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotId:" + slotId);
+    public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) {
+        if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex);
         if (iccId == null) {
             logd("[addSubscriptionInfoRecord]- null iccId");
         }
-        if (!isValidSlotId(slotId)) {
-            logd("[addSubscriptionInfoRecord]- invalid slotId");
+        if (!isValidSlotIndex(slotIndex)) {
+            logd("[addSubscriptionInfoRecord]- invalid slotIndex");
         }
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
                 // FIXME: This returns 1 on success, 0 on error should should we return it?
-                iSub.addSubInfoRecord(iccId, slotId);
+                iSub.addSubInfoRecord(iccId, slotIndex);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -830,15 +830,15 @@
     }
 
     /**
-     * Get slotId associated with the subscription.
-     * @return slotId as a positive integer or a negative value if an error either
+     * Get slotIndex associated with the subscription.
+     * @return slotIndex as a positive integer or a negative value if an error either
      * SIM_NOT_INSERTED or < 0 if an invalid slot index
      * @hide
      */
-    public static int getSlotId(int subId) {
+    public static int getSlotIndex(int subId) {
         if (!isValidSubscriptionId(subId)) {
             if (DBG) {
-                logd("[getSlotId]- fail");
+                logd("[getSlotIndex]- fail");
             }
         }
 
@@ -847,7 +847,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                result = iSub.getSlotId(subId);
+                result = iSub.getSlotIndex(subId);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -858,8 +858,8 @@
     }
 
     /** @hide */
-    public static int[] getSubId(int slotId) {
-        if (!isValidSlotId(slotId)) {
+    public static int[] getSubId(int slotIndex) {
+        if (!isValidSlotIndex(slotIndex)) {
             logd("[getSubId]- fail");
             return null;
         }
@@ -869,7 +869,7 @@
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subId = iSub.getSubId(slotId);
+                subId = iSub.getSubId(slotIndex);
             }
         } catch (RemoteException ex) {
             // ignore it
@@ -1155,8 +1155,8 @@
     }
 
     /** @hide */
-    public static boolean isValidSlotId(int slotId) {
-        return slotId >= 0 && slotId < TelephonyManager.getDefault().getSimCount();
+    public static boolean isValidSlotIndex(int slotIndex) {
+        return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount();
     }
 
     /** @hide */
@@ -1179,7 +1179,7 @@
         if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId);
         intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId);
         intent.putExtra(PhoneConstants.PHONE_KEY, phoneId);
-        //FIXME this is using phoneId and slotId interchangeably
+        //FIXME this is using phoneId and slotIndex interchangeably
         //Eventually, this should be removed as it is not the slot id
         intent.putExtra(PhoneConstants.SLOT_KEY, phoneId);
     }
@@ -1228,9 +1228,9 @@
     }
 
     /**
-     * Returns a constant indicating the state of sim for the slot idx.
+     * Returns a constant indicating the state of sim for the slot index.
      *
-     * @param slotIdx
+     * @param slotIndex
      *
      * {@See TelephonyManager#SIM_STATE_UNKNOWN}
      * {@See TelephonyManager#SIM_STATE_ABSENT}
@@ -1244,13 +1244,13 @@
      *
      * {@hide}
      */
-    public static int getSimStateForSlotIdx(int slotIdx) {
+    public static int getSimStateForSlotIndex(int slotIndex) {
         int simState = TelephonyManager.SIM_STATE_UNKNOWN;
 
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                simState = iSub.getSimStateForSlotIdx(slotIdx);
+                simState = iSub.getSimStateForSlotIndex(slotIndex);
             }
         } catch (RemoteException ex) {
         }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index c691879..a61496d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -46,6 +46,7 @@
 
 import com.android.ims.internal.IImsServiceController;
 import com.android.ims.internal.IImsServiceFeatureListener;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telecom.ITelecomService;
 import com.android.internal.telephony.CellNetworkScanResult;
 import com.android.internal.telephony.IPhoneSubInfo;
@@ -863,15 +864,15 @@
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
-     * @param slotId of which deviceID is returned
+     * @param slotIndex of which deviceID is returned
      */
     /** {@hide} */
-    public String getDeviceSoftwareVersion(int slotId) {
+    public String getDeviceSoftwareVersion(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
 
         try {
-            return telephony.getDeviceSoftwareVersionForSlot(slotId, getOpPackageName());
+            return telephony.getDeviceSoftwareVersionForSlot(slotIndex, getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -885,7 +886,11 @@
      *
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     *
+     * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
+     * MEID for CDMA.
      */
+    @Deprecated
     public String getDeviceId() {
         try {
             ITelephony telephony = getITelephony();
@@ -906,15 +911,19 @@
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *
-     * @param slotId of which deviceID is returned
+     * @param slotIndex of which deviceID is returned
+     *
+     * @deprecated Use (@link getImei} which returns IMEI for GSM or (@link getMeid} which returns
+     * MEID for CDMA.
      */
-    public String getDeviceId(int slotId) {
-        // FIXME this assumes phoneId == slotId
+    @Deprecated
+    public String getDeviceId(int slotIndex) {
+        // FIXME this assumes phoneId == slotIndex
         try {
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
                 return null;
-            return info.getDeviceIdForPhone(slotId, mContext.getOpPackageName());
+            return info.getDeviceIdForPhone(slotIndex, mContext.getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -923,35 +932,62 @@
     }
 
     /**
-     * Returns the IMEI. Return null if IMEI is not available.
+     * 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}
-     *
-     * @hide
      */
-    @SystemApi
     public String getImei() {
         return getImei(getDefaultSim());
     }
 
     /**
-     * Returns the IMEI. Return null if IMEI is not available.
+     * 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}
      *
-     * @param slotId of which deviceID is returned
-     *
-     * @hide
+     * @param slotIndex of which IMEI is returned
      */
-    @SystemApi
-    public String getImei(int slotId) {
+    public String getImei(int slotIndex) {
         ITelephony telephony = getITelephony();
         if (telephony == null) return null;
 
         try {
-            return telephony.getImeiForSlot(slotId, getOpPackageName());
+            return telephony.getImeiForSlot(slotIndex, getOpPackageName());
+        } catch (RemoteException ex) {
+            return null;
+        } catch (NullPointerException ex) {
+            return null;
+        }
+    }
+
+    /**
+     * 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}
+     */
+    public String getMeid() {
+        return getMeid(getDefaultSim());
+    }
+
+    /**
+     * 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}
+     *
+     * @param slotIndex of which MEID is returned
+     */
+    public String getMeid(int slotIndex) {
+        ITelephony telephony = getITelephony();
+        if (telephony == null) return null;
+
+        try {
+            return telephony.getMeidForSlot(slotIndex, getOpPackageName());
         } catch (RemoteException ex) {
             return null;
         } catch (NullPointerException ex) {
@@ -971,11 +1007,11 @@
     /**
      * Returns the NAI. Return null if NAI is not available.
      *
-     *  @param slotId of which Nai is returned
+     *  @param slotIndex of which Nai is returned
      */
     /** {@hide}*/
-    public String getNai(int slotId) {
-        int[] subId = SubscriptionManager.getSubId(slotId);
+    public String getNai(int slotIndex) {
+        int[] subId = SubscriptionManager.getSubId(slotIndex);
         try {
             IPhoneSubInfo info = getSubscriberInfo();
             if (info == null)
@@ -1171,23 +1207,23 @@
      *
      * @hide
      */
-    public int getCurrentPhoneTypeForSlot(int slotId) {
+    public int getCurrentPhoneTypeForSlot(int slotIndex) {
         try{
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getActivePhoneTypeForSlot(slotId);
+                return telephony.getActivePhoneTypeForSlot(slotIndex);
             } else {
                 // This can happen when the ITelephony interface is not up yet.
-                return getPhoneTypeFromProperty(slotId);
+                return getPhoneTypeFromProperty(slotIndex);
             }
         } catch (RemoteException ex) {
             // This shouldn't happen in the normal case, as a backup we
             // read from the system property.
-            return getPhoneTypeFromProperty(slotId);
+            return getPhoneTypeFromProperty(slotIndex);
         } catch (NullPointerException ex) {
             // This shouldn't happen in the normal case, as a backup we
             // read from the system property.
-            return getPhoneTypeFromProperty(slotId);
+            return getPhoneTypeFromProperty(slotIndex);
         }
     }
 
@@ -1900,17 +1936,17 @@
     /**
      * @return true if a ICC card is present for a subscription
      *
-     * @param slotId for which icc card presence is checked
+     * @param slotIndex for which icc card presence is checked
      */
     /** {@hide} */
-    // FIXME Input argument slotId should be of type int
-    public boolean hasIccCard(int slotId) {
+    // FIXME Input argument slotIndex should be of type int
+    public boolean hasIccCard(int slotIndex) {
 
         try {
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return false;
-            return telephony.hasIccCardUsingSlotId(slotId);
+            return telephony.hasIccCardUsingSlotIndex(slotIndex);
         } catch (RemoteException ex) {
             // Assume no ICC card if remote exception which shouldn't happen
             return false;
@@ -1935,31 +1971,31 @@
      * @see #SIM_STATE_CARD_RESTRICTED
      */
     public int getSimState() {
-        int slotIdx = getDefaultSim();
-        // slotIdx may be invalid due to sim being absent. In that case query all slots to get
+        int slotIndex = getDefaultSim();
+        // slotIndex may be invalid due to sim being absent. In that case query all slots to get
         // sim state
-        if (slotIdx < 0) {
+        if (slotIndex < 0) {
             // query for all slots and return absent if all sim states are absent, otherwise
             // return unknown
             for (int i = 0; i < getPhoneCount(); i++) {
                 int simState = getSimState(i);
                 if (simState != SIM_STATE_ABSENT) {
-                    Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", sim state for " +
-                            "slotIdx=" + i + " is " + simState + ", return state as unknown");
+                    Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", sim state for " +
+                            "slotIndex=" + i + " is " + simState + ", return state as unknown");
                     return SIM_STATE_UNKNOWN;
                 }
             }
-            Rlog.d(TAG, "getSimState: default sim:" + slotIdx + ", all SIMs absent, return " +
+            Rlog.d(TAG, "getSimState: default sim:" + slotIndex + ", all SIMs absent, return " +
                     "state as absent");
             return SIM_STATE_ABSENT;
         }
-        return getSimState(slotIdx);
+        return getSimState(slotIndex);
     }
 
     /**
      * Returns a constant indicating the state of the device SIM card in a slot.
      *
-     * @param slotIdx
+     * @param slotIndex
      *
      * @see #SIM_STATE_UNKNOWN
      * @see #SIM_STATE_ABSENT
@@ -1972,8 +2008,8 @@
      * @see #SIM_STATE_CARD_IO_ERROR
      * @see #SIM_STATE_CARD_RESTRICTED
      */
-    public int getSimState(int slotIdx) {
-        int simState = SubscriptionManager.getSimStateForSlotIdx(slotIdx);
+    public int getSimState(int slotIndex) {
+        int simState = SubscriptionManager.getSimStateForSlotIndex(slotIndex);
         return simState;
     }
 
@@ -3065,12 +3101,12 @@
      *
      * @hide
      */
-    public int getCallStateForSlot(int slotId) {
+    public int getCallStateForSlot(int slotIndex) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony == null)
                 return CALL_STATE_IDLE;
-            return telephony.getCallStateForSlot(slotId);
+            return telephony.getCallStateForSlot(slotIndex);
         } catch (RemoteException ex) {
             // the phone process is restarting.
             return CALL_STATE_IDLE;
@@ -3204,7 +3240,7 @@
     public void listen(PhoneStateListener listener, int events) {
         if (mContext == null) return;
         try {
-            Boolean notifyNow = (getITelephony() != null);
+            boolean notifyNow = (getITelephony() != null);
             // If the listener has not explicitly set the subId (for example, created with the
             // default constructor), replace the subId so it will listen to the account the
             // telephony manager is created with.
@@ -3886,9 +3922,19 @@
         return SubscriptionManager.getPhoneId(SubscriptionManager.getDefaultSubscriptionId());
     }
 
-    /** {@hide} */
+    /**
+     *  @return default SIM's slot index. If SIM is not inserted, return default SIM slot index.
+     *
+     * {@hide}
+     */
+    @VisibleForTesting
     public int getDefaultSim() {
-        return SubscriptionManager.getSlotId(SubscriptionManager.getDefaultSubscriptionId());
+        int slotIndex = SubscriptionManager.getSlotIndex(
+                SubscriptionManager.getDefaultSubscriptionId());
+        if (slotIndex == SubscriptionManager.SIM_NOT_INSERTED) {
+            slotIndex = SubscriptionManager.DEFAULT_SIM_SLOT_INDEX;
+        }
+        return slotIndex;
     }
 
     /**
@@ -4253,7 +4299,7 @@
      * feature or {@link null} if the service is not available. If an ImsServiceController is
      * available, the {@link IImsServiceFeatureListener} callback is registered as a listener for
      * feature updates.
-     * @param slotId The SIM slot that we are requesting the {@link IImsServiceController} for.
+     * @param slotIndex The SIM slot that we are requesting the {@link IImsServiceController} for.
      * @param feature The IMS Feature we are requesting, corresponding to {@link ImsFeature}.
      * @param callback Listener that will send updates to ImsManager when there are updates to
      * ImsServiceController.
@@ -4261,12 +4307,12 @@
      * it is unavailable.
      * @hide
      */
-    public IImsServiceController getImsServiceControllerAndListen(int slotId, @Feature int feature,
+    public IImsServiceController getImsServiceControllerAndListen(int slotIndex, @Feature int feature,
             IImsServiceFeatureListener callback) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                return telephony.getImsServiceControllerAndListen(slotId, feature, callback);
+                return telephony.getImsServiceControllerAndListen(slotIndex, feature, callback);
             }
         } catch (RemoteException e) {
             Rlog.e(TAG, "getImsServiceControllerAndListen, RemoteException: " + e.getMessage());
@@ -5404,7 +5450,7 @@
     /**
      * Set SIM card power state. Request is equivalent to inserting or removing the card.
      *
-     * @param slotId SIM slot id
+     * @param slotIndex SIM slot id
      * @param powerUp True if powering up the SIM, otherwise powering down
      *
      * <p>Requires Permission:
@@ -5412,11 +5458,11 @@
      *
      * @hide
      **/
-    public void setSimPowerStateForSlot(int slotId, boolean powerUp) {
+    public void setSimPowerStateForSlot(int slotIndex, boolean powerUp) {
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                telephony.setSimPowerStateForSlot(slotId, powerUp);
+                telephony.setSimPowerStateForSlot(slotIndex, powerUp);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#setSimPowerStateForSlot", e);
@@ -5952,7 +5998,7 @@
     }
 
     /**
-     * Set the allowed carrier list for slotId
+     * Set the allowed carrier list for slotIndex
      * Require system privileges. In the future we may add this to carrier APIs.
      *
      * <p>Requires Permission:
@@ -5966,11 +6012,11 @@
      * @hide
      */
     @SystemApi
-    public int setAllowedCarriers(int slotId, List<CarrierIdentifier> carriers) {
+    public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.setAllowedCarriers(slotId, carriers);
+                return service.setAllowedCarriers(slotIndex, carriers);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#setAllowedCarriers", e);
@@ -5981,7 +6027,7 @@
     }
 
     /**
-     * Get the allowed carrier list for slotId.
+     * Get the allowed carrier list for slotIndex.
      * Require system privileges. In the future we may add this to carrier APIs.
      *
      * <p>Requires Permission:
@@ -5995,11 +6041,11 @@
      * @hide
      */
     @SystemApi
-    public List<CarrierIdentifier> getAllowedCarriers(int slotId) {
+    public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.getAllowedCarriers(slotId);
+                return service.getAllowedCarriers(slotIndex);
             }
         } catch (RemoteException e) {
             Log.e(TAG, "Error calling ITelephony#getAllowedCarriers", e);
diff --git a/telephony/java/com/android/ims/ImsReasonInfo.java b/telephony/java/com/android/ims/ImsReasonInfo.java
index e4f380f..bd8492b3 100644
--- a/telephony/java/com/android/ims/ImsReasonInfo.java
+++ b/telephony/java/com/android/ims/ImsReasonInfo.java
@@ -318,6 +318,66 @@
      */
     public static final int CODE_IKEV2_AUTH_FAILURE = 1408;
 
+    /** The call cannot be established because RADIO is OFF */
+    public static final int CODE_RADIO_OFF = 1500;
+
+    /** The call cannot be established because of no valid SIM */
+    public static final int CODE_NO_VALID_SIM = 1501;
+
+    /** The failure is due internal error at modem */
+    public static final int CODE_RADIO_INTERNAL_ERROR = 1502;
+
+    /** The failure is due to UE timer expired while waiting for a response from network */
+    public static final int CODE_NETWORK_RESP_TIMEOUT = 1503;
+
+    /** The failure is due to explicit reject from network */
+    public static final int CODE_NETWORK_REJECT = 1504;
+
+    /** The failure is due to radio access failure. ex. RACH failure */
+    public static final int CODE_RADIO_ACCESS_FAILURE = 1505;
+
+    /** Call/IMS registration failed/dropped because of a RLF */
+    public static final int CODE_RADIO_LINK_FAILURE = 1506;
+
+    /** Call/IMS registration failed/dropped because of radio link lost */
+    public static final int CODE_RADIO_LINK_LOST = 1507;
+
+    /** The call Call/IMS registration failed because of a radio uplink issue */
+    public static final int CODE_RADIO_UPLINK_FAILURE = 1508;
+
+    /** Call failed because of a RRC connection setup failure */
+    public static final int CODE_RADIO_SETUP_FAILURE = 1509;
+
+    /** Call failed/dropped because of RRC connection release from NW */
+    public static final int CODE_RADIO_RELEASE_NORMAL = 1510;
+
+    /** Call failed/dropped because of RRC abnormally released by modem/network */
+    public static final int CODE_RADIO_RELEASE_ABNORMAL = 1511;
+
+    /** Call failed because of access class barring */
+    public static final int CODE_ACCESS_CLASS_BLOCKED = 1512;
+
+    /** Call/IMS registration is failed/dropped because of a network detach */
+    public static final int CODE_NETWORK_DETACH = 1513;
+
+    /* OEM specific error codes. To be used by OEMs when they don't want to
+   reveal error code which would be replaced by ERROR_UNSPECIFIED */
+    public static final int CODE_OEM_CAUSE_1 = 0xf001;
+    public static final int CODE_OEM_CAUSE_2 = 0xf002;
+    public static final int CODE_OEM_CAUSE_3 = 0xf003;
+    public static final int CODE_OEM_CAUSE_4 = 0xf004;
+    public static final int CODE_OEM_CAUSE_5 = 0xf005;
+    public static final int CODE_OEM_CAUSE_6 = 0xf006;
+    public static final int CODE_OEM_CAUSE_7 = 0xf007;
+    public static final int CODE_OEM_CAUSE_8 = 0xf008;
+    public static final int CODE_OEM_CAUSE_9 = 0xf009;
+    public static final int CODE_OEM_CAUSE_10 = 0xf00a;
+    public static final int CODE_OEM_CAUSE_11 = 0xf00b;
+    public static final int CODE_OEM_CAUSE_12 = 0xf00c;
+    public static final int CODE_OEM_CAUSE_13 = 0xf00d;
+    public static final int CODE_OEM_CAUSE_14 = 0xf00e;
+    public static final int CODE_OEM_CAUSE_15 = 0xf00f;
+
     /**
      * Network string error messages.
      * mExtraMessage may have these values.
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index f6aef08..71f2c6b 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -52,12 +52,12 @@
     SubscriptionInfo getActiveSubscriptionInfoForIccId(String iccId, String callingPackage);
 
     /**
-     * Get the active SubscriptionInfo associated with the slotIdx
-     * @param slotIdx the slot which the subscription is inserted
+     * Get the active SubscriptionInfo associated with the slotIndex
+     * @param slotIndex the slot which the subscription is inserted
      * @param callingPackage The package maing the call.
      * @return SubscriptionInfo, maybe null if its not active
      */
-    SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIdx, String callingPackage);
+    SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, String callingPackage);
 
     /**
      * Get the SubscriptionInfo(s) of the active subscriptions. The records will be sorted
@@ -96,10 +96,10 @@
     /**
      * Add a new SubscriptionInfo to subinfo database if needed
      * @param iccId the IccId of the SIM card
-     * @param slotId the slot which the SIM is inserted
+     * @param slotIndex the slot which the SIM is inserted
      * @return the URL of the newly created row or the updated row
      */
-    int addSubInfoRecord(String iccId, int slotId);
+    int addSubInfoRecord(String iccId, int slotIndex);
 
     /**
      * Set SIM icon tint color by simInfo index
@@ -142,9 +142,9 @@
      */
     int setDataRoaming(int roaming, int subId);
 
-    int getSlotId(int subId);
+    int getSlotIndex(int subId);
 
-    int[] getSubId(int slotId);
+    int[] getSubId(int slotIndex);
 
     int getDefaultSubId();
 
@@ -177,10 +177,10 @@
     String getSubscriptionProperty(int subId, String propKey, String callingPackage);
 
     /**
-     * Get the SIM state for the slot idx
+     * Get the SIM state for the slot index
      * @return SIM state as the ordinal of IccCardConstants.State
      */
-    int getSimStateForSlotIdx(int slotIdx);
+    int getSimStateForSlotIndex(int slotIndex);
 
     boolean isActiveSubId(int subId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index d21efc6..5c37822 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -370,7 +370,7 @@
     /**
      * Returns the call state for a slot.
      */
-     int getCallStateForSlot(int slotId);
+     int getCallStateForSlot(int slotIndex);
 
      int getDataActivity();
      int getDataState();
@@ -386,9 +386,9 @@
      * Returns the current active phone type as integer for particular slot.
      * Returns TelephonyManager.PHONE_TYPE_CDMA if RILConstants.CDMA_PHONE
      * and TelephonyManager.PHONE_TYPE_GSM if RILConstants.GSM_PHONE
-     * @param slotId - slot to query.
+     * @param slotIndex - slot to query.
      */
-    int getActivePhoneTypeForSlot(int slotId);
+    int getActivePhoneTypeForSlot(int slotIndex);
 
     /**
      * Returns the CDMA ERI icon index to display
@@ -542,10 +542,10 @@
 
     /**
      * Return true if an ICC card is present for a subId.
-     * @param slotId user preferred slotId.
+     * @param slotIndex user preferred slotIndex.
      * Return true if an ICC card is present
      */
-    boolean hasIccCardUsingSlotId(int slotId);
+    boolean hasIccCardUsingSlotIndex(int slotIndex);
 
     /**
      * Return if the current radio is LTE on CDMA. This
@@ -746,7 +746,7 @@
      *  requested as well as registering the ImsServiceController for callbacks using the
      *  IImsServiceFeatureListener interface.
      */
-    IImsServiceController getImsServiceControllerAndListen(int slotId, int feature,
+    IImsServiceController getImsServiceControllerAndListen(int slotIndex, int feature,
                 IImsServiceFeatureListener callback);
 
     /**
@@ -1054,22 +1054,32 @@
     /**
      * Returns the IMEI for the given slot.
      *
-     * @param slotId - device slot.
+     * @param slotIndex - device slot.
      * @param callingPackage The package making the call.
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
-    String getImeiForSlot(int slotId, String callingPackage);
+    String getImeiForSlot(int slotIndex, String callingPackage);
+
+    /**
+     * Returns the MEID for the given slot.
+     *
+     * @param slotIndex - device slot.
+     * @param callingPackage The package making the call.
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+     */
+    String getMeidForSlot(int slotIndex, String callingPackage);
 
     /**
      * Returns the device software version.
      *
-     * @param slotId - device slot.
+     * @param slotIndex - device slot.
      * @param callingPackage The package making the call.
      * <p>Requires Permission:
      *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      */
-    String getDeviceSoftwareVersionForSlot(int slotId, String callingPackage);
+    String getDeviceSoftwareVersionForSlot(int slotIndex, String callingPackage);
 
     /**
      * Returns the subscription ID associated with the specified PhoneAccount.
@@ -1167,22 +1177,22 @@
     List<TelephonyHistogram> getTelephonyHistograms();
 
     /**
-     * Set the allowed carrier list for slotId
+     * Set the allowed carrier list for slotIndex
      * Require system privileges. In the future we may add this to carrier APIs.
      *
      * @return The number of carriers set successfully. Should match length of
      * carriers on success.
      */
-    int setAllowedCarriers(int slotId, in List<CarrierIdentifier> carriers);
+    int setAllowedCarriers(int slotIndex, in List<CarrierIdentifier> carriers);
 
     /**
-     * Get the allowed carrier list for slotId.
+     * Get the allowed carrier list for slotIndex.
      * Require system privileges. In the future we may add this to carrier APIs.
      *
      * @return List of {@link android.service.carrier.CarrierIdentifier}; empty list
      * means all carriers are allowed.
      */
-    List<CarrierIdentifier> getAllowedCarriers(int slotId);
+    List<CarrierIdentifier> getAllowedCarriers(int slotIndex);
 
     /**
      * Action set from carrier signalling broadcast receivers to enable/disable metered apns
@@ -1229,11 +1239,11 @@
 
     /**
      * Set SIM card power state. Request is equivalent to inserting or removing the card.
-     * @param slotId SIM slot id
+     * @param slotIndex SIM slot id
      * @param powerUp True if powering up the SIM, otherwise powering down
      * @hide
      * */
-    void setSimPowerStateForSlot(int slotId, boolean powerUp);
+    void setSimPowerStateForSlot(int slotIndex, boolean powerUp);
 
     /**
      * Returns a list of Forbidden PLMNs from the specified SIM App
diff --git a/tests/net/java/android/net/ip/IpManagerTest.java b/tests/net/java/android/net/ip/IpManagerTest.java
new file mode 100644
index 0000000..025b017
--- /dev/null
+++ b/tests/net/java/android/net/ip/IpManagerTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.net.ip;
+
+import static org.mockito.Mockito.when;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.INetworkManagementService;
+import android.provider.Settings;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.test.mock.MockContentResolver;
+
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.R;
+
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for IpManager.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class IpManagerTest {
+    private static final int DEFAULT_AVOIDBADWIFI_CONFIG_VALUE = 1;
+
+    @Mock private Context mContext;
+    @Mock private INetworkManagementService mNMService;
+    @Mock private Resources mResources;
+    private MockContentResolver mContentResolver;
+
+    @Before public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        when(mContext.getResources()).thenReturn(mResources);
+        when(mResources.getInteger(R.integer.config_networkAvoidBadWifi))
+                .thenReturn(DEFAULT_AVOIDBADWIFI_CONFIG_VALUE);
+
+        mContentResolver = new MockContentResolver();
+        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+    }
+
+    @Test
+    public void testNullCallbackDoesNotThrow() throws Exception {
+        final IpManager ipm = new IpManager(mContext, "lo", null, mNMService);
+    }
+
+    @Test
+    public void testInvalidInterfaceDoesNotThrow() throws Exception {
+        final IpManager.Callback cb = new IpManager.Callback();
+        final IpManager ipm = new IpManager(mContext, "test_wlan0", cb, mNMService);
+    }
+}
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 18c1245..af48d0a 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -16,7 +16,11 @@
 
 package android.net.wifi;
 
+
+import android.content.pm.ParceledListSlice;
+
 import android.net.wifi.hotspot2.PasspointConfiguration;
+
 import android.net.wifi.WifiConfiguration;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.ScanSettings;
@@ -51,9 +55,9 @@
      */
     oneway void requestActivityInfo(in ResultReceiver result);
 
-    List<WifiConfiguration> getConfiguredNetworks();
+    ParceledListSlice getConfiguredNetworks();
 
-    List<WifiConfiguration> getPrivilegedConfiguredNetworks();
+    ParceledListSlice getPrivilegedConfiguredNetworks();
 
     WifiConfiguration getMatchingWifiConfig(in ScanResult scanResult);
 
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 6095c86..dac511e 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -281,7 +281,9 @@
     public int apChannel = 0;
 
     /**
-     * Pre-shared key for use with WPA-PSK.
+     * Pre-shared key for use with WPA-PSK. Either an ASCII string enclosed in
+     * double quotation marks (e.g., {@code "abcdefghij"} for PSK passphrase or
+     * a string of 64 hex digits for raw PSK.
      * <p/>
      * When the value of this key is read, the actual key is
      * not returned, just a "*" if the key has a value, or the null
@@ -305,7 +307,7 @@
     /**
      * Priority determines the preference given to a network by {@code wpa_supplicant}
      * when choosing an access point with which to associate.
-     * @deprecated Priority is no longer used.
+     * @deprecated This field does not exist anymore.
      */
     @Deprecated
     public int priority;
@@ -434,6 +436,13 @@
     public int dtimInterval = 0;
 
     /**
+     * Flag indicating if this configuration represents a legacy Passpoint configuration
+     * (Release N or older).  This is used for migrating Passpoint configuration from N to O.
+     * This will no longer be needed after O.
+     * @hide
+     */
+    public boolean isLegacyPasspointConfig = false;
+    /**
      * @hide
      * Uid of app creating the configuration
      */
@@ -1951,6 +1960,7 @@
             mCachedConfigKey = null; //force null configKey
             selfAdded = source.selfAdded;
             validatedInternetAccess = source.validatedInternetAccess;
+            isLegacyPasspointConfig = source.isLegacyPasspointConfig;
             ephemeral = source.ephemeral;
             meteredHint = source.meteredHint;
             meteredOverride = source.meteredOverride;
@@ -2027,6 +2037,7 @@
         dest.writeInt(selfAdded ? 1 : 0);
         dest.writeInt(didSelfAdd ? 1 : 0);
         dest.writeInt(validatedInternetAccess ? 1 : 0);
+        dest.writeInt(isLegacyPasspointConfig ? 1 : 0);
         dest.writeInt(ephemeral ? 1 : 0);
         dest.writeInt(meteredHint ? 1 : 0);
         dest.writeInt(meteredOverride ? 1 : 0);
@@ -2093,6 +2104,7 @@
                 config.selfAdded = in.readInt() != 0;
                 config.didSelfAdd = in.readInt() != 0;
                 config.validatedInternetAccess = in.readInt() != 0;
+                config.isLegacyPasspointConfig = in.readInt() != 0;
                 config.ephemeral = in.readInt() != 0;
                 config.meteredHint = in.readInt() != 0;
                 config.meteredOverride = in.readInt() != 0;
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index ed6a166..824c436 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -21,6 +21,7 @@
 import android.annotation.SystemApi;
 import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
+import android.content.pm.ParceledListSlice;
 import android.net.ConnectivityManager;
 import android.net.DhcpInfo;
 import android.net.Network;
@@ -46,6 +47,7 @@
 import java.net.InetAddress;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
+import java.util.Collections;
 
 /**
  * This class provides the primary API for managing all aspects of Wi-Fi
@@ -114,166 +116,125 @@
     public static final int WIFI_CREDENTIAL_FORGOT = 1;
 
     /**
-     * Broadcast intent action indicating that the a Passpoint release 2 icon has been received.
-     * @hide
-     */
-    public static final String PASSPOINT_ICON_RECEIVED_ACTION =
-            "android.net.wifi.PASSPOINT_ICON_RECEIVED";
-    /** @hide */
-    public static final String EXTRA_PASSPOINT_ICON_FILE = "file";
-
-    /**
-     * Broadcast intent action indicating that the a Passpoint release
-     * 2 WNM frame has been received.
-     * @hide
-     */
-    public static final String PASSPOINT_WNM_FRAME_RECEIVED_ACTION =
-            "android.net.wifi.PASSPOINT_WNM_FRAME_RECEIVED";
-    /**
-     * Originating BSS
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_BSSID = "bssid";
-    /**
-     * SOAP-XML or OMA-DM
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_METHOD = "method";
-    /**
-     * Type of Passpoint match
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_PPOINT_MATCH = "match";
-    /**
-     * String
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_URL = "url";
-    /**
-     * Boolean true=ess, false=bss
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_ESS = "ess";
-    /**
-     * Delay in seconds
-     * @hide */
-    public static final String EXTRA_PASSPOINT_WNM_DELAY = "delay";
-
-    /**
      * Broadcast intent action indicating that a Passpoint provider icon has been received.
      *
+     * Included extras:
+     * {@link #EXTRA_BSSID_LONG}
+     * {@link #EXTRA_FILENAME}
+     * {@link #EXTRA_ICON}
+     *
      * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
-     */
-    public static final String ACTION_PASSPOINT_ICON =
-            "android.net.wifi.action.PASSPOINT_ICON";
-    /**
-     * BSSID of the sender.
      *
-     * Type: long
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
      */
-    public static final String EXTRA_PASSPOINT_ICON_BSSID =
-            "android.net.wifi.extra.PASSPOINT_ICON_BSSID";
+    public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
     /**
-     * Filename of the icon.
+     * BSSID of an AP in long representation.  The {@link #EXTRA_BSSID} contains BSSID in
+     * String representation.
      *
-     * Type: String
+     * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}.
      */
-    public static final String EXTRA_PASSPOINT_ICON_FILENAME =
-            "android.net.wifi.extra.PASSPOINT_ICON_FILENAME";
+    public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
     /**
-     * Binary blob of the icon.
+     * Icon data.
      *
-     * Type: byte[]
+     * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into
+     * {@link android.graphics.drawable.Icon}.
      */
-    public static final String EXTRA_PASSPOINT_ICON_DATA =
-            "android.net.wifi.extra.PASSPOINT_ICON_DATA";
+    public static final String EXTRA_ICON = "android.net.wifi.extra.ICON";
+    /**
+     * Name of a file.
+     *
+     * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+     */
+    public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
 
     /**
      * Broadcast intent action indicating a Passpoint OSU Providers List element has been received.
      *
+     * Included extras:
+     * {@link #EXTRA_BSSID_LONG}
+     * {@link #EXTRA_ANQP_ELEMENT_DATA}
+     *
      * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     *
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
+     *
      */
     public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST =
             "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
     /**
-     * BSSID of the sender.
+     * Raw binary data of an ANQP (Access Network Query Protocol) element.
      *
-     * Type: long
+     * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}.
      */
-    public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_BSSID =
-            "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_BSSID";
-    /**
-     * Raw data of OSU Providers List ANQP element.  Refer to Section 4.8 of Hotspot 2.0 Release 2
-     * Technical Specification for the exact data format.
-     *
-     * Type: byte[]
-     */
-    public static final String EXTRA_PASSPOINT_OSU_PROVIDERS_LIST_DATA =
-            "android.net.wifi.extra.PASSPOINT_OSU_PROVIDERS_LIST_DATA";
+    public static final String EXTRA_ANQP_ELEMENT_DATA =
+            "android.net.wifi.extra.ANQP_ELEMENT_DATA";
 
     /**
      * Broadcast intent action indicating that a Passpoint Deauth Imminent frame has been received.
      *
+     * Included extras:
+     * {@link #EXTRA_BSSID_LONG}
+     * {@link #EXTRA_ESS}
+     * {@link #EXTRA_DELAY}
+     * {@link #EXTRA_URL}
+     *
      * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     *
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
+     *
      */
     public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT =
             "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
     /**
-     * The BSSID of the sender.
+     * Flag indicating BSS (Basic Service Set) or ESS (Extended Service Set). This will be set to
+     * {@code true} for ESS.
      *
-     * Type: long
+     * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}.
      */
-    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_BSSID =
-            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_BSSID";
+    public static final String EXTRA_ESS = "android.net.wifi.extra.ESS";
     /**
-     * Flag indicating failure at BSS (Basic Service Set) or ESS (Extended Service Set) level.
+     * Delay in seconds.
      *
-     * Type: boolean
+     * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
      */
-    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS =
-            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_ESS";
+    public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
     /**
-     * Delay in seconds that a device shall wait before attempting re-association to the same BSS
-     * or ESS (as indicated by {@link #EXTRA_PASSPOINT_DEAUTH_IMMINENT_ESS}.
+     * String representation of an URL.
      *
-     * Type: int
+     * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
      */
-    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY =
-            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REAUTH_DELAY";
-    /**
-     * URL that provides a webpage explaining the deauth reason.
-     *
-     * Type: String
-     */
-    public static final String EXTRA_PASSPOINT_DEAUTH_IMMINENT_REASON_URL =
-            "android.net.wifi.extra.PASSPOINT_DEAUTH_IMMINENT_REASON_URL";
+    public static final String EXTRA_URL = "android.net.wifi.extra.URL";
 
     /**
      * Broadcast intent action indicating a Passpoint subscription remediation frame has been
      * received.
      *
+     * Included extras:
+     * {@link #EXTRA_BSSID_LONG}
+     * {@link #EXTRA_SUBSCRIPTION_REMEDIATION_METHOD}
+     * {@link #EXTRA_URL}
+     *
      * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
+     *
+     ** <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * components will be launched.
      */
     public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION =
             "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     /**
-     * The BSSID of the sender.
-     *
-     * Type: long
-     */
-    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID =
-            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_BSSID";
-    /**
      * The protocol supported by the subscription remediation server. The possible values are:
      * 0 - OMA DM
      * 1 - SOAP XML SPP
      *
-     * Type: int
+     * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
      */
-    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD =
-            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_METHOD";
-    /**
-     * URL of the subscription remediation server.
-     *
-     * Type: String
-     */
-    public static final String EXTRA_PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL =
-            "android.net.wifi.extra.PASSPOINT_SUBSCRIPTION_REMEDIATION_SERVER_URL";
+    public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD =
+            "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
 
     /**
      * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
@@ -859,7 +820,12 @@
      */
     public List<WifiConfiguration> getConfiguredNetworks() {
         try {
-            return mService.getConfiguredNetworks();
+            ParceledListSlice<WifiConfiguration> parceledList =
+                mService.getConfiguredNetworks();
+            if (parceledList == null) {
+                return Collections.emptyList();
+            }
+            return parceledList.getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -869,7 +835,12 @@
     @SystemApi
     public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
         try {
-            return mService.getPrivilegedConfiguredNetworks();
+            ParceledListSlice<WifiConfiguration> parceledList =
+                mService.getPrivilegedConfiguredNetworks();
+            if (parceledList == null) {
+                return Collections.emptyList();
+            }
+            return parceledList.getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -972,12 +943,15 @@
      * Name).  In the case when there is an existing configuration with the same
      * FQDN, the new configuration will replace the existing configuration.
      *
+     * An {@link IllegalArgumentException} will be thrown on failure.
+     *
      * @param config The Passpoint configuration to be added
-     * @return true on success
      */
-    public boolean addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
+    public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
         try {
-            return mService.addOrUpdatePasspointConfiguration(config);
+            if (!mService.addOrUpdatePasspointConfiguration(config)) {
+                throw new IllegalArgumentException();
+            }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -986,12 +960,15 @@
     /**
      * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
      *
+     * An {@link IllegalArgumentException} will be thrown on failure.
+     *
      * @param fqdn The FQDN of the passpoint configuration to be removed
-     * @return true on success
      */
-    public boolean removePasspointConfiguration(String fqdn) {
+    public void removePasspointConfiguration(String fqdn) {
         try {
-            return mService.removePasspointConfiguration(fqdn);
+            if (!mService.removePasspointConfiguration(fqdn)) {
+                throw new IllegalArgumentException();
+            }
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1013,10 +990,13 @@
     }
 
     /**
-     * Query for a Hotspot 2.0 release 2 OSU icon file.
+     * Query for a Hotspot 2.0 release 2 OSU icon file. An {@link #ACTION_PASSPOINT_ICON} intent
+     * will be broadcasted once the request is completed.  The presence of the intent extra
+     * {@link #EXTRA_ICON} will indicate the result of the request.
+     * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
      *
      * @param bssid The BSSID of the AP
-     * @param fileName File name of the icon to query
+     * @param fileName Name of the icon file (remote file) to query from the AP
      */
     public void queryPasspointIcon(long bssid, String fileName) {
         try {
diff --git a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
index 027b049a..e8e8731 100644
--- a/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/ConfigParser.java
@@ -111,6 +111,7 @@
      *
      * Content-Type: multipart/mixed; boundary={boundary}
      * Content-Transfer-Encoding: base64
+     * [Skip uninterested headers]
      *
      * --{boundary}
      * Content-Type: application/x-passpoint-profile
@@ -326,7 +327,8 @@
                     header.encodingType = entry.getValue();
                     break;
                 default:
-                    throw new IOException("Unexpected header: " + entry.getKey());
+                    Log.d(TAG, "Ignore header: " + entry.getKey());
+                    break;
             }
         }
         return header;
@@ -344,21 +346,24 @@
      * @throws IOException
      */
     private static Pair<String, String> parseContentType(String contentType) throws IOException {
-        String[] attributes = contentType.toString().split(";");
+        String[] attributes = contentType.split(";");
         String type = null;
         String boundary = null;
 
-        if (attributes.length < 1 || attributes.length > 2) {
+        if (attributes.length < 1) {
             throw new IOException("Invalid Content-Type: " + contentType);
         }
 
+        // The type is always the first attribute.
         type = attributes[0].trim();
-        if (attributes.length == 2) {
-            boundary = attributes[1].trim();
-            if (!boundary.startsWith(BOUNDARY)) {
-                throw new IOException("Invalid Content-Type: " + contentType);
+        // Look for boundary string from the rest of the attributes.
+        for (int i = 1; i < attributes.length; i++) {
+            String attribute = attributes[i].trim();
+            if (!attribute.startsWith(BOUNDARY)) {
+                Log.d(TAG, "Ignore Content-Type attribute: " + attributes[i]);
+                continue;
             }
-            boundary = boundary.substring(BOUNDARY.length());
+            boundary = attribute.substring(BOUNDARY.length());
             // Remove the leading and trailing quote if present.
             if (boundary.length() > 1 && boundary.startsWith("\"") && boundary.endsWith("\"")) {
                 boundary = boundary.substring(1, boundary.length()-1);
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 1f661c4..333a4f7d 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -28,6 +28,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
@@ -329,10 +330,55 @@
                 mUsageLimitStartTimeInMs, mUsageLimitDataLimit, mUsageLimitTimeLimitInMinutes);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UpdateIdentifier: ").append(mUpdateIdentifier).append("\n");
+        builder.append("CredentialPriority: ").append(mCredentialPriority).append("\n");
+        builder.append("SubscriptionCreationTime: ").append(
+                mSubscriptionCreationTimeInMs != Long.MIN_VALUE
+                ? new Date(mSubscriptionCreationTimeInMs) : "Not specified").append("\n");
+        builder.append("SubscriptionExpirationTime: ").append(
+                mSubscriptionExpirationTimeInMs != Long.MIN_VALUE
+                ? new Date(mSubscriptionExpirationTimeInMs) : "Not specified").append("\n");
+        builder.append("UsageLimitStartTime: ").append(mUsageLimitStartTimeInMs != Long.MIN_VALUE
+                ? new Date(mUsageLimitStartTimeInMs) : "Not specified").append("\n");
+        builder.append("UsageTimePeriod: ").append(mUsageLimitUsageTimePeriodInMinutes)
+                .append("\n");
+        builder.append("UsageLimitDataLimit: ").append(mUsageLimitDataLimit).append("\n");
+        builder.append("UsageLimitTimeLimit: ").append(mUsageLimitTimeLimitInMinutes).append("\n");
+        if (mHomeSp != null) {
+            builder.append("HomeSP Begin ---\n");
+            builder.append(mHomeSp);
+            builder.append("HomeSP End ---\n");
+        }
+        if (mCredential != null) {
+            builder.append("Credential Begin ---\n");
+            builder.append(mCredential);
+            builder.append("Credential End ---\n");
+        }
+        if (mPolicy != null) {
+            builder.append("Policy Begin ---\n");
+            builder.append(mPolicy);
+            builder.append("Policy End ---\n");
+        }
+        if (mSubscriptionUpdate != null) {
+            builder.append("SubscriptionUpdate Begin ---\n");
+            builder.append(mSubscriptionUpdate);
+            builder.append("SubscriptionUpdate End ---\n");
+        }
+        if (mTrustRootCertList != null) {
+            builder.append("TrustRootCertServers: ").append(mTrustRootCertList.keySet())
+                    .append("\n");
+        }
+        return builder.toString();
+    }
+
     /**
      * Validate the configuration data.
      *
      * @return true on success or false on failure
+     * @hide
      */
     public boolean validate() {
         if (mHomeSp == null || !mHomeSp.validate()) {
diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
index 2ffe428..5dc5d13 100644
--- a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
+++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java
@@ -144,6 +144,8 @@
     private static final String NODE_TIME_LIMIT = "TimeLimit";
     private static final String NODE_USAGE_TIME_PERIOD = "UsageTimePeriod";
     private static final String NODE_CREDENTIAL_PRIORITY = "CredentialPriority";
+    private static final String NODE_EXTENSION = "Extension";
+
     /**
      * Fields under HomeSP subtree.
      */
@@ -629,6 +631,10 @@
                 case NODE_CREDENTIAL_PRIORITY:
                     config.setCredentialPriority(parseInteger(getPpsNodeValue(child)));
                     break;
+                case NODE_EXTENSION:
+                    // All vendor specific information will be under this node.
+                    Log.d(TAG, "Ignore Extension node for vendor specific information");
+                    break;
                 default:
                     throw new ParsingException("Unknown node: " + child.getName());
             }
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
index 2388841..67fa1bb 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Credential.java
@@ -30,6 +30,7 @@
 import java.security.cert.CertificateEncodingException;
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.Objects;
 import java.util.Set;
@@ -282,10 +283,23 @@
                     mAbleToShare, mEapType, mNonEapInnerMethod);
         }
 
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Username: ").append(mUsername).append("\n");
+            builder.append("MachineManaged: ").append(mMachineManaged).append("\n");
+            builder.append("SoftTokenApp: ").append(mSoftTokenApp).append("\n");
+            builder.append("AbleToShare: ").append(mAbleToShare).append("\n");
+            builder.append("EAPType: ").append(mEapType).append("\n");
+            builder.append("AuthMethod: ").append(mNonEapInnerMethod).append("\n");
+            return builder.toString();
+        }
+
         /**
          * Validate the configuration data.
          *
          * @return true on success or false on failure
+         * @hide
          */
         public boolean validate() {
             if (TextUtils.isEmpty(mUsername)) {
@@ -439,10 +453,16 @@
             return Objects.hash(mCertType, mCertSha256Fingerprint);
         }
 
+        @Override
+        public String toString() {
+            return "CertificateType: " + mCertType + "\n";
+        }
+
         /**
          * Validate the configuration data.
          *
          * @return true on success or false on failure
+         * @hide
          */
         public boolean validate() {
             if (!TextUtils.equals(CERT_TYPE_X509V3, mCertType)) {
@@ -560,6 +580,14 @@
         }
 
         @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("IMSI: ").append(mImsi).append("\n");
+            builder.append("EAPType: ").append(mEapType).append("\n");
+            return builder.toString();
+        }
+
+        @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeString(mImsi);
             dest.writeInt(mEapType);
@@ -569,6 +597,7 @@
          * Validate the configuration data.
          *
          * @return true on success or false on failure
+         * @hide
          */
         public boolean validate() {
             // Note: this only validate the format of IMSI string itself.  Additional verification
@@ -764,10 +793,38 @@
                 mCaCertificate, mClientCertificateChain, mClientPrivateKey);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Realm: ").append(mRealm).append("\n");
+        builder.append("CreationTime: ").append(mCreationTimeInMs != Long.MIN_VALUE
+                ? new Date(mCreationTimeInMs) : "Not specified").append("\n");
+        builder.append("ExpirationTime: ").append(mExpirationTimeInMs != Long.MIN_VALUE
+                ? new Date(mExpirationTimeInMs) : "Not specified").append("\n");
+        builder.append("CheckAAAServerStatus: ").append(mCheckAaaServerCertStatus).append("\n");
+        if (mUserCredential != null) {
+            builder.append("UserCredential Begin ---\n");
+            builder.append(mUserCredential);
+            builder.append("UserCredential End ---\n");
+        }
+        if (mCertCredential != null) {
+            builder.append("CertificateCredential Begin ---\n");
+            builder.append(mCertCredential);
+            builder.append("CertificateCredential End ---\n");
+        }
+        if (mSimCredential != null) {
+            builder.append("SIMCredential Begin ---\n");
+            builder.append(mSimCredential);
+            builder.append("SIMCredential End ---\n");
+        }
+        return builder.toString();
+    }
+
     /**
      * Validate the configuration data.
      *
      * @return true on success or false on failure
+     * @hide
      */
     public boolean validate() {
         if (TextUtils.isEmpty(mRealm)) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
index 8ec40c0..9192ab0 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
@@ -241,10 +241,25 @@
                 mMatchAnyOis, mOtherHomePartners, mRoamingConsortiumOis);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("FQDN: ").append(mFqdn).append("\n");
+        builder.append("FriendlyName: ").append(mFriendlyName).append("\n");
+        builder.append("IconURL: ").append(mIconUrl).append("\n");
+        builder.append("HomeNetworkIDs: ").append(mHomeNetworkIds).append("\n");
+        builder.append("MatchAllOIs: ").append(mMatchAllOis).append("\n");
+        builder.append("MatchAnyOIs: ").append(mMatchAnyOis).append("\n");
+        builder.append("OtherHomePartners: ").append(mOtherHomePartners).append("\n");
+        builder.append("RoamingConsortiumOIs: ").append(mRoamingConsortiumOis).append("\n");
+        return builder.toString();
+    }
+
     /**
      * Validate HomeSp data.
      *
      * @return true on success or false on failure
+     * @hide
      */
     public boolean validate() {
         if (TextUtils.isEmpty(mFqdn)) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
index 63238e8..1df70f8 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/Policy.java
@@ -249,10 +249,21 @@
             return Objects.hash(mFqdn, mFqdnExactMatch, mPriority, mCountries);
         }
 
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("FQDN: ").append(mFqdn).append("\n");
+            builder.append("ExactMatch: ").append("mFqdnExactMatch").append("\n");
+            builder.append("Priority: ").append(mPriority).append("\n");
+            builder.append("Countries: ").append(mCountries).append("\n");
+            return builder.toString();
+        }
+
         /**
          * Validate RoamingParnter data.
          *
          * @return true on success
+         * @hide
          */
         public boolean validate() {
             if (TextUtils.isEmpty(mFqdn)) {
@@ -389,10 +400,34 @@
                 mPolicyUpdate);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MinHomeDownlinkBandwidth: ").append(mMinHomeDownlinkBandwidth)
+                .append("\n");
+        builder.append("MinHomeUplinkBandwidth: ").append(mMinHomeUplinkBandwidth).append("\n");
+        builder.append("MinRoamingDownlinkBandwidth: ").append(mMinRoamingDownlinkBandwidth)
+                .append("\n");
+        builder.append("MinRoamingUplinkBandwidth: ").append(mMinRoamingUplinkBandwidth)
+                .append("\n");
+        builder.append("ExcludedSSIDList: ").append(mExcludedSsidList).append("\n");
+        builder.append("RequiredProtoPortMap: ").append(mRequiredProtoPortMap).append("\n");
+        builder.append("MaximumBSSLoadValue: ").append(mMaximumBssLoadValue).append("\n");
+        builder.append("PreferredRoamingPartnerList: ").append(mPreferredRoamingPartnerList)
+                .append("\n");
+        if (mPolicyUpdate != null) {
+            builder.append("PolicyUpdate Begin ---\n");
+            builder.append(mPolicyUpdate);
+            builder.append("PolicyUpdate End ---\n");
+        }
+        return builder.toString();
+    }
+
     /**
      * Validate Policy data.
      *
      * @return true on success
+     * @hide
      */
     public boolean validate() {
         if (mPolicyUpdate == null) {
diff --git a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
index 70264b0e..a7adfeb 100644
--- a/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
+++ b/wifi/java/android/net/wifi/hotspot2/pps/UpdateParameter.java
@@ -247,10 +247,23 @@
                 mTrustRootCertSha256Fingerprint);
     }
 
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UpdateInterval: ").append(mUpdateIntervalInMinutes).append("\n");
+        builder.append("UpdateMethod: ").append(mUpdateMethod).append("\n");
+        builder.append("Restriction: ").append(mRestriction).append("\n");
+        builder.append("ServerURI: ").append(mServerUri).append("\n");
+        builder.append("Username: ").append(mUsername).append("\n");
+        builder.append("TrustRootCertURL: ").append(mTrustRootCertUrl).append("\n");
+        return builder.toString();
+    }
+
     /**
      * Validate UpdateParameter data.
      *
      * @return true on success
+     * @hide
      */
     public boolean validate() {
         if (mUpdateIntervalInMinutes == Long.MIN_VALUE) {
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64 b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
index 995963d..56919c2 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.base64
@@ -1,85 +1,86 @@
-Q29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5PXtib3VuZGFyeX0KQ29udGVu
-dC1UcmFuc2Zlci1FbmNvZGluZzogYmFzZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBh
-cHBsaWNhdGlvbi94LXBhc3Nwb2ludC1wcm9maWxlCkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6
-IGJhc2U2NAoKUEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29n
-SUR4V1pYSkVWRVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVo
-YldVK1VHVnlVSEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0Fn
-UEZKVVVISnZjR1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhi
-V1UrZFhKdU9uZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZ
-M0pwY0hScGIyNDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThM
-MUpVVUhKdmNHVnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSth
-VEF3TVR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRt
-RnRaVDVJYjIxbFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
-QWdJQ0FnSUNBOFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklD
-QWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcx
-bFBrWlJSRTQ4TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1
-MWF6d3ZWbUZzZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdv
-Z0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2
-ClpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpo
-YkhWbFBnb2dJQ0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4
-VG05a1pUNEtJQ0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVo
-YldVK0NpQWdJQ0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhi
-RzA4CkwwNXZaR1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHlj
-bVZrTG1OdmJUd3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9i
-MlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThM
-MDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2Iy
-UmxUbUZ0ClpUNVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDVxWVcxbGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lD
-QWdJQ0E4VG05a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BD
-OU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3
-dlZtRnNkV1UrCkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0
-S0lDQWdJQ0FnSUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldV
-K0NpQWdJQ0FnSUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1G
-dFpUNUZRVkJVZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1Ur
-TWpFOEwxWmhiSFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0Fn
-SUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2
-WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0
-VmpJOEwxWmhiSFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThM
-MDV2WkdVK0NpQWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJ
-Q0FnSUNBZ1BFNXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhi
-V1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQ
-a05sY25ScFptbGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lX
-eDFaVDU0TlRBNWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lD
-QWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1q
-VTJSbWx1WjJWeWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdV
-KwpNV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpG
-bU1XWXhaakZtTVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNB
-OEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNB
-Z0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4
-VG05awpaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFs
-UGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0Fn
-SUNBOEwwNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2
-WkdWT1lXMWxQa1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNk
-V1UrTWpROApMMVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZU
-bTlrWlQ0S0lDQWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQ
-QzlOWjIxMFZISmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94
-LXg1MDktY2EtY2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFD
-UlVkSlRpQkRSVkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtR
-VWxNYkVaa2QzcE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5U
-bFlLUWtGTlZFSXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpU
-azFxV1hkTlZFRTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5V
-VEJGZUUxSlNVSkpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMw
-TkJVVVZCQ25wdVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZY
-TldkVzFFWWxsSWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01T
-dHZSMWhhZGtoM2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJV
-RkRaV1pXYW1vd2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJo
-U1FqZzFNVEpRUWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdK
-ck1IVjVhM1JrWW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtz
-M2FFUTRjRkIyWmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxh
-CmFYQllOREY0UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVX
-TTJreGRIRXdOR3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZH
-U1hkWU5IWnpPRUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFF
-YlVGR1NYZFlOSFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJk
-MFJuCldVUldVVkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldV
-akJVUWtGVmQwRjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZ
-MDVCVVVWTVFsRkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZD
-amxIUlZBdmRXOW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNY
-ZEpWV00zCmQyazNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1Ew
-OTBhWE5rUW5FeWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JX
-MVdUQW94Y1VKS2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVF
-MXVWR3c0ZUVWWFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhw
-aFNFb3hkVlk0Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpG
-S1VDdHNlRllLYlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNS
-a1RrNTJRMWw2YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmts
-RFFWUkZMUzB0TFMwSwotLXtib3VuZGFyeX0tLQo=
+TUlNRS1WZXJzaW9uOiAxLjAKQ29udGVudC1UeXBlOiBtdWx0aXBhcnQvbWl4ZWQ7IGJvdW5kYXJ5
+PXtib3VuZGFyeX07IGNoYXJzZXQ9VVRGLTgKQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogYmFz
+ZTY0CgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXBhc3Nwb2ludC1w
+cm9maWxlOyBjaGFyc2V0PVVURi04CkNvbnRlbnQtVHJhbnNmZXItRW5jb2Rpbmc6IGJhc2U2NAoK
+UEUxbmJYUlVjbVZsSUhodGJHNXpQU0p6ZVc1amJXdzZaRzFrWkdZeExqSWlQZ29nSUR4V1pYSkVW
+RVErTVM0eVBDOVdaWEpFVkVRKwpDaUFnUEU1dlpHVStDaUFnSUNBOFRtOWtaVTVoYldVK1VHVnlV
+SEp2ZG1sa1pYSlRkV0p6WTNKcGNIUnBiMjQ4TDA1dlpHVk9ZVzFsClBnb2dJQ0FnUEZKVVVISnZj
+R1Z5ZEdsbGN6NEtJQ0FnSUNBZ1BGUjVjR1UrQ2lBZ0lDQWdJQ0FnUEVSRVJrNWhiV1UrZFhKdU9u
+ZG0KWVRwdGJ6cG9iM1J6Y0c5ME1tUnZkREF0Y0dWeWNISnZkbWxrWlhKemRXSnpZM0pwY0hScGIy
+NDZNUzR3UEM5RVJFWk9ZVzFsUGdvZwpJQ0FnSUNBOEwxUjVjR1UrQ2lBZ0lDQThMMUpVVUhKdmNH
+VnlkR2xsY3o0S0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBOFRtOWtaVTVoCmJXVSthVEF3TVR3dlRt
+OWtaVTVoYldVK0NpQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJRHhPYjJSbFRtRnRaVDVJYjIx
+bFUxQTgKTDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
+dlpHVk9ZVzFsUGtaeWFXVnVaR3g1VG1GdApaVHd2VG05a1pVNWhiV1UrQ2lBZ0lDQWdJQ0FnSUNB
+OFZtRnNkV1UrUTJWdWRIVnllU0JJYjNWelpUd3ZWbUZzZFdVK0NpQWdJQ0FnCklDQWdQQzlPYjJS
+bFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrWlJSRTQ4
+TDA1dlpHVk8KWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBtMXBOaTVqYnk1MWF6d3ZWbUZz
+ZFdVK0NpQWdJQ0FnSUNBZ1BDOU9iMlJsUGdvZwpJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0Fn
+SUNBZ1BFNXZaR1ZPWVcxbFBsSnZZVzFwYm1kRGIyNXpiM0owYVhWdFQwazhMMDV2ClpHVk9ZVzFs
+UGdvZ0lDQWdJQ0FnSUNBZ1BGWmhiSFZsUGpFeE1qSXpNeXcwTkRVMU5qWThMMVpoYkhWbFBnb2dJ
+Q0FnSUNBZ0lEd3YKVG05a1pUNEtJQ0FnSUNBZ1BDOU9iMlJsUGdvZ0lDQWdJQ0E4VG05a1pUNEtJ
+Q0FnSUNBZ0lDQThUbTlrWlU1aGJXVStRM0psWkdWdQpkR2xoYkR3dlRtOWtaVTVoYldVK0NpQWdJ
+Q0FnSUNBZ1BFNXZaR1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVTVoYldVK1VtVmhiRzA4CkwwNXZa
+R1ZPWVcxbFBnb2dJQ0FnSUNBZ0lDQWdQRlpoYkhWbFBuTm9ZV3RsYmk1emRHbHljbVZrTG1OdmJU
+d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lD
+QWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBsVnpaWEp1WVcxbApVR0Z6YzNkdmNtUThMMDV2WkdWT1lX
+MWxQZ29nSUNBZ0lDQWdJQ0FnUEU1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxUbUZ0ClpU
+NVZjMlZ5Ym1GdFpUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDVxWVcx
+bGN6d3ZWbUZzZFdVK0NpQWcKSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0E4VG05
+a1pUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEU1dlpHVk9ZVzFsUGxCaApjM04zYjNKa1BDOU9iMlJsVG1G
+dFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQbGx0T1hWYVJFRjNUbmM5UFR3dlZtRnNkV1Ur
+CkNpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThUbTlrWlQ0S0lDQWdJQ0Fn
+SUNBZ0lDQWdQRTV2WkdWT1lXMWwKUGtWQlVFMWxkR2h2WkR3dlRtOWtaVTVoYldVK0NpQWdJQ0Fn
+SUNBZ0lDQWdJRHhPYjJSbFBnb2dJQ0FnSUNBZ0lDQWdJQ0FnSUR4TwpiMlJsVG1GdFpUNUZRVkJV
+ZVhCbFBDOU9iMlJsVG1GdFpUNEtJQ0FnSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpFOEwxWmhi
+SFZsClBnb2dJQ0FnSUNBZ0lDQWdJQ0E4TDA1dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmxQ
+Z29nSUNBZ0lDQWdJQ0FnSUNBZ0lEeE8KYjJSbFRtRnRaVDVKYm01bGNrMWxkR2h2WkR3dlRtOWta
+VTVoYldVK0NpQWdJQ0FnSUNBZ0lDQWdJQ0FnUEZaaGJIVmxQazFUTFVOSQpRVkF0VmpJOEwxWmhi
+SFZsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0NpQWdJQ0FnSUNBZ0lDQThMMDV2WkdVK0Np
+QWdJQ0FnCklDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEeE9iMlJsUGdvZ0lDQWdJQ0FnSUNBZ1BF
+NXZaR1ZPWVcxbFBrUnBaMmwwWVd4RFpYSjAKYVdacFkyRjBaVHd2VG05a1pVNWhiV1UrQ2lBZ0lD
+QWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbApQa05sY25ScFpt
+bGpZWFJsVkhsd1pUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0FnSUR4V1lXeDFaVDU0TlRB
+NWRqTThMMVpoCmJIVmxQZ29nSUNBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWdJQ0FnUEU1
+dlpHVStDaUFnSUNBZ0lDQWdJQ0FnSUR4T2IyUmwKVG1GdFpUNURaWEowVTBoQk1qVTJSbWx1WjJW
+eWNISnBiblE4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJQ0FnSUNBZ0lDQThWbUZzZFdVKwpNV1l4WmpG
+bU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZtTVdZeFpqRm1NV1l4WmpGbU1XWXhaakZt
+TVdZeFpqRm1NV1l4ClpqRm1NV1l4Wmp3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZaR1Ur
+Q2lBZ0lDQWdJQ0FnUEM5T2IyUmxQZ29nSUNBZ0lDQWcKSUR4T2IyUmxQZ29nSUNBZ0lDQWdJQ0Fn
+UEU1dlpHVk9ZVzFsUGxOSlRUd3ZUbTlrWlU1aGJXVStDaUFnSUNBZ0lDQWdJQ0E4VG05awpaVDRL
+SUNBZ0lDQWdJQ0FnSUNBZ1BFNXZaR1ZPWVcxbFBrbE5VMGs4TDA1dlpHVk9ZVzFsUGdvZ0lDQWdJ
+Q0FnSUNBZ0lDQThWbUZzCmRXVSthVzF6YVR3dlZtRnNkV1UrQ2lBZ0lDQWdJQ0FnSUNBOEwwNXZa
+R1UrQ2lBZ0lDQWdJQ0FnSUNBOFRtOWtaVDRLSUNBZ0lDQWcKSUNBZ0lDQWdQRTV2WkdWT1lXMWxQ
+a1ZCVUZSNWNHVThMMDV2WkdWT1lXMWxQZ29nSUNBZ0lDQWdJQ0FnSUNBOFZtRnNkV1UrTWpROApM
+MVpoYkhWbFBnb2dJQ0FnSUNBZ0lDQWdQQzlPYjJSbFBnb2dJQ0FnSUNBZ0lEd3ZUbTlrWlQ0S0lD
+QWdJQ0FnUEM5T2IyUmxQZ29nCklDQWdQQzlPYjJSbFBnb2dJRHd2VG05a1pUNEtQQzlOWjIxMFZI
+SmxaVDRLCgotLXtib3VuZGFyeX0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi94LXg1MDktY2Et
+Y2VydApDb250ZW50LVRyYW5zZmVyLUVuY29kaW5nOiBiYXNlNjQKCkxTMHRMUzFDUlVkSlRpQkRS
+VkpVU1VaSlEwRlVSUzB0TFMwdENrMUpTVVJMUkVORFFXaERaMEYzU1VKQlowbEtRVWxNYkVaa2Qz
+cE0KVm5WeVRVRXdSME5UY1VkVFNXSXpSRkZGUWtOM1ZVRk5Ra2w0UlVSQlQwSm5UbFlLUWtGTlZF
+SXdWa0pWUTBKRVVWUkZkMGhvWTA1TgpWRmwzVFZSRmVVMVVSVEZOUkVVeFYyaGpUazFxV1hkTlZF
+RTFUVlJGTVUxRVJURlhha0ZUVFZKQmR3cEVaMWxFVmxGUlJFVjNaRVpSClZrRm5VVEJGZUUxSlNV
+Skpha0ZPUW1kcmNXaHJhVWM1ZHpCQ1FWRkZSa0ZCVDBOQlVUaEJUVWxKUWtOblMwTkJVVVZCQ25w
+dVFWQlYKZWpJMlRYTmhaVFIzY3pRelkzcFNOREV2U2pKUmRISlRTVnBWUzIxV1ZYTldkVzFFWWxs
+SWNsQk9kbFJZUzFOTldFRmpaWGRQVWtSUgpXVmdLVW5GMlNIWndiamhEYzJOQ01TdHZSMWhhZGto
+M2VHbzBlbFl3VjB0dlN6SjZaVmhyWVhVemRtTjViRE5JU1V0MWNFcG1jVEpVClJVRkRaV1pXYW1v
+d2RBcEtWeXRZTXpWUVIxZHdPUzlJTlhwSlZVNVdUbFpxVXpkVmJYTTRORWwyUzJoU1FqZzFNVEpR
+UWpsVmVVaGgKWjFoWlZsZzFSMWR3UVdOV2NIbG1jbXhTQ2taSk9WRmthR2dyVUdKck1IVjVhM1Jr
+WW1ZdlEyUm1aMGhQYjJWaWNsUjBkMUpzYWswdwpiMFIwV0NzeVEzWTJhakIzUWtzM2FFUTRjRkIy
+WmpFcmRYa0tSM3BqZW1sblFWVXZORXQzTjJWYWNYbGtaamxDS3pWU2RYQlNLMGxhCmFYQllOREY0
+UldsSmNrdFNkM0ZwTlRFM1YxZDZXR05xWVVjeVkwNWlaalExTVFwNGNFZzFVRzVXTTJreGRIRXdO
+R3BOUjFGVmVrWjMKU1VSQlVVRkNielJIUVUxSU5IZElVVmxFVmxJd1QwSkNXVVZHU1hkWU5IWnpP
+RUpwUW1OVFkyOWtDalZ1YjFwSVVrMDRSVFFyYVUxRgpTVWRCTVZWa1NYZFJOMDFFYlVGR1NYZFlO
+SFp6T0VKcFFtTlRZMjlrTlc1dldraFNUVGhGTkN0cGIxSmhhMFpFUVZNS1RWSkJkMFJuCldVUldV
+VkZFUlhka1JsRldRV2RSTUVWNFoyZHJRV2QxVlZZelJFMTBWelp6ZDBSQldVUldVakJVUWtGVmQw
+RjNSVUl2ZWtGTVFtZE8KVmdwSVVUaEZRa0ZOUTBGUldYZEVVVmxLUzI5YVNXaDJZMDVCVVVWTVFs
+RkJSR2RuUlVKQlJtWlJjVTlVUVRkU2RqZExLMngxVVRkdwpibUZ6TkVKWmQwaEZDamxIUlZBdmRX
+OW9kalpMVDNrd1ZFZFJSbUp5VWxScVJtOU1WazVDT1VKYU1YbHRUVVJhTUM5VVNYZEpWV00zCmQy
+azNZVGgwTlcxRmNWbElNVFV6ZDFjS1lWZHZiMmxUYW5sTVRHaDFTVFJ6VG5KT1EwOTBhWE5rUW5F
+eWNqSk5SbGgwTm1nd2JVRlIKV1U5UWRqaFNPRXMzTDJablUzaEhSbkY2YUhsT2JXMVdUQW94Y1VK
+S2JHUjRNelJUY0hkelZFRk1VVlpRWWpSb1IzZEtlbHBtY2pGUQpZM0JGVVhnMmVFMXVWR3c0ZUVW
+WFdrVXpUWE01T1hWaFZYaGlVWEZKZDFKMUNreG5RVTlyVGtOdFdUSnRPRGxXYUhwaFNFb3hkVlk0
+Ck5VRmtUUzkwUkN0WmMyMXNibTVxZERsTVVrTmxhbUpDYVhCcVNVZHFUMWh5WnpGS1VDdHNlRllL
+YlhWTk5IWklLMUF2Yld4dGVITlEKVUhvd1pEWTFZaXRGUjIxS1duQnZUR3RQTDNSa1RrNTJRMWw2
+YWtwd1ZFVlhjRVZ6VHpaT1RXaExXVzg5Q2kwdExTMHRSVTVFSUVORgpVbFJKUmtsRFFWUkZMUzB0
+TFMwSwotLXtib3VuZGFyeX0tLQo=
diff --git a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
index 3ddd09f..a44b542 100644
--- a/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
+++ b/wifi/tests/assets/hsr1/HSR1ProfileWithCACert.conf
@@ -1,8 +1,9 @@
-Content-Type: multipart/mixed; boundary={boundary}
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary={boundary}; charset=UTF-8
 Content-Transfer-Encoding: base64
 
 --{boundary}
-Content-Type: application/x-passpoint-profile
+Content-Type: application/x-passpoint-profile; charset=UTF-8
 Content-Transfer-Encoding: base64
 
 PE1nbXRUcmVlIHhtbG5zPSJzeW5jbWw6ZG1kZGYxLjIiPgogIDxWZXJEVEQ+MS4yPC9WZXJEVEQ+
diff --git a/wifi/tests/assets/pps/PerProviderSubscription.xml b/wifi/tests/assets/pps/PerProviderSubscription.xml
index 7f2d95d..1fb8309 100644
--- a/wifi/tests/assets/pps/PerProviderSubscription.xml
+++ b/wifi/tests/assets/pps/PerProviderSubscription.xml
@@ -14,6 +14,13 @@
     <Node>
       <NodeName>i001</NodeName>
       <Node>
+        <NodeName>Extension</NodeName>
+        <Node>
+          <NodeName>VendorSpecific</NodeName>
+          <Value>Test</Value>
+        </Node>
+      </Node>
+      <Node>
         <NodeName>HomeSP</NodeName>
         <Node>
           <NodeName>FriendlyName</NodeName>