diff options
43 files changed, 5512 insertions, 141 deletions
diff --git a/Android.mk b/Android.mk index 3b1991cce502..81113f791bee 100644 --- a/Android.mk +++ b/Android.mk @@ -386,6 +386,7 @@ LOCAL_SRC_FILES += \ 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 35423fdcbfe3..4663a0d613da 100644 --- a/api/current.txt +++ b/api/current.txt @@ -17867,9 +17867,18 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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; } @@ -25862,6 +25881,7 @@ package android.provider { public static final class VoicemailContract.Status implements android.provider.BaseColumns { method public static android.net.Uri buildSourceUri(java.lang.String); + method public static void setStatus(android.content.Context, android.telecom.PhoneAccountHandle, int, int, int); field public static final java.lang.String CONFIGURATION_STATE = "configuration_state"; field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2 field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1 @@ -25876,6 +25896,8 @@ package android.provider { 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 +25905,13 @@ package android.provider { 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 +25919,8 @@ package android.provider { 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 +28195,81 @@ package android.system { 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 +28278,10 @@ package android.telecom { 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 +28290,63 @@ package android.telecom { 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); + } + } package android.telephony { @@ -28378,6 +28540,7 @@ package android.telephony { 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 +28557,8 @@ package android.telephony { 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 729f65618046..ec0559fc6f67 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -19294,9 +19294,18 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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 @@ package android.net.wifi { 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; @@ -27454,6 +27504,7 @@ package android.provider { public static final class VoicemailContract.Status implements android.provider.BaseColumns { method public static android.net.Uri buildSourceUri(java.lang.String); + method public static void setStatus(android.content.Context, android.telecom.PhoneAccountHandle, int, int, int); field public static final java.lang.String CONFIGURATION_STATE = "configuration_state"; field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2 field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1 @@ -27468,6 +27519,8 @@ package android.provider { 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 +27528,13 @@ package android.provider { 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 +27542,8 @@ package android.provider { 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 +29956,22 @@ package android.telecom { 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 +30278,14 @@ package android.telecom { 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 +30298,9 @@ package android.telecom { 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 +30316,11 @@ package android.telecom { 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 +30445,7 @@ package android.telecom { 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 +30457,7 @@ package android.telecom { 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 +30466,63 @@ package android.telecom { 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); + } + } package android.telephony { @@ -30573,6 +30716,7 @@ package android.telephony { 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 +30733,8 @@ package android.telephony { 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 d2a29975c3e7..8003afb3e860 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -56,6 +56,30 @@ public class NetworkUtils { /** * 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 @@ public class NetworkUtils { * 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 f023df7de0b4..2df9dbfb467b 100644 --- a/core/java/android/provider/CallLog.java +++ b/core/java/android/provider/CallLog.java @@ -33,9 +33,12 @@ import android.provider.ContactsContract.CommonDataKinds.Callable; 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 @@ import java.util.List; * 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 @@ public class CallLog { // 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 @@ public class CallLog { 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 @@ public class CallLog { } 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 d71ad03b6456..0da4fd5ec276 100644 --- a/core/java/android/provider/VoicemailContract.java +++ b/core/java/android/provider/VoicemailContract.java @@ -19,10 +19,18 @@ package android.provider; 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.database.Cursor; import android.net.Uri; import android.provider.CallLog.Calls; +import android.telecom.PhoneAccountHandle; +import android.telecom.Voicemail; + +import java.util.List; /** * The contract between the voicemail provider and applications. Contains @@ -199,13 +207,100 @@ public class VoicemailContract { */ 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 +317,27 @@ public class VoicemailContract { 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. @@ -318,5 +430,50 @@ public class VoicemailContract { return Status.CONTENT_URI.buildUpon() .appendQueryParameter(PARAM_KEY_SOURCE_PACKAGE, packageName).build(); } + + /** + * A helper method to set the status of a voicemail source. + * + * @param context The context from the package calling the method. This will be the source. + * @param accountHandle The handle for the account the source is associated with. + * @param configurationState See {@link Status#CONFIGURATION_STATE} + * @param dataChannelState See {@link Status#DATA_CHANNEL_STATE} + * @param notificationChannelState See {@link Status#NOTIFICATION_CHANNEL_STATE} + */ + public static void setStatus(Context context, PhoneAccountHandle accountHandle, + int configurationState, int dataChannelState, int notificationChannelState) { + ContentResolver contentResolver = context.getContentResolver(); + Uri statusUri = buildSourceUri(context.getPackageName()); + ContentValues values = new ContentValues(); + values.put(Status.PHONE_ACCOUNT_COMPONENT_NAME, + accountHandle.getComponentName().toString()); + values.put(Status.PHONE_ACCOUNT_ID, accountHandle.getId()); + values.put(Status.CONFIGURATION_STATE, configurationState); + values.put(Status.DATA_CHANNEL_STATE, dataChannelState); + values.put(Status.NOTIFICATION_CHANNEL_STATE, notificationChannelState); + + if (isStatusPresent(contentResolver, statusUri)) { + contentResolver.update(statusUri, values, null, null); + } else { + contentResolver.insert(statusUri, values); + } + } + + /** + * Determines if a voicemail source exists in the status table. + * + * @param contentResolver A content resolver constructed from the appropriate context. + * @param statusUri The content uri for the source. + * @return {@code true} if a status entry for this source exists + */ + private static boolean isStatusPresent(ContentResolver contentResolver, Uri statusUri) { + Cursor cursor = null; + try { + cursor = contentResolver.query(statusUri, null, null, null, null); + return cursor != null && cursor.getCount() != 0; + } finally { + if (cursor != null) cursor.close(); + } + } } } diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp index 8b9f5744d244..e64f1defb663 100644 --- a/core/jni/android_net_NetUtils.cpp +++ b/core/jni/android_net_NetUtils.cpp @@ -31,27 +31,18 @@ int ifc_enable(const char *ifname); 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 @@ static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz, 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 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr 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 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr 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 jboolean android_net_utils_protectFromVpn(JNIEnv *env, jobject thiz, jint 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 81db6c58776b..7633950d0af9 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 687a14ee3152..bfda753eb5d1 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 687a14ee3152..bfda753eb5d1 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 1b0f0a481edd..8348be9f1c5b 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 8c56c8c5f057..0437a2acc85f 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -1374,7 +1374,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub 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 64a67fc239f5..22fee22141f1 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 @@ public class TelecomLoaderService extends SystemService { 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 334cdf6246aa..0705fbdeaaeb 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -677,7 +677,8 @@ public final class SystemServer { 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 000000000000..39717c3e0fc2 --- /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/Call.java b/telecomm/java/android/telecom/Call.java index 541e398ac712..d0d94aadd055 100644 --- a/telecomm/java/android/telecom/Call.java +++ b/telecomm/java/android/telecom/Call.java @@ -141,28 +141,42 @@ public final class Call { public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; /** - * Local device supports video telephony. + * Local device supports receiving video. * @hide */ - public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100; /** - * Remote device supports video telephony. + * Local device supports transmitting video. * @hide */ - public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200; /** - * Call is using high definition audio. + * Local device supports bidirectional video calling. * @hide */ - public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL = + CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX; /** - * Call is using WIFI. + * Remote device supports receiving video. * @hide */ - public static final int CAPABILITY_WIFI = 0x00000800; + public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400; + + /** + * Remote device supports transmitting video. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800; + + /** + * Remote device supports bidirectional video calling. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE = + CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX; /** * Call is able to be separated from its parent {@code Conference}, if any. @@ -182,6 +196,22 @@ public final class Call { */ public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000; + /** + * Call is using high definition audio. + * @hide + */ + public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000; + + /** + * Call is using WIFI. + * @hide + */ + public static final int CAPABILITY_WIFI = 0x00010000; + + //****************************************************************************************** + // Next CAPABILITY value: 0x00020000 + //****************************************************************************************** + private final Uri mHandle; private final int mHandlePresentation; private final String mCallerDisplayName; @@ -249,9 +279,21 @@ public final class Call { if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { builder.append(" CAPABILITY_MANAGE_CONFERENCE"); } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX"); + } if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) { builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL"); } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX"); + } if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) { builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE"); } diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java index f8468d702d21..d72c08037bd3 100644 --- a/telecomm/java/android/telecom/Connection.java +++ b/telecomm/java/android/telecom/Connection.java @@ -106,28 +106,42 @@ public abstract class Connection implements IConferenceable { public static final int CAPABILITY_MANAGE_CONFERENCE = 0x00000080; /** - * Local device supports video telephony. + * Local device supports receiving video. * @hide */ - public static final int CAPABILITY_SUPPORTS_VT_LOCAL = 0x00000100; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL_RX = 0x00000100; /** - * Remote device supports video telephony. + * Local device supports transmitting video. * @hide */ - public static final int CAPABILITY_SUPPORTS_VT_REMOTE = 0x00000200; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL_TX = 0x00000200; /** - * Connection is using high definition audio. + * Local device supports bidirectional video calling. * @hide */ - public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00000400; + public static final int CAPABILITY_SUPPORTS_VT_LOCAL = + CAPABILITY_SUPPORTS_VT_LOCAL_RX | CAPABILITY_SUPPORTS_VT_LOCAL_TX; /** - * Connection is using WIFI. + * Remote device supports receiving video. * @hide */ - public static final int CAPABILITY_WIFI = 0x00000800; + public static final int CAPABILITY_SUPPORTS_VT_REMOTE_RX = 0x00000400; + + /** + * Remote device supports transmitting video. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE_TX = 0x00000800; + + /** + * Remote device supports bidirectional video calling. + * @hide + */ + public static final int CAPABILITY_SUPPORTS_VT_REMOTE = + CAPABILITY_SUPPORTS_VT_REMOTE_RX | CAPABILITY_SUPPORTS_VT_REMOTE_TX; /** * Connection is able to be separated from its parent {@code Conference}, if any. @@ -147,6 +161,22 @@ public abstract class Connection implements IConferenceable { */ public static final int CAPABILITY_GENERIC_CONFERENCE = 0x00004000; + /** + * Connection is using high definition audio. + * @hide + */ + public static final int CAPABILITY_HIGH_DEF_AUDIO = 0x00008000; + + /** + * Connection is using WIFI. + * @hide + */ + public static final int CAPABILITY_WIFI = 0x000010000; + + //********************************************************************************************** + // Next CAPABILITY value: 0x00020000 + //********************************************************************************************** + // Flag controlling whether PII is emitted into the logs private static final boolean PII_DEBUG = Log.isLoggable(android.util.Log.DEBUG); @@ -218,9 +248,21 @@ public abstract class Connection implements IConferenceable { if (can(capabilities, CAPABILITY_MANAGE_CONFERENCE)) { builder.append(" CAPABILITY_MANAGE_CONFERENCE"); } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_RX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_RX"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL_TX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL_TX"); + } if (can(capabilities, CAPABILITY_SUPPORTS_VT_LOCAL)) { builder.append(" CAPABILITY_SUPPORTS_VT_LOCAL"); } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_RX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_RX"); + } + if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE_TX)) { + builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE_TX"); + } if (can(capabilities, CAPABILITY_SUPPORTS_VT_REMOTE)) { builder.append(" CAPABILITY_SUPPORTS_VT_REMOTE"); } diff --git a/telecomm/java/android/telecom/PhoneAccount.java b/telecomm/java/android/telecom/PhoneAccount.java index 052a481f1ab2..a94c2f6487a4 100644 --- a/telecomm/java/android/telecom/PhoneAccount.java +++ b/telecomm/java/android/telecom/PhoneAccount.java @@ -40,15 +40,13 @@ import java.util.MissingResourceException; /** * 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 @@ public class PhoneAccount implements Parcelable { * 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 @@ public class PhoneAccount implements Parcelable { * <p> * {@hide} */ + @SystemApi public static final int CAPABILITY_CALL_PROVIDER = 0x2; /** @@ -94,6 +95,7 @@ public class PhoneAccount implements Parcelable { * See {@link #getCapabilities} * @hide */ + @SystemApi public static final int CAPABILITY_VIDEO_CALLING = 0x8; /** @@ -111,6 +113,7 @@ public class PhoneAccount implements Parcelable { * See {@link #getCapabilities} * @hide */ + @SystemApi public static final int CAPABILITY_MULTI_USER = 0x20; /** @@ -203,6 +206,7 @@ public class PhoneAccount implements Parcelable { } /** @hide */ + @SystemApi public Builder setAccountHandle(PhoneAccountHandle accountHandle) { mAccountHandle = accountHandle; return this; @@ -333,6 +337,7 @@ public class PhoneAccount implements Parcelable { * @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 @@ public class PhoneAccount implements Parcelable { * @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 97af41afd31a..4600b724e3ef 100644 --- a/telecomm/java/android/telecom/PhoneAccountHandle.java +++ b/telecomm/java/android/telecom/PhoneAccountHandle.java @@ -29,16 +29,13 @@ import java.util.Objects; * 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 @@ public class PhoneAccountHandle implements Parcelable { } /** @hide */ + @SystemApi public PhoneAccountHandle( ComponentName componentName, String id, @@ -61,8 +59,8 @@ public class PhoneAccountHandle implements Parcelable { } /** - * 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 @@ public class PhoneAccountHandle implements Parcelable { /** * 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 @@ public class PhoneAccountHandle implements Parcelable { * ({@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 @@ public class PhoneAccountHandle implements Parcelable { * @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 1a6b2928af8e..8be3e66ca331 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -92,6 +92,15 @@ public class TelecomManager { "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 @@ public class TelecomManager { * {@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 @@ public class TelecomManager { * {@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 @@ public class TelecomManager { * {@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 @@ public class TelecomManager { * * @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 f5cb054b0f50..e62e9949bff2 100644 --- a/telecomm/java/android/telecom/VideoProfile.java +++ b/telecomm/java/android/telecom/VideoProfile.java @@ -21,8 +21,6 @@ import android.os.Parcelable; /** * 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 000000000000..864c6b1765e5 --- /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/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java index c043659f15a9..3572846da665 100644 --- a/telephony/java/android/telephony/PhoneNumberUtils.java +++ b/telephony/java/android/telephony/PhoneNumberUtils.java @@ -34,11 +34,11 @@ import android.text.Editable; 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 @@ public class PhoneNumberUtils * * @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 @@ public class PhoneNumberUtils * @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 a7350c9a3baa..b96f52852fb4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -29,6 +29,7 @@ import android.os.Bundle; 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 @@ public class TelephonyManager { /** * Returns the IMS Registration Status - *@hide + * @hide */ public boolean isImsRegistered() { try { @@ -4130,4 +4131,21 @@ public class TelephonyManager { 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 bf3ee09daa97..62c8746f7ea9 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -18,6 +18,7 @@ package com.android.internal.telephony; 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 @@ interface ITelephony { * {@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 b87a1e94c6c8..bc95a36a0f69 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -79,6 +79,8 @@ interface IWifiManager 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 9729c9191640..b4f49276a1d6 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 class ScanResult implements Parcelable { */ 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 class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 @@ public class ScanResult implements Parcelable { 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 87db951e0bd3..872eb6f2de70 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -19,19 +19,18 @@ package android.net.wifi; 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 class WifiConfiguration implements Parcelable { public static final String updateIdentiferVarName = "update_identifier"; /** {@hide} */ public static final int INVALID_NETWORK_ID = -1; + /** * Recognized key management schemes. */ @@ -233,17 +233,21 @@ public class WifiConfiguration implements Parcelable { * <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 class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { SSID = null; BSSID = null; FQDN = null; - naiRealm = null; + roamingConsortiumIds = new HashSet<Long>(); priority = 0; hiddenSSID = false; disableReason = DISABLED_UNKNOWN_REASON; @@ -907,6 +926,17 @@ public class WifiConfiguration implements Parcelable { } } + 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 @@ public class WifiConfiguration implements Parcelable { 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 cf3cba3ec0da..36fc96b81feb 100644 --- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java +++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java @@ -54,6 +54,8 @@ public class WifiEnterpriseConfig implements Parcelable { /** @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 class WifiEnterpriseConfig implements Parcelable { 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 @@ public class WifiEnterpriseConfig implements Parcelable { } /** - * 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 b001bb8ce13c..40d40bb292bd 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -1238,6 +1238,21 @@ public class WifiManager { } /** + * 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 aaa2f9893645..fea934f860c6 100644 --- a/wifi/java/android/net/wifi/WifiScanner.java +++ b/wifi/java/android/net/wifi/WifiScanner.java @@ -158,6 +158,11 @@ public class WifiScanner { 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 @@ public class WifiScanner { dest.writeInt(periodInMs); dest.writeInt(reportEvents); dest.writeInt(numBssidsPerScan); + dest.writeInt(maxScansToCache); if (channels != null) { dest.writeInt(channels.length); @@ -194,6 +200,7 @@ public class WifiScanner { 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 @@ public class WifiScanner { } - /** @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 @@ public class WifiScanner { } /** - * 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 class WifiScanner { */ 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 @@ public class WifiScanner { 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 @@ public class WifiScanner { * @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 class WifiScanner { 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 @@ public class WifiScanner { 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 @@ public class WifiScanner { ((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 @@ public class WifiScanner { ((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 000000000000..50bec33ea6d2 --- /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 000000000000..cfd36059063f --- /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 000000000000..0a7230f42383 --- /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 000000000000..6a88b2e2c1ee --- /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 000000000000..bbf5fc608ed2 --- /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 000000000000..27f23bc3dc45 --- /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 000000000000..33db3f5491f8 --- /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 000000000000..b9b17ebedd04 --- /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 000000000000..088136f5e98c --- /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 000000000000..b54b70ceb087 --- /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 000000000000..1d61da00ed15 --- /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 000000000000..f84ac88c0caf --- /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]; + } + }; +} |