Merge "Add strings for IMS Registration error notifications." into lmp-mr1-wfc-dev
automerge: 8b438c8

* commit '8b438c8c1abc3e5e5cce2c9ee22f64c9a5a30290':
  Add strings for IMS Registration error notifications.
diff --git a/Android.mk b/Android.mk
index 3b1991c..81113f7 100644
--- a/Android.mk
+++ b/Android.mk
@@ -386,6 +386,7 @@
 	wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl \
 	wifi/java/android/net/wifi/IWifiScanner.aidl \
 	wifi/java/android/net/wifi/IRttManager.aidl \
+	wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl \
 	packages/services/PacProcessor/com/android/net/IProxyService.aidl \
 	packages/services/Proxy/com/android/net/IProxyCallback.aidl \
 	packages/services/Proxy/com/android/net/IProxyPortListener.aidl \
diff --git a/api/current.txt b/api/current.txt
index 35423fd..ab31f76 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -17867,9 +17867,18 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
+    field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+    field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+    field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+    field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+    field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
     field public java.lang.String SSID;
     field public java.lang.String capabilities;
+    field public int centerFreq0;
+    field public int centerFreq1;
+    field public int channelWidth;
     field public int frequency;
+    field public boolean is80211McRTTResponder;
     field public int level;
     field public long timestamp;
   }
@@ -17907,11 +17916,15 @@
     field public java.util.BitSet allowedKeyManagement;
     field public java.util.BitSet allowedPairwiseCiphers;
     field public java.util.BitSet allowedProtocols;
+    field public int apBand;
+    field public int apChannel;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
     field public int networkId;
     field public java.lang.String preSharedKey;
     field public int priority;
+    field public java.lang.String providerFriendlyName;
+    field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
     field public int status;
     field public java.lang.String[] wepKeys;
     field public int wepTxKeyIndex;
@@ -17969,6 +17982,7 @@
     ctor public WifiEnterpriseConfig();
     ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
     method public int describeContents();
+    method public java.lang.String getAltSubjectMatch();
     method public java.lang.String getAnonymousIdentity();
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate getClientCertificate();
@@ -17976,7 +17990,10 @@
     method public java.lang.String getIdentity();
     method public java.lang.String getPassword();
     method public int getPhase2Method();
-    method public java.lang.String getSubjectMatch();
+    method public java.lang.String getPlmn();
+    method public java.lang.String getRealm();
+    method public deprecated java.lang.String getSubjectMatch();
+    method public void setAltSubjectMatch(java.lang.String);
     method public void setAnonymousIdentity(java.lang.String);
     method public void setCaCertificate(java.security.cert.X509Certificate);
     method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
@@ -17984,7 +18001,9 @@
     method public void setIdentity(java.lang.String);
     method public void setPassword(java.lang.String);
     method public void setPhase2Method(int);
-    method public void setSubjectMatch(java.lang.String);
+    method public void setPlmn(java.lang.String);
+    method public void setRealm(java.lang.String);
+    method public deprecated void setSubjectMatch(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
   }
@@ -25876,6 +25895,8 @@
     field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
     field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
     field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+    field public static final java.lang.String PHONE_ACCOUNT_ID = "phone_account_id";
     field public static final java.lang.String SETTINGS_URI = "settings_uri";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
@@ -25883,8 +25904,13 @@
 
   public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
     method public static android.net.Uri buildSourceUri(java.lang.String);
+    method public static int deleteAll(android.content.Context);
+    method public static android.net.Uri insert(android.content.Context, android.telecom.Voicemail);
+    method public static int insert(android.content.Context, java.util.List<android.telecom.Voicemail>);
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String DIRTY = "dirty";
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
@@ -25892,6 +25918,8 @@
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
     field public static final java.lang.String MIME_TYPE = "mime_type";
     field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+    field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
     field public static final java.lang.String SOURCE_DATA = "source_data";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -28166,8 +28194,81 @@
 
 package android.telecom {
 
+  public class AuthenticatorService extends android.app.Service {
+    ctor public AuthenticatorService();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+  public class AuthenticatorService.Authenticator extends android.accounts.AbstractAccountAuthenticator {
+    ctor public AuthenticatorService.Authenticator(android.content.Context);
+    method public android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+    method public android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public java.lang.String getAuthTokenLabel(java.lang.String);
+    method public android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+  }
+
+  public class PhoneAccount implements android.os.Parcelable {
+    method public static android.telecom.PhoneAccount.Builder builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+    method public android.graphics.drawable.Drawable createIconDrawable(android.content.Context);
+    method public int describeContents();
+    method public android.telecom.PhoneAccountHandle getAccountHandle();
+    method public android.net.Uri getAddress();
+    method public int getCapabilities();
+    method public int getHighlightColor();
+    method public android.graphics.Bitmap getIconBitmap();
+    method public java.lang.String getIconPackageName();
+    method public int getIconResId();
+    method public int getIconTint();
+    method public java.lang.CharSequence getLabel();
+    method public java.lang.CharSequence getShortDescription();
+    method public android.net.Uri getSubscriptionAddress();
+    method public java.util.List<java.lang.String> getSupportedUriSchemes();
+    method public boolean hasCapabilities(int);
+    method public boolean supportsUriScheme(java.lang.String);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
+    field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
+    field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
+    field public static final int NO_ICON_TINT = 0; // 0x0
+    field public static final int NO_RESOURCE_ID = -1; // 0xffffffff
+    field public static final java.lang.String SCHEME_SIP = "sip";
+    field public static final java.lang.String SCHEME_TEL = "tel";
+    field public static final java.lang.String SCHEME_VOICEMAIL = "voicemail";
+  }
+
+  public static class PhoneAccount.Builder {
+    ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
+    ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+    method public android.telecom.PhoneAccount build();
+    method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
+    method public android.telecom.PhoneAccount.Builder setCapabilities(int);
+    method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.content.Context, int, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(java.lang.String, int, int);
+    method public android.telecom.PhoneAccount.Builder setIcon(android.graphics.Bitmap);
+    method public android.telecom.PhoneAccount.Builder setShortDescription(java.lang.CharSequence);
+    method public android.telecom.PhoneAccount.Builder setSubscriptionAddress(android.net.Uri);
+    method public android.telecom.PhoneAccount.Builder setSupportedUriSchemes(java.util.List<java.lang.String>);
+  }
+
+  public class PhoneAccountHandle implements android.os.Parcelable {
+    ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+    method public int describeContents();
+    method public android.content.ComponentName getComponentName();
+    method public java.lang.String getId();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
+  }
+
   public class TelecomManager {
     method public void cancelMissedCallsNotification();
+    method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method public boolean handleMmi(java.lang.String);
     method public boolean isInCall();
     method public void showInCallScreen(boolean);
@@ -28176,7 +28277,10 @@
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecom.extra.CALL_DISCONNECT_CAUSE";
     field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecom.extra.CALL_DISCONNECT_MESSAGE";
+    field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
+    field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -28185,6 +28289,79 @@
     field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
   }
 
+  public class VideoProfile implements android.os.Parcelable {
+    ctor public VideoProfile(int);
+    ctor public VideoProfile(int, int);
+    method public int describeContents();
+    method public int getQuality();
+    method public int getVideoState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+    field public static final int QUALITY_DEFAULT = 4; // 0x4
+    field public static final int QUALITY_HIGH = 1; // 0x1
+    field public static final int QUALITY_LOW = 3; // 0x3
+    field public static final int QUALITY_MEDIUM = 2; // 0x2
+  }
+
+  public static class VideoProfile.VideoState {
+    ctor public VideoProfile.VideoState();
+    method public static boolean isAudioOnly(int);
+    method public static boolean isBidirectional(int);
+    method public static boolean isPaused(int);
+    method public static boolean isReceptionEnabled(int);
+    method public static boolean isTransmissionEnabled(int);
+    field public static final int AUDIO_ONLY = 0; // 0x0
+    field public static final int BIDIRECTIONAL = 3; // 0x3
+    field public static final int PAUSED = 4; // 0x4
+    field public static final int RX_ENABLED = 2; // 0x2
+    field public static final int TX_ENABLED = 1; // 0x1
+  }
+
+  public class Voicemail implements android.os.Parcelable {
+    method public static android.telecom.Voicemail.Builder createForInsertion(long, java.lang.String);
+    method public int describeContents();
+    method public long getDuration();
+    method public long getId();
+    method public java.lang.String getNumber();
+    method public java.lang.String getSourceData();
+    method public java.lang.String getSourcePackage();
+    method public long getTimestampMillis();
+    method public android.net.Uri getUri();
+    method public boolean hasContent();
+    method public boolean isRead();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.Voicemail> CREATOR;
+  }
+
+  public static class Voicemail.Builder {
+    method public android.telecom.Voicemail build();
+    method public android.telecom.Voicemail.Builder setDuration(long);
+    method public android.telecom.Voicemail.Builder setHasContent(boolean);
+    method public android.telecom.Voicemail.Builder setId(long);
+    method public android.telecom.Voicemail.Builder setIsRead(boolean);
+    method public android.telecom.Voicemail.Builder setNumber(java.lang.String);
+    method public android.telecom.Voicemail.Builder setSourceData(java.lang.String);
+    method public android.telecom.Voicemail.Builder setSourcePackage(java.lang.String);
+    method public android.telecom.Voicemail.Builder setTimestamp(long);
+    method public android.telecom.Voicemail.Builder setUri(android.net.Uri);
+  }
+
+  public class VvmSyncService extends android.app.Service {
+    ctor public VvmSyncService();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+  public class VvmSyncService.VvmSyncAdapter extends android.content.AbstractThreadedSyncAdapter {
+    ctor public VvmSyncService.VvmSyncAdapter(android.content.Context, boolean);
+    method protected java.util.List<android.telecom.Voicemail> downloadVoicemails();
+    method public void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult);
+    method protected void syncToServer();
+    field public static final java.lang.String NEW_VOICEMAIL_DATA = "extra_new_voicemail_data";
+    field public static final java.lang.String SYNC_EXTRA_CODE = "sync_extra_code";
+    field public static final int SYNC_EXTRA_MAILBOX_UPDATE = 2; // 0x2
+    field public static final int SYNC_EXTRA_NEW_VOICEMAIL = 1; // 0x1
+  }
+
 }
 
 package android.telephony {
@@ -28378,6 +28555,7 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
+    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
@@ -28394,6 +28572,8 @@
     method public static java.lang.String formatNumberToE164(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
diff --git a/api/system-current.txt b/api/system-current.txt
index 729f656..98105a4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -19294,9 +19294,18 @@
     method public int describeContents();
     method public void writeToParcel(android.os.Parcel, int);
     field public java.lang.String BSSID;
+    field public static final int CHANNEL_WIDTH_160MHZ = 3; // 0x3
+    field public static final int CHANNEL_WIDTH_20MHZ = 0; // 0x0
+    field public static final int CHANNEL_WIDTH_40MHZ = 1; // 0x1
+    field public static final int CHANNEL_WIDTH_80MHZ = 2; // 0x2
+    field public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4; // 0x4
     field public java.lang.String SSID;
     field public java.lang.String capabilities;
+    field public int centerFreq0;
+    field public int centerFreq1;
+    field public int channelWidth;
     field public int frequency;
+    field public boolean is80211McRTTResponder;
     field public int level;
     field public long timestamp;
   }
@@ -19334,6 +19343,8 @@
     field public java.util.BitSet allowedKeyManagement;
     field public java.util.BitSet allowedPairwiseCiphers;
     field public java.util.BitSet allowedProtocols;
+    field public int apBand;
+    field public int apChannel;
     field public int creatorUid;
     field public android.net.wifi.WifiEnterpriseConfig enterpriseConfig;
     field public boolean hiddenSSID;
@@ -19344,6 +19355,8 @@
     field public int numScorerOverrideAndSwitchedNetwork;
     field public java.lang.String preSharedKey;
     field public int priority;
+    field public java.lang.String providerFriendlyName;
+    field public java.util.HashSet<java.lang.Long> roamingConsortiumIds;
     field public int status;
     field public java.lang.String[] wepKeys;
     field public int wepTxKeyIndex;
@@ -19416,6 +19429,7 @@
     ctor public WifiEnterpriseConfig();
     ctor public WifiEnterpriseConfig(android.net.wifi.WifiEnterpriseConfig);
     method public int describeContents();
+    method public java.lang.String getAltSubjectMatch();
     method public java.lang.String getAnonymousIdentity();
     method public java.security.cert.X509Certificate getCaCertificate();
     method public java.security.cert.X509Certificate getClientCertificate();
@@ -19423,7 +19437,10 @@
     method public java.lang.String getIdentity();
     method public java.lang.String getPassword();
     method public int getPhase2Method();
-    method public java.lang.String getSubjectMatch();
+    method public java.lang.String getPlmn();
+    method public java.lang.String getRealm();
+    method public deprecated java.lang.String getSubjectMatch();
+    method public void setAltSubjectMatch(java.lang.String);
     method public void setAnonymousIdentity(java.lang.String);
     method public void setCaCertificate(java.security.cert.X509Certificate);
     method public void setClientKeyEntry(java.security.PrivateKey, java.security.cert.X509Certificate);
@@ -19431,7 +19448,9 @@
     method public void setIdentity(java.lang.String);
     method public void setPassword(java.lang.String);
     method public void setPhase2Method(int);
-    method public void setSubjectMatch(java.lang.String);
+    method public void setPlmn(java.lang.String);
+    method public void setRealm(java.lang.String);
+    method public deprecated void setSubjectMatch(java.lang.String);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.net.wifi.WifiEnterpriseConfig> CREATOR;
   }
@@ -19595,9 +19614,11 @@
     method public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
     method public android.net.wifi.ScanResult[] getScanResults();
     method public void startBackgroundScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
+    method public void startScan(android.net.wifi.WifiScanner.ScanSettings, android.net.wifi.WifiScanner.ScanListener);
     method public void startTrackingBssids(android.net.wifi.WifiScanner.BssidInfo[], int, android.net.wifi.WifiScanner.BssidListener);
     method public void startTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
     method public void stopBackgroundScan(android.net.wifi.WifiScanner.ScanListener);
+    method public void stopScan(android.net.wifi.WifiScanner.ScanListener);
     method public void stopTrackingBssids(android.net.wifi.WifiScanner.BssidListener);
     method public void stopTrackingWifiChange(android.net.wifi.WifiScanner.WifiChangeListener);
     field public static final int MAX_SCAN_PERIOD_MS = 1024000; // 0xfa000
@@ -19634,6 +19655,7 @@
 
   public static abstract interface WifiScanner.BssidListener implements android.net.wifi.WifiScanner.ActionListener {
     method public abstract void onFound(android.net.wifi.ScanResult[]);
+    method public abstract void onLost(android.net.wifi.ScanResult[]);
   }
 
   public static class WifiScanner.ChannelSpec {
@@ -19649,10 +19671,37 @@
     field public android.net.wifi.WifiScanner.BssidInfo[] bssidInfos;
   }
 
+  public static class WifiScanner.ParcelableScanData implements android.os.Parcelable {
+    ctor public WifiScanner.ParcelableScanData(android.net.wifi.WifiScanner.ScanData[]);
+    method public int describeContents();
+    method public android.net.wifi.WifiScanner.ScanData[] getResults();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public android.net.wifi.WifiScanner.ScanData[] mResults;
+  }
+
+  public static class WifiScanner.ParcelableScanResults implements android.os.Parcelable {
+    ctor public WifiScanner.ParcelableScanResults(android.net.wifi.ScanResult[]);
+    method public int describeContents();
+    method public android.net.wifi.ScanResult[] getResults();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public android.net.wifi.ScanResult[] mResults;
+  }
+
+  public static class WifiScanner.ScanData implements android.os.Parcelable {
+    ctor public WifiScanner.ScanData(int, int, android.net.wifi.ScanResult[]);
+    ctor public WifiScanner.ScanData(android.net.wifi.WifiScanner.ScanData);
+    method public int describeContents();
+    method public int getFlags();
+    method public int getId();
+    method public android.net.wifi.ScanResult[] getResults();
+    method public void writeToParcel(android.os.Parcel, int);
+  }
+
   public static abstract interface WifiScanner.ScanListener implements android.net.wifi.WifiScanner.ActionListener {
     method public abstract void onFullResult(android.net.wifi.ScanResult);
     method public abstract void onPeriodChanged(int);
-    method public abstract void onResults(android.net.wifi.ScanResult[]);
+    method public abstract deprecated void onResults(android.net.wifi.ScanResult[]);
+    method public abstract void onResults(android.net.wifi.WifiScanner.ScanData[]);
   }
 
   public static class WifiScanner.ScanSettings implements android.os.Parcelable {
@@ -19661,6 +19710,7 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public int band;
     field public android.net.wifi.WifiScanner.ChannelSpec[] channels;
+    field public int maxScansToCache;
     field public int numBssidsPerScan;
     field public int periodInMs;
     field public int reportEvents;
@@ -27468,6 +27518,8 @@
     field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
     field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
     field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+    field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+    field public static final java.lang.String PHONE_ACCOUNT_ID = "phone_account_id";
     field public static final java.lang.String SETTINGS_URI = "settings_uri";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
@@ -27475,8 +27527,13 @@
 
   public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns android.provider.OpenableColumns {
     method public static android.net.Uri buildSourceUri(java.lang.String);
+    method public static int deleteAll(android.content.Context);
+    method public static android.net.Uri insert(android.content.Context, android.telecom.Voicemail);
+    method public static int insert(android.content.Context, java.util.List<android.telecom.Voicemail>);
     field public static final android.net.Uri CONTENT_URI;
     field public static final java.lang.String DATE = "date";
+    field public static final java.lang.String DELETED = "deleted";
+    field public static final java.lang.String DIRTY = "dirty";
     field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
     field public static final java.lang.String DURATION = "duration";
     field public static final java.lang.String HAS_CONTENT = "has_content";
@@ -27484,6 +27541,8 @@
     field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
     field public static final java.lang.String MIME_TYPE = "mime_type";
     field public static final java.lang.String NUMBER = "number";
+    field public static final java.lang.String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+    field public static final java.lang.String PHONE_ACCOUNT_ID = "subscription_id";
     field public static final java.lang.String SOURCE_DATA = "source_data";
     field public static final java.lang.String SOURCE_PACKAGE = "source_package";
     field public static final java.lang.String TRANSCRIPTION = "transcription";
@@ -29896,6 +29955,22 @@
     field public final int supportedRouteMask;
   }
 
+  public class AuthenticatorService extends android.app.Service {
+    ctor public AuthenticatorService();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+  public class AuthenticatorService.Authenticator extends android.accounts.AbstractAccountAuthenticator {
+    ctor public AuthenticatorService.Authenticator(android.content.Context);
+    method public android.os.Bundle addAccount(android.accounts.AccountAuthenticatorResponse, java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle confirmCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle editProperties(android.accounts.AccountAuthenticatorResponse, java.lang.String);
+    method public android.os.Bundle getAuthToken(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+    method public java.lang.String getAuthTokenLabel(java.lang.String);
+    method public android.os.Bundle hasFeatures(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String[]) throws android.accounts.NetworkErrorException;
+    method public android.os.Bundle updateCredentials(android.accounts.AccountAuthenticatorResponse, android.accounts.Account, java.lang.String, android.os.Bundle) throws android.accounts.NetworkErrorException;
+  }
+
   public final class Call {
     method public void addListener(android.telecom.Call.Listener);
     method public void answer(int);
@@ -30202,10 +30277,14 @@
     method public java.util.List<java.lang.String> getSupportedUriSchemes();
     method public boolean hasCapabilities(int);
     method public boolean supportsUriScheme(java.lang.String);
+    method public android.telecom.PhoneAccount.Builder toBuilder();
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPABILITY_CALL_PROVIDER = 2; // 0x2
     field public static final int CAPABILITY_CONNECTION_MANAGER = 1; // 0x1
+    field public static final int CAPABILITY_MULTI_USER = 32; // 0x20
     field public static final int CAPABILITY_PLACE_EMERGENCY_CALLS = 16; // 0x10
     field public static final int CAPABILITY_SIM_SUBSCRIPTION = 4; // 0x4
+    field public static final int CAPABILITY_VIDEO_CALLING = 8; // 0x8
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccount> CREATOR;
     field public static final int NO_HIGHLIGHT_COLOR = 0; // 0x0
     field public static final int NO_ICON_TINT = 0; // 0x0
@@ -30218,7 +30297,9 @@
   public static class PhoneAccount.Builder {
     ctor public PhoneAccount.Builder(android.telecom.PhoneAccountHandle, java.lang.CharSequence);
     ctor public PhoneAccount.Builder(android.telecom.PhoneAccount);
+    method public android.telecom.PhoneAccount.Builder addSupportedUriScheme(java.lang.String);
     method public android.telecom.PhoneAccount build();
+    method public android.telecom.PhoneAccount.Builder setAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telecom.PhoneAccount.Builder setAddress(android.net.Uri);
     method public android.telecom.PhoneAccount.Builder setCapabilities(int);
     method public android.telecom.PhoneAccount.Builder setHighlightColor(int);
@@ -30234,9 +30315,11 @@
 
   public class PhoneAccountHandle implements android.os.Parcelable {
     ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String);
+    ctor public PhoneAccountHandle(android.content.ComponentName, java.lang.String, android.os.UserHandle);
     method public int describeContents();
     method public android.content.ComponentName getComponentName();
     method public java.lang.String getId();
+    method public android.os.UserHandle getUserHandle();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final android.os.Parcelable.Creator<android.telecom.PhoneAccountHandle> CREATOR;
   }
@@ -30361,6 +30444,7 @@
     method public void unregisterPhoneAccount(android.telecom.PhoneAccountHandle);
     field public static final java.lang.String ACTION_CHANGE_PHONE_ACCOUNTS = "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
     field public static final java.lang.String ACTION_CONNECTION_SERVICE_CONFIGURE = "android.telecom.action.CONNECTION_SERVICE_CONFIGURE";
+    field public static final java.lang.String ACTION_PHONE_ACCOUNT_REGISTERED = "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
     field public static final java.lang.String ACTION_SHOW_CALL_SETTINGS = "android.telecom.action.SHOW_CALL_SETTINGS";
     field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
     field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
@@ -30372,6 +30456,7 @@
     field public static final java.lang.String EXTRA_OUTGOING_CALL_EXTRAS = "android.telecom.extra.OUTGOING_CALL_EXTRAS";
     field public static final java.lang.String EXTRA_PHONE_ACCOUNT_HANDLE = "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
     field public static final java.lang.String EXTRA_START_CALL_WITH_SPEAKERPHONE = "android.telecom.extra.START_CALL_WITH_SPEAKERPHONE";
+    field public static final java.lang.String EXTRA_START_CALL_WITH_VIDEO_STATE = "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
     field public static final java.lang.String GATEWAY_ORIGINAL_ADDRESS = "android.telecom.extra.GATEWAY_ORIGINAL_ADDRESS";
     field public static final java.lang.String GATEWAY_PROVIDER_PACKAGE = "android.telecom.extra.GATEWAY_PROVIDER_PACKAGE";
     field public static final int PRESENTATION_ALLOWED = 1; // 0x1
@@ -30380,6 +30465,79 @@
     field public static final int PRESENTATION_UNKNOWN = 3; // 0x3
   }
 
+  public class VideoProfile implements android.os.Parcelable {
+    ctor public VideoProfile(int);
+    ctor public VideoProfile(int, int);
+    method public int describeContents();
+    method public int getQuality();
+    method public int getVideoState();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.VideoProfile> CREATOR;
+    field public static final int QUALITY_DEFAULT = 4; // 0x4
+    field public static final int QUALITY_HIGH = 1; // 0x1
+    field public static final int QUALITY_LOW = 3; // 0x3
+    field public static final int QUALITY_MEDIUM = 2; // 0x2
+  }
+
+  public static class VideoProfile.VideoState {
+    ctor public VideoProfile.VideoState();
+    method public static boolean isAudioOnly(int);
+    method public static boolean isBidirectional(int);
+    method public static boolean isPaused(int);
+    method public static boolean isReceptionEnabled(int);
+    method public static boolean isTransmissionEnabled(int);
+    field public static final int AUDIO_ONLY = 0; // 0x0
+    field public static final int BIDIRECTIONAL = 3; // 0x3
+    field public static final int PAUSED = 4; // 0x4
+    field public static final int RX_ENABLED = 2; // 0x2
+    field public static final int TX_ENABLED = 1; // 0x1
+  }
+
+  public class Voicemail implements android.os.Parcelable {
+    method public static android.telecom.Voicemail.Builder createForInsertion(long, java.lang.String);
+    method public int describeContents();
+    method public long getDuration();
+    method public long getId();
+    method public java.lang.String getNumber();
+    method public java.lang.String getSourceData();
+    method public java.lang.String getSourcePackage();
+    method public long getTimestampMillis();
+    method public android.net.Uri getUri();
+    method public boolean hasContent();
+    method public boolean isRead();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator<android.telecom.Voicemail> CREATOR;
+  }
+
+  public static class Voicemail.Builder {
+    method public android.telecom.Voicemail build();
+    method public android.telecom.Voicemail.Builder setDuration(long);
+    method public android.telecom.Voicemail.Builder setHasContent(boolean);
+    method public android.telecom.Voicemail.Builder setId(long);
+    method public android.telecom.Voicemail.Builder setIsRead(boolean);
+    method public android.telecom.Voicemail.Builder setNumber(java.lang.String);
+    method public android.telecom.Voicemail.Builder setSourceData(java.lang.String);
+    method public android.telecom.Voicemail.Builder setSourcePackage(java.lang.String);
+    method public android.telecom.Voicemail.Builder setTimestamp(long);
+    method public android.telecom.Voicemail.Builder setUri(android.net.Uri);
+  }
+
+  public class VvmSyncService extends android.app.Service {
+    ctor public VvmSyncService();
+    method public android.os.IBinder onBind(android.content.Intent);
+  }
+
+  public class VvmSyncService.VvmSyncAdapter extends android.content.AbstractThreadedSyncAdapter {
+    ctor public VvmSyncService.VvmSyncAdapter(android.content.Context, boolean);
+    method protected java.util.List<android.telecom.Voicemail> downloadVoicemails();
+    method public void onPerformSync(android.accounts.Account, android.os.Bundle, java.lang.String, android.content.ContentProviderClient, android.content.SyncResult);
+    method protected void syncToServer();
+    field public static final java.lang.String NEW_VOICEMAIL_DATA = "extra_new_voicemail_data";
+    field public static final java.lang.String SYNC_EXTRA_CODE = "sync_extra_code";
+    field public static final int SYNC_EXTRA_MAILBOX_UPDATE = 2; // 0x2
+    field public static final int SYNC_EXTRA_NEW_VOICEMAIL = 1; // 0x1
+  }
+
 }
 
 package android.telephony {
@@ -30573,6 +30731,7 @@
 
   public class PhoneNumberUtils {
     ctor public PhoneNumberUtils();
+    method public static void addPhoneTtsSpan(android.text.Spannable, int, int);
     method public static java.lang.String calledPartyBCDFragmentToString(byte[], int, int);
     method public static java.lang.String calledPartyBCDToString(byte[], int, int);
     method public static boolean compare(java.lang.String, java.lang.String);
@@ -30589,6 +30748,8 @@
     method public static java.lang.String formatNumberToE164(java.lang.String, java.lang.String);
     method public static deprecated int getFormatTypeForLocale(java.util.Locale);
     method public static java.lang.String getNumberFromIntent(android.content.Intent, android.content.Context);
+    method public static android.text.style.TtsSpan getPhoneTtsSpan(java.lang.String);
+    method public static java.lang.CharSequence getPhoneTtsSpannable(java.lang.CharSequence);
     method public static java.lang.String getStrippedReversed(java.lang.String);
     method public static final boolean is12Key(char);
     method public static final boolean isDialable(char);
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index d2a2997..8003afb 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -56,6 +56,30 @@
 
     /**
      * Start the DHCP client daemon, in order to have it request addresses
+     * for the named interface.  This returns {@code true} if the DHCPv4 daemon
+     * starts, {@code false} otherwise.  This call blocks until such time as a
+     * result is available or the default discovery timeout has been reached.
+     * Callers should check {@link #getDhcpResults} to determine whether DHCP
+     * succeeded or failed, and if it succeeded, to fetch the {@link DhcpResults}.
+     * @param interfaceName the name of the interface to configure
+     * @return {@code true} for success, {@code false} for failure
+     */
+    public native static boolean startDhcp(String interfaceName);
+
+    /**
+     * Initiate renewal on the DHCP client daemon for the named interface.  This
+     * returns {@code true} if the DHCPv4 daemon has been notified, {@code false}
+     * otherwise.  This call blocks until such time as a result is available or
+     * the default renew timeout has been reached.  Callers should check
+     * {@link #getDhcpResults} to determine whether DHCP succeeded or failed,
+     * and if it succeeded, to fetch the {@link DhcpResults}.
+     * @param interfaceName the name of the interface to configure
+     * @return {@code true} for success, {@code false} for failure
+     */
+    public native static boolean startDhcpRenew(String interfaceName);
+
+    /**
+     * Start the DHCP client daemon, in order to have it request addresses
      * for the named interface, and then configure the interface with those
      * addresses. This call blocks until it obtains a result (either success
      * or failure) from the daemon.
@@ -64,17 +88,31 @@
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcp(String interfaceName, DhcpResults dhcpResults);
+    public static boolean runDhcp(String interfaceName, DhcpResults dhcpResults) {
+        return startDhcp(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
+    }
 
     /**
-     * Initiate renewal on the Dhcp client daemon. This call blocks until it obtains
+     * Initiate renewal on the DHCP client daemon. This call blocks until it obtains
      * a result (either success or failure) from the daemon.
      * @param interfaceName the name of the interface to configure
      * @param dhcpResults if the request succeeds, this object is filled in with
      * the IP address information.
      * @return {@code true} for success, {@code false} for failure
      */
-    public native static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults);
+    public static boolean runDhcpRenew(String interfaceName, DhcpResults dhcpResults) {
+        return startDhcpRenew(interfaceName) && getDhcpResults(interfaceName, dhcpResults);
+    }
+
+    /**
+     * Fetch results from the DHCP client daemon. This call returns {@code true} if
+     * if there are results available to be read, {@code false} otherwise.
+     * @param interfaceName the name of the interface to configure
+     * @param dhcpResults if the request succeeds, this object is filled in with
+     * the IP address information.
+     * @return {@code true} for success, {@code false} for failure
+     */
+    public native static boolean getDhcpResults(String interfaceName, DhcpResults dhcpResults);
 
     /**
      * Shut down the DHCP client daemon.
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f023df7..2df9dbf 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -33,9 +33,12 @@
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.Data;
 import android.provider.ContactsContract.DataUsageFeedback;
+import android.telecom.PhoneAccount;
 import android.telecom.PhoneAccountHandle;
+import android.telecom.TelecomManager;
 import android.telephony.PhoneNumberUtils;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.android.internal.telephony.CallerInfo;
 import com.android.internal.telephony.PhoneConstants;
@@ -46,6 +49,8 @@
  * The CallLog provider contains information about placed and received calls.
  */
 public class CallLog {
+    private static final String LOG_TAG = "CallLog";
+
     public static final String AUTHORITY = "call_log";
 
     /**
@@ -336,24 +341,44 @@
         // that was encoded into call log databases.
 
         /**
-         * The component name of the account in string form.
+         * The component name of the account used to place or receive the call; in string form.
          * <P>Type: TEXT</P>
          */
         public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
 
         /**
-         * The identifier of a account that is unique to a specified component.
+         * The identifier for the account used to place or receive the call.
          * <P>Type: TEXT</P>
          */
         public static final String PHONE_ACCOUNT_ID = "subscription_id";
 
         /**
-         * The identifier of a account that is unique to a specified component. Equivalent value
-         * to {@link #PHONE_ACCOUNT_ID}. For ContactsProvider internal use only.
+         * The address associated with the account used to place or receive the call; in string
+         * form. For SIM-based calls, this is the user's own phone number.
+         * <P>Type: TEXT</P>
+         *
+         * @hide
+         */
+        public static final String PHONE_ACCOUNT_ADDRESS = "phone_account_address";
+
+        /**
+         * Indicates that the entry will be hidden from all queries until the associated
+         * {@link android.telecom.PhoneAccount} is registered with the system.
          * <P>Type: INTEGER</P>
          *
          * @hide
          */
+        public static final String PHONE_ACCOUNT_HIDDEN = "phone_account_hidden";
+
+        /**
+         * The subscription ID used to place this call.  This is no longer used and has been
+         * replaced with PHONE_ACCOUNT_COMPONENT_NAME/PHONE_ACCOUNT_ID.
+         * For ContactsProvider internal use only.
+         * <P>Type: INTEGER</P>
+         *
+         * @Deprecated
+         * @hide
+         */
         public static final String SUB_ID = "sub_id";
 
         /**
@@ -421,6 +446,29 @@
                 long start, int duration, Long dataUsage, boolean addForAllUsers) {
             final ContentResolver resolver = context.getContentResolver();
             int numberPresentation = PRESENTATION_ALLOWED;
+            boolean isHidden = false;
+
+            TelecomManager tm = null;
+            try {
+                tm = TelecomManager.from(context);
+            } catch (UnsupportedOperationException e) {}
+
+            String accountAddress = null;
+            if (tm != null && accountHandle != null) {
+                PhoneAccount account = tm.getPhoneAccount(accountHandle);
+                if (account != null) {
+                    Uri address = account.getSubscriptionAddress();
+                    if (address != null) {
+                        accountAddress = address.getSchemeSpecificPart();
+                    }
+                } else {
+                    // We could not find the account through telecom. For call log entries that
+                    // are added with a phone account which is not registered, we automatically
+                    // mark them as hidden. They are unhidden once the account is registered.
+                    Log.i(LOG_TAG, "Marking call log entry as hidden.");
+                    isHidden = true;
+                }
+            }
 
             // Remap network specified number presentation types
             // PhoneConstants.PRESENTATION_xxx to calllog number presentation types
@@ -463,6 +511,8 @@
             }
             values.put(PHONE_ACCOUNT_COMPONENT_NAME, accountComponentString);
             values.put(PHONE_ACCOUNT_ID, accountId);
+            values.put(PHONE_ACCOUNT_ADDRESS, accountAddress);
+            values.put(PHONE_ACCOUNT_HIDDEN, Integer.valueOf(isHidden ? 1 : 0));
             values.put(NEW, Integer.valueOf(1));
 
             if (callType == MISSED_TYPE) {
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index d71ad03..03cf6e3 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -19,10 +19,16 @@
 import android.Manifest;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.provider.CallLog.Calls;
+import android.telecom.Voicemail;
+
+import java.util.List;
 
 /**
  * The contract between the voicemail provider and applications. Contains
@@ -199,13 +205,100 @@
          */
         public static final String _DATA = "_data";
 
+        // Note: PHONE_ACCOUNT_* constant values are "subscription_*" due to a historic naming
+        // that was encoded into call log databases.
+
+        /**
+         * The component name of the account in string form.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PHONE_ACCOUNT_COMPONENT_NAME = "subscription_component_name";
+
+        /**
+         * The identifier of a account that is unique to a specified component.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PHONE_ACCOUNT_ID = "subscription_id";
+
+        /**
+         * Flag used to indicate that local, unsynced changes are present.
+         * Currently, this is used to indicate that the voicemail was read or deleted.
+         * The value will be 1 if dirty is true, 0 if false.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String DIRTY = "dirty";
+
+        /**
+         * Flag used to indicate that the voicemail was deleted but not synced to the server.
+         * A deleted row should be ignored.
+         * The value will be 1 if deleted is true, 0 if false.
+         * <P>Type: INTEGER (boolean)</P>
+         */
+        public static final String DELETED = "deleted";
+
         /**
          * A convenience method to build voicemail URI specific to a source package by appending
          * {@link VoicemailContract#PARAM_KEY_SOURCE_PACKAGE} param to the base URI.
          */
         public static Uri buildSourceUri(String packageName) {
             return Voicemails.CONTENT_URI.buildUpon()
-                    .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build();
+                    .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName)
+                    .build();
+        }
+
+        /**
+         * Inserts a new voicemail into the voicemail content provider.
+         *
+         * @param context The context of the app doing the inserting
+         * @param voicemail Data to be inserted
+         * @return {@link Uri} of the newly inserted {@link Voicemail}
+         */
+        public static Uri insert(Context context, Voicemail voicemail) {
+            ContentResolver contentResolver = context.getContentResolver();
+            ContentValues contentValues = getContentValues(voicemail);
+            return contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+        }
+
+        /**
+         * Inserts a list of voicemails into the voicemail content provider.
+         *
+         * @param context The context of the app doing the inserting
+         * @param voicemails Data to be inserted
+         * @return the number of voicemails inserted
+         */
+        public static int insert(Context context, List<Voicemail> voicemails) {
+            ContentResolver contentResolver = context.getContentResolver();
+            int count = voicemails.size();
+            for (int i = 0; i < count; i++) {
+                ContentValues contentValues = getContentValues(voicemails.get(i));
+                contentResolver.insert(Voicemails.CONTENT_URI, contentValues);
+            }
+            return count;
+        }
+
+        /**
+         * Clears all voicemails accessible to this voicemail content provider for the calling
+         * package. By default, a package only has permission to delete voicemails it inserted.
+         *
+         * @return the number of voicemails deleted
+         */
+        public static int deleteAll(Context context) {
+            return context.getContentResolver().delete(
+                    buildSourceUri(context.getPackageName()), "", new String[0]);
+        }
+
+        /**
+         * Maps structured {@link Voicemail} to {@link ContentValues} in content provider.
+         */
+        private static ContentValues getContentValues(Voicemail voicemail) {
+            ContentValues contentValues = new ContentValues();
+            contentValues.put(Voicemails.DATE, String.valueOf(voicemail.getTimestampMillis()));
+            contentValues.put(Voicemails.NUMBER, voicemail.getNumber());
+            contentValues.put(Voicemails.DURATION, String.valueOf(voicemail.getDuration()));
+            contentValues.put(Voicemails.SOURCE_PACKAGE, voicemail.getSourcePackage());
+            contentValues.put(Voicemails.SOURCE_DATA, voicemail.getSourceData());
+            contentValues.put(Voicemails.IS_READ, voicemail.isRead() ? 1 : 0);
+            return contentValues;
         }
     }
 
@@ -222,10 +315,27 @@
         private Status() {
         }
         /**
-         * The package name of the voicemail source. There can only be a one entry per source.
+         * The package name of the voicemail source. There can only be a one entry per account
+         * per source.
          * <P>Type: TEXT</P>
          */
         public static final String SOURCE_PACKAGE = SOURCE_PACKAGE_FIELD;
+
+        // Note: Multiple entries may exist for a single source if they are differentiated by the
+        // PHONE_ACCOUNT_* fields.
+
+        /**
+         * The component name of the account in string form.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PHONE_ACCOUNT_COMPONENT_NAME = "phone_account_component_name";
+
+        /**
+         * The identifier of a account that is unique to a specified component.
+         * <P>Type: TEXT</P>
+         */
+        public static final String PHONE_ACCOUNT_ID = "phone_account_id";
+
         /**
          * The URI to call to invoke source specific voicemail settings screen. On a user request
          * to setup voicemail an intent with action VIEW with this URI will be fired by the system.
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 8b9f574..e64f1de 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -31,27 +31,18 @@
 int ifc_disable(const char *ifname);
 int ifc_reset_connections(const char *ifname, int reset_mask);
 
-int dhcp_do_request(const char * const ifname,
-                    const char *ipaddr,
-                    const char *gateway,
-                    uint32_t *prefixLength,
-                    const char *dns[],
-                    const char *server,
-                    uint32_t *lease,
-                    const char *vendorInfo,
-                    const char *domains,
-                    const char *mtu);
-
-int dhcp_do_request_renew(const char * const ifname,
-                    const char *ipaddr,
-                    const char *gateway,
-                    uint32_t *prefixLength,
-                    const char *dns[],
-                    const char *server,
-                    uint32_t *lease,
-                    const char *vendorInfo,
-                    const char *domains,
-                    const char *mtu);
+int dhcp_start(const char * const ifname);
+int dhcp_start_renew(const char * const ifname);
+int dhcp_get_results(const char * const ifname,
+                     const char *ipaddr,
+                     const char *gateway,
+                     uint32_t *prefixLength,
+                     const char *dns[],
+                     const char *server,
+                     uint32_t *lease,
+                     const char *vendorInfo,
+                     const char *domains,
+                     const char *mtu);
 
 int dhcp_stop(const char *ifname);
 int dhcp_release_lease(const char *ifname);
@@ -93,8 +84,8 @@
     return (jint)result;
 }
 
-static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstring ifname,
-        jobject dhcpResults, bool renew)
+static jboolean android_net_utils_getDhcpResults(JNIEnv* env, jobject clazz, jstring ifname,
+        jobject dhcpResults)
 {
     int result;
     char  ipaddr[PROPERTY_VALUE_MAX];
@@ -114,15 +105,10 @@
     const char *nameStr = env->GetStringUTFChars(ifname, NULL);
     if (nameStr == NULL) return (jboolean)false;
 
-    if (renew) {
-        result = ::dhcp_do_request_renew(nameStr, ipaddr, gateway, &prefixLength,
-                dns, server, &lease, vendorInfo, domains, mtu);
-    } else {
-        result = ::dhcp_do_request(nameStr, ipaddr, gateway, &prefixLength,
-                dns, server, &lease, vendorInfo, domains, mtu);
-    }
+    result = ::dhcp_get_results(nameStr, ipaddr, gateway, &prefixLength,
+            dns, server, &lease, vendorInfo, domains, mtu);
     if (result != 0) {
-        ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new");
+        ALOGD("dhcp_get_results failed : %s (%s)", nameStr);
     }
 
     env->ReleaseStringUTFChars(ifname, nameStr);
@@ -182,19 +168,28 @@
     return (jboolean)(result == 0);
 }
 
-
-static jboolean android_net_utils_runDhcp(JNIEnv* env, jobject clazz, jstring ifname, jobject info)
+static jboolean android_net_utils_startDhcp(JNIEnv* env, jobject clazz, jstring ifname)
 {
-    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, false);
+    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
+    if (nameStr == NULL) return (jboolean)false;
+    if (::dhcp_start(nameStr) != 0) {
+        ALOGD("dhcp_start failed : %s", nameStr);
+        return (jboolean)false;
+    }
+    return (jboolean)true;
 }
 
-static jboolean android_net_utils_runDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname,
-        jobject info)
+static jboolean android_net_utils_startDhcpRenew(JNIEnv* env, jobject clazz, jstring ifname)
 {
-    return android_net_utils_runDhcpCommon(env, clazz, ifname, info, true);
+    const char *nameStr = env->GetStringUTFChars(ifname, NULL);
+    if (nameStr == NULL) return (jboolean)false;
+    if (::dhcp_start_renew(nameStr) != 0) {
+        ALOGD("dhcp_start_renew failed : %s", nameStr);
+        return (jboolean)false;
+    }
+    return (jboolean)true;
 }
 
-
 static jboolean android_net_utils_stopDhcp(JNIEnv* env, jobject clazz, jstring ifname)
 {
     int result;
@@ -255,8 +250,9 @@
 static JNINativeMethod gNetworkUtilMethods[] = {
     /* name, signature, funcPtr */
     { "resetConnections", "(Ljava/lang/String;I)I",  (void *)android_net_utils_resetConnections },
-    { "runDhcp", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcp },
-    { "runDhcpRenew", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_runDhcpRenew },
+    { "startDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_startDhcp },
+    { "startDhcpRenew", "(Ljava/lang/String;)Z",  (void *)android_net_utils_startDhcpRenew },
+    { "getDhcpResults", "(Ljava/lang/String;Landroid/net/DhcpResults;)Z",  (void *)android_net_utils_getDhcpResults },
     { "stopDhcp", "(Ljava/lang/String;)Z",  (void *)android_net_utils_stopDhcp },
     { "releaseDhcpLease", "(Ljava/lang/String;)Z",  (void *)android_net_utils_releaseDhcpLease },
     { "getDhcpError", "()Ljava/lang/String;", (void*) android_net_utils_getDhcpError },
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 81db6c5..7633950 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3828,10 +3828,10 @@
     </plurals>
 
     <!-- A notification is shown when a wifi captive portal network is detected.  This is the notification's title. -->
-    <string name="wifi_available_sign_in">Sign into Wi-Fi network</string>
+    <string name="wifi_available_sign_in">Sign in to Wi-Fi network</string>
 
     <!-- A notification is shown when a captive portal network is detected.  This is the notification's title. -->
-    <string name="network_available_sign_in">Sign into network</string>
+    <string name="network_available_sign_in">Sign in to network</string>
 
     <!-- A notification is shown when a captive portal network is detected.  This is the notification's message. -->
     <string name="network_available_sign_in_detailed"><xliff:g id="network_ssid">%1$s</xliff:g></string>
diff --git a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
index 687a14e..bfda753 100644
--- a/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rGB/strings.xml
@@ -4,5 +4,5 @@
     <string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
     <string name="action_use_network" msgid="6076184727448466030">"Use this network as is"</string>
     <string name="action_do_not_use_network" msgid="4577366536956516683">"Do not use this network"</string>
-    <string name="action_bar_label" msgid="2573986763322074279">"Sign-in to network"</string>
+    <string name="action_bar_label" msgid="2573986763322074279">"Sign in to network"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
index 687a14e..bfda753 100644
--- a/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
+++ b/packages/CaptivePortalLogin/res/values-en-rIN/strings.xml
@@ -4,5 +4,5 @@
     <string name="app_name" msgid="5934709770924185752">"CaptivePortalLogin"</string>
     <string name="action_use_network" msgid="6076184727448466030">"Use this network as is"</string>
     <string name="action_do_not_use_network" msgid="4577366536956516683">"Do not use this network"</string>
-    <string name="action_bar_label" msgid="2573986763322074279">"Sign-in to network"</string>
+    <string name="action_bar_label" msgid="2573986763322074279">"Sign in to network"</string>
 </resources>
diff --git a/packages/CaptivePortalLogin/res/values/strings.xml b/packages/CaptivePortalLogin/res/values/strings.xml
index 1b0f0a4..8348be9 100644
--- a/packages/CaptivePortalLogin/res/values/strings.xml
+++ b/packages/CaptivePortalLogin/res/values/strings.xml
@@ -4,6 +4,6 @@
     <string name="app_name">CaptivePortalLogin</string>
     <string name="action_use_network">Use this network as is</string>
     <string name="action_do_not_use_network">Do not use this network</string>
-    <string name="action_bar_label">Sign-in to network</string>
+    <string name="action_bar_label">Sign in to network</string>
 
 </resources>
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 8c56c8c..0437a2a 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1374,7 +1374,8 @@
                 mConnector.execute("softap", "set", wlanIface);
             } else {
                 mConnector.execute("softap", "set", wlanIface, wifiConfig.SSID,
-                                   "broadcast", "6", getSecurityType(wifiConfig),
+                                   "broadcast", Integer.toString(wifiConfig.apChannel),
+                                   getSecurityType(wifiConfig),
                                    new SensitiveArg(wifiConfig.preSharedKey));
             }
             mConnector.execute("softap", "startap");
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index 64a67fc..22fee22 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -63,7 +63,7 @@
 
     private static final ComponentName SERVICE_COMPONENT = new ComponentName(
             "com.android.server.telecom",
-            "com.android.server.telecom.TelecomService");
+            "com.android.server.telecom.components.TelecomService");
 
     private static final String SERVICE_ACTION = "com.android.ITelecomService";
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 334cdf6..0705fbd 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -677,7 +677,8 @@
 
                 mSystemServiceManager.startService("com.android.server.wifi.RttService");
 
-                if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) {
+                if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) ||
+                    mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) {
                     mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS);
                 }
 
diff --git a/telecomm/java/android/telecom/AuthenticatorService.java b/telecomm/java/android/telecom/AuthenticatorService.java
new file mode 100644
index 0000000..39717c3
--- /dev/null
+++ b/telecomm/java/android/telecom/AuthenticatorService.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2015 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.telecom;
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.Account;
+import android.accounts.AccountAuthenticatorResponse;
+import android.accounts.NetworkErrorException;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+
+/**
+ * A generic stub account authenticator service often used for sync adapters that do not directly
+ * involve accounts.
+ */
+public class AuthenticatorService extends Service {
+    private static Authenticator mAuthenticator;
+
+    @Override
+    public void onCreate() {
+        mAuthenticator = new Authenticator(this);
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mAuthenticator.getIBinder();
+    }
+
+    /**
+     * Stub account authenticator. All methods either return null or throw an exception.
+     */
+    public class Authenticator extends AbstractAccountAuthenticator {
+        public Authenticator(Context context) {
+            super(context);
+        }
+
+        @Override
+        public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                     String s) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Bundle addAccount(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                 String s, String s2, String[] strings, Bundle bundle)
+                throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                         Account account, Bundle bundle)
+                throws NetworkErrorException {
+            return null;
+        }
+
+        @Override
+        public Bundle getAuthToken(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                   Account account, String s, Bundle bundle)
+                throws NetworkErrorException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String getAuthTokenLabel(String s) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                        Account account, String s, Bundle bundle)
+                throws NetworkErrorException {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse,
+                                  Account account, String[] strings)
+                throws NetworkErrorException {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java
index 052a481..a94c2f6 100644
--- a/telecomm/java/android/telecom/PhoneAccount.java
+++ b/telecomm/java/android/telecom/PhoneAccount.java
@@ -40,15 +40,13 @@
 /**
  * Represents a distinct method to place or receive a phone call. Apps which can place calls and
  * want those calls to be integrated into the dialer and in-call UI should build an instance of
- * this class and register it with the system using {@link TelecomManager#registerPhoneAccount}.
+ * this class and register it with the system using {@link TelecomManager}.
  * <p>
  * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
  * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
- * should supply a valid {@link PhoneAccountHandle} that references the {@link ConnectionService}
+ * should supply a valid {@link PhoneAccountHandle} that references the connection service
  * implementation Telecom will use to interact with the app.
- * @hide
  */
-@SystemApi
 public class PhoneAccount implements Parcelable {
 
     /**
@@ -62,7 +60,9 @@
      * if the user has explicitly selected it to be used as the default connection manager.
      * <p>
      * See {@link #getCapabilities}
+     * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_CONNECTION_MANAGER = 0x1;
 
     /**
@@ -76,6 +76,7 @@
      * <p>
      * {@hide}
      */
+    @SystemApi
     public static final int CAPABILITY_CALL_PROVIDER = 0x2;
 
     /**
@@ -94,6 +95,7 @@
      * See {@link #getCapabilities}
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_VIDEO_CALLING = 0x8;
 
     /**
@@ -111,6 +113,7 @@
      * See {@link #getCapabilities}
      * @hide
      */
+    @SystemApi
     public static final int CAPABILITY_MULTI_USER = 0x20;
 
     /**
@@ -203,6 +206,7 @@
         }
 
         /** @hide */
+        @SystemApi
         public Builder setAccountHandle(PhoneAccountHandle accountHandle) {
             mAccountHandle = accountHandle;
             return this;
@@ -333,6 +337,7 @@
          * @return The builder.
          * @hide
          */
+        @SystemApi
         public Builder addSupportedUriScheme(String uriScheme) {
             if (!TextUtils.isEmpty(uriScheme) && !mSupportedUriSchemes.contains(uriScheme)) {
                 this.mSupportedUriSchemes.add(uriScheme);
@@ -423,6 +428,7 @@
      * @return The builder.
      * @hide
      */
+    @SystemApi
     public Builder toBuilder() { return new Builder(this); }
 
     /**
diff --git a/telecomm/java/android/telecom/PhoneAccountHandle.java b/telecomm/java/android/telecom/PhoneAccountHandle.java
index 97af41a..4600b72 100644
--- a/telecomm/java/android/telecom/PhoneAccountHandle.java
+++ b/telecomm/java/android/telecom/PhoneAccountHandle.java
@@ -29,16 +29,13 @@
  * The unique identifier for a {@link PhoneAccount}. A {@code PhoneAccountHandle} is made of two
  * parts:
  * <ul>
- *  <li>The component name of the associated {@link ConnectionService}.</li>
+ *  <li>The component name of the associated connection service.</li>
  *  <li>A string identifier that is unique across {@code PhoneAccountHandle}s with the same
  *      component name.</li>
  * </ul>
  *
- * See {@link PhoneAccount},
- * {@link TelecomManager#registerPhoneAccount TelecomManager.registerPhoneAccount}.
- * @hide
+ * See {@link PhoneAccount}, {@link TelecomManager}.
  */
-@SystemApi
 public class PhoneAccountHandle implements Parcelable {
     private final ComponentName mComponentName;
     private final String mId;
@@ -51,6 +48,7 @@
     }
 
     /** @hide */
+    @SystemApi
     public PhoneAccountHandle(
             ComponentName componentName,
             String id,
@@ -61,8 +59,8 @@
     }
 
     /**
-     * The {@code ComponentName} of the {@link android.telecom.ConnectionService} which is
-     * responsible for making phone calls using this {@code PhoneAccountHandle}.
+     * The {@code ComponentName} of the connection service which is responsible for making phone
+     * calls using this {@code PhoneAccountHandle}.
      *
      * @return A suitable {@code ComponentName}.
      */
@@ -72,9 +70,9 @@
 
     /**
      * A string that uniquely distinguishes this particular {@code PhoneAccountHandle} from all the
-     * others supported by the {@link ConnectionService} that created it.
+     * others supported by the connection service that created it.
      * <p>
-     * A {@code ConnectionService} must select identifiers that are stable for the lifetime of
+     * A connection service must select identifiers that are stable for the lifetime of
      * their users' relationship with their service, across many Android devices. For example, a
      * good set of identifiers might be the email addresses with which with users registered for
      * their accounts with a particular service. Depending on how a service chooses to operate,
@@ -82,6 +80,9 @@
      * ({@code 0}, {@code 1}, {@code 2}, ...) that are generated locally on each phone and could
      * collide with values generated on other phones or after a data wipe of a given phone.
      *
+     * Important: A non-unique identifier could cause non-deterministic call-log backup/restore
+     * behavior.
+     *
      * @return A service-specific unique identifier for this {@code PhoneAccountHandle}.
      */
     public String getId() {
@@ -92,6 +93,7 @@
      * @return the {@link UserHandle} to use when connecting to this PhoneAccount.
      * @hide
      */
+    @SystemApi
     public UserHandle getUserHandle() {
         return mUserHandle;
     }
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 1a6b292..8be3e66 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -92,6 +92,15 @@
             "android.telecom.action.CHANGE_PHONE_ACCOUNTS";
 
     /**
+     * The {@link android.content.Intent} action used indicate that a new phone account was
+     * just registered.
+     * @hide
+     */
+    @SystemApi
+    public static final String ACTION_PHONE_ACCOUNT_REGISTERED =
+            "android.telecom.action.PHONE_ACCOUNT_REGISTERED";
+
+    /**
      * Optional extra for {@link android.content.Intent#ACTION_CALL} containing a boolean that
      * determines whether the speakerphone should be automatically turned on for an outgoing call.
      */
@@ -106,7 +115,6 @@
      * {@link VideoProfile.VideoState#BIDIRECTIONAL},
      * {@link VideoProfile.VideoState#RX_ENABLED},
      * {@link VideoProfile.VideoState#TX_ENABLED}.
-     * @hide
      */
     public static final String EXTRA_START_CALL_WITH_VIDEO_STATE =
             "android.telecom.extra.START_CALL_WITH_VIDEO_STATE";
@@ -117,9 +125,7 @@
      * {@link PhoneAccountHandle} to use when making the call.
      * <p class="note">
      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}.
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_PHONE_ACCOUNT_HANDLE =
             "android.telecom.extra.PHONE_ACCOUNT_HANDLE";
 
@@ -139,10 +145,7 @@
      * {@link android.content.Intent#ACTION_DIAL} {@code Intent} containing a {@link Bundle}
      * which contains metadata about the call. This {@link Bundle} will be saved into
      * {@code Call.Details}.
-     *
-     * @hide
      */
-    @SystemApi
     public static final String EXTRA_OUTGOING_CALL_EXTRAS =
             "android.telecom.extra.OUTGOING_CALL_EXTRAS";
 
@@ -554,9 +557,7 @@
      *
      * @param account The {@link PhoneAccountHandle}.
      * @return The {@link PhoneAccount} object.
-     * @hide
      */
-    @SystemApi
     public PhoneAccount getPhoneAccount(PhoneAccountHandle account) {
         try {
             if (isServiceConnected()) {
diff --git a/telecomm/java/android/telecom/VideoProfile.java b/telecomm/java/android/telecom/VideoProfile.java
index f5cb054..e62e994 100644
--- a/telecomm/java/android/telecom/VideoProfile.java
+++ b/telecomm/java/android/telecom/VideoProfile.java
@@ -21,8 +21,6 @@
 
 /**
  * Represents attributes of video calls.
- *
- * {@hide}
  */
 public class VideoProfile implements Parcelable {
     /**
diff --git a/telecomm/java/android/telecom/Voicemail.java b/telecomm/java/android/telecom/Voicemail.java
new file mode 100644
index 0000000..864c6b1
--- /dev/null
+++ b/telecomm/java/android/telecom/Voicemail.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2015 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.telecom;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a single voicemail stored in the voicemail content provider.
+ */
+public class Voicemail implements Parcelable {
+    private final Long mTimestamp;
+    private final String mNumber;
+    private final Long mId;
+    private final Long mDuration;
+    private final String mSource;
+    private final String mProviderData;
+    private final Uri mUri;
+    private final Boolean mIsRead;
+    private final Boolean mHasContent;
+
+    private Voicemail(Long timestamp, String number, Long id, Long duration, String source,
+            String providerData, Uri uri, Boolean isRead, Boolean hasContent) {
+        mTimestamp = timestamp;
+        mNumber = number;
+        mId = id;
+        mDuration = duration;
+        mSource = source;
+        mProviderData = providerData;
+        mUri = uri;
+        mIsRead = isRead;
+        mHasContent = hasContent;
+    }
+
+    /**
+     * Create a {@link Builder} for a new {@link Voicemail} to be inserted.
+     * <p>
+     * The number and the timestamp are mandatory for insertion.
+     */
+    public static Builder createForInsertion(long timestamp, String number) {
+        return new Builder().setNumber(number).setTimestamp(timestamp);
+    }
+
+    /**
+     * Builder pattern for creating a {@link Voicemail}. The builder must be created with the
+     * {@link #createForInsertion(long, String)} method.
+     * <p>
+     * This class is <b>not thread safe</b>
+     */
+    public static class Builder {
+        private Long mBuilderTimestamp;
+        private String mBuilderNumber;
+        private Long mBuilderId;
+        private Long mBuilderDuration;
+        private String mBuilderSourcePackage;
+        private String mBuilderSourceData;
+        private Uri mBuilderUri;
+        private Boolean mBuilderIsRead;
+        private boolean mBuilderHasContent;
+
+        /** You should use the correct factory method to construct a builder. */
+        private Builder() {
+        }
+
+        public Builder setNumber(String number) {
+            mBuilderNumber = number;
+            return this;
+        }
+
+        public Builder setTimestamp(long timestamp) {
+            mBuilderTimestamp = timestamp;
+            return this;
+        }
+
+        public Builder setId(long id) {
+            mBuilderId = id;
+            return this;
+        }
+
+        public Builder setDuration(long duration) {
+            mBuilderDuration = duration;
+            return this;
+        }
+
+        public Builder setSourcePackage(String sourcePackage) {
+            mBuilderSourcePackage = sourcePackage;
+            return this;
+        }
+
+        public Builder setSourceData(String sourceData) {
+            mBuilderSourceData = sourceData;
+            return this;
+        }
+
+        public Builder setUri(Uri uri) {
+            mBuilderUri = uri;
+            return this;
+        }
+
+        public Builder setIsRead(boolean isRead) {
+            mBuilderIsRead = isRead;
+            return this;
+        }
+
+        public Builder setHasContent(boolean hasContent) {
+            mBuilderHasContent = hasContent;
+            return this;
+        }
+
+        public Voicemail build() {
+            mBuilderId = mBuilderId == null ? -1 : mBuilderId;
+            mBuilderTimestamp = mBuilderTimestamp == null ? 0 : mBuilderTimestamp;
+            mBuilderDuration = mBuilderDuration == null ? 0: mBuilderDuration;
+            mBuilderIsRead = mBuilderIsRead == null ? false : mBuilderIsRead;
+            return new Voicemail(mBuilderTimestamp, mBuilderNumber, mBuilderId, mBuilderDuration,
+                    mBuilderSourcePackage, mBuilderSourceData, mBuilderUri, mBuilderIsRead,
+                    mBuilderHasContent);
+        }
+    }
+
+    /**
+     * The identifier of the voicemail in the content provider.
+     * <p>
+     * This may be missing in the case of a new {@link Voicemail} that we plan to insert into the
+     * content provider, since until it has been inserted we don't know what id it should have. If
+     * none is specified, we return -1.
+     */
+    public long getId() {
+        return mId;
+    }
+
+    /** The number of the person leaving the voicemail, empty string if unknown, null if not set. */
+    public String getNumber() {
+        return mNumber;
+    }
+
+    /** The timestamp the voicemail was received, in millis since the epoch, zero if not set. */
+    public long getTimestampMillis() {
+        return mTimestamp;
+    }
+
+    /** Gets the duration of the voicemail in millis, or zero if the field is not set. */
+    public long getDuration() {
+        return mDuration;
+    }
+
+    /**
+     * Returns the package name of the source that added this voicemail, or null if this field is
+     * not set.
+     */
+    public String getSourcePackage() {
+        return mSource;
+    }
+
+    /**
+     * Returns the application-specific data type stored with the voicemail, or null if this field
+     * is not set.
+     * <p>
+     * Source data is typically used as an identifier to uniquely identify the voicemail against
+     * the voicemail server. This is likely to be something like the IMAP UID, or some other
+     * server-generated identifying string.
+     */
+    public String getSourceData() {
+        return mProviderData;
+    }
+
+    /**
+     * Gets the Uri that can be used to refer to this voicemail, and to make it play.
+     * <p>
+     * Returns null if we don't know the Uri.
+     */
+    public Uri getUri() {
+        return mUri;
+    }
+
+    /**
+     * Tells us if the voicemail message has been marked as read.
+     * <p>
+     * Always returns false if this field has not been set, i.e. if hasRead() returns false.
+     */
+    public boolean isRead() {
+        return mIsRead;
+    }
+
+    /**
+     * Tells us if there is content stored at the Uri.
+     */
+    public boolean hasContent() {
+        return mHasContent;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(mTimestamp);
+        dest.writeCharSequence(mNumber);
+        dest.writeLong(mId);
+        dest.writeLong(mDuration);
+        dest.writeCharSequence(mSource);
+        dest.writeCharSequence(mProviderData);
+        if (mUri == null) {
+            dest.writeInt(0);
+        } else {
+            dest.writeInt(1);
+            mUri.writeToParcel(dest, flags);
+        }
+        if (mIsRead) {
+            dest.writeInt(1);
+        } else {
+            dest.writeInt(0);
+        }
+        if (mHasContent) {
+            dest.writeInt(1);
+        } else {
+            dest.writeInt(0);
+        }
+    }
+
+    public static final Creator<Voicemail> CREATOR
+            = new Creator<Voicemail>() {
+        @Override
+        public Voicemail createFromParcel(Parcel in) {
+            return new Voicemail(in);
+        }
+
+        @Override
+        public Voicemail[] newArray(int size) {
+            return new Voicemail[size];
+        }
+    };
+
+    private Voicemail(Parcel in) {
+        mTimestamp = in.readLong();
+        mNumber = (String) in.readCharSequence();
+        mId = in.readLong();
+        mDuration = in.readLong();
+        mSource = (String) in.readCharSequence();
+        mProviderData = (String) in.readCharSequence();
+        if (in.readInt() > 0) {
+            mUri = Uri.CREATOR.createFromParcel(in);
+        } else {
+            mUri = null;
+        }
+        mIsRead = in.readInt() > 0 ? true : false;
+        mHasContent = in.readInt() > 0 ? true : false;
+    }
+}
\ No newline at end of file
diff --git a/telecomm/java/android/telecom/VvmSyncService.java b/telecomm/java/android/telecom/VvmSyncService.java
new file mode 100644
index 0000000..2aaf348
--- /dev/null
+++ b/telecomm/java/android/telecom/VvmSyncService.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2015 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
+ */
+
+/**
+ * A {@link Service} which runs the internal implementation of {@link AbstractThreadedSyncAdapter},
+ * syncing voicemails to and from a visual voicemail server.
+ */
+
+package android.telecom;
+
+import android.accounts.Account;
+import android.app.Service;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentProviderClient;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.SyncResult;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.provider.VoicemailContract;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A service to run the VvmSyncAdapter.
+ */
+public class VvmSyncService extends Service {
+    // Storage for an instance of the sync adapter
+    private static VvmSyncAdapter sSyncAdapter = null;
+    // Object to use as a thread-safe lock
+    private static final Object sSyncAdapterLock = new Object();
+
+    @Override
+    public void onCreate() {
+        synchronized (sSyncAdapterLock) {
+            if (sSyncAdapter == null) {
+                sSyncAdapter = new VvmSyncAdapter(getApplicationContext(), true);
+            }
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return sSyncAdapter.getSyncAdapterBinder();
+    }
+
+    public class VvmSyncAdapter extends AbstractThreadedSyncAdapter {
+        /** The key to get the extra designating the type of sync action to perform. */
+        public final static String SYNC_EXTRA_CODE = "sync_extra_code";
+        /** The key to get the {@code Voicemail} object for a new voicemail. */
+        public final static String NEW_VOICEMAIL_DATA = "extra_new_voicemail_data";
+        /** Sync a new voicemail from the carrier to the device. */
+        public final static int SYNC_EXTRA_NEW_VOICEMAIL = 1;
+        /** Sync all voicemails because the mailbox was changed remotely. */
+        public final static int SYNC_EXTRA_MAILBOX_UPDATE = 2;
+
+        private final Context mContext;
+
+        public VvmSyncAdapter(Context context, boolean autoInitialize) {
+            super(context, autoInitialize);
+            mContext = context;
+        }
+
+        @Override
+        public void onPerformSync(Account account, Bundle extras, String authority,
+                ContentProviderClient provider, SyncResult syncResult) {
+            if (extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false)) {
+                // notify server that voicemail has been changed
+                syncToServer();
+            }
+
+            final int syncAction = extras.getInt(SYNC_EXTRA_CODE);
+            switch (syncAction) {
+                /** sync from carrier */
+                case SYNC_EXTRA_NEW_VOICEMAIL:
+                    // Log new voicemail in voicemail provider.
+                    Voicemail newVoicemail = extras.getParcelable(NEW_VOICEMAIL_DATA);
+                    VoicemailContract.Voicemails.insert(mContext, newVoicemail);
+                    break;
+                case SYNC_EXTRA_MAILBOX_UPDATE:
+                    // Clear and reload all voicemails because the mailbox was updated remotely.
+                    VoicemailContract.Voicemails.deleteAll(mContext);
+                    List<Voicemail> voicemails = downloadVoicemails();
+                    VoicemailContract.Voicemails.insert(mContext, voicemails);
+                    break;
+                 default:
+                     break;
+            }
+        }
+
+        /** Subclasses should implement this method to sync changes to server */
+        protected void syncToServer() { }
+
+        /** Subclasses should implement this method to download voicemails */
+        protected List<Voicemail> downloadVoicemails() {
+            return new ArrayList<Voicemail>();
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index c043659..3572846 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -34,11 +34,11 @@
 import android.text.Spannable;
 import android.text.SpannableStringBuilder;
 import android.text.TextUtils;
-import android.telephony.Rlog;
 import android.text.style.TtsSpan;
 import android.util.SparseIntArray;
 
-import static com.android.internal.telephony.PhoneConstants.SUBSCRIPTION_KEY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
+import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_OPERATOR_IDP_STRING;
 
 import java.util.Locale;
@@ -2311,15 +2311,13 @@
      *
      * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
      * @return A {@code CharSequence} with appropriate annotations.
-     *
-     * @hide
      */
-    public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+    public static CharSequence getPhoneTtsSpannable(CharSequence phoneNumber) {
         if (phoneNumber == null) {
             return null;
         }
         Spannable spannable = Spannable.Factory.getInstance().newSpannable(phoneNumber);
-        PhoneNumberUtils.ttsSpanAsPhoneNumber(spannable, 0, spannable.length());
+        PhoneNumberUtils.addPhoneTtsSpan(spannable, 0, spannable.length());
         return spannable;
     }
 
@@ -2330,19 +2328,83 @@
      * @param s A {@code Spannable} to annotate.
      * @param start The starting character position of the phone number in {@code s}.
      * @param end The ending character position of the phone number in {@code s}.
-     *
-     * @hide
      */
-    public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
-        s.setSpan(
-                new TtsSpan.TelephoneBuilder()
-                        .setNumberParts(splitAtNonNumerics(s.subSequence(start, end)))
-                        .build(),
+    public static void addPhoneTtsSpan(Spannable s, int start, int end) {
+        s.setSpan(getPhoneTtsSpan(s.subSequence(start, end).toString()),
                 start,
                 end,
                 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
     }
 
+    /**
+     * Wrap the supplied {@code CharSequence} with a {@code TtsSpan}, annotating it as
+     * containing a phone number in its entirety.
+     *
+     * @param phoneNumber A {@code CharSequence} the entirety of which represents a phone number.
+     * @return A {@code CharSequence} with appropriate annotations.
+     * @deprecated Renamed {@link #getPhoneTtsSpannable}.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static CharSequence ttsSpanAsPhoneNumber(CharSequence phoneNumber) {
+        return getPhoneTtsSpannable(phoneNumber);
+    }
+
+    /**
+     * Attach a {@link TtsSpan} to the supplied {@code Spannable} at the indicated location,
+     * annotating that location as containing a phone number.
+     *
+     * @param s A {@code Spannable} to annotate.
+     * @param start The starting character position of the phone number in {@code s}.
+     * @param end The ending character position of the phone number in {@code s}.
+     *
+     * @deprecated Renamed {@link #addPhoneTtsSpan}.
+     *
+     * @hide
+     */
+    @Deprecated
+    public static void ttsSpanAsPhoneNumber(Spannable s, int start, int end) {
+        addPhoneTtsSpan(s, start, end);
+    }
+
+    /**
+     * Create a {@code TtsSpan} for the supplied {@code String}.
+     *
+     * @param phoneNumberString A {@code String} the entirety of which represents a phone number.
+     * @return A {@code TtsSpan} for {@param phoneNumberString}.
+     */
+    public static TtsSpan getPhoneTtsSpan(String phoneNumberString) {
+        if (phoneNumberString == null) {
+            return null;
+        }
+
+        // Parse the phone number
+        final PhoneNumberUtil phoneNumberUtil = PhoneNumberUtil.getInstance();
+        PhoneNumber phoneNumber = null;
+        try {
+            // Don't supply a defaultRegion so this fails for non-international numbers because
+            // we don't want to TalkBalk to read a country code (e.g. +1) if it is not already
+            // present
+            phoneNumber = phoneNumberUtil.parse(phoneNumberString, /* defaultRegion */ null);
+        } catch (NumberParseException ignored) {
+        }
+
+        // Build a telephone tts span
+        final TtsSpan.TelephoneBuilder builder = new TtsSpan.TelephoneBuilder();
+        if (phoneNumber == null) {
+            // Strip separators otherwise TalkBack will be silent
+            // (this behavior was observed with TalkBalk 4.0.2 from their alpha channel)
+            builder.setNumberParts(splitAtNonNumerics(phoneNumberString));
+        } else {
+            if (phoneNumber.hasCountryCode()) {
+                builder.setCountryCode(Integer.toString(phoneNumber.getCountryCode()));
+            }
+            builder.setNumberParts(Long.toString(phoneNumber.getNationalNumber()));
+        }
+        return builder.build();
+    }
+
     // Split a phone number like "+20(123)-456#" using spaces, ignoring anything that is not
     // a digit, to produce a result like "20 123 456".
     private static String splitAtNonNumerics(CharSequence number) {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index a7350c9..b96f528 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -29,6 +29,7 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.telecom.PhoneAccount;
 import android.util.Log;
 
 import com.android.internal.telecom.ITelecomService;
@@ -3779,7 +3780,7 @@
 
    /**
     * Returns the IMS Registration Status
-    *@hide
+    * @hide
     */
    public boolean isImsRegistered() {
        try {
@@ -4130,4 +4131,21 @@
                     ServiceState.rilRadioTechnologyToString(type));
         }
     }
+
+    /**
+     * Returns the subscription ID for the given phone account.
+     * @hide
+     */
+    public int getSubIdForPhoneAccount(PhoneAccount phoneAccount) {
+        int retval = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+        try {
+            ITelephony service = getITelephony();
+            if (service != null) {
+                retval = service.getSubIdForPhoneAccount(phoneAccount);
+            }
+        } catch (RemoteException e) {
+        }
+
+        return retval;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index bf3ee09..62c8746 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.os.Bundle;
+import android.telecom.PhoneAccount;
 import android.telephony.CellInfo;
 import android.telephony.IccOpenLogicalChannelResponse;
 import android.telephony.NeighboringCellInfo;
@@ -879,4 +880,9 @@
       *   {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
       */
     String getDeviceId();
+
+    /**
+     * Returns the subscription ID associated with the specified PhoneAccount.
+     */
+    int getSubIdForPhoneAccount(in PhoneAccount phoneAccount);
 }
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index b87a1e9..bc95a36 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -79,6 +79,8 @@
 
     void setCountryCode(String country, boolean persist);
 
+    String getCountryCode();
+
     void setFrequencyBand(int band, boolean persist);
 
     int getFrequencyBand();
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 9729c91..b4f4927 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -16,6 +16,8 @@
 
 package android.net.wifi;
 
+import android.net.wifi.passpoint.WifiPasspointInfo;
+import android.net.wifi.passpoint.WifiPasspointManager;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -53,11 +55,55 @@
      */
     public int level;
     /**
-     * The frequency in MHz of the channel over which the client is communicating
+     * The primary 20 MHz frequency (in MHz) of the channel over which the client is communicating
      * with the access point.
      */
     public int frequency;
 
+   /**
+    * AP Channel bandwidth is 20 MHZ
+    */
+    public static final int CHANNEL_WIDTH_20MHZ = 0;
+   /**
+    * AP Channel bandwidth is 40 MHZ
+    */
+    public static final int CHANNEL_WIDTH_40MHZ = 1;
+   /**
+    * AP Channel bandwidth is 80 MHZ
+    */
+    public static final int CHANNEL_WIDTH_80MHZ = 2;
+   /**
+    * AP Channel bandwidth is 160 MHZ
+    */
+    public static final int CHANNEL_WIDTH_160MHZ = 3;
+   /**
+    * AP Channel bandwidth is 160 MHZ, but 80MHZ + 80MHZ
+    */
+    public static final int CHANNEL_WIDTH_80MHZ_PLUS_MHZ = 4;
+
+   /**
+    * AP Channel bandwidth
+    */
+    public int channelWidth;
+
+    /**
+     * Not used if the AP bandwidth is 20 MHz
+     * If the AP use 40, 80 or 160 MHz, this is the center frequency
+     * if the AP use 80 + 80 MHz, this is the center frequency of the first segment
+     */
+    public int centerFreq0;
+
+    /**
+     * Only used if the AP bandwidth is 80 + 80 MHz
+     * if the AP use 80 + 80 MHz, this is the center frequency of the second segment
+     */
+    public int centerFreq1;
+
+    /**
+     * Whether the AP support 802.11mc Responder
+     */
+   public boolean is80211McRTTResponder;
+
     /**
      * timestamp in microseconds (since boot) when
      * this result was last seen.
@@ -169,6 +215,13 @@
     public int distanceSdCm;
 
     /**
+     * Passpoint ANQP information. This is not fetched automatically.
+     * Use {@link WifiPasspointManager#requestAnqpInfo} to request ANQP info.
+     * {@hide}
+     */
+    public WifiPasspointInfo passpoint;
+
+    /**
      * {@hide}
      */
     public final static int UNSPECIFIED = -1;
@@ -235,6 +288,10 @@
         this.timestamp = tsf;
         this.distanceCm = UNSPECIFIED;
         this.distanceSdCm = UNSPECIFIED;
+        this.channelWidth = UNSPECIFIED;
+        this.centerFreq0 = UNSPECIFIED;
+        this.centerFreq1 = UNSPECIFIED;
+        this.is80211McRTTResponder = false;
     }
 
     /** {@hide} */
@@ -249,6 +306,29 @@
         this.timestamp = tsf;
         this.distanceCm = distCm;
         this.distanceSdCm = distSdCm;
+        this.channelWidth = UNSPECIFIED;
+        this.centerFreq0 = UNSPECIFIED;
+        this.centerFreq1 = UNSPECIFIED;
+        this.is80211McRTTResponder = false;
+    }
+
+    /** {@hide} */
+    public ScanResult(WifiSsid wifiSsid, String BSSID, String caps, int level, int frequency,
+            long tsf, int distCm, int distSdCm, int channelWidth, int centerFreq0, int centerFreq1,
+            boolean is80211McRTTResponder) {
+        this.wifiSsid = wifiSsid;
+        this.SSID = (wifiSsid != null) ? wifiSsid.toString() : WifiSsid.NONE;
+        this.BSSID = BSSID;
+        this.capabilities = caps;
+        this.level = level;
+        this.frequency = frequency;
+        this.timestamp = tsf;
+        this.distanceCm = distCm;
+        this.distanceSdCm = distSdCm;
+        this.channelWidth = channelWidth;
+        this.centerFreq0 = centerFreq0;
+        this.centerFreq1 = centerFreq1;
+        this.is80211McRTTResponder = is80211McRTTResponder;
     }
 
     /** copy constructor {@hide} */
@@ -260,10 +340,15 @@
             capabilities = source.capabilities;
             level = source.level;
             frequency = source.frequency;
+            channelWidth = source.channelWidth;
+            centerFreq0 = source.centerFreq0;
+            centerFreq1 = source.centerFreq1;
+            is80211McRTTResponder = source.is80211McRTTResponder;
             timestamp = source.timestamp;
             distanceCm = source.distanceCm;
             distanceSdCm = source.distanceSdCm;
             seen = source.seen;
+            passpoint = source.passpoint;
             autoJoinStatus = source.autoJoinStatus;
             untrusted = source.untrusted;
             numConnection = source.numConnection;
@@ -303,9 +388,15 @@
         sb.append(", distanceSd: ").append((distanceSdCm != UNSPECIFIED ? distanceSdCm : "?")).
                 append("(cm)");
 
+        sb.append(", passpoint: ").append(passpoint != null ? "yes" : "no");
         if (autoJoinStatus != 0) {
             sb.append(", status: ").append(autoJoinStatus);
         }
+        sb.append(", ChannelBandwidth: ").append(channelWidth);
+        sb.append(", centerFreq0: ").append(centerFreq0);
+        sb.append(", centerFreq1: ").append(centerFreq1);
+        sb.append(", 80211mcResponder: ").append(is80211McRTTResponder?
+                "is supported":"is not supported");
         return sb.toString();
     }
 
@@ -329,6 +420,10 @@
         dest.writeLong(timestamp);
         dest.writeInt(distanceCm);
         dest.writeInt(distanceSdCm);
+        dest.writeInt(channelWidth);
+        dest.writeInt(centerFreq0);
+        dest.writeInt(centerFreq1);
+        dest.writeInt(is80211McRTTResponder ? 1 : 0);
         dest.writeLong(seen);
         dest.writeInt(autoJoinStatus);
         dest.writeInt(untrusted ? 1 : 0);
@@ -336,6 +431,12 @@
         dest.writeInt(numUsage);
         dest.writeInt(numIpConfigFailures);
         dest.writeInt(isAutoJoinCandidate);
+        if (passpoint != null) {
+            dest.writeInt(1);
+            passpoint.writeToParcel(dest, flags);
+        } else {
+            dest.writeInt(0);
+        }
         if (informationElements != null) {
             dest.writeInt(informationElements.length);
             for (int i = 0; i < informationElements.length; i++) {
@@ -364,7 +465,11 @@
                     in.readInt(),
                     in.readLong(),
                     in.readInt(),
-                    in.readInt()
+                    in.readInt(),
+                    in.readInt(),
+                    in.readInt(),
+                    in.readInt(),
+                    in.readInt() == 1
                 );
                 sr.seen = in.readLong();
                 sr.autoJoinStatus = in.readInt();
@@ -373,6 +478,9 @@
                 sr.numUsage = in.readInt();
                 sr.numIpConfigFailures = in.readInt();
                 sr.isAutoJoinCandidate = in.readInt();
+                if (in.readInt() == 1) {
+                    sr.passpoint = WifiPasspointInfo.CREATOR.createFromParcel(in);
+                }
                 int n = in.readInt();
                 if (n != 0) {
                     sr.informationElements = new InformationElement[n];
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 87db951..872eb6f 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -19,19 +19,18 @@
 import android.annotation.SystemApi;
 import android.net.IpConfiguration;
 import android.net.IpConfiguration.ProxySettings;
-import android.net.IpConfiguration.IpAssignment;
 import android.net.ProxyInfo;
 import android.net.StaticIpConfiguration;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.TextUtils;
-import android.annotation.SystemApi;
 
 import java.util.HashMap;
 import java.util.BitSet;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashSet;
 
 /**
  * A class representing a configured Wi-Fi network, including the
@@ -59,6 +58,7 @@
     public static final String updateIdentiferVarName = "update_identifier";
     /** {@hide} */
     public static final int INVALID_NETWORK_ID = -1;
+
     /**
      * Recognized key management schemes.
      */
@@ -233,17 +233,21 @@
      * <code>XX:XX:XX:XX:XX:XX</code> where each <code>X</code> is a hex digit.
      */
     public String BSSID;
+
     /**
-     * Fully qualified domain name (FQDN) of AAA server or RADIUS server
-     * e.g. {@code "mail.example.com"}.
+     * The band which AP resides on
+     * 0-2G  1-5G
+     * By default, 2G is chosen
      */
-    public String FQDN;
+    public int apBand = 0;
+
     /**
-     * Network access identifier (NAI) realm, for Passpoint credential.
-     * e.g. {@code "myhost.example.com"}.
-     * @hide
+     * The channel which AP resides on,currently, US only
+     * 2G  1-11
+     * 5G  36,40,44,48,149,153,157,161,165
+     * 0 - find a random available channel according to the apBand
      */
-    public String naiRealm;
+    public int apChannel = 0;
 
     /**
      * Pre-shared key for use with WPA-PSK.
@@ -328,6 +332,21 @@
     public WifiEnterpriseConfig enterpriseConfig;
 
     /**
+     * Fully qualified domain name of a passpoint configuration
+     */
+    public String FQDN;
+
+    /**
+     * Service provider name, for Passpoint credential.
+     */
+    public String providerFriendlyName;
+
+    /**
+     * Roaming Consortium Id, for Passpoint credential.
+     */
+    public HashSet<Long> roamingConsortiumIds;
+
+    /**
      * @hide
      */
     private IpConfiguration mIpConfiguration;
@@ -862,7 +881,7 @@
         SSID = null;
         BSSID = null;
         FQDN = null;
-        naiRealm = null;
+        roamingConsortiumIds = new HashSet<Long>();
         priority = 0;
         hiddenSSID = false;
         disableReason = DISABLED_UNKNOWN_REASON;
@@ -907,6 +926,17 @@
             }
         }
 
+        if (FQDN != null) {
+            /* must have a providerFriendlyName */
+            if (providerFriendlyName == null) {
+                return false;
+            }
+            /* this is passpoint configuration; it must have enterprise config */
+            if (enterpriseConfig == null) {
+                return false;
+            }
+        }
+
         // TODO: Add more checks
         return true;
     }
@@ -1042,8 +1072,9 @@
             sbuf.append("- DSBLE ");
         }
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
+                append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN).
-                append(" REALM: ").append(this.naiRealm).append(" PRIO: ").append(this.priority).
+                append(" PRIO: ").append(this.priority).
                 append('\n');
         if (this.numConnectionFailures > 0) {
             sbuf.append(" numConnectFailures ").append(this.numConnectionFailures).append("\n");
@@ -1383,6 +1414,8 @@
         String key;
         if (allowCached && mCachedConfigKey != null) {
             key = mCachedConfigKey;
+        } else if (providerFriendlyName != null) {
+            key = FQDN + KeyMgmt.strings[KeyMgmt.WPA_EAP];
         } else {
             if (allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
                 key = SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK];
@@ -1498,9 +1531,17 @@
             SSID = source.SSID;
             BSSID = source.BSSID;
             FQDN = source.FQDN;
-            naiRealm = source.naiRealm;
+            roamingConsortiumIds = new HashSet<Long>();
+            for (Long roamingConsortiumId : source.roamingConsortiumIds) {
+                roamingConsortiumIds.add(roamingConsortiumId);
+            }
+
+            providerFriendlyName = source.providerFriendlyName;
             preSharedKey = source.preSharedKey;
 
+            apBand = source.apBand;
+            apChannel = source.apChannel;
+
             wepKeys = new String[4];
             for (int i = 0; i < wepKeys.length; i++) {
                 wepKeys[i] = source.wepKeys[i];
@@ -1593,9 +1634,15 @@
         dest.writeInt(disableReason);
         dest.writeString(SSID);
         dest.writeString(BSSID);
+        dest.writeInt(apBand);
+        dest.writeInt(apChannel);
         dest.writeString(autoJoinBSSID);
         dest.writeString(FQDN);
-        dest.writeString(naiRealm);
+        dest.writeString(providerFriendlyName);
+        dest.writeInt(roamingConsortiumIds.size());
+        for (Long roamingConsortiumId : roamingConsortiumIds) {
+            dest.writeLong(roamingConsortiumId);
+        }
         dest.writeString(preSharedKey);
         for (String wepKey : wepKeys) {
             dest.writeString(wepKey);
@@ -1658,9 +1705,15 @@
                 config.disableReason = in.readInt();
                 config.SSID = in.readString();
                 config.BSSID = in.readString();
+                config.apBand = in.readInt();
+                config.apChannel = in.readInt();
                 config.autoJoinBSSID = in.readString();
                 config.FQDN = in.readString();
-                config.naiRealm = in.readString();
+                config.providerFriendlyName = in.readString();
+                int numRoamingConsortiumIds = in.readInt();
+                for (int i = 0; i < numRoamingConsortiumIds; i++) {
+                    config.roamingConsortiumIds.add(in.readLong());
+                }
                 config.preSharedKey = in.readString();
                 for (int i = 0; i < config.wepKeys.length; i++) {
                     config.wepKeys[i] = in.readString();
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index cf3cba3..36fc96b 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -54,6 +54,8 @@
     /** @hide */
     public static final String SUBJECT_MATCH_KEY   = "subject_match";
     /** @hide */
+    public static final String ALTSUBJECT_MATCH_KEY = "altsubject_match";
+    /** @hide */
     public static final String OPP_KEY_CACHING     = "proactive_key_caching";
     /**
      * String representing the keystore OpenSSL ENGINE's ID.
@@ -93,6 +95,11 @@
     public static final String ENGINE_ID_KEY       = "engine_id";
     /** @hide */
     public static final String PRIVATE_KEY_ID_KEY  = "key_id";
+    /** @hide */
+    public static final String REALM_KEY           = "realm";
+    /** @hide */
+    public static final String PLMN_KEY            = "plmn";
+
 
     private HashMap<String, String> mFields = new HashMap<String, String>();
     private X509Certificate mCaCert;
@@ -530,22 +537,74 @@
     }
 
     /**
-     * Set subject match. This is the substring to be matched against the subject of the
-     * authentication server certificate.
+     * Set subject match (deprecated). This is the substring to be matched against the subject of
+     * the authentication server certificate.
      * @param subjectMatch substring to be matched
+     * @deprecated in favor of altSubjectMatch
      */
     public void setSubjectMatch(String subjectMatch) {
         setFieldValue(SUBJECT_MATCH_KEY, subjectMatch, "");
     }
 
     /**
-     * Get subject match
+     * Get subject match (deprecated)
      * @return the subject match string
+     * @deprecated in favor of altSubjectMatch
      */
     public String getSubjectMatch() {
         return getFieldValue(SUBJECT_MATCH_KEY, "");
     }
 
+    /**
+     * Set alternate subject match. This is the substring to be matched against the
+     * alternate subject of the authentication server certificate.
+     * @param altSubjectMatch substring to be matched, for example
+     *                     DNS:server.example.com;EMAIL:server@example.com
+     */
+    public void setAltSubjectMatch(String altSubjectMatch) {
+        setFieldValue(ALTSUBJECT_MATCH_KEY, altSubjectMatch, "");
+    }
+
+    /**
+     * Get alternate subject match
+     * @return the alternate subject match string
+     */
+    public String getAltSubjectMatch() {
+        return getFieldValue(ALTSUBJECT_MATCH_KEY, "");
+    }
+
+    /**
+     * Set realm for passpoint credential
+     * @param realm the realm
+     */
+    public void setRealm(String realm) {
+        setFieldValue(REALM_KEY, realm, "");
+    }
+
+    /**
+     * Get realm for passpoint credential
+     * @return the realm
+     */
+    public String getRealm() {
+        return getFieldValue(REALM_KEY, "");
+    }
+
+    /**
+     * Set plmn for passpoint credential
+     * @param plmn the plmn value derived from mcc & mnc
+     */
+    public void setPlmn(String plmn) {
+        setFieldValue(PLMN_KEY, plmn, "");
+    }
+
+    /**
+     * Set plmn for passpoint credential
+     * @return the plmn
+     */
+    public String getPlmn() {
+        return getFieldValue(PLMN_KEY, "");
+    }
+
     /** See {@link WifiConfiguration#getKeyIdForCredentials} @hide */
     String getKeyId(WifiEnterpriseConfig current) {
         String eap = mFields.get(EAP_KEY);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index b001bb8..40d40bb 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1238,6 +1238,21 @@
     }
 
     /**
+    * get the country code.
+    * @return the country code in ISO 3166 format.
+    *
+    * @hide
+    */
+    public String getCountryCode() {
+       try {
+           String country = mService.getCountryCode();
+           return(country);
+       } catch (RemoteException e) {
+           return null;
+       }
+    }
+
+    /**
      * Set the operational frequency band.
      * @param band  One of
      *     {@link #WIFI_FREQUENCY_BAND_AUTO},
diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java
index aaa2f98..fea934f 100644
--- a/wifi/java/android/net/wifi/WifiScanner.java
+++ b/wifi/java/android/net/wifi/WifiScanner.java
@@ -158,6 +158,11 @@
         public int reportEvents;
         /** defines number of bssids to cache from each scan */
         public int numBssidsPerScan;
+        /**
+         * defines number of scans to cache; use it with REPORT_EVENT_AFTER_BUFFER_FULL
+         * to wake up at fixed interval
+         */
+        public int maxScansToCache;
 
         /** Implement the Parcelable interface {@hide} */
         public int describeContents() {
@@ -170,6 +175,7 @@
             dest.writeInt(periodInMs);
             dest.writeInt(reportEvents);
             dest.writeInt(numBssidsPerScan);
+            dest.writeInt(maxScansToCache);
 
             if (channels != null) {
                 dest.writeInt(channels.length);
@@ -194,6 +200,7 @@
                         settings.periodInMs = in.readInt();
                         settings.reportEvents = in.readInt();
                         settings.numBssidsPerScan = in.readInt();
+                        settings.maxScansToCache = in.readInt();
                         int num_channels = in.readInt();
                         settings.channels = new ChannelSpec[num_channels];
                         for (int i = 0; i < num_channels; i++) {
@@ -215,8 +222,143 @@
 
     }
 
-    /** @hide */
+    /**
+     * all the information garnered from a single scan
+     */
+    public static class ScanData implements Parcelable {
+        /** scan identifier */
+        private int mId;
+        /** additional information about scan
+         * 0 => no special issues encountered in the scan
+         * non-zero => scan was truncated, so results may not be complete
+         */
+        private int mFlags;
+        /** all scan results discovered in this scan, sorted by timestamp in ascending order */
+        private ScanResult mResults[];
+
+        ScanData() {}
+
+        public ScanData(int id, int flags, ScanResult[] results) {
+            mId = id;
+            mFlags = flags;
+            mResults = results;
+        }
+
+        public ScanData(ScanData s) {
+            mId = s.mId;
+            mFlags = s.mFlags;
+            mResults = new ScanResult[s.mResults.length];
+            for (int i = 0; i < s.mResults.length; i++) {
+                ScanResult result = s.mResults[i];
+                WifiSsid wifiSsid = WifiSsid.createFromAsciiEncoded(result.SSID);
+                ScanResult newResult = new ScanResult(result);
+                newResult.wifiSsid = wifiSsid;
+                mResults[i] = newResult;
+            }
+        }
+
+        public int getId() {
+            return mId;
+        }
+
+        public int getFlags() {
+            return mFlags;
+        }
+
+        public ScanResult[] getResults() {
+            return mResults;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            if (mResults != null) {
+                dest.writeInt(mId);
+                dest.writeInt(mFlags);
+                dest.writeInt(mResults.length);
+                for (int i = 0; i < mResults.length; i++) {
+                    ScanResult result = mResults[i];
+                    result.writeToParcel(dest, flags);
+                }
+            } else {
+                dest.writeInt(0);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<ScanData> CREATOR =
+                new Creator<ScanData>() {
+                    public ScanData createFromParcel(Parcel in) {
+                        int id = in.readInt();
+                        int flags = in.readInt();
+                        int n = in.readInt();
+                        ScanResult results[] = new ScanResult[n];
+                        for (int i = 0; i < n; i++) {
+                            results[i] = ScanResult.CREATOR.createFromParcel(in);
+                        }
+                        return new ScanData(id, flags, results);
+                    }
+
+                    public ScanData[] newArray(int size) {
+                        return new ScanData[size];
+                    }
+                };
+    }
+
+    public static class ParcelableScanData implements Parcelable {
+
+        public ScanData mResults[];
+
+        public ParcelableScanData(ScanData[] results) {
+            mResults = results;
+        }
+
+        public ScanData[] getResults() {
+            return mResults;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public int describeContents() {
+            return 0;
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public void writeToParcel(Parcel dest, int flags) {
+            if (mResults != null) {
+                dest.writeInt(mResults.length);
+                for (int i = 0; i < mResults.length; i++) {
+                    ScanData result = mResults[i];
+                    result.writeToParcel(dest, flags);
+                }
+            } else {
+                dest.writeInt(0);
+            }
+        }
+
+        /** Implement the Parcelable interface {@hide} */
+        public static final Creator<ParcelableScanData> CREATOR =
+                new Creator<ParcelableScanData>() {
+                    public ParcelableScanData createFromParcel(Parcel in) {
+                        int n = in.readInt();
+                        ScanData results[] = new ScanData[n];
+                        for (int i = 0; i < n; i++) {
+                            results[i] = ScanData.CREATOR.createFromParcel(in);
+                        }
+                        return new ParcelableScanData(results);
+                    }
+
+                    public ParcelableScanData[] newArray(int size) {
+                        return new ParcelableScanData[size];
+                    }
+                };
+    }
+
     public static class ParcelableScanResults implements Parcelable {
+
         public ScanResult mResults[];
 
         public ParcelableScanResults(ScanResult[] results) {
@@ -264,7 +406,8 @@
     }
 
     /**
-     * interface to get scan events on; specify this on {@link #startBackgroundScan}
+     * interface to get scan events on; specify this on {@link #startBackgroundScan} or
+     * {@link #startScan}
      */
     public interface ScanListener extends ActionListener {
         /**
@@ -273,10 +416,15 @@
          */
         public void onPeriodChanged(int periodInMs);
         /**
-         * reports results retrieved from background scan
+         * reports results retrieved from background scan and single shot scans
+         * @deprecated in favor of {@link #onResults(ScanData[])}
          */
         public void onResults(ScanResult[] results);
         /**
+         * reports results retrieved from background scan and single shot scans
+         */
+        public void onResults(ScanData[] results);
+        /**
          * reports full scan result for each access point found in scan
          */
         public void onFullResult(ScanResult fullScanResult);
@@ -303,13 +451,36 @@
         sAsyncChannel.sendMessage(CMD_STOP_BACKGROUND_SCAN, 0, removeListener(listener));
     }
     /**
-     * retrieves currently available scan results
+     * reports currently available scan results on appropriate listeners
      */
     public ScanResult[] getScanResults() {
         validateChannel();
         Message reply = sAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
-        ScanResult[] results = (ScanResult[]) reply.obj;
-        return results;
+        // return reply.what == CMD_OP_SUCCEEDED;
+        return null;
+    }
+
+    /**
+     * starts a single scan and reports results asynchronously
+     * @param settings specifies various parameters for the scan; for more information look at
+     * {@link ScanSettings}
+     * @param listener specifies the object to report events to. This object is also treated as a
+     *                 key for this scan, and must also be specified to cancel the scan. Multiple
+     *                 scans should also not share this object.
+     */
+    public void startScan(ScanSettings settings, ScanListener listener) {
+        validateChannel();
+        sAsyncChannel.sendMessage(CMD_START_SINGLE_SCAN, 0, putListener(listener), settings);
+    }
+
+    /**
+     * stops an ongoing single shot scan; only useful after {@link #startScan} if onResults()
+     * hasn't been called on the listener, ignored otherwise
+     * @param listener
+     */
+    public void stopScan(ScanListener listener) {
+        validateChannel();
+        sAsyncChannel.sendMessage(CMD_STOP_SINGLE_SCAN, 0, removeListener(listener));
     }
 
     /** specifies information about an access point of interest */
@@ -468,6 +639,10 @@
          * @param results list of scan results, one for each access point visible currently
          */
         public void onFound(ScanResult[] results);
+        /** indicates that access points were missed by on going scans
+         * @param results list of scan results, for each access point that is not visible anymore
+         */
+        public void onLost(ScanResult[] results);
     }
 
     /** @hide */
@@ -593,6 +768,12 @@
     public static final int CMD_PERIOD_CHANGED              = BASE + 19;
     /** @hide */
     public static final int CMD_FULL_SCAN_RESULT            = BASE + 20;
+    /** @hide */
+    public static final int CMD_START_SINGLE_SCAN           = BASE + 21;
+    /** @hide */
+    public static final int CMD_STOP_SINGLE_SCAN            = BASE + 22;
+    /** @hide */
+    public static final int CMD_SINGLE_SCAN_COMPLETED       = BASE + 23;
 
     private Context mContext;
     private IWifiScanner mService;
@@ -800,7 +981,7 @@
                     break;
                 case CMD_SCAN_RESULT :
                     ((ScanListener) listener).onResults(
-                            ((ParcelableScanResults) msg.obj).getResults());
+                            ((ParcelableScanData) msg.obj).getResults());
                     return;
                 case CMD_FULL_SCAN_RESULT :
                     ScanResult result = (ScanResult) msg.obj;
@@ -813,6 +994,10 @@
                     ((BssidListener) listener).onFound(
                             ((ParcelableScanResults) msg.obj).getResults());
                     return;
+                case CMD_AP_LOST:
+                    ((BssidListener) listener).onLost(
+                            ((ParcelableScanResults) msg.obj).getResults());
+                    return;
                 case CMD_WIFI_CHANGE_DETECTED:
                     ((WifiChangeListener) listener).onChanging(
                             ((ParcelableScanResults) msg.obj).getResults());
@@ -821,6 +1006,10 @@
                     ((WifiChangeListener) listener).onQuiescence(
                             ((ParcelableScanResults) msg.obj).getResults());
                     return;
+                case CMD_SINGLE_SCAN_COMPLETED:
+                    Log.d(TAG, "removing listener for single scan");
+                    removeListener(msg.arg2);
+                    break;
                 default:
                     if (DBG) Log.d(TAG, "Ignoring message " + msg.what);
                     return;
diff --git a/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
new file mode 100644
index 0000000..50bec33
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/IWifiPasspointManager.aidl
@@ -0,0 +1,45 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.net.wifi.ScanResult;
+import android.net.wifi.passpoint.WifiPasspointPolicy;
+import android.net.wifi.passpoint.WifiPasspointCredential;
+import android.os.Messenger;
+
+/**
+ * Interface that allows controlling and querying Wifi Passpoint connectivity.
+ *
+ * {@hide}
+ */
+interface IWifiPasspointManager
+{
+    Messenger getMessenger();
+
+    int getPasspointState();
+
+    List<WifiPasspointPolicy> requestCredentialMatch(in List<ScanResult> requested);
+
+    List<WifiPasspointCredential> getCredentials();
+
+    boolean addCredential(in WifiPasspointCredential cred);
+
+    boolean updateCredential(in WifiPasspointCredential cred);
+
+    boolean removeCredential(in WifiPasspointCredential cred);
+}
+
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
new file mode 100644
index 0000000..cfd3605
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+parcelable WifiPasspointCredential;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
new file mode 100644
index 0000000..0a7230f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointCredential.java
@@ -0,0 +1,667 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.net.wifi.WifiEnterpriseConfig;
+import android.os.Parcelable;
+import android.os.Parcel;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * A class representing a Wi-Fi Passpoint credential.
+ * @hide
+ */
+public class WifiPasspointCredential implements Parcelable {
+
+    private final static String TAG = "PasspointCredential";
+    private final static boolean DBG = true;
+
+    /** Wi-Fi nodes**/
+    private String mWifiSpFqdn;
+
+    /** PerProviderSubscription nodes **/
+    private String mCredentialName;
+
+    /** SubscriptionUpdate nodes **/
+    private String mSubscriptionUpdateInterval;
+    private String mSubscriptionUpdateMethod;
+    private String mSubscriptionUpdateRestriction;
+    private String mSubscriptionUpdateURI;
+    private String mSubscriptionUpdateUsername;
+    private String mSubscriptionUpdatePassword;
+
+    /** HomeSP nodes **/
+    private String mHomeSpFqdn;
+    private String mFriendlyName;
+    private Collection<WifiPasspointDmTree.HomeOIList> mHomeOIList;
+    private Collection<WifiPasspointDmTree.OtherHomePartners> mOtherHomePartnerList;
+
+    /** SubscriptionParameters nodes**/
+    private String mCreationDate;
+    private String mExpirationDate;
+
+    /** Credential nodes **/
+    private String mType;
+    private String mInnerMethod;
+    private String mCertType;
+    private String mCertSha256Fingerprint;
+    private String mUpdateIdentifier;
+    private String mUsername;
+    private String mPasswd;
+    private String mRealm;
+    private String mImsi;
+    private String mMcc;
+    private String mMnc;
+    private String mCaRootCert;
+    private String mClientCert;
+    private boolean mCheckAaaServerCertStatus;
+
+    /** Policy nodes **/
+    private String mPolicyUpdateUri;
+    private String mPolicyUpdateInterval;
+    private String mPolicyUpdateUsername;
+    private String mPolicyUpdatePassword;
+    private String mPolicyUpdateRestriction;
+    private String mPolicyUpdateMethod;
+    private Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> mPreferredRoamingPartnerList;
+    private Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> mMinBackhaulThresholdNetwork;
+    private Collection<WifiPasspointDmTree.SPExclusionList> mSpExclusionList;
+    private Collection<WifiPasspointDmTree.RequiredProtoPortTuple> mRequiredProtoPortTuple;
+    private String mMaxBssLoad;
+
+    /** CrednetialPriority node **/
+    private int mCrednetialPriority;
+
+    /** AAAServerTrustRoot nodes **/
+    private String mAaaCertUrl;
+    private String mAaaSha256Fingerprint;
+
+    /** Others **/
+    private boolean mIsMachineRemediation;
+    private boolean mUserPreferred = false;
+    private String mWifiTreePath;
+    private WifiEnterpriseConfig mEnterpriseConfig;
+
+    /** @hide */
+    public WifiPasspointCredential() {}
+
+    /**
+     * Constructor
+     * @param realm Realm of the passpoint credential
+     * @param fqdn Fully qualified domain name (FQDN) of the credential
+     * @param config Enterprise config, must be either EAP-TLS or EAP-TTLS
+     * @see WifiEnterpriseConfig
+     */
+    public WifiPasspointCredential(String realm, String fqdn, WifiEnterpriseConfig config) {
+        mRealm = realm;
+        switch (config.getEapMethod()) {
+            case WifiEnterpriseConfig.Eap.TLS:
+            case WifiEnterpriseConfig.Eap.TTLS:
+                mEnterpriseConfig = new WifiEnterpriseConfig(config);
+                break;
+            default:
+                // ignore
+        }
+    }
+
+    /** @hide */
+    public WifiPasspointCredential(String type,
+            String caroot,
+            String clientcert,
+            String mcc,
+            String mnc,
+            WifiPasspointDmTree.SpFqdn sp,
+            WifiPasspointDmTree.CredentialInfo credinfo) {
+
+        if (credinfo == null) {
+            return;
+        }
+
+        mType = type;
+        mCaRootCert = caroot;
+        mClientCert = clientcert;
+
+        mWifiSpFqdn = sp.nodeName;
+        mUpdateIdentifier = sp.perProviderSubscription.UpdateIdentifier;
+
+        mCredentialName = credinfo.nodeName;
+        mOtherHomePartnerList = credinfo.homeSP.otherHomePartners.values();
+
+        Set set = credinfo.aAAServerTrustRoot.entrySet();
+        Iterator i = set.iterator();
+        if (i.hasNext()) {
+            Map.Entry entry3 = (Map.Entry) i.next();
+            WifiPasspointDmTree.AAAServerTrustRoot aaa = (WifiPasspointDmTree.AAAServerTrustRoot) entry3.getValue();
+            mAaaCertUrl = aaa.CertURL;
+            mAaaSha256Fingerprint = aaa.CertSHA256Fingerprint;
+        }
+
+        mCertType = credinfo.credential.digitalCertificate.CertificateType;
+        mCertSha256Fingerprint = credinfo.credential.digitalCertificate.CertSHA256Fingerprint;
+        mUsername = credinfo.credential.usernamePassword.Username;
+        mPasswd = credinfo.credential.usernamePassword.Password;
+        mIsMachineRemediation = credinfo.credential.usernamePassword.MachineManaged;
+        mInnerMethod = credinfo.credential.usernamePassword.eAPMethod.InnerMethod;
+        mImsi = credinfo.credential.sim.IMSI;
+        mMcc = mcc;
+        mMnc = mnc;
+        mCreationDate = credinfo.credential.CreationDate;
+        mExpirationDate = credinfo.credential.ExpirationDate;
+        mRealm = credinfo.credential.Realm;
+
+        if (credinfo.credentialPriority == null) {
+            mCrednetialPriority = 128;
+        } else {
+            mCrednetialPriority = Integer.parseInt(credinfo.credentialPriority);
+        }
+
+        mHomeSpFqdn = credinfo.homeSP.FQDN;
+
+        mSubscriptionUpdateInterval = credinfo.subscriptionUpdate.UpdateInterval;
+        mSubscriptionUpdateMethod = credinfo.subscriptionUpdate.UpdateMethod;
+        mSubscriptionUpdateRestriction = credinfo.subscriptionUpdate.Restriction;
+        mSubscriptionUpdateURI = credinfo.subscriptionUpdate.URI;
+        mSubscriptionUpdateUsername = credinfo.subscriptionUpdate.usernamePassword.Username;
+        mSubscriptionUpdatePassword = credinfo.subscriptionUpdate.usernamePassword.Password;
+
+        mPolicyUpdateUri = credinfo.policy.policyUpdate.URI;
+        mPolicyUpdateInterval = credinfo.policy.policyUpdate.UpdateInterval;
+        mPolicyUpdateUsername = credinfo.policy.policyUpdate.usernamePassword.Username;
+        mPolicyUpdatePassword = credinfo.policy.policyUpdate.usernamePassword.Password;
+        mPolicyUpdateRestriction = credinfo.policy.policyUpdate.Restriction;
+        mPolicyUpdateMethod = credinfo.policy.policyUpdate.UpdateMethod;
+        mPreferredRoamingPartnerList = credinfo.policy.preferredRoamingPartnerList.values();
+        mMinBackhaulThresholdNetwork = credinfo.policy.minBackhaulThreshold.values();
+        mRequiredProtoPortTuple = credinfo.policy.requiredProtoPortTuple.values();
+        mMaxBssLoad = credinfo.policy.maximumBSSLoadValue;
+        mSpExclusionList = credinfo.policy.sPExclusionList.values();
+
+        mHomeOIList = credinfo.homeSP.homeOIList.values();
+        mFriendlyName = credinfo.homeSP.FriendlyName;
+        mCheckAaaServerCertStatus = credinfo.credential.CheckAAAServerCertStatus;
+    }
+
+    /** @hide */
+    public String getUpdateIdentifier() {
+        return mUpdateIdentifier;
+    }
+
+    /** @hide */
+    public String getUpdateMethod() {
+        return mSubscriptionUpdateMethod;
+    }
+
+    /** @hide */
+    public void setUpdateMethod(String method) {
+        mSubscriptionUpdateMethod = method;
+    }
+
+    /** @hide */
+    public String getWifiSpFqdn() {
+        return mWifiSpFqdn;
+    }
+
+    /** @hide */
+    public String getCredName() {
+        return mCredentialName;
+    }
+
+    /** @hide */
+    public String getType() {
+        return mType;
+    }
+
+    /**
+     * Get enterprise config of this Passpoint credential.
+     * @return Enterprise config
+     * @see WifiEnterpriseConfig
+     */
+    public WifiEnterpriseConfig getEnterpriseConfig() {
+        return new WifiEnterpriseConfig(mEnterpriseConfig);
+    }
+
+    /**
+     * Set enterprise config of this Passpoint credential.
+     * @param config Enterprise config, must be either EAP-TLS or EAP-TTLS
+     * @see WifiEnterpriseConfig
+     */
+    public void setEnterpriseConfig(WifiEnterpriseConfig config) {
+        // TODO
+    }
+
+    /** @hide */
+    public String getCertType() {
+        return mCertType;
+    }
+
+    /** @hide */
+    public String getCertSha256Fingerprint() {
+        return mCertSha256Fingerprint;
+    }
+
+    /** @hide */
+    public String getUserName() {
+        return mUsername;
+    }
+
+    /** @hide */
+    public String getPassword() {
+        // TODO: guarded by connectivity internal
+        return mPasswd;
+    }
+
+    /** @hide */
+    public String getImsi() {
+        return mImsi;
+    }
+
+    /** @hide */
+    public String getMcc() {
+        return mMcc;
+    }
+
+    /** @hide */
+    public String getMnc() {
+        return mMnc;
+    }
+
+    /** @hide */
+    public String getCaRootCertPath() {
+        return mCaRootCert;
+    }
+
+    /** @hide */
+    public String getClientCertPath() {
+        return mClientCert;
+    }
+
+    /**
+     * Get the realm of this Passpoint credential.
+     * @return Realm
+     */
+    public String getRealm() {
+        return mRealm;
+    }
+
+    /**
+     * Set the ream of this Passpoint credential.
+     * @param realm Realm
+     */
+    public void setRealm(String realm) {
+        mRealm = realm;
+    }
+
+    /** @hide */
+    public int getPriority() {
+        if (mUserPreferred) {
+            return 0;
+        }
+
+        return mCrednetialPriority;
+    }
+
+    /**
+     * Get the fully qualified domain name (FQDN) of this Passpoint credential.
+     * @return FQDN
+     */
+    public String getHomeSpFqdn() {
+        return mHomeSpFqdn;
+    }
+
+    /**
+     * Set the fully qualified domain name (FQDN) of this Passpoint credential.
+     * @param fqdn FQDN
+     */
+    public void setHomeFqdn(String fqdn) {
+        mHomeSpFqdn = fqdn;
+    }
+
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.OtherHomePartners> getOtherHomePartnerList() {
+        return mOtherHomePartnerList;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateUsername() {
+        return mSubscriptionUpdateUsername;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdatePassword() {
+        return mSubscriptionUpdatePassword;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateUri() {
+        return mPolicyUpdateUri;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateInterval() {
+        return mPolicyUpdateInterval;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateUsername() {
+        return mPolicyUpdateUsername;
+    }
+
+    /** @hide */
+    public String getPolicyUpdatePassword() {
+        return mPolicyUpdatePassword;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateRestriction() {
+        return mPolicyUpdateRestriction;
+    }
+
+    /** @hide */
+    public String getPolicyUpdateMethod() {
+        return mPolicyUpdateMethod;
+    }
+
+    /** @hide */
+    public String getCreationDate() {
+        return mCreationDate;
+    }
+
+    /** @hide */
+    public String getExpirationDate() {
+        return mExpirationDate;
+    }
+
+    /** @hide */
+    public void setExpirationDate(String expirationdate) {
+        mExpirationDate = expirationdate;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.PreferredRoamingPartnerList> getPreferredRoamingPartnerList() {
+        return mPreferredRoamingPartnerList;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.HomeOIList> getHomeOiList() {
+        return mHomeOIList;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.MinBackhaulThresholdNetwork> getBackhaulThresholdList() {
+        return mMinBackhaulThresholdNetwork;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.RequiredProtoPortTuple> getRequiredProtoPortList() {
+        return mRequiredProtoPortTuple;
+    }
+
+    /** @hide */
+    public Collection<WifiPasspointDmTree.SPExclusionList> getSPExclusionList() {
+        return mSpExclusionList;
+    }
+
+    /** @hide */
+    public boolean getIsMachineRemediation() {
+        return mIsMachineRemediation;
+    }
+
+    /** @hide */
+    public String getAaaCertUrl() {
+        return mAaaCertUrl;
+    }
+
+    /** @hide */
+    public String getAaaSha256Fingerprint() {
+        return mAaaSha256Fingerprint;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateRestriction() {
+        return mSubscriptionUpdateRestriction;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateURI() {
+        return mSubscriptionUpdateURI;
+    }
+
+    /** @hide */
+    public String getSubscriptionUpdateInterval() {
+        return mSubscriptionUpdateInterval;
+    }
+
+    /** @hide */
+    public String getFriendlyName() {
+        return mFriendlyName;
+    }
+
+    /** @hide */
+    public String getMaxBssLoad() {
+        return mMaxBssLoad;
+    }
+
+    /** @hide */
+    public boolean getUserPreference() {
+        return mUserPreferred;
+    }
+
+    /** @hide */
+    public boolean getCheckAaaServerCertStatus() {
+        return mCheckAaaServerCertStatus;
+    }
+
+    /** @hide */
+    public void setUserPreference(boolean value) {
+        mUserPreferred = value;
+    }
+
+    @Override
+    /** @hide */
+    public boolean equals(Object obj) {
+        boolean result = false;
+        if (obj instanceof WifiPasspointCredential) {
+            final WifiPasspointCredential other = (WifiPasspointCredential) obj;
+            if (this.mType.equals(other.mType)) {
+                if (this.mType.equals("TTLS")) {
+                    result = this.mUsername.equals(other.mUsername) &&
+                            this.mPasswd.equals(other.mPasswd) &&
+                            this.mRealm.equals(other.mRealm) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+                }
+                if (this.mType.equals("TLS")) {
+                    result = this.mRealm.equals(other.mRealm) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn) &&
+                            this.mClientCert.equals(other.mClientCert);
+                }
+                if (this.mType.equals("SIM")) {
+                    result = this.mMcc.equals(other.mMcc) &&
+                            this.mMnc.equals(other.mMnc) &&
+                            this.mImsi.equals(other.mImsi) &&
+                            this.mHomeSpFqdn.equals(other.mHomeSpFqdn);
+                }
+            }
+        }
+        return result;
+    }
+
+    @Override
+    /** @hide */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        String none = "<none>";
+
+        if (!DBG) {
+            sb.append(none);
+        } else {
+            sb.append(", UpdateIdentifier: ")
+            .append(mUpdateIdentifier == null ? none : mUpdateIdentifier)
+            .append(", SubscriptionUpdateMethod: ")
+            .append(mSubscriptionUpdateMethod == null ? none : mSubscriptionUpdateMethod)
+            .append(", Type: ").append(mType == null ? none : mType)
+            .append(", Username: ").append(mUsername == null ? none : mUsername)
+            .append(", Passwd: ").append(mPasswd == null ? none : mPasswd)
+            .append(", SubDMAccUsername: ")
+            .append(mSubscriptionUpdateUsername == null ? none : mSubscriptionUpdateUsername)
+            .append(", SubDMAccPassword: ")
+            .append(mSubscriptionUpdatePassword == null ? none : mSubscriptionUpdatePassword)
+            .append(", PolDMAccUsername: ")
+            .append(mPolicyUpdateUsername == null ? none : mPolicyUpdateUsername)
+            .append(", PolDMAccPassword: ")
+            .append(mPolicyUpdatePassword == null ? none : mPolicyUpdatePassword)
+            .append(", Imsi: ").append(mImsi == null ? none : mImsi)
+            .append(", Mcc: ").append(mMcc == null ? none : mMcc)
+            .append(", Mnc: ").append(mMnc == null ? none : mMnc)
+            .append(", CaRootCert: ").append(mCaRootCert == null ? none : mCaRootCert)
+            .append(", Realm: ").append(mRealm == null ? none : mRealm)
+            .append(", Priority: ").append(mCrednetialPriority)
+            .append(", Fqdn: ").append(mHomeSpFqdn == null ? none : mHomeSpFqdn)
+            .append(", Otherhomepartners: ")
+            .append(mOtherHomePartnerList == null ? none : mOtherHomePartnerList)
+            .append(", ExpirationDate: ")
+            .append(mExpirationDate == null ? none : mExpirationDate)
+            .append(", MaxBssLoad: ").append(mMaxBssLoad == null ? none : mMaxBssLoad)
+            .append(", SPExclusionList: ").append(mSpExclusionList);
+
+            if (mPreferredRoamingPartnerList != null) {
+                sb.append("PreferredRoamingPartnerList:");
+                for (WifiPasspointDmTree.PreferredRoamingPartnerList prpListItem : mPreferredRoamingPartnerList) {
+                    sb.append("[fqdnmatch:").append(prpListItem.FQDN_Match).
+                            append(", priority:").append(prpListItem.Priority).
+                            append(", country:").append(prpListItem.Country).append("]");
+                }
+            }
+
+            if (mHomeOIList != null) {
+                sb.append("HomeOIList:");
+                for (WifiPasspointDmTree.HomeOIList HomeOIListItem : mHomeOIList) {
+                    sb.append("[HomeOI:").append(HomeOIListItem.HomeOI).
+                            append(", HomeOIRequired:").append(HomeOIListItem.HomeOIRequired).
+                            append("]");
+                }
+            }
+
+            if (mMinBackhaulThresholdNetwork != null) {
+                sb.append("BackHaulThreshold:");
+                for (WifiPasspointDmTree.MinBackhaulThresholdNetwork BhtListItem : mMinBackhaulThresholdNetwork) {
+                    sb.append("[networkType:").append(BhtListItem.NetworkType).
+                            append(", dlBandwidth:").append(BhtListItem.DLBandwidth).
+                            append(", ulBandwidth:").append(BhtListItem.ULBandwidth).
+                            append("]");
+                }
+            }
+
+            if (mRequiredProtoPortTuple != null) {
+                sb.append("WifiMORequiredProtoPortTupleList:");
+                for (WifiPasspointDmTree.RequiredProtoPortTuple RpptListItem : mRequiredProtoPortTuple) {
+                    sb.append("[IPProtocol:").append(RpptListItem.IPProtocol).
+                            append(", PortNumber:").append(RpptListItem.PortNumber).
+                            append("]");
+                }
+            }
+        }
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mWifiSpFqdn);
+        dest.writeString(mCredentialName);
+        dest.writeString(mType);
+        dest.writeInt(mCrednetialPriority);
+        dest.writeString(mHomeSpFqdn);
+        dest.writeString(mRealm);
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public void readFromParcel(Parcel in) {
+        mWifiSpFqdn = in.readString();
+        mCredentialName = in.readString();
+        mType = in.readString();
+        mCrednetialPriority = in.readInt();
+        mHomeSpFqdn = in.readString();
+        mRealm = in.readString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiPasspointCredential> CREATOR =
+            new Creator<WifiPasspointCredential>() {
+                public WifiPasspointCredential createFromParcel(Parcel in) {
+                    WifiPasspointCredential pc = new WifiPasspointCredential();
+                    pc.mWifiSpFqdn = in.readString();
+                    pc.mCredentialName = in.readString();
+                    pc.mType = in.readString();
+                    pc.mCrednetialPriority = in.readInt();
+                    pc.mHomeSpFqdn = in.readString();
+                    pc.mRealm = in.readString();
+                    return pc;
+                }
+
+                public WifiPasspointCredential[] newArray(int size) {
+                    return new WifiPasspointCredential[size];
+                }
+            };
+
+    /** @hide */
+    public int compareTo(WifiPasspointCredential another) {
+
+        //The smaller the higher
+        if (mCrednetialPriority < another.mCrednetialPriority) {
+            return -1;
+        } else if (mCrednetialPriority == another.mCrednetialPriority) {
+            return this.mType.compareTo(another.mType);
+        } else {
+            return 1;
+        }
+    }
+
+    @Override
+    /** @hide */
+    public int hashCode() {
+        int hash = 208;
+        if (mType != null) {
+            hash += mType.hashCode();
+        }
+        if (mRealm != null) {
+            hash += mRealm.hashCode();
+        }
+        if (mHomeSpFqdn != null) {
+            hash += mHomeSpFqdn.hashCode();
+        }
+        if (mUsername != null) {
+            hash += mUsername.hashCode();
+        }
+        if (mPasswd != null) {
+            hash += mPasswd.hashCode();
+        }
+
+        return hash;
+    }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
new file mode 100644
index 0000000..6a88b2e
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+parcelable WifiPasspointDmTree;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
new file mode 100644
index 0000000..bbf5fc6
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointDmTree.java
@@ -0,0 +1,1377 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * Required Mobile Device Management Tree Structure
+ *
+ *                   +----------+
+ *                   | ./(Root) |
+ *                   +----+-----+
+ *                        |
+ *  +---------+           |         +---------+  +---------+
+ *  | DevInfo |-----------+---------|  Wi-Fi  |--|SP FQDN* |
+ *  +---------+           |         +---------+  +---------+
+ *  +---------+           |                           |
+ *  |DevDetail|-----------+                      +-----------------------+
+ *  +---------+                                  |PerproviderSubscription|--<X>+
+ *                                               +-----------------------+
+ *
+ * This class contains all nodes start from Wi-Fi
+ * @hide
+ **/
+public class WifiPasspointDmTree implements Parcelable {
+    private final static String TAG = "WifiTree";
+    public int PpsMoId;//plugfest used only
+    public HashMap<String, SpFqdn> spFqdn = new HashMap<String, SpFqdn>();//Maps.newHashMap();
+
+    public SpFqdn createSpFqdn(String name) {
+        SpFqdn obj = new SpFqdn(name);
+        spFqdn.put(name, obj);
+        return obj;
+    }
+
+    public static class SpFqdn implements Parcelable {
+        public String nodeName;
+        public PerProviderSubscription perProviderSubscription = new PerProviderSubscription();
+
+        public SpFqdn(String name) {
+            nodeName = name;
+        }
+
+        public SpFqdn() {
+        }
+
+        public SpFqdn(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeParcelable(perProviderSubscription, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                perProviderSubscription = in.readParcelable(PerProviderSubscription.class
+                        .getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SpFqdn> CREATOR = new Parcelable.Creator<SpFqdn>() {
+            public SpFqdn createFromParcel(Parcel in) {
+                return new SpFqdn(in);
+            }
+
+            public SpFqdn[] newArray(int size) {
+                return new SpFqdn[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription
+     **/
+    public static class PerProviderSubscription implements Parcelable {
+        /**
+         * PerProviderSubscription/UpdateIdentifier
+         **/
+        public String UpdateIdentifier;
+        public HashMap<String, CredentialInfo> credentialInfo = new HashMap<String, CredentialInfo>();
+
+        public CredentialInfo createCredentialInfo(String name) {
+            CredentialInfo obj = new CredentialInfo(name);
+            credentialInfo.put(name, obj);
+            return obj;
+        }
+
+        public PerProviderSubscription() {
+        }
+
+        public PerProviderSubscription(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateIdentifier);
+            out.writeMap(credentialInfo);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateIdentifier = in.readString();
+                in.readMap(credentialInfo, CredentialInfo.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<PerProviderSubscription> CREATOR = new Parcelable.Creator<PerProviderSubscription>() {
+            public PerProviderSubscription createFromParcel(Parcel in) {
+                return new PerProviderSubscription(in);
+            }
+
+            public PerProviderSubscription[] newArray(int size) {
+                return new PerProviderSubscription[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>
+     * This interior node contains the Home SP information, subscription policy, management and credential information.
+     **/
+    public static class CredentialInfo implements Parcelable {
+        public String nodeName;
+        public Policy policy = new Policy();
+        public String credentialPriority;
+        public HashMap<String, AAAServerTrustRoot> aAAServerTrustRoot = new HashMap<String, AAAServerTrustRoot>();
+        public SubscriptionUpdate subscriptionUpdate = new SubscriptionUpdate();
+        public HomeSP homeSP = new HomeSP();
+        public SubscriptionParameters subscriptionParameters = new SubscriptionParameters();
+        public Credential credential = new Credential();
+        public Extension extension = new Extension();
+
+        public CredentialInfo(String nn) {
+            nodeName = nn;
+        }
+
+        public AAAServerTrustRoot createAAAServerTrustRoot(String name, String url, String fp) {
+            AAAServerTrustRoot obj = new AAAServerTrustRoot(name, url, fp);
+            aAAServerTrustRoot.put(name, obj);
+            return obj;
+        }
+
+        public CredentialInfo() {
+        }
+
+        public CredentialInfo(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeParcelable(policy, flags);
+            out.writeString(credentialPriority);
+            out.writeMap(aAAServerTrustRoot);
+            out.writeParcelable(subscriptionUpdate, flags);
+            out.writeParcelable(homeSP, flags);
+            out.writeParcelable(subscriptionParameters, flags);
+            out.writeParcelable(credential, flags);
+            //out.writeParcelable(extension, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                policy = in.readParcelable(Policy.class.getClassLoader());
+                credentialPriority = in.readString();
+                in.readMap(aAAServerTrustRoot, AAAServerTrustRoot.class.getClassLoader());
+                subscriptionUpdate = in.readParcelable(SubscriptionUpdate.class.getClassLoader());
+                homeSP = in.readParcelable(HomeSP.class.getClassLoader());
+                subscriptionParameters = in.readParcelable(SubscriptionParameters.class
+                        .getClassLoader());
+                credential = in.readParcelable(Credential.class.getClassLoader());
+                //extension = in.readParcelable(Extension.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<CredentialInfo> CREATOR = new Parcelable.Creator<CredentialInfo>() {
+            public CredentialInfo createFromParcel(Parcel in) {
+                return new CredentialInfo(in);
+            }
+
+            public CredentialInfo[] newArray(int size) {
+                return new CredentialInfo[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy
+     **/
+    public static class Policy implements Parcelable {
+        public HashMap<String, PreferredRoamingPartnerList> preferredRoamingPartnerList = new HashMap<String, PreferredRoamingPartnerList>();
+        public HashMap<String, MinBackhaulThresholdNetwork> minBackhaulThreshold = new HashMap<String, MinBackhaulThresholdNetwork>();
+        public PolicyUpdate policyUpdate = new PolicyUpdate();
+        public HashMap<String, SPExclusionList> sPExclusionList = new HashMap<String, SPExclusionList>();
+        public HashMap<String, RequiredProtoPortTuple> requiredProtoPortTuple = new HashMap<String, RequiredProtoPortTuple>();
+        public String maximumBSSLoadValue;
+
+        public PreferredRoamingPartnerList createPreferredRoamingPartnerList(String name,
+                String fqdn, String priority, String country) {
+            PreferredRoamingPartnerList obj = new PreferredRoamingPartnerList(name, fqdn, priority,
+                    country);
+            preferredRoamingPartnerList.put(name, obj);
+            return obj;
+        }
+
+        public MinBackhaulThresholdNetwork createMinBackhaulThreshold(String name, String type,
+                String dl, String ul) {
+            MinBackhaulThresholdNetwork obj = new MinBackhaulThresholdNetwork(name, type, dl, ul);
+            minBackhaulThreshold.put(name, obj);
+            return obj;
+        }
+
+        public SPExclusionList createSPExclusionList(String name, String ssid) {
+            SPExclusionList obj = new SPExclusionList(name, ssid);
+            sPExclusionList.put(name, obj);
+            return obj;
+        }
+
+        public RequiredProtoPortTuple createRequiredProtoPortTuple(String name, String proto,
+                String port) {
+            RequiredProtoPortTuple obj = new RequiredProtoPortTuple(name, proto, port);
+            requiredProtoPortTuple.put(name, obj);
+            return obj;
+        }
+
+        public Policy() {
+        }
+
+        public Policy(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeMap(preferredRoamingPartnerList);
+            out.writeMap(minBackhaulThreshold);
+            out.writeParcelable(policyUpdate, flags);
+            out.writeMap(sPExclusionList);
+            out.writeMap(requiredProtoPortTuple);
+            out.writeString(maximumBSSLoadValue);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                in.readMap(preferredRoamingPartnerList,
+                        PreferredRoamingPartnerList.class.getClassLoader());
+                in.readMap(minBackhaulThreshold, MinBackhaulThresholdNetwork.class.getClassLoader());
+                policyUpdate = in.readParcelable(PolicyUpdate.class.getClassLoader());
+                in.readMap(sPExclusionList, SPExclusionList.class.getClassLoader());
+                in.readMap(requiredProtoPortTuple, RequiredProtoPortTuple.class.getClassLoader());
+                maximumBSSLoadValue = in.readString();
+
+            }
+        }
+
+        public static final Parcelable.Creator<Policy> CREATOR = new Parcelable.Creator<Policy>() {
+            public Policy createFromParcel(Parcel in) {
+                return new Policy(in);
+            }
+
+            public Policy[] newArray(int size) {
+                return new Policy[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>
+     **/
+    public static class PreferredRoamingPartnerList implements Parcelable {
+        public String nodeName;
+        public String FQDN_Match; //maximum 255 + ",includeSubdomains", equals 273
+        public String Priority;
+        public String Country; // maximum 600 octets
+
+        public PreferredRoamingPartnerList(String nn, String f, String p, String c) {
+            nodeName = nn;
+            FQDN_Match = f;
+            Priority = p;
+            Country = c;
+        }
+
+        public PreferredRoamingPartnerList() {
+        }
+
+        public PreferredRoamingPartnerList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(FQDN_Match);
+            out.writeString(Priority);
+            out.writeString(Country);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                FQDN_Match = in.readString();
+                Priority = in.readString();
+                Country = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<PreferredRoamingPartnerList> CREATOR = new Parcelable.Creator<PreferredRoamingPartnerList>() {
+            public PreferredRoamingPartnerList createFromParcel(Parcel in) {
+                return new PreferredRoamingPartnerList(in);
+            }
+
+            public PreferredRoamingPartnerList[] newArray(int size) {
+                return new PreferredRoamingPartnerList[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/MinBackhaulThreshold
+     **/
+    public static class MinBackhaulThresholdNetwork implements Parcelable {
+        public String nodeName;
+        public String NetworkType;
+        public String DLBandwidth;
+        public String ULBandwidth;
+
+        public MinBackhaulThresholdNetwork(String nn, String nt, String d, String u) {
+            nodeName = nn;
+            NetworkType = nt;
+            DLBandwidth = d;
+            ULBandwidth = u;
+        }
+
+        public MinBackhaulThresholdNetwork() {
+        }
+
+        public MinBackhaulThresholdNetwork(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(NetworkType);
+            out.writeString(DLBandwidth);
+            out.writeString(ULBandwidth);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                NetworkType = in.readString();
+                DLBandwidth = in.readString();
+                ULBandwidth = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<MinBackhaulThresholdNetwork> CREATOR = new Parcelable.Creator<MinBackhaulThresholdNetwork>() {
+            public MinBackhaulThresholdNetwork createFromParcel(Parcel in) {
+                return new MinBackhaulThresholdNetwork(in);
+            }
+
+            public MinBackhaulThresholdNetwork[] newArray(int size) {
+                return new MinBackhaulThresholdNetwork[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate
+     **/
+    public static class PolicyUpdate implements Parcelable {
+        public String UpdateInterval;
+        public String UpdateMethod;
+        public String Restriction;
+        public String URI;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public String Other;
+        public TrustRoot trustRoot = new TrustRoot();
+
+        public PolicyUpdate() {
+        }
+
+        public PolicyUpdate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateInterval);
+            out.writeString(UpdateMethod);
+            out.writeString(Restriction);
+            out.writeString(URI);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeString(Other);
+            out.writeParcelable(trustRoot, flags);
+
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateInterval = in.readString();
+                UpdateMethod = in.readString();
+                Restriction = in.readString();
+                URI = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                Other = in.readString();
+                trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<PolicyUpdate> CREATOR = new Parcelable.Creator<PolicyUpdate>() {
+            public PolicyUpdate createFromParcel(Parcel in) {
+                return new PolicyUpdate(in);
+            }
+
+            public PolicyUpdate[] newArray(int size) {
+                return new PolicyUpdate[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/SPExclusionList
+     **/
+    public static class SPExclusionList implements Parcelable {
+        public String nodeName;
+        public String SSID;
+
+        public SPExclusionList(String nn, String s) {
+            nodeName = nn;
+            SSID = s;
+        }
+
+        public SPExclusionList() {
+        }
+
+        public SPExclusionList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(SSID);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                SSID = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<SPExclusionList> CREATOR = new Parcelable.Creator<SPExclusionList>() {
+            public SPExclusionList createFromParcel(Parcel in) {
+                return new SPExclusionList(in);
+            }
+
+            public SPExclusionList[] newArray(int size) {
+                return new SPExclusionList[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/RequiredProtoPortTuple
+     **/
+    public static class RequiredProtoPortTuple implements Parcelable {
+        public String nodeName;
+        public String IPProtocol;
+        public String PortNumber;
+
+        public RequiredProtoPortTuple() {
+        }
+
+        public RequiredProtoPortTuple(String nn, String protocol, String port) {
+            nodeName = nn;
+            IPProtocol = protocol;
+            PortNumber = port;
+        }
+
+        public RequiredProtoPortTuple(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(IPProtocol);
+            out.writeString(PortNumber);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                IPProtocol = in.readString();
+                PortNumber = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<RequiredProtoPortTuple> CREATOR = new Parcelable.Creator<RequiredProtoPortTuple>() {
+            public RequiredProtoPortTuple createFromParcel(Parcel in) {
+                return new RequiredProtoPortTuple(in);
+            }
+
+            public RequiredProtoPortTuple[] newArray(int size) {
+                return new RequiredProtoPortTuple[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/AAAServerTrustRoot
+     **/
+    public static class AAAServerTrustRoot implements Parcelable {
+        public String nodeName;
+        public String CertURL;
+        public String CertSHA256Fingerprint;
+
+        public AAAServerTrustRoot(String nn, String url, String fp) {
+            nodeName = nn;
+            CertURL = url;
+            CertSHA256Fingerprint = fp;
+        }
+
+        public AAAServerTrustRoot() {
+        }
+
+        public AAAServerTrustRoot(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(CertURL);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                CertURL = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<AAAServerTrustRoot> CREATOR = new Parcelable.Creator<AAAServerTrustRoot>() {
+            public AAAServerTrustRoot createFromParcel(Parcel in) {
+                return new AAAServerTrustRoot(in);
+            }
+
+            public AAAServerTrustRoot[] newArray(int size) {
+                return new AAAServerTrustRoot[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionUpdate
+     **/
+    public static class SubscriptionUpdate implements Parcelable {
+        public String UpdateInterval;
+        public String UpdateMethod;
+        public String Restriction;
+        public String URI;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public String Other;
+        public TrustRoot trustRoot = new TrustRoot();
+
+        public SubscriptionUpdate() {
+        }
+
+        public SubscriptionUpdate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(UpdateInterval);
+            out.writeString(UpdateMethod);
+            out.writeString(Restriction);
+            out.writeString(URI);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeString(Other);
+            out.writeParcelable(trustRoot, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                UpdateInterval = in.readString();
+                UpdateMethod = in.readString();
+                Restriction = in.readString();
+                URI = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                Other = in.readString();
+                trustRoot = in.readParcelable(TrustRoot.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SubscriptionUpdate> CREATOR = new Parcelable.Creator<SubscriptionUpdate>() {
+            public SubscriptionUpdate createFromParcel(Parcel in) {
+                return new SubscriptionUpdate(in);
+            }
+
+            public SubscriptionUpdate[] newArray(int size) {
+                return new SubscriptionUpdate[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate/TrustRoot
+     * PerProviderSubscription/<X+>/SubscriptionUpdate/TrustRoot
+     * PerProviderSubscription/<X+>/AAAServerTrustRoot/<X+>
+     **/
+    public static class TrustRoot implements Parcelable {
+        public String CertURL;
+        public String CertSHA256Fingerprint;
+
+        public TrustRoot() {
+        }
+
+        public TrustRoot(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CertURL);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CertURL = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<TrustRoot> CREATOR = new Parcelable.Creator<TrustRoot>() {
+            public TrustRoot createFromParcel(Parcel in) {
+                return new TrustRoot(in);
+            }
+
+            public TrustRoot[] newArray(int size) {
+                return new TrustRoot[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Policy/PolicyUpdate/UsernamePassword
+     * PerProviderSubscription/<X+>/SubscriptionUpdate/UsernamePassword
+     * PerProviderSubscription/<X+>/Credential/UsernamePassword
+     **/
+    public static class UsernamePassword implements Parcelable {
+        public String Username;
+        public String Password;
+        //following are Credential node used only
+        public boolean MachineManaged;
+        public String SoftTokenApp;
+        public String AbleToShare;
+        public EAPMethod eAPMethod = new EAPMethod();
+
+        public UsernamePassword() {
+        }
+
+        public UsernamePassword(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(Username);
+            out.writeString(Password);
+            out.writeInt(MachineManaged ? 1 : 0);
+            out.writeString(SoftTokenApp);
+            out.writeString(AbleToShare);
+            out.writeParcelable(eAPMethod, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                Username = in.readString();
+                Password = in.readString();
+                MachineManaged = (in.readInt() == 1) ? true : false;
+                SoftTokenApp = in.readString();
+                AbleToShare = in.readString();
+                eAPMethod = in.readParcelable(EAPMethod.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<UsernamePassword> CREATOR = new Parcelable.Creator<UsernamePassword>() {
+            public UsernamePassword createFromParcel(Parcel in) {
+                return new UsernamePassword(in);
+            }
+
+            public UsernamePassword[] newArray(int size) {
+                return new UsernamePassword[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/UsernamePassword/EAPMethod
+     **/
+    public static class EAPMethod implements Parcelable {
+        public String EAPType;
+        public String VendorId;
+        public String VendorType;
+        public String InnerEAPType;
+        public String InnerVendorId;
+        public String InnerVendorType;
+        public String InnerMethod;
+
+        public EAPMethod() {
+        }
+
+        public EAPMethod(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(EAPType);
+            out.writeString(VendorId);
+            out.writeString(VendorType);
+            out.writeString(InnerEAPType);
+            out.writeString(InnerVendorId);
+            out.writeString(InnerVendorType);
+            out.writeString(InnerMethod);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                EAPType = in.readString();
+                VendorId = in.readString();
+                VendorType = in.readString();
+                InnerEAPType = in.readString();
+                InnerVendorId = in.readString();
+                InnerVendorType = in.readString();
+                InnerMethod = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<EAPMethod> CREATOR = new Parcelable.Creator<EAPMethod>() {
+            public EAPMethod createFromParcel(Parcel in) {
+                return new EAPMethod(in);
+            }
+
+            public EAPMethod[] newArray(int size) {
+                return new EAPMethod[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP
+     **/
+    public static class HomeSP implements Parcelable {
+        public HashMap<String, NetworkID> networkID = new HashMap<String, NetworkID>();
+        public String FriendlyName;
+        public String IconURL;
+        public String FQDN;
+        public HashMap<String, HomeOIList> homeOIList = new HashMap<String, HomeOIList>();
+        public HashMap<String, OtherHomePartners> otherHomePartners = new HashMap<String, OtherHomePartners>();
+        public String RoamingConsortiumOI;
+
+        public NetworkID createNetworkID(String name, String ssid, String hessid) {
+            NetworkID obj = new NetworkID(name, ssid, hessid);
+            networkID.put(name, obj);
+            return obj;
+        }
+
+        public HomeOIList createHomeOIList(String name, String homeoi, boolean required) {
+            HomeOIList obj = new HomeOIList(name, homeoi, required);
+            homeOIList.put(name, obj);
+            return obj;
+        }
+
+        public OtherHomePartners createOtherHomePartners(String name, String fqdn) {
+            OtherHomePartners obj = new OtherHomePartners(name, fqdn);
+            otherHomePartners.put(name, obj);
+            return obj;
+        }
+
+        public HomeSP() {
+        }
+
+        public HomeSP(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeMap(networkID);
+            out.writeString(FriendlyName);
+            out.writeString(IconURL);
+            out.writeString(FQDN);
+            out.writeMap(homeOIList);
+            out.writeMap(otherHomePartners);
+            out.writeString(RoamingConsortiumOI);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                in.readMap(networkID, NetworkID.class.getClassLoader());
+                FriendlyName = in.readString();
+                IconURL = in.readString();
+                FQDN = in.readString();
+                in.readMap(homeOIList, HomeOIList.class.getClassLoader());
+                in.readMap(otherHomePartners, OtherHomePartners.class.getClassLoader());
+                RoamingConsortiumOI = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<HomeSP> CREATOR = new Parcelable.Creator<HomeSP>() {
+            public HomeSP createFromParcel(Parcel in) {
+                return new HomeSP(in);
+            }
+
+            public HomeSP[] newArray(int size) {
+                return new HomeSP[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/NetworkID
+     **/
+    public static class NetworkID implements Parcelable {
+        public String nodeName;
+        public String SSID;
+        public String HESSID;
+
+        public NetworkID(String nn, String s, String h) {
+            nodeName = nn;
+            SSID = s;
+            HESSID = h;
+        }
+
+        public NetworkID() {
+        }
+
+        public NetworkID(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(SSID);
+            out.writeString(HESSID);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                SSID = in.readString();
+                HESSID = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<NetworkID> CREATOR = new Parcelable.Creator<NetworkID>() {
+            public NetworkID createFromParcel(Parcel in) {
+                return new NetworkID(in);
+            }
+
+            public NetworkID[] newArray(int size) {
+                return new NetworkID[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/HomeOIList
+     **/
+    public static class HomeOIList implements Parcelable {
+        public String nodeName;
+        public String HomeOI;
+        public boolean HomeOIRequired;
+
+        public HomeOIList(String nn, String h, boolean r) {
+            nodeName = nn;
+            HomeOI = h;
+            HomeOIRequired = r;
+        }
+
+        public HomeOIList() {
+        }
+
+        public HomeOIList(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(HomeOI);
+            out.writeInt(HomeOIRequired ? 1 : 0);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                HomeOI = in.readString();
+                HomeOIRequired = (in.readInt() == 1) ? true : false;
+            }
+        }
+
+        public static final Parcelable.Creator<HomeOIList> CREATOR = new Parcelable.Creator<HomeOIList>() {
+            public HomeOIList createFromParcel(Parcel in) {
+                return new HomeOIList(in);
+            }
+
+            public HomeOIList[] newArray(int size) {
+                return new HomeOIList[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/HomeSP/OtherHomePartners
+     **/
+    public static class OtherHomePartners implements Parcelable {
+        public String nodeName;
+        public String FQDN;
+
+        public OtherHomePartners(String nn, String f) {
+            nodeName = nn;
+            FQDN = f;
+        }
+
+        public OtherHomePartners() {
+        }
+
+        public OtherHomePartners(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(nodeName);
+            out.writeString(FQDN);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                nodeName = in.readString();
+                FQDN = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<OtherHomePartners> CREATOR = new Parcelable.Creator<OtherHomePartners>() {
+            public OtherHomePartners createFromParcel(Parcel in) {
+                return new OtherHomePartners(in);
+            }
+
+            public OtherHomePartners[] newArray(int size) {
+                return new OtherHomePartners[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionParameters
+     **/
+    public static class SubscriptionParameters implements Parcelable {
+        public String CreationDate;
+        public String ExpirationDate;
+        public String TypeOfSubscription;
+        public UsageLimits usageLimits = new UsageLimits();
+
+        public SubscriptionParameters() {
+        }
+
+        public SubscriptionParameters(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CreationDate);
+            out.writeString(ExpirationDate);
+            out.writeString(TypeOfSubscription);
+            out.writeParcelable(usageLimits, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CreationDate = in.readString();
+                ExpirationDate = in.readString();
+                TypeOfSubscription = in.readString();
+                usageLimits = in.readParcelable(UsageLimits.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<SubscriptionParameters> CREATOR = new Parcelable.Creator<SubscriptionParameters>() {
+            public SubscriptionParameters createFromParcel(Parcel in) {
+                return new SubscriptionParameters(in);
+            }
+
+            public SubscriptionParameters[] newArray(int size) {
+                return new SubscriptionParameters[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/SubscriptionParameters/UsageLimits
+     **/
+    public static class UsageLimits implements Parcelable {
+        public String DataLimit;
+        public String StartDate;
+        public String TimeLimit;
+        public String UsageTimePeriod;
+
+        public UsageLimits() {
+        }
+
+        public UsageLimits(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(DataLimit);
+            out.writeString(StartDate);
+            out.writeString(TimeLimit);
+            out.writeString(UsageTimePeriod);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                DataLimit = in.readString();
+                StartDate = in.readString();
+                TimeLimit = in.readString();
+                UsageTimePeriod = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<UsageLimits> CREATOR = new Parcelable.Creator<UsageLimits>() {
+            public UsageLimits createFromParcel(Parcel in) {
+                return new UsageLimits(in);
+            }
+
+            public UsageLimits[] newArray(int size) {
+                return new UsageLimits[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential
+     **/
+    public static class Credential implements Parcelable {
+        public String CreationDate;
+        public String ExpirationDate;
+        public UsernamePassword usernamePassword = new UsernamePassword();
+        public DigitalCertificate digitalCertificate = new DigitalCertificate();
+        public String Realm;
+        public boolean CheckAAAServerCertStatus;
+        public SIM sim = new SIM();
+
+        public Credential() {
+        }
+
+        public Credential(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CreationDate);
+            out.writeString(ExpirationDate);
+            out.writeParcelable(usernamePassword, flags);
+            out.writeParcelable(digitalCertificate, flags);
+            out.writeString(Realm);
+            out.writeInt(CheckAAAServerCertStatus ? 1 : 0);
+            out.writeParcelable(sim, flags);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CreationDate = in.readString();
+                ExpirationDate = in.readString();
+                usernamePassword = in.readParcelable(UsernamePassword.class.getClassLoader());
+                digitalCertificate = in.readParcelable(DigitalCertificate.class.getClassLoader());
+                Realm = in.readString();
+                CheckAAAServerCertStatus = (in.readInt() == 1) ? true : false;
+                sim = in.readParcelable(SIM.class.getClassLoader());
+            }
+        }
+
+        public static final Parcelable.Creator<Credential> CREATOR = new Parcelable.Creator<Credential>() {
+            public Credential createFromParcel(Parcel in) {
+                return new Credential(in);
+            }
+
+            public Credential[] newArray(int size) {
+                return new Credential[size];
+            }
+        };
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/DigitalCertificate
+     **/
+    public static class DigitalCertificate implements Parcelable {
+        public String CertificateType;
+        public String CertSHA256Fingerprint;
+
+        public DigitalCertificate() {
+        }
+
+        public DigitalCertificate(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(CertificateType);
+            out.writeString(CertSHA256Fingerprint);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                CertificateType = in.readString();
+                CertSHA256Fingerprint = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<DigitalCertificate> CREATOR = new Parcelable.Creator<DigitalCertificate>() {
+            public DigitalCertificate createFromParcel(Parcel in) {
+                return new DigitalCertificate(in);
+            }
+
+            public DigitalCertificate[] newArray(int size) {
+                return new DigitalCertificate[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Credential/SIM
+     **/
+    public static class SIM implements Parcelable {
+        public String IMSI;
+        public String EAPType;
+
+        public SIM() {
+        }
+
+        public SIM(Parcel in) {
+            readFromParcel(in);
+        }
+
+        public int describeContents() {
+            return 0;
+        }
+
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(IMSI);
+            out.writeString(EAPType);
+        }
+
+        public void readFromParcel(Parcel in) {
+            if (in == null) {
+                //log here
+            } else {
+                IMSI = in.readString();
+                EAPType = in.readString();
+            }
+        }
+
+        public static final Parcelable.Creator<SIM> CREATOR = new Parcelable.Creator<SIM>() {
+            public SIM createFromParcel(Parcel in) {
+                return new SIM(in);
+            }
+
+            public SIM[] newArray(int size) {
+                return new SIM[size];
+            }
+        };
+
+    }
+
+    /**
+     * PerProviderSubscription/<X+>/Extension
+     **/
+    public static class Extension {
+        public String empty;
+    }
+
+    public WifiPasspointDmTree() {
+    }
+
+    public WifiPasspointDmTree(Parcel in) {
+        readFromParcel(in);
+    }
+
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeMap(spFqdn);
+    }
+
+    public void readFromParcel(Parcel in) {
+        if (in == null) {
+            //log here
+        } else {
+            in.readMap(spFqdn, SpFqdn.class.getClassLoader());
+        }
+    }
+
+    public static final Parcelable.Creator<WifiPasspointDmTree> CREATOR = new Parcelable.Creator<WifiPasspointDmTree>() {
+        public WifiPasspointDmTree createFromParcel(Parcel in) {
+            return new WifiPasspointDmTree(in);
+        }
+
+        public WifiPasspointDmTree[] newArray(int size) {
+            return new WifiPasspointDmTree[size];
+        }
+    };
+
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
new file mode 100644
index 0000000..27f23bc
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+parcelable WifiPasspointInfo;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
new file mode 100644
index 0000000..33db3f5
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** @hide */
+public class WifiPasspointInfo implements Parcelable {
+
+    /** TODO doc */
+    public static final int ANQP_CAPABILITY = 1 << 0;
+
+    /** TODO doc */
+    public static final int VENUE_NAME = 1 << 1;
+
+    /** TODO doc */
+    public static final int NETWORK_AUTH_TYPE = 1 << 2;
+
+    /** TODO doc */
+    public static final int ROAMING_CONSORTIUM = 1 << 3;
+
+    /** TODO doc */
+    public static final int IP_ADDR_TYPE_AVAILABILITY = 1 << 4;
+
+    /** TODO doc */
+    public static final int NAI_REALM = 1 << 5;
+
+    /** TODO doc */
+    public static final int CELLULAR_NETWORK = 1 << 6;
+
+    /** TODO doc */
+    public static final int DOMAIN_NAME = 1 << 7;
+
+    /** TODO doc */
+    public static final int HOTSPOT_CAPABILITY = 1 << 8;
+
+    /** TODO doc */
+    public static final int OPERATOR_FRIENDLY_NAME = 1 << 9;
+
+    /** TODO doc */
+    public static final int WAN_METRICS = 1 << 10;
+
+    /** TODO doc */
+    public static final int CONNECTION_CAPABILITY = 1 << 11;
+
+    /** TODO doc */
+    public static final int OSU_PROVIDER = 1 << 12;
+
+    /** TODO doc */
+    public static final int PRESET_CRED_MATCH =
+            ANQP_CAPABILITY |
+                    HOTSPOT_CAPABILITY |
+                    NAI_REALM |
+                    CELLULAR_NETWORK |
+                    DOMAIN_NAME;
+
+    /** TODO doc */
+    public static final int PRESET_ALL =
+            ANQP_CAPABILITY |
+                    VENUE_NAME |
+                    NETWORK_AUTH_TYPE |
+                    ROAMING_CONSORTIUM |
+                    IP_ADDR_TYPE_AVAILABILITY |
+                    NAI_REALM |
+                    CELLULAR_NETWORK |
+                    DOMAIN_NAME |
+                    HOTSPOT_CAPABILITY |
+                    OPERATOR_FRIENDLY_NAME |
+                    WAN_METRICS |
+                    CONNECTION_CAPABILITY |
+                    OSU_PROVIDER;
+
+
+    public static class WanMetrics {
+        public static final int STATUS_RESERVED = 0;
+        public static final int STATUS_UP = 1;
+        public static final int STATUS_DOWN = 2;
+        public static final int STATUS_TEST = 3;
+
+        public int wanInfo;
+        public long downlinkSpeed;
+        public long uplinkSpeed;
+        public int downlinkLoad;
+        public int uplinkLoad;
+        public int lmd;
+
+        public int getLinkStatus() {
+            return wanInfo & 0x3;
+        }
+
+        public boolean getSymmetricLink() {
+            return (wanInfo & (1 << 2)) != 0;
+        }
+
+        public boolean getAtCapacity() {
+            return (wanInfo & (1 << 3)) != 0;
+        }
+
+        @Override
+        public String toString() {
+            return wanInfo + "," + downlinkSpeed + "," + uplinkSpeed + "," +
+                    downlinkLoad + "," + uplinkLoad + "," + lmd;
+        }
+    }
+
+    public static class IpProtoPort {
+        public static final int STATUS_CLOSED = 0;
+        public static final int STATUS_OPEN = 1;
+        public static final int STATUS_UNKNOWN = 2;
+
+        public int proto;
+        public int port;
+        public int status;
+
+        @Override
+        public String toString() {
+            return proto + "," + port + "," + status;
+        }
+    }
+
+    public static class NetworkAuthType {
+        public static final int TYPE_TERMS_AND_CONDITION = 0;
+        public static final int TYPE_ONLINE_ENROLLMENT = 1;
+        public static final int TYPE_HTTP_REDIRECTION = 2;
+        public static final int TYPE_DNS_REDIRECTION = 3;
+
+        public int type;
+        public String redirectUrl;
+
+        @Override
+        public String toString() {
+            return type + "," + redirectUrl;
+        }
+    }
+
+    public static class IpAddressType {
+        public static final int IPV6_NOT_AVAILABLE = 0;
+        public static final int IPV6_AVAILABLE = 1;
+        public static final int IPV6_UNKNOWN = 2;
+
+        public static final int IPV4_NOT_AVAILABLE = 0;
+        public static final int IPV4_PUBLIC = 1;
+        public static final int IPV4_PORT_RESTRICTED = 2;
+        public static final int IPV4_SINGLE_NAT = 3;
+        public static final int IPV4_DOUBLE_NAT = 4;
+        public static final int IPV4_PORT_RESTRICTED_SINGLE_NAT = 5;
+        public static final int IPV4_PORT_RESTRICTED_DOUBLE_NAT = 6;
+        public static final int IPV4_PORT_UNKNOWN = 7;
+
+        private static final int NULL_VALUE = -1;
+
+        public int availability;
+
+        public int getIpv6Availability() {
+            return availability & 0x3;
+        }
+
+        public int getIpv4Availability() {
+            return (availability & 0xFF) >> 2;
+        }
+
+        @Override
+        public String toString() {
+            return getIpv6Availability() + "," + getIpv4Availability();
+        }
+    }
+
+    public static class NaiRealm {
+        public static final int ENCODING_RFC4282 = 0;
+        public static final int ENCODING_UTF8 = 1;
+
+        public int encoding;
+        public String realm;
+
+        @Override
+        public String toString() {
+            return encoding + "," + realm;
+        }
+    }
+
+    public static class CellularNetwork {
+        public String mcc;
+        public String mnc;
+
+        @Override
+        public String toString() {
+            return mcc + "," + mnc;
+        }
+    }
+
+    /** BSSID */
+    public String bssid;
+
+    /** venue name */
+    public String venueName;
+
+    /** list of network authentication types */
+    public List<NetworkAuthType> networkAuthTypeList;
+
+    /** list of roaming consortium OIs */
+    public List<String> roamingConsortiumList;
+
+    /** IP address availability */
+    public IpAddressType ipAddrTypeAvailability;
+
+    /** list of NAI realm */
+    public List<NaiRealm> naiRealmList;
+
+    /** list of 3GPP cellular network */
+    public List<CellularNetwork> cellularNetworkList;
+
+    /** list of fully qualified domain name (FQDN) */
+    public List<String> domainNameList;
+
+    /** HS 2.0 operator friendly name */
+    public String operatorFriendlyName;
+
+    /** HS 2.0 wan metrics */
+    public WanMetrics wanMetrics;
+
+    /** list of HS 2.0 IP proto port */
+    public List<IpProtoPort> connectionCapabilityList;
+
+    /** list of HS 2.0 OSU providers */
+    public List<WifiPasspointOsuProvider> osuProviderList;
+
+    /**
+     * Convert mask to ANQP subtypes, for supplicant command use.
+     *
+     * @param mask The ANQP subtypes mask.
+     * @return String of ANQP subtypes, good for supplicant command use
+     * @hide
+     */
+    public static String toAnqpSubtypes(int mask) {
+        StringBuilder sb = new StringBuilder();
+        if ((mask & ANQP_CAPABILITY) != 0)
+            sb.append("257,");
+        if ((mask & VENUE_NAME) != 0)
+            sb.append("258,");
+        if ((mask & NETWORK_AUTH_TYPE) != 0)
+            sb.append("260,");
+        if ((mask & ROAMING_CONSORTIUM) != 0)
+            sb.append("261,");
+        if ((mask & IP_ADDR_TYPE_AVAILABILITY) != 0)
+            sb.append("262,");
+        if ((mask & NAI_REALM) != 0)
+            sb.append("263,");
+        if ((mask & CELLULAR_NETWORK) != 0)
+            sb.append("264,");
+        if ((mask & DOMAIN_NAME) != 0)
+            sb.append("268,");
+        if ((mask & HOTSPOT_CAPABILITY) != 0)
+            sb.append("hs20:2,");
+        if ((mask & OPERATOR_FRIENDLY_NAME) != 0)
+            sb.append("hs20:3,");
+        if ((mask & WAN_METRICS) != 0)
+            sb.append("hs20:4,");
+        if ((mask & CONNECTION_CAPABILITY) != 0)
+            sb.append("hs20:5,");
+        if ((mask & OSU_PROVIDER) != 0)
+            sb.append("hs20:8,");
+        if (sb.length() > 0)
+            sb.deleteCharAt(sb.length() - 1);
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("BSSID: ").append("(").append(bssid).append(")");
+
+        if (venueName != null)
+            sb.append(" venueName: ").append("(")
+              .append(venueName.replace("\n", "\\n")).append(")");
+
+        if (networkAuthTypeList != null) {
+            sb.append(" networkAuthType: ");
+            for (NetworkAuthType auth : networkAuthTypeList)
+                sb.append("(").append(auth.toString()).append(")");
+        }
+
+        if (roamingConsortiumList != null) {
+            sb.append(" roamingConsortium: ");
+            for (String oi : roamingConsortiumList)
+                sb.append("(").append(oi).append(")");
+        }
+
+        if (ipAddrTypeAvailability != null) {
+            sb.append(" ipAddrTypeAvaibility: ").append("(")
+              .append(ipAddrTypeAvailability.toString()).append(")");
+        }
+
+        if (naiRealmList != null) {
+            sb.append(" naiRealm: ");
+            for (NaiRealm realm : naiRealmList)
+                sb.append("(").append(realm.toString()).append(")");
+        }
+
+        if (cellularNetworkList != null) {
+            sb.append(" cellularNetwork: ");
+            for (CellularNetwork plmn : cellularNetworkList)
+                sb.append("(").append(plmn.toString()).append(")");
+        }
+
+        if (domainNameList != null) {
+            sb.append(" domainName: ");
+            for (String fqdn : domainNameList)
+                sb.append("(").append(fqdn).append(")");
+        }
+
+        if (operatorFriendlyName != null)
+            sb.append(" operatorFriendlyName: ").append("(")
+              .append(operatorFriendlyName).append(")");
+
+        if (wanMetrics != null)
+            sb.append(" wanMetrics: ").append("(")
+              .append(wanMetrics.toString()).append(")");
+
+        if (connectionCapabilityList != null) {
+            sb.append(" connectionCapability: ");
+            for (IpProtoPort ip : connectionCapabilityList)
+                sb.append("(").append(ip.toString()).append(")");
+        }
+
+        if (osuProviderList != null) {
+            sb.append(" osuProviderList: ");
+            for (WifiPasspointOsuProvider osu : osuProviderList)
+                sb.append("(").append(osu.toString()).append(")");
+        }
+
+        return sb.toString();
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(bssid);
+        out.writeString(venueName);
+
+        if (networkAuthTypeList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(networkAuthTypeList.size());
+            for (NetworkAuthType auth : networkAuthTypeList) {
+                out.writeInt(auth.type);
+                out.writeString(auth.redirectUrl);
+            }
+        }
+
+        if (roamingConsortiumList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(roamingConsortiumList.size());
+            for (String oi : roamingConsortiumList)
+                out.writeString(oi);
+        }
+
+        if (ipAddrTypeAvailability == null) {
+            out.writeInt(IpAddressType.NULL_VALUE);
+        } else {
+            out.writeInt(ipAddrTypeAvailability.availability);
+        }
+
+        if (naiRealmList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(naiRealmList.size());
+            for (NaiRealm realm : naiRealmList) {
+                out.writeInt(realm.encoding);
+                out.writeString(realm.realm);
+            }
+        }
+
+        if (cellularNetworkList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(cellularNetworkList.size());
+            for (CellularNetwork plmn : cellularNetworkList) {
+                out.writeString(plmn.mcc);
+                out.writeString(plmn.mnc);
+            }
+        }
+
+
+        if (domainNameList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(domainNameList.size());
+            for (String fqdn : domainNameList)
+                out.writeString(fqdn);
+        }
+
+        out.writeString(operatorFriendlyName);
+
+        if (wanMetrics == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(1);
+            out.writeInt(wanMetrics.wanInfo);
+            out.writeLong(wanMetrics.downlinkSpeed);
+            out.writeLong(wanMetrics.uplinkSpeed);
+            out.writeInt(wanMetrics.downlinkLoad);
+            out.writeInt(wanMetrics.uplinkLoad);
+            out.writeInt(wanMetrics.lmd);
+        }
+
+        if (connectionCapabilityList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(connectionCapabilityList.size());
+            for (IpProtoPort ip : connectionCapabilityList) {
+                out.writeInt(ip.proto);
+                out.writeInt(ip.port);
+                out.writeInt(ip.status);
+            }
+        }
+
+        if (osuProviderList == null) {
+            out.writeInt(0);
+        } else {
+            out.writeInt(osuProviderList.size());
+            for (WifiPasspointOsuProvider osu : osuProviderList)
+                osu.writeToParcel(out, flags);
+        }
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Parcelable.Creator<WifiPasspointInfo> CREATOR =
+            new Parcelable.Creator<WifiPasspointInfo>() {
+                @Override
+                public WifiPasspointInfo createFromParcel(Parcel in) {
+                    WifiPasspointInfo p = new WifiPasspointInfo();
+                    int n;
+
+                    p.bssid = in.readString();
+                    p.venueName = in.readString();
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.networkAuthTypeList = new ArrayList<NetworkAuthType>();
+                        for (int i = 0; i < n; i++) {
+                            NetworkAuthType auth = new NetworkAuthType();
+                            auth.type = in.readInt();
+                            auth.redirectUrl = in.readString();
+                            p.networkAuthTypeList.add(auth);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.roamingConsortiumList = new ArrayList<String>();
+                        for (int i = 0; i < n; i++)
+                            p.roamingConsortiumList.add(in.readString());
+                    }
+
+                    n = in.readInt();
+                    if (n != IpAddressType.NULL_VALUE) {
+                        p.ipAddrTypeAvailability = new IpAddressType();
+                        p.ipAddrTypeAvailability.availability = n;
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.naiRealmList = new ArrayList<NaiRealm>();
+                        for (int i = 0; i < n; i++) {
+                            NaiRealm realm = new NaiRealm();
+                            realm.encoding = in.readInt();
+                            realm.realm = in.readString();
+                            p.naiRealmList.add(realm);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.cellularNetworkList = new ArrayList<CellularNetwork>();
+                        for (int i = 0; i < n; i++) {
+                            CellularNetwork plmn = new CellularNetwork();
+                            plmn.mcc = in.readString();
+                            plmn.mnc = in.readString();
+                            p.cellularNetworkList.add(plmn);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.domainNameList = new ArrayList<String>();
+                        for (int i = 0; i < n; i++)
+                            p.domainNameList.add(in.readString());
+                    }
+
+                    p.operatorFriendlyName = in.readString();
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.wanMetrics = new WanMetrics();
+                        p.wanMetrics.wanInfo = in.readInt();
+                        p.wanMetrics.downlinkSpeed = in.readLong();
+                        p.wanMetrics.uplinkSpeed = in.readLong();
+                        p.wanMetrics.downlinkLoad = in.readInt();
+                        p.wanMetrics.uplinkLoad = in.readInt();
+                        p.wanMetrics.lmd = in.readInt();
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.connectionCapabilityList = new ArrayList<IpProtoPort>();
+                        for (int i = 0; i < n; i++) {
+                            IpProtoPort ip = new IpProtoPort();
+                            ip.proto = in.readInt();
+                            ip.port = in.readInt();
+                            ip.status = in.readInt();
+                            p.connectionCapabilityList.add(ip);
+                        }
+                    }
+
+                    n = in.readInt();
+                    if (n > 0) {
+                        p.osuProviderList = new ArrayList<WifiPasspointOsuProvider>();
+                        for (int i = 0; i < n; i++) {
+                            WifiPasspointOsuProvider osu = WifiPasspointOsuProvider.CREATOR
+                                    .createFromParcel(in);
+                            p.osuProviderList.add(osu);
+                        }
+                    }
+
+                    return p;
+                }
+
+                @Override
+                public WifiPasspointInfo[] newArray(int size) {
+                    return new WifiPasspointInfo[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
new file mode 100644
index 0000000..b9b17eb
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointManager.java
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.content.Context;
+import android.net.wifi.ScanResult;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Provides APIs for managing Wifi Passpoint credentials.
+ * @hide
+ */
+public class WifiPasspointManager {
+
+    private static final String TAG = "PasspointManager";
+
+    private static final boolean DBG = true;
+
+    /* Passpoint states values */
+
+    /** Passpoint is in an unknown state. This should only occur in boot time */
+    public static final int PASSPOINT_STATE_UNKNOWN = 0;
+
+    /** Passpoint is disabled. This occurs when wifi is disabled */
+    public static final int PASSPOINT_STATE_DISABLED = 1;
+
+    /** Passpoint is enabled and in discovery state */
+    public static final int PASSPOINT_STATE_DISCOVERY = 2;
+
+    /** Passpoint is enabled and in access state */
+    public static final int PASSPOINT_STATE_ACCESS = 3;
+
+    /** Passpoint is enabled and in provisioning state */
+    public static final int PASSPOINT_STATE_PROVISION = 4;
+
+    /* Passpoint callback error codes */
+
+    /** Indicates that the operation failed due to an internal error */
+    public static final int REASON_ERROR = 0;
+
+    /** Indicates that the operation failed because wifi is disabled */
+    public static final int REASON_WIFI_DISABLED = 1;
+
+    /** Indicates that the operation failed because the framework is busy */
+    public static final int REASON_BUSY = 2;
+
+    /** Indicates that the operation failed because parameter is invalid */
+    public static final int REASON_INVALID_PARAMETER = 3;
+
+    /** Indicates that the operation failed because the server is not trusted */
+    public static final int REASON_NOT_TRUSTED = 4;
+
+    /**
+     * protocol supported for Passpoint
+     */
+    public static final String PROTOCOL_DM = "OMA-DM-ClientInitiated";
+
+    /**
+     * protocol supported for Passpoint
+     */
+    public static final String PROTOCOL_SOAP = "SPP-ClientInitiated";
+
+    /* Passpoint broadcasts */
+
+    /**
+     * Broadcast intent action indicating that the state of Passpoint
+     * connectivity has changed
+     */
+    public static final String PASSPOINT_STATE_CHANGED_ACTION =
+            "android.net.wifi.passpoint.STATE_CHANGE";
+
+    /**
+     * Broadcast intent action indicating that the saved Passpoint credential
+     * list has changed
+     */
+    public static final String PASSPOINT_CRED_CHANGED_ACTION =
+            "android.net.wifi.passpoint.CRED_CHANGE";
+
+    /**
+     * Broadcast intent action indicating that Passpoint online sign up is
+     * avaiable.
+     */
+    public static final String PASSPOINT_OSU_AVAILABLE_ACTION =
+            "android.net.wifi.passpoint.OSU_AVAILABLE";
+
+    /**
+     * Broadcast intent action indicating that user remediation is required
+     */
+    public static final String PASSPOINT_USER_REM_REQ_ACTION =
+            "android.net.wifi.passpoint.USER_REM_REQ";
+
+    /**
+     * Interface for callback invocation when framework channel is lost
+     */
+    public interface ChannelListener {
+        /**
+         * The channel to the framework has been disconnected. Application could
+         * try re-initializing using {@link #initialize}
+         */
+        public void onChannelDisconnected();
+    }
+
+    /**
+     * Interface for callback invocation on an application action
+     */
+    public interface ActionListener {
+        /** The operation succeeded */
+        public void onSuccess();
+
+        /**
+         * The operation failed
+         *
+         * @param reason The reason for failure could be one of
+         *            {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+         */
+        public void onFailure(int reason);
+    }
+
+    /**
+     * Interface for callback invocation when doing OSU or user remediation
+     */
+    public interface OsuRemListener {
+        /** The operation succeeded */
+        public void onSuccess();
+
+        /**
+         * The operation failed
+         *
+         * @param reason The reason for failure could be one of
+         *            {@link #WIFI_DISABLED}, {@link #ERROR} or {@link #BUSY}
+         */
+        public void onFailure(int reason);
+
+        /**
+         * Browser launch is requried for user interaction. When this callback
+         * is called, app should launch browser / webview to the given URI.
+         *
+         * @param uri URI for browser launch
+         */
+        public void onBrowserLaunch(String uri);
+
+        /**
+         * When this is called, app should dismiss the previously lanched browser.
+         */
+        public void onBrowserDismiss();
+    }
+
+    /**
+     * A channel that connects the application to the wifi passpoint framework.
+     * Most passpoint operations require a Channel as an argument.
+     * An instance of Channel is obtained by doing a call on {@link #initialize}
+     */
+    public static class Channel {
+        private final static int INVALID_LISTENER_KEY = 0;
+
+        private ChannelListener mChannelListener;
+
+        private HashMap<Integer, Object> mListenerMap = new HashMap<Integer, Object>();
+        private HashMap<Integer, Integer> mListenerMapCount = new HashMap<Integer, Integer>();
+        private Object mListenerMapLock = new Object();
+        private int mListenerKey = 0;
+
+        private List<ScanResult> mAnqpRequest = new LinkedList<ScanResult>();
+        private Object mAnqpRequestLock = new Object();
+
+        private AsyncChannel mAsyncChannel;
+        private PasspointHandler mHandler;
+        Context mContext;
+
+        Channel(Context context, Looper looper, ChannelListener l) {
+            mAsyncChannel = new AsyncChannel();
+            mHandler = new PasspointHandler(looper);
+            mChannelListener = l;
+            mContext = context;
+        }
+
+        private int putListener(Object listener) {
+            return putListener(listener, 1);
+        }
+
+        private int putListener(Object listener, int count) {
+            if (listener == null || count <= 0)
+                return INVALID_LISTENER_KEY;
+            int key;
+            synchronized (mListenerMapLock) {
+                do {
+                    key = mListenerKey++;
+                } while (key == INVALID_LISTENER_KEY);
+                mListenerMap.put(key, listener);
+                mListenerMapCount.put(key, count);
+            }
+            return key;
+        }
+
+        private Object peekListener(int key) {
+            Log.d(TAG, "peekListener() key=" + key);
+            if (key == INVALID_LISTENER_KEY)
+                return null;
+            synchronized (mListenerMapLock) {
+                return mListenerMap.get(key);
+            }
+        }
+
+
+        private Object getListener(int key, boolean forceRemove) {
+            Log.d(TAG, "getListener() key=" + key + " force=" + forceRemove);
+            if (key == INVALID_LISTENER_KEY)
+                return null;
+            synchronized (mListenerMapLock) {
+                if (!forceRemove) {
+                    int count = mListenerMapCount.get(key);
+                    Log.d(TAG, "count=" + count);
+                    mListenerMapCount.put(key, --count);
+                    if (count > 0)
+                        return null;
+                }
+                Log.d(TAG, "remove key");
+                mListenerMapCount.remove(key);
+                return mListenerMap.remove(key);
+            }
+        }
+
+        private void anqpRequestStart(ScanResult sr) {
+            Log.d(TAG, "anqpRequestStart sr.bssid=" + sr.BSSID);
+            synchronized (mAnqpRequestLock) {
+                mAnqpRequest.add(sr);
+            }
+        }
+
+        private void anqpRequestFinish(WifiPasspointInfo result) {
+            Log.d(TAG, "anqpRequestFinish pi.bssid=" + result.bssid);
+            synchronized (mAnqpRequestLock) {
+                for (ScanResult sr : mAnqpRequest)
+                    if (sr.BSSID.equals(result.bssid)) {
+                        Log.d(TAG, "find hit " + result.bssid);
+                        sr.passpoint = result;
+                        mAnqpRequest.remove(sr);
+                        Log.d(TAG, "mAnqpRequest.len=" + mAnqpRequest.size());
+                        break;
+                    }
+            }
+        }
+
+        private void anqpRequestFinish(ScanResult sr) {
+            Log.d(TAG, "anqpRequestFinish sr.bssid=" + sr.BSSID);
+            synchronized (mAnqpRequestLock) {
+                for (ScanResult sr1 : mAnqpRequest)
+                    if (sr1.BSSID.equals(sr.BSSID)) {
+                        mAnqpRequest.remove(sr1);
+                        break;
+                    }
+            }
+        }
+
+        class PasspointHandler extends Handler {
+            PasspointHandler(Looper looper) {
+                super(looper);
+            }
+
+            @Override
+            public void handleMessage(Message message) {
+                Object listener = null;
+
+                switch (message.what) {
+                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
+                        if (mChannelListener != null) {
+                            mChannelListener.onChannelDisconnected();
+                            mChannelListener = null;
+                        }
+                        break;
+
+                    case REQUEST_ANQP_INFO_SUCCEEDED:
+                        WifiPasspointInfo result = (WifiPasspointInfo) message.obj;
+                        anqpRequestFinish(result);
+                        listener = getListener(message.arg2, false);
+                        if (listener != null) {
+                            ((ActionListener) listener).onSuccess();
+                        }
+                        break;
+
+                    case REQUEST_ANQP_INFO_FAILED:
+                        anqpRequestFinish((ScanResult) message.obj);
+                        listener = getListener(message.arg2, false);
+                        if (listener == null)
+                            getListener(message.arg2, true);
+                        if (listener != null) {
+                            ((ActionListener) listener).onFailure(message.arg1);
+                        }
+                        break;
+
+                    case START_OSU_SUCCEEDED:
+                        listener = getListener(message.arg2, true);
+                        if (listener != null) {
+                            ((OsuRemListener) listener).onSuccess();
+                        }
+                        break;
+
+                    case START_OSU_FAILED:
+                        listener = getListener(message.arg2, true);
+                        if (listener != null) {
+                            ((OsuRemListener) listener).onFailure(message.arg1);
+                        }
+                        break;
+
+                    case START_OSU_BROWSER:
+                        listener = peekListener(message.arg2);
+                        if (listener != null) {
+                            ParcelableString str = (ParcelableString) message.obj;
+                            if (str == null || str.string == null)
+                                ((OsuRemListener) listener).onBrowserDismiss();
+                            else
+                                ((OsuRemListener) listener).onBrowserLaunch(str.string);
+                        }
+                        break;
+
+                    default:
+                        Log.d(TAG, "Ignored " + message);
+                        break;
+                }
+            }
+        }
+
+    }
+
+    public static class ParcelableString implements Parcelable {
+        public String string;
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(Parcel out, int flags) {
+            out.writeString(string);
+        }
+
+        public static final Parcelable.Creator<ParcelableString> CREATOR =
+                new Parcelable.Creator<ParcelableString>() {
+                    @Override
+                    public ParcelableString createFromParcel(Parcel in) {
+                        ParcelableString ret = new ParcelableString();
+                        ret.string = in.readString();
+                        return ret;
+                    }
+                    @Override
+                    public ParcelableString[] newArray(int size) {
+                        return new ParcelableString[size];
+                    }
+        };
+    }
+
+    private static final int BASE = Protocol.BASE_WIFI_PASSPOINT_MANAGER;
+
+    public static final int REQUEST_ANQP_INFO                   = BASE + 1;
+    public static final int REQUEST_ANQP_INFO_FAILED            = BASE + 2;
+    public static final int REQUEST_ANQP_INFO_SUCCEEDED         = BASE + 3;
+    public static final int REQUEST_OSU_ICON                    = BASE + 4;
+    public static final int REQUEST_OSU_ICON_FAILED             = BASE + 5;
+    public static final int REQUEST_OSU_ICON_SUCCEEDED          = BASE + 6;
+    public static final int START_OSU                           = BASE + 7;
+    public static final int START_OSU_BROWSER                   = BASE + 8;
+    public static final int START_OSU_FAILED                    = BASE + 9;
+    public static final int START_OSU_SUCCEEDED                 = BASE + 10;
+
+    private Context mContext;
+    IWifiPasspointManager mService;
+
+    /**
+     * TODO: doc
+     * @param context
+     * @param service
+     */
+    public WifiPasspointManager(Context context, IWifiPasspointManager service) {
+        mContext = context;
+        mService = service;
+    }
+
+    /**
+     * Registers the application with the framework. This function must be the
+     * first to be called before any async passpoint operations are performed.
+     *
+     * @param srcContext is the context of the source
+     * @param srcLooper is the Looper on which the callbacks are receivied
+     * @param listener for callback at loss of framework communication. Can be
+     *            null.
+     * @return Channel instance that is necessary for performing any further
+     *         passpoint operations
+     *
+     */
+    public Channel initialize(Context srcContext, Looper srcLooper, ChannelListener listener) {
+        Messenger messenger = getMessenger();
+        if (messenger == null)
+            return null;
+
+        Channel c = new Channel(srcContext, srcLooper, listener);
+        if (c.mAsyncChannel.connectSync(srcContext, c.mHandler, messenger)
+                == AsyncChannel.STATUS_SUCCESSFUL) {
+            return c;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * STOPSHIP: temp solution, should use supplicant manager instead, check
+     * with b/13931972
+     */
+    public Messenger getMessenger() {
+        try {
+            return mService.getMessenger();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    public int getPasspointState() {
+        try {
+            return mService.getPasspointState();
+        } catch (RemoteException e) {
+            return PASSPOINT_STATE_UNKNOWN;
+        }
+    }
+
+    public void requestAnqpInfo(Channel c, List<ScanResult> requested, int mask,
+            ActionListener listener) {
+        Log.d(TAG, "requestAnqpInfo start");
+        Log.d(TAG, "requested.size=" + requested.size());
+        checkChannel(c);
+        List<ScanResult> list = new ArrayList<ScanResult>();
+        for (ScanResult sr : requested)
+            if (sr.capabilities.contains("[HS20]")) {
+                list.add(sr);
+                c.anqpRequestStart(sr);
+                Log.d(TAG, "adding " + sr.BSSID);
+            }
+        int count = list.size();
+        Log.d(TAG, "after filter, count=" + count);
+        if (count == 0) {
+            if (DBG)
+                Log.d(TAG, "ANQP info request contains no HS20 APs, skipped");
+            listener.onSuccess();
+            return;
+        }
+        int key = c.putListener(listener, count);
+        for (ScanResult sr : list)
+            c.mAsyncChannel.sendMessage(REQUEST_ANQP_INFO, mask, key, sr);
+        Log.d(TAG, "requestAnqpInfo end");
+    }
+
+    public void requestOsuIcons(Channel c, List<WifiPasspointOsuProvider> requested,
+            int resolution, ActionListener listener) {
+    }
+
+    public List<WifiPasspointPolicy> requestCredentialMatch(List<ScanResult> requested) {
+        try {
+            return mService.requestCredentialMatch(requested);
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Get a list of saved Passpoint credentials. Only those credentials owned
+     * by the caller will be returned.
+     *
+     * @return The list of credentials
+     */
+    public List<WifiPasspointCredential> getCredentials() {
+        try {
+            return mService.getCredentials();
+        } catch (RemoteException e) {
+            return null;
+        }
+    }
+
+    /**
+     * Add a new Passpoint credential.
+     *
+     * @param cred The credential to be added
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean addCredential(WifiPasspointCredential cred) {
+        try {
+            return mService.addCredential(cred);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Update an existing Passpoint credential. Only system or the owner of this
+     * credential has the permission to do this.
+     *
+     * @param cred The credential to be updated
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean updateCredential(WifiPasspointCredential cred) {
+        try {
+            return mService.updateCredential(cred);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Remove an existing Passpoint credential. Only system or the owner of this
+     * credential has the permission to do this.
+     *
+     * @param cred The credential to be removed
+     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     */
+    public boolean removeCredential(WifiPasspointCredential cred) {
+        try {
+            return mService.removeCredential(cred);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    public void startOsu(Channel c, WifiPasspointOsuProvider osu, OsuRemListener listener) {
+        Log.d(TAG, "startOsu start");
+        checkChannel(c);
+        int key = c.putListener(listener);
+        c.mAsyncChannel.sendMessage(START_OSU, 0, key, osu);
+        Log.d(TAG, "startOsu end");
+    }
+
+    public void startRemediation(Channel c, OsuRemListener listener) {
+    }
+
+    public void connect(WifiPasspointPolicy policy) {
+    }
+
+    private static void checkChannel(Channel c) {
+        if (c == null) throw new IllegalArgumentException("Channel needs to be initialized");
+    }
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
new file mode 100644
index 0000000..088136f
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+parcelable WifiPasspointOsuProvider;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
new file mode 100644
index 0000000..b54b70c
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointOsuProvider.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class WifiPasspointOsuProvider implements Parcelable {
+
+    /** TODO: doc
+     * @hide
+     */
+    public static final int OSU_METHOD_UNKNOWN = -1;
+
+    /** TODO: doc
+     * @hide
+     */
+    public static final int OSU_METHOD_OMADM = 0;
+
+    /** TODO: doc
+     * @hide
+     */
+    public static final int OSU_METHOD_SOAP = 1;
+
+    /** TODO: doc */
+    public String ssid;
+
+    /** TODO: doc */
+    public String friendlyName;
+
+    /** TODO: doc
+     * @hide
+     */
+    public String serverUri;
+
+    /** TODO: doc
+     * @hide
+     */
+    public int osuMethod = OSU_METHOD_UNKNOWN;
+
+    /** TODO: doc */
+    public int iconWidth;
+
+    /** TODO: doc */
+    public int iconHeight;
+
+    /** TODO: doc */
+    public String iconType;
+
+    /** TODO: doc */
+    public String iconFileName;
+
+    /** TODO: doc */
+    public Object icon; // TODO: should change to image format
+
+    /** TODO: doc */
+    public String osuNai;
+
+    /** TODO: doc */
+    public String osuService;
+
+    /** default constructor @hide */
+    public WifiPasspointOsuProvider() {
+        // TODO
+    }
+
+    /** copy constructor @hide */
+    public WifiPasspointOsuProvider(WifiPasspointOsuProvider source) {
+        // TODO
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+        sb.append("SSID: ").append("<").append(ssid).append(">");
+        if (friendlyName != null)
+            sb.append(" friendlyName: ").append("<").append(friendlyName).append(">");
+        if (serverUri != null)
+            sb.append(" serverUri: ").append("<").append(serverUri).append(">");
+        sb.append(" osuMethod: ").append("<").append(osuMethod).append(">");
+        if (iconFileName != null) {
+            sb.append(" icon: <").append(iconWidth).append("x")
+                    .append(iconHeight).append(" ")
+                    .append(iconType).append(" ")
+                    .append(iconFileName).append(">");
+        }
+        if (osuNai != null)
+            sb.append(" osuNai: ").append("<").append(osuNai).append(">");
+        if (osuService != null)
+            sb.append(" osuService: ").append("<").append(osuService).append(">");
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(ssid);
+        out.writeString(friendlyName);
+        out.writeString(serverUri);
+        out.writeInt(osuMethod);
+        out.writeInt(iconWidth);
+        out.writeInt(iconHeight);
+        out.writeString(iconType);
+        out.writeString(iconFileName);
+        out.writeString(osuNai);
+        out.writeString(osuService);
+        // TODO: icon image?
+    }
+
+    public static final Parcelable.Creator<WifiPasspointOsuProvider> CREATOR =
+            new Parcelable.Creator<WifiPasspointOsuProvider>() {
+                @Override
+                public WifiPasspointOsuProvider createFromParcel(Parcel in) {
+                    WifiPasspointOsuProvider osu = new WifiPasspointOsuProvider();
+                    osu.ssid = in.readString();
+                    osu.friendlyName = in.readString();
+                    osu.serverUri = in.readString();
+                    osu.osuMethod = in.readInt();
+                    osu.iconWidth = in.readInt();
+                    osu.iconHeight = in.readInt();
+                    osu.iconType = in.readString();
+                    osu.iconFileName = in.readString();
+                    osu.osuNai = in.readString();
+                    osu.osuService = in.readString();
+                    return osu;
+                }
+
+                @Override
+                public WifiPasspointOsuProvider[] newArray(int size) {
+                    return new WifiPasspointOsuProvider[size];
+                }
+            };
+}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
new file mode 100644
index 0000000..1d61da0
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+parcelable WifiPasspointPolicy;
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
new file mode 100644
index 0000000..f84ac88
--- /dev/null
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointPolicy.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.wifi.passpoint;
+
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.ScanResult;
+import android.os.Parcelable;
+import android.os.Parcel;
+import android.security.Credentials;
+import android.util.Log;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.List;
+
+
+/** @hide */
+public class WifiPasspointPolicy implements Parcelable {
+
+    private final static String TAG = "PasspointPolicy";
+
+    /** @hide */
+    public static final int HOME_SP = 0;
+
+    /** @hide */
+    public static final int ROAMING_PARTNER = 1;
+
+    /** @hide */
+    public static final int UNRESTRICTED = 2;
+
+    private String mName;
+    private int mCredentialPriority;
+    private int mRoamingPriority;
+    private String mBssid;
+    private String mSsid;
+    private WifiPasspointCredential mCredential;
+    private int mRestriction;// Permitted values are "HomeSP", "RoamingPartner", or "Unrestricted"
+    private boolean mIsHomeSp;
+
+    private final String INT_PRIVATE_KEY = "private_key";
+    private final String INT_PHASE2 = "phase2";
+    private final String INT_PASSWORD = "password";
+    private final String INT_IDENTITY = "identity";
+    private final String INT_EAP = "eap";
+    private final String INT_CLIENT_CERT = "client_cert";
+    private final String INT_CA_CERT = "ca_cert";
+    private final String INT_ANONYMOUS_IDENTITY = "anonymous_identity";
+    private final String INT_SIM_SLOT = "sim_slot";
+    private final String INT_ENTERPRISEFIELD_NAME ="android.net.wifi.WifiConfiguration$EnterpriseField";
+    private final String ISO8601DATEFORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+    private final String ENTERPRISE_PHASE2_MSCHAPV2 = "auth=MSCHAPV2";
+    private final String ENTERPRISE_PHASE2_MSCHAP = "auth=MSCHAP";
+
+    /** @hide */
+    public WifiPasspointPolicy(String name, String ssid,
+            String bssid, WifiPasspointCredential pc,
+            int restriction, boolean ishomesp) {
+        mName = name;
+        if (pc != null) {
+            mCredentialPriority = pc.getPriority();
+        }
+        //PerProviderSubscription/<X+>/Policy/PreferredRoamingPartnerList/<X+>/Priority
+        mRoamingPriority = 128; //default priority value of 128
+        mSsid = ssid;
+        mCredential = pc;
+        mBssid = bssid;
+        mRestriction = restriction;
+        mIsHomeSp = ishomesp;
+    }
+
+    public String getSsid() {
+        return mSsid;
+    }
+
+    /** @hide */
+    public void setBssid(String bssid) {
+        mBssid = bssid;
+    }
+
+    public String getBssid() {
+        return mBssid;
+    }
+
+    /** @hide */
+    public void setRestriction(int r) {
+        mRestriction = r;
+    }
+
+    /** @hide */
+    public int getRestriction() {
+        return mRestriction;
+    }
+
+    /** @hide */
+    public void setHomeSp(boolean b) {
+        mIsHomeSp = b;
+    }
+
+    /** @hide */
+    public boolean isHomeSp() {
+        return mIsHomeSp;
+    }
+
+    /** @hide */
+    public void setCredential(WifiPasspointCredential newCredential) {
+        mCredential = newCredential;
+    }
+
+    public WifiPasspointCredential getCredential() {
+        // TODO: return a copy
+        return mCredential;
+    }
+
+    /** @hide */
+    public void setCredentialPriority(int priority) {
+        mCredentialPriority = priority;
+    }
+
+    /** @hide */
+    public void setRoamingPriority(int priority) {
+        mRoamingPriority = priority;
+    }
+
+    public int getCredentialPriority() {
+        return mCredentialPriority;
+    }
+
+    public int getRoamingPriority() {
+        return mRoamingPriority;
+    }
+
+    public WifiConfiguration createWifiConfiguration() {
+        WifiConfiguration wfg = new WifiConfiguration();
+        if (mBssid != null) {
+            Log.d(TAG, "create bssid:" + mBssid);
+            wfg.BSSID = mBssid;
+        }
+
+        if (mSsid != null) {
+            Log.d(TAG, "create ssid:" + mSsid);
+            wfg.SSID = mSsid;
+        }
+        //TODO: 1. add pmf configuration
+        //      2. add ocsp configuration
+        //      3. add eap-sim configuration
+        /*Key management*/
+        wfg.status = WifiConfiguration.Status.ENABLED;
+        wfg.allowedKeyManagement.clear();
+        wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
+        wfg.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X);
+
+        /*Group Ciphers*/
+        wfg.allowedGroupCiphers.clear();
+        wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+        wfg.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
+
+        /*Protocols*/
+        wfg.allowedProtocols.clear();
+        wfg.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+        wfg.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
+
+        Class[] enterpriseFieldArray  = WifiConfiguration.class.getClasses();
+        Class<?> enterpriseFieldClass = null;
+
+
+        for(Class<?> myClass : enterpriseFieldArray) {
+            if(myClass.getName().equals(INT_ENTERPRISEFIELD_NAME)) {
+                enterpriseFieldClass = myClass;
+                break;
+            }
+        }
+        Log.d(TAG, "class chosen " + enterpriseFieldClass.getName() );
+
+
+        Field anonymousId = null, caCert = null, clientCert = null,
+              eap = null, identity = null, password = null,
+              phase2 = null, privateKey =  null;
+
+        Field[] fields = WifiConfiguration.class.getFields();
+
+
+        for (Field tempField : fields) {
+            if (tempField.getName().trim().equals(INT_ANONYMOUS_IDENTITY)) {
+                anonymousId = tempField;
+                Log.d(TAG, "field " + anonymousId.getName() );
+            } else if (tempField.getName().trim().equals(INT_CA_CERT)) {
+                caCert = tempField;
+            } else if (tempField.getName().trim().equals(INT_CLIENT_CERT)) {
+                clientCert = tempField;
+                Log.d(TAG, "field " + clientCert.getName() );
+            } else if (tempField.getName().trim().equals(INT_EAP)) {
+                eap = tempField;
+                Log.d(TAG, "field " + eap.getName() );
+            } else if (tempField.getName().trim().equals(INT_IDENTITY)) {
+                identity = tempField;
+                Log.d(TAG, "field " + identity.getName() );
+            } else if (tempField.getName().trim().equals(INT_PASSWORD)) {
+                password = tempField;
+                Log.d(TAG, "field " + password.getName() );
+            } else if (tempField.getName().trim().equals(INT_PHASE2)) {
+                phase2 = tempField;
+                Log.d(TAG, "field " + phase2.getName() );
+
+            } else if (tempField.getName().trim().equals(INT_PRIVATE_KEY)) {
+                privateKey = tempField;
+            }
+        }
+
+
+        Method setValue = null;
+
+        for(Method m: enterpriseFieldClass.getMethods()) {
+            if(m.getName().trim().equals("setValue")) {
+                Log.d(TAG, "method " + m.getName() );
+                setValue = m;
+                break;
+            }
+        }
+
+        try {
+            // EAP
+            String eapmethod = mCredential.getType();
+            Log.d(TAG, "eapmethod:" + eapmethod);
+            setValue.invoke(eap.get(wfg), eapmethod);
+
+            // Username, password, EAP Phase 2
+            if ("TTLS".equals(eapmethod)) {
+                setValue.invoke(phase2.get(wfg), ENTERPRISE_PHASE2_MSCHAPV2);
+                setValue.invoke(identity.get(wfg), mCredential.getUserName());
+                setValue.invoke(password.get(wfg), mCredential.getPassword());
+                setValue.invoke(anonymousId.get(wfg), "anonymous@" + mCredential.getRealm());
+            }
+
+            // EAP CA Certificate
+            String cacertificate = null;
+            String rootCA = mCredential.getCaRootCertPath();
+            if (rootCA == null){
+                cacertificate = null;
+            } else {
+                cacertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.CA_CERTIFICATE + rootCA;
+            }
+            Log.d(TAG, "cacertificate:" + cacertificate);
+            setValue.invoke(caCert.get(wfg), cacertificate);
+
+            //User certificate
+            if ("TLS".equals(eapmethod)) {
+                String usercertificate = null;
+                String privatekey = null;
+                String clientCertPath = mCredential.getClientCertPath();
+                if (clientCertPath != null){
+                    privatekey = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_PRIVATE_KEY + clientCertPath;
+                    usercertificate = "keystore://" + Credentials.WIFI + "HS20" + Credentials.USER_CERTIFICATE + clientCertPath;
+                }
+                Log.d(TAG, "privatekey:" + privatekey);
+                Log.d(TAG, "usercertificate:" + usercertificate);
+                if (privatekey != null && usercertificate != null) {
+                    setValue.invoke(privateKey.get(wfg), privatekey);
+                    setValue.invoke(clientCert.get(wfg), usercertificate);
+                }
+            }
+        } catch (Exception e) {
+            Log.d(TAG, "createWifiConfiguration err:" + e);
+        }
+
+        return wfg;
+    }
+
+    /** {@inheritDoc} @hide */
+    public int compareTo(WifiPasspointPolicy another) {
+        Log.d(TAG, "this:" + this);
+        Log.d(TAG, "another:" + another);
+
+        if (another == null) {
+            return -1;
+        } else if (this.mIsHomeSp == true && another.isHomeSp() == false) {
+            //home sp priority is higher then roaming
+            Log.d(TAG, "compare HomeSP  first, this is HomeSP, another isn't");
+            return -1;
+        } else if ((this.mIsHomeSp == true && another.isHomeSp() == true)) {
+            Log.d(TAG, "both HomeSP");
+            //if both home sp, compare credential priority
+            if (this.mCredentialPriority < another.getCredentialPriority()) {
+                Log.d(TAG, "this priority is higher");
+                return -1;
+            } else if (this.mCredentialPriority == another.getCredentialPriority()) {
+                Log.d(TAG, "both priorities equal");
+                //if priority still the same, compare name(ssid)
+                if (this.mName.compareTo(another.mName) != 0) {
+                    Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+                    return this.mName.compareTo(another.mName);
+                }
+                /**
+                 *if name still the same, compare credential
+                 *the device may has two more credentials(TLS,SIM..etc)
+                 *it can associate to one AP(same ssid). so we should compare by credential
+                 */
+                if (this.mCredential != null && another.mCredential != null) {
+                    if (this.mCredential.compareTo(another.mCredential) != 0) {
+                        Log.d(TAG,
+                                "compare mCredential return:" + this.mName.compareTo(another.mName));
+                        return this.mCredential.compareTo(another.mCredential);
+                    }
+                }
+            } else {
+                return 1;
+            }
+        } else if ((this.mIsHomeSp == false && another.isHomeSp() == false)) {
+            Log.d(TAG, "both RoamingSp");
+            //if both roaming sp, compare roaming priority(preferredRoamingPartnerList/<X+>/priority)
+            if (this.mRoamingPriority < another.getRoamingPriority()) {
+                Log.d(TAG, "this priority is higher");
+                return -1;
+            } else if (this.mRoamingPriority == another.getRoamingPriority()) {//priority equals, compare name
+                Log.d(TAG, "both priorities equal");
+                //if priority still the same, compare name(ssid)
+                if (this.mName.compareTo(another.mName) != 0) {
+                    Log.d(TAG, "compare mName return:" + this.mName.compareTo(another.mName));
+                    return this.mName.compareTo(another.mName);
+                }
+                //if name still the same, compare credential
+                if (this.mCredential != null && another.mCredential != null) {
+                    if (this.mCredential.compareTo(another.mCredential) != 0) {
+                        Log.d(TAG,
+                                "compare mCredential return:"
+                                        + this.mCredential.compareTo(another.mCredential));
+                        return this.mCredential.compareTo(another.mCredential);
+                    }
+                }
+            } else {
+                return 1;
+            }
+        }
+
+        Log.d(TAG, "both policies equal");
+        return 0;
+    }
+
+    @Override
+    /** @hide */
+    public String toString() {
+        return "PasspointPolicy: name=" + mName + " CredentialPriority=" + mCredentialPriority +
+                " mRoamingPriority" + mRoamingPriority +
+                " ssid=" + mSsid + " restriction=" + mRestriction +
+                " ishomesp=" + mIsHomeSp + " Credential=" + mCredential;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        // TODO
+    }
+
+    /** Implement the Parcelable interface {@hide} */
+    public static final Creator<WifiPasspointPolicy> CREATOR =
+            new Creator<WifiPasspointPolicy>() {
+                @Override
+                public WifiPasspointPolicy createFromParcel(Parcel in) {
+                    return null;
+                }
+
+                @Override
+                public WifiPasspointPolicy[] newArray(int size) {
+                    return new WifiPasspointPolicy[size];
+                }
+            };
+}