diff options
Diffstat (limited to 'wifi/java')
20 files changed, 2548 insertions, 273 deletions
diff --git a/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl new file mode 100644 index 000000000000..f472a021b031 --- /dev/null +++ b/wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import android.net.wifi.INetworkRequestUserSelectionCallback; +import android.net.wifi.WifiConfiguration; + +/** + * Interface for network request match callback. + * + * @hide + */ +oneway interface INetworkRequestMatchCallback +{ + void onUserSelectionCallbackRegistration(in INetworkRequestUserSelectionCallback userSelectionCallback); + + void onMatch(in List<WifiConfiguration> wificonfigurations); + + void onUserSelectionConnectSuccess(in WifiConfiguration wificonfiguration); + + void onUserSelectionConnectFailure(in WifiConfiguration wificonfiguration); +} diff --git a/wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl b/wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl new file mode 100644 index 000000000000..524cefbb295f --- /dev/null +++ b/wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import android.net.wifi.WifiConfiguration; + +/** + * Interface for providing user selection in response to + * network request match callback. + * @hide + */ +oneway interface INetworkRequestUserSelectionCallback +{ + void select(in WifiConfiguration wificonfiguration); + + void reject(); +} diff --git a/wifi/java/android/net/wifi/ITrafficStateCallback.aidl b/wifi/java/android/net/wifi/ITrafficStateCallback.aidl new file mode 100644 index 000000000000..0c8e777f67ba --- /dev/null +++ b/wifi/java/android/net/wifi/ITrafficStateCallback.aidl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +/** + * Interface for Traffic state callback. + * + * @hide + */ +oneway interface ITrafficStateCallback +{ + /** + * Callback invoked to inform clients about the current traffic state. + * + * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, + * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. + * @hide + */ + void onStateChanged(int state); +} diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index af44b7e6cd16..1fd68ec1df70 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -25,7 +25,9 @@ import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.DhcpInfo; import android.net.Network; +import android.net.wifi.INetworkRequestMatchCallback; import android.net.wifi.ISoftApCallback; +import android.net.wifi.ITrafficStateCallback; import android.net.wifi.PasspointManagementObjectDefinition; import android.net.wifi.ScanResult; import android.net.wifi.WifiActivityEnergyInfo; @@ -125,7 +127,7 @@ interface IWifiManager void acquireMulticastLock(IBinder binder, String tag); - void releaseMulticastLock(); + void releaseMulticastLock(String tag); void updateInterfaceIpState(String ifaceName, int mode); @@ -180,5 +182,13 @@ interface IWifiManager void registerSoftApCallback(in IBinder binder, in ISoftApCallback callback, int callbackIdentifier); void unregisterSoftApCallback(int callbackIdentifier); + + void registerTrafficStateCallback(in IBinder binder, in ITrafficStateCallback callback, int callbackIdentifier); + + void unregisterTrafficStateCallback(int callbackIdentifier); + + void registerNetworkRequestMatchCallback(in IBinder binder, in INetworkRequestMatchCallback callback, int callbackIdentifier); + + void unregisterNetworkRequestMatchCallback(int callbackIdentifier); } diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java index 3a4e88b49daf..9b9247dba17c 100644 --- a/wifi/java/android/net/wifi/ScanResult.java +++ b/wifi/java/android/net/wifi/ScanResult.java @@ -86,9 +86,9 @@ public class ScanResult implements Parcelable { public static final int PROTOCOL_WPA = 1; /** * @hide - * Security protocol type: WPA version 2, also called RSN. + * Security protocol type: RSN, for WPA version 2, and version 3. */ - public static final int PROTOCOL_WPA2 = 2; + public static final int PROTOCOL_RSN = 2; /** * @hide * Security protocol type: @@ -138,7 +138,21 @@ public class ScanResult implements Parcelable { * Used for Hotspot 2.0. */ public static final int KEY_MGMT_OSEN = 7; - + /** + * @hide + * Security key management scheme: SAE. + */ + public static final int KEY_MGMT_SAE = 8; + /** + * @hide + * Security key management scheme: OWE. + */ + public static final int KEY_MGMT_OWE = 9; + /** + * @hide + * Security key management scheme: SUITE_B_192. + */ + public static final int KEY_MGMT_EAP_SUITE_B_192 = 10; /** * @hide * No cipher suite. @@ -159,6 +173,11 @@ public class ScanResult implements Parcelable { * Cipher suite: CCMP */ public static final int CIPHER_CCMP = 3; + /** + * @hide + * Cipher suite: GCMP + */ + public static final int CIPHER_GCMP_256 = 4; /** * The detected signal level in dBm, also known as the RSSI. diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 74722787f441..8fc9b9759469 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -23,6 +23,7 @@ import android.content.pm.PackageManager; import android.net.IpConfiguration; import android.net.IpConfiguration.ProxySettings; import android.net.MacAddress; +import android.net.NetworkSpecifier; import android.net.ProxyInfo; import android.net.StaticIpConfiguration; import android.net.Uri; @@ -47,7 +48,11 @@ import java.util.HashMap; /** * A class representing a configured Wi-Fi network, including the * security configuration. + * + * @deprecated Use {@link WifiNetworkConfigBuilder} to create {@link NetworkSpecifier} and + * {@link WifiNetworkSuggestion}. This will become a system use only object in the future. */ +@Deprecated public class WifiConfiguration implements Parcelable { private static final String TAG = "WifiConfiguration"; /** @@ -125,10 +130,26 @@ public class WifiConfiguration implements Parcelable { */ public static final int FT_EAP = 7; + /** + * Simultaneous Authentication of Equals + */ + public static final int SAE = 8; + + /** + * Opportunististic Wireless Encryption + */ + public static final int OWE = 9; + + /** + * SUITE_B_192 192 bit level + */ + public static final int SUITE_B_192 = 10; + public static final String varName = "key_mgmt"; public static final String[] strings = { "NONE", "WPA_PSK", "WPA_EAP", - "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP" }; + "IEEE8021X", "WPA2_PSK", "OSEN", "FT_PSK", "FT_EAP", + "SAE", "OWE", "SUITE_B_192"}; } /** @@ -142,7 +163,7 @@ public class WifiConfiguration implements Parcelable { * is discouraged. WPA-2 (RSN) should be used instead. */ @Deprecated public static final int WPA = 0; - /** WPA2/IEEE 802.11i */ + /** RSN WPA2/WPA3/IEEE 802.11i */ public static final int RSN = 1; /** HS2.0 r2 OSEN * @hide @@ -190,10 +211,14 @@ public class WifiConfiguration implements Parcelable { public static final int TKIP = 1; /** AES in Counter mode with CBC-MAC [RFC 3610, IEEE 802.11i/D7.0] */ public static final int CCMP = 2; + /** + * AES in Galois/Counter Mode + */ + public static final int GCMP_256 = 3; public static final String varName = "pairwise"; - public static final String[] strings = { "NONE", "TKIP", "CCMP" }; + public static final String[] strings = { "NONE", "TKIP", "CCMP", "GCMP_256" }; } /** @@ -203,6 +228,7 @@ public class WifiConfiguration implements Parcelable { * TKIP = Temporal Key Integrity Protocol [IEEE 802.11i/D7.0] * WEP104 = WEP (Wired Equivalent Privacy) with 104-bit key * WEP40 = WEP (Wired Equivalent Privacy) with 40-bit key (original 802.11) + * GCMP_256 = AES in Galois/Counter Mode * </pre> */ public static class GroupCipher { @@ -226,12 +252,64 @@ public class WifiConfiguration implements Parcelable { * @hide */ public static final int GTK_NOT_USED = 4; + /** + * AES in Galois/Counter Mode + */ + public static final int GCMP_256 = 5; public static final String varName = "group"; public static final String[] strings = { /* deprecated */ "WEP40", /* deprecated */ "WEP104", - "TKIP", "CCMP", "GTK_NOT_USED" }; + "TKIP", "CCMP", "GTK_NOT_USED", "GCMP_256" }; + } + + /** + * Recognized group management ciphers. + * <pre> + * BIP_CMAC_256 = Cipher-based Message Authentication Code 256 bits + * BIP_GMAC_128 = Galois Message Authentication Code 128 bits + * BIP_GMAC_256 = Galois Message Authentication Code 256 bits + * </pre> + */ + public static class GroupMgmtCipher { + private GroupMgmtCipher() { } + + /** CMAC-256 = Cipher-based Message Authentication Code */ + public static final int BIP_CMAC_256 = 0; + + /** GMAC-128 = Galois Message Authentication Code */ + public static final int BIP_GMAC_128 = 1; + + /** GMAC-256 = Galois Message Authentication Code */ + public static final int BIP_GMAC_256 = 2; + + private static final String varName = "groupMgmt"; + + private static final String[] strings = { "BIP_CMAC_256", + "BIP_GMAC_128", "BIP_GMAC_256"}; + } + + /** + * Recognized suiteB ciphers. + * <pre> + * ECDHE_ECDSA + * ECDHE_RSA + * </pre> + * @hide + */ + public static class SuiteBCipher { + private SuiteBCipher() { } + + /** Diffie-Hellman with Elliptic Curve_ECDSA signature */ + public static final int ECDHE_ECDSA = 0; + + /** Diffie-Hellman with_RSA signature */ + public static final int ECDHE_RSA = 1; + + private static final String varName = "SuiteB"; + + private static final String[] strings = { "ECDHE_ECDSA", "ECDHE_RSA" }; } /** Possible status of a network configuration. */ @@ -409,6 +487,17 @@ public class WifiConfiguration implements Parcelable { */ public BitSet allowedGroupCiphers; /** + * The set of group management ciphers supported by this configuration. + * See {@link GroupMgmtCipher} for descriptions of the values. + */ + public BitSet allowedGroupMgmtCiphers; + /** + * The set of SuiteB ciphers supported by this configuration. + * To be used for WPA3-Enterprise mode. + * See {@link SuiteBCipher} for descriptions of the values. + */ + public BitSet allowedSuiteBCiphers; + /** * The enterprise configuration details specifying the EAP method, * certificates and other settings associated with the EAP. */ @@ -733,7 +822,8 @@ public class WifiConfiguration implements Parcelable { public boolean isOpenNetwork() { final int cardinality = allowedKeyManagement.cardinality(); final boolean hasNoKeyMgmt = cardinality == 0 - || (cardinality == 1 && allowedKeyManagement.get(KeyMgmt.NONE)); + || (cardinality == 1 && (allowedKeyManagement.get(KeyMgmt.NONE) + || allowedKeyManagement.get(KeyMgmt.OWE))); boolean hasNoWepKeys = true; if (wepKeys != null) { @@ -785,6 +875,23 @@ public class WifiConfiguration implements Parcelable { /** * @hide + * Use factory MAC when connecting to this network + */ + public static final int RANDOMIZATION_NONE = 0; + /** + * @hide + * Generate a randomized MAC once and reuse it for all connections to this network + */ + public static final int RANDOMIZATION_PERSISTENT = 1; + + /** + * @hide + * Level of MAC randomization for this network + */ + public int macRandomizationSetting = RANDOMIZATION_PERSISTENT; + + /** + * @hide * Randomized MAC address to use with this particular network */ @NonNull @@ -1521,6 +1628,8 @@ public class WifiConfiguration implements Parcelable { allowedAuthAlgorithms = new BitSet(); allowedPairwiseCiphers = new BitSet(); allowedGroupCiphers = new BitSet(); + allowedGroupMgmtCiphers = new BitSet(); + allowedSuiteBCiphers = new BitSet(); wepKeys = new String[4]; for (int i = 0; i < wepKeys.length; i++) { wepKeys[i] = null; @@ -1574,7 +1683,8 @@ public class WifiConfiguration implements Parcelable { @UnsupportedAppUsage public boolean isEnterprise() { return (allowedKeyManagement.get(KeyMgmt.WPA_EAP) - || allowedKeyManagement.get(KeyMgmt.IEEE8021X)) + || allowedKeyManagement.get(KeyMgmt.IEEE8021X) + || allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) && enterpriseConfig != null && enterpriseConfig.getEapMethod() != WifiEnterpriseConfig.Eap.NONE; } @@ -1592,6 +1702,7 @@ public class WifiConfiguration implements Parcelable { append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN) .append(" PRIO: ").append(this.priority) .append(" HIDDEN: ").append(this.hiddenSSID) + .append(" PMF: ").append(this.requirePMF) .append('\n'); @@ -1645,6 +1756,7 @@ public class WifiConfiguration implements Parcelable { if (this.meteredOverride != METERED_OVERRIDE_NONE) { sbuf.append(" meteredOverride ").append(meteredOverride).append("\n"); } + sbuf.append(" macRandomizationSetting ").append(macRandomizationSetting).append("\n"); sbuf.append(" KeyMgmt:"); for (int k = 0; k < this.allowedKeyManagement.size(); k++) { if (this.allowedKeyManagement.get(k)) { @@ -1703,10 +1815,35 @@ public class WifiConfiguration implements Parcelable { } } } - sbuf.append('\n').append(" PSK: "); + sbuf.append('\n'); + sbuf.append(" GroupMgmtCiphers:"); + for (int gmc = 0; gmc < this.allowedGroupMgmtCiphers.size(); gmc++) { + if (this.allowedGroupMgmtCiphers.get(gmc)) { + sbuf.append(" "); + if (gmc < GroupMgmtCipher.strings.length) { + sbuf.append(GroupMgmtCipher.strings[gmc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n'); + sbuf.append(" SuiteBCiphers:"); + for (int sbc = 0; sbc < this.allowedSuiteBCiphers.size(); sbc++) { + if (this.allowedSuiteBCiphers.get(sbc)) { + sbuf.append(" "); + if (sbc < SuiteBCipher.strings.length) { + sbuf.append(SuiteBCipher.strings[sbc]); + } else { + sbuf.append("??"); + } + } + } + sbuf.append('\n').append(" PSK/SAE: "); if (this.preSharedKey != null) { sbuf.append('*'); } + sbuf.append("\nEnterprise config:\n"); sbuf.append(enterpriseConfig); @@ -1869,6 +2006,12 @@ public class WifiConfiguration implements Parcelable { return KeyMgmt.WPA_EAP; } else if (allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return KeyMgmt.IEEE8021X; + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + return KeyMgmt.SAE; + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + return KeyMgmt.OWE; + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + return KeyMgmt.SUITE_B_192; } return KeyMgmt.NONE; } @@ -1900,6 +2043,12 @@ public class WifiConfiguration implements Parcelable { key = SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; } else if (wepKeys[0] != null) { key = SSID + "WEP"; + } else if (allowedKeyManagement.get(KeyMgmt.OWE)) { + key = SSID + KeyMgmt.strings[KeyMgmt.OWE]; + } else if (allowedKeyManagement.get(KeyMgmt.SAE)) { + key = SSID + KeyMgmt.strings[KeyMgmt.SAE]; + } else if (allowedKeyManagement.get(KeyMgmt.SUITE_B_192)) { + key = SSID + KeyMgmt.strings[KeyMgmt.SUITE_B_192]; } else { key = SSID + KeyMgmt.strings[KeyMgmt.NONE]; } @@ -2068,6 +2217,8 @@ public class WifiConfiguration implements Parcelable { allowedAuthAlgorithms = (BitSet) source.allowedAuthAlgorithms.clone(); allowedPairwiseCiphers = (BitSet) source.allowedPairwiseCiphers.clone(); allowedGroupCiphers = (BitSet) source.allowedGroupCiphers.clone(); + allowedGroupMgmtCiphers = (BitSet) source.allowedGroupMgmtCiphers.clone(); + allowedSuiteBCiphers = (BitSet) source.allowedSuiteBCiphers.clone(); enterpriseConfig = new WifiEnterpriseConfig(source.enterpriseConfig); defaultGwMacAddress = source.defaultGwMacAddress; @@ -2109,6 +2260,8 @@ public class WifiConfiguration implements Parcelable { shared = source.shared; recentFailure.setAssociationStatus(source.recentFailure.getAssociationStatus()); mRandomizedMacAddress = source.mRandomizedMacAddress; + macRandomizationSetting = source.macRandomizationSetting; + requirePMF = source.requirePMF; } } @@ -2144,6 +2297,8 @@ public class WifiConfiguration implements Parcelable { writeBitSet(dest, allowedAuthAlgorithms); writeBitSet(dest, allowedPairwiseCiphers); writeBitSet(dest, allowedGroupCiphers); + writeBitSet(dest, allowedGroupMgmtCiphers); + writeBitSet(dest, allowedSuiteBCiphers); dest.writeParcelable(enterpriseConfig, flags); @@ -2173,6 +2328,7 @@ public class WifiConfiguration implements Parcelable { dest.writeString(mPasspointManagementObjectTree); dest.writeInt(recentFailure.getAssociationStatus()); dest.writeParcelable(mRandomizedMacAddress, flags); + dest.writeInt(macRandomizationSetting); } /** Implement the Parcelable interface {@hide} */ @@ -2211,6 +2367,8 @@ public class WifiConfiguration implements Parcelable { config.allowedAuthAlgorithms = readBitSet(in); config.allowedPairwiseCiphers = readBitSet(in); config.allowedGroupCiphers = readBitSet(in); + config.allowedGroupMgmtCiphers = readBitSet(in); + config.allowedSuiteBCiphers = readBitSet(in); config.enterpriseConfig = in.readParcelable(null); config.setIpConfiguration(in.readParcelable(null)); @@ -2239,6 +2397,7 @@ public class WifiConfiguration implements Parcelable { config.mPasspointManagementObjectTree = in.readString(); config.recentFailure.setAssociationStatus(in.readInt()); config.mRandomizedMacAddress = in.readParcelable(null); + config.macRandomizationSetting = in.readInt(); return config; } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 15e092bc8623..954b51f02820 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -21,24 +21,21 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; -import android.annotation.SuppressLint; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.UnsupportedAppUsage; +import android.app.PendingIntent; import android.content.Context; import android.content.pm.ParceledListSlice; import android.net.ConnectivityManager; import android.net.DhcpInfo; import android.net.Network; -import android.net.NetworkCapabilities; -import android.net.NetworkRequest; +import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.OsuProvider; import android.net.wifi.hotspot2.PasspointConfiguration; -import android.net.wifi.hotspot2.IProvisioningCallback; import android.net.wifi.hotspot2.ProvisioningCallback; import android.os.Binder; -import android.os.Build; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -53,7 +50,6 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.AsyncChannel; import com.android.internal.util.Protocol; -import com.android.server.net.NetworkPinner; import dalvik.system.CloseGuard; @@ -319,6 +315,31 @@ public class WifiManager { "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD"; /** + * Activity Action: lunch OSU (Online Sign Up) view. + * Included extras: + * + * {@link #EXTRA_OSU_NETWORK}: {@link Network} instance associated with OSU AP. + * {@link #EXTRA_URL}: String representation of a server URL used for OSU process. + * + * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered + * components will be launched. + * + * @hide + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_PASSPOINT_LAUNCH_OSU_VIEW = + "android.net.wifi.action.PASSPOINT_LAUNCH_OSU_VIEW"; + + /** + * The lookup key for a {@link android.net.Network} associated with OSU server. + * + * Retrieve with {@link android.content.Intent#getParcelableExtra(String)}. + * + * @hide + */ + public static final String EXTRA_OSU_NETWORK = "android.net.wifi.extra.OSU_NETWORK"; + + /** * Broadcast intent action indicating that Wi-Fi has been enabled, disabled, * enabling, disabling, or unknown. One extra provides this state as an int. * Another extra provides the previous state, if available. @@ -759,9 +780,12 @@ public class WifiManager { @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.BATCHED_RESULTS"; + /** * The RSSI (signal strength) has changed. - * @see #EXTRA_NEW_RSSI + * + * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE + * @see {@link #EXTRA_NEW_RSSI} */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED"; @@ -928,22 +952,6 @@ public class WifiManager { @UnsupportedAppUsage public static final int WIFI_FREQUENCY_BAND_2GHZ = 2; - /** List of asyncronous notifications - * @hide - */ - public static final int DATA_ACTIVITY_NOTIFICATION = 1; - - //Lowest bit indicates data reception and the second lowest - //bit indicates data transmitted - /** @hide */ - public static final int DATA_ACTIVITY_NONE = 0x00; - /** @hide */ - public static final int DATA_ACTIVITY_IN = 0x01; - /** @hide */ - public static final int DATA_ACTIVITY_OUT = 0x02; - /** @hide */ - public static final int DATA_ACTIVITY_INOUT = 0x03; - /** @hide */ public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false; @@ -970,6 +978,7 @@ public class WifiManager { private AsyncChannel mAsyncChannel; private CountDownLatch mConnected; private Looper mLooper; + private boolean mVerboseLoggingEnabled = false; /* LocalOnlyHotspot callback message types */ /** @hide */ @@ -1002,6 +1011,7 @@ public class WifiManager { mService = service; mLooper = looper; mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion; + updateVerboseLoggingEnabledFromService(); } /** @@ -1022,7 +1032,17 @@ public class WifiManager { * </ul> * @return a list of network configurations in the form of a list * of {@link WifiConfiguration} objects. + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return an empty list. */ + @Deprecated public List<WifiConfiguration> getConfiguredNetworks() { try { ParceledListSlice<WifiConfiguration> parceledList = @@ -1122,7 +1142,17 @@ public class WifiManager { * @return the ID of the newly created network description. This is used in * other operations to specified the network to be acted upon. * Returns {@code -1} on failure. + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return {@code -1}. */ + @Deprecated public int addNetwork(WifiConfiguration config) { if (config == null) { return -1; @@ -1147,7 +1177,17 @@ public class WifiManager { * Returns {@code -1} on failure, including when the {@code networkId} * field of the {@code WifiConfiguration} does not refer to an * existing network. + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return {@code -1}. */ + @Deprecated public int updateNetwork(WifiConfiguration config) { if (config == null || config.networkId < 0) { return -1; @@ -1172,6 +1212,301 @@ public class WifiManager { } /** + * Interface for indicating user selection from the list of networks presented in the + * {@link NetworkRequestMatchCallback#onMatch(List)}. + * + * The platform will implement this callback and pass it along with the + * {@link NetworkRequestMatchCallback#onUserSelectionCallbackRegistration( + * NetworkRequestUserSelectionCallback)}. The UI component handling + * {@link NetworkRequestMatchCallback} will invoke {@link #select(WifiConfiguration)} or + * {@link #reject()} to return the user's selection back to the platform via this callback. + * @hide + */ + @SystemApi + public interface NetworkRequestUserSelectionCallback { + /** + * User selected this network to connect to. + * @param wifiConfiguration WifiConfiguration object corresponding to the network + * user selected. + */ + void select(@NonNull WifiConfiguration wifiConfiguration); + + /** + * User rejected the app's request. + */ + void reject(); + } + + /** + * Interface for network request callback. Should be implemented by applications and passed when + * calling {@link #registerNetworkRequestMatchCallback(NetworkRequestMatchCallback, Handler)}. + * + * This is meant to be implemented by a UI component to present the user with a list of networks + * matching the app's request. The user is allowed to pick one of these networks to connect to + * or reject the request by the app. + * @hide + */ + @SystemApi + public interface NetworkRequestMatchCallback { + /** + * Invoked to register a callback to be invoked to convey user selection. The callback + * object paased in this method is to be invoked by the UI component after the service sends + * a list of matching scan networks using {@link #onMatch(List)} and user picks a network + * from that list. + * + * @param userSelectionCallback Callback object to send back the user selection. + */ + void onUserSelectionCallbackRegistration( + @NonNull NetworkRequestUserSelectionCallback userSelectionCallback); + + /** + * Invoked when a network request initiated by an app matches some networks in scan results. + * This may be invoked multiple times for a single network request as the platform finds new + * networks in scan results. + * + * @param wifiConfigurations List of {@link WifiConfiguration} objects corresponding to the + * networks matching the request. + */ + void onMatch(@NonNull List<WifiConfiguration> wifiConfigurations); + + /** + * Invoked on a successful connection with the network that the user selected + * via {@link NetworkRequestUserSelectionCallback}. + * + * @param wifiConfiguration WifiConfiguration object corresponding to the network that the + * user selected. + */ + void onUserSelectionConnectSuccess(@NonNull WifiConfiguration wifiConfiguration); + + /** + * Invoked on failure to establish connection with the network that the user selected + * via {@link NetworkRequestUserSelectionCallback}. + * + * @param wifiConfiguration WifiConfiguration object corresponding to the network + * user selected. + */ + void onUserSelectionConnectFailure(@NonNull WifiConfiguration wifiConfiguration); + } + + /** + * Callback proxy for NetworkRequestUserSelectionCallback objects. + * @hide + */ + private class NetworkRequestUserSelectionCallbackProxy implements + NetworkRequestUserSelectionCallback { + private final INetworkRequestUserSelectionCallback mCallback; + + NetworkRequestUserSelectionCallbackProxy( + INetworkRequestUserSelectionCallback callback) { + mCallback = callback; + } + + @Override + public void select(@NonNull WifiConfiguration wifiConfiguration) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: select " + + "wificonfiguration: " + wifiConfiguration); + } + try { + mCallback.select(wifiConfiguration); + } catch (RemoteException e) { + Log.e(TAG, "Failed to invoke onSelected", e); + throw e.rethrowFromSystemServer(); + } + } + + @Override + public void reject() { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestUserSelectionCallbackProxy: reject"); + } + try { + mCallback.reject(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to invoke onRejected", e); + throw e.rethrowFromSystemServer(); + } + } + } + + /** + * Callback proxy for NetworkRequestMatchCallback objects. + * @hide + */ + private class NetworkRequestMatchCallbackProxy extends INetworkRequestMatchCallback.Stub { + private final Handler mHandler; + private final NetworkRequestMatchCallback mCallback; + + NetworkRequestMatchCallbackProxy(Looper looper, NetworkRequestMatchCallback callback) { + mHandler = new Handler(looper); + mCallback = callback; + } + + @Override + public void onUserSelectionCallbackRegistration( + INetworkRequestUserSelectionCallback userSelectionCallback) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestMatchCallbackProxy: " + + "onUserSelectionCallbackRegistration callback: " + userSelectionCallback); + } + mHandler.post(() -> { + mCallback.onUserSelectionCallbackRegistration( + new NetworkRequestUserSelectionCallbackProxy(userSelectionCallback)); + }); + } + + @Override + public void onMatch(List<WifiConfiguration> wifiConfigurations) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestMatchCallbackProxy: onMatch wificonfigurations: " + + wifiConfigurations); + } + mHandler.post(() -> { + mCallback.onMatch(wifiConfigurations); + }); + } + + @Override + public void onUserSelectionConnectSuccess(WifiConfiguration wifiConfiguration) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectSuccess " + + " wificonfiguration: " + wifiConfiguration); + } + mHandler.post(() -> { + mCallback.onUserSelectionConnectSuccess(wifiConfiguration); + }); + } + + @Override + public void onUserSelectionConnectFailure(WifiConfiguration wifiConfiguration) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "NetworkRequestMatchCallbackProxy: onUserSelectionConnectFailure" + + " wificonfiguration: " + wifiConfiguration); + } + mHandler.post(() -> { + mCallback.onUserSelectionConnectFailure(wifiConfiguration); + }); + } + } + + /** + * Registers a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. + * Caller can unregister a previously registered callback using + * {@link #unregisterNetworkRequestMatchCallback(NetworkRequestMatchCallback)} + * <p> + * Applications should have the + * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers + * without the permission will trigger a {@link java.lang.SecurityException}. + * <p> + * + * @param callback Callback for network match events + * @param handler The Handler on whose thread to execute the callbacks of the {@code callback} + * object. If null, then the application's main thread will be used. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void registerNetworkRequestMatchCallback(@NonNull NetworkRequestMatchCallback callback, + @Nullable Handler handler) { + if (callback == null) throw new IllegalArgumentException("callback cannot be null"); + Log.v(TAG, "registerNetworkRequestMatchCallback: callback=" + callback + + ", handler=" + handler); + + Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); + Binder binder = new Binder(); + try { + mService.registerNetworkRequestMatchCallback( + binder, new NetworkRequestMatchCallbackProxy(looper, callback), + callback.hashCode()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Unregisters a callback for NetworkRequest matches. See {@link NetworkRequestMatchCallback}. + * <p> + * Applications should have the + * {@link android.Manifest.permission#NETWORK_SETTINGS} permission. Callers + * without the permission will trigger a {@link java.lang.SecurityException}. + * <p> + * + * @param callback Callback for network match events + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void unregisterNetworkRequestMatchCallback( + @NonNull NetworkRequestMatchCallback callback) { + if (callback == null) throw new IllegalArgumentException("callback cannot be null"); + Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback); + + try { + mService.unregisterNetworkRequestMatchCallback(callback.hashCode()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Provide a list of network suggestions to the device. See {@link WifiNetworkSuggestion} + * for a detailed explanation of the parameters. + *<p> + * When the device decides to connect to one of the provided network suggestions, platform fires + * the associated {@code pendingIntent} if + * the network was created with {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} + * flag set and the provided {@code pendingIntent} is non-null. + *<p> + * Registration of a non-null pending intent {@code pendingIntent} requires + * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or + * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission. + *<p> + * NOTE: + * <li> These networks are just a suggestion to the platform. The platform will ultimately + * decide on which network the device connects to. </li> + * <li> When an app is uninstalled, all its suggested networks are discarded. If the device is + * currently connected to a suggested network which is being removed then the device will + * disconnect from that network.</li> + * <li> No in-place modification of existing suggestions are allowed. Apps are expected to + * remove suggestions using {@link #removeNetworkSuggestions(List)} and then add the modified + * suggestion back using this API.</li> + * + * @param networkSuggestions List of network suggestions provided by the app. + * @param pendingIntent Pending intent to be fired post connection for networks. These will be + * fired only when connecting to a network that was created with + * {@link WifiNetworkConfigBuilder#setIsAppInteractionRequired()} flag set. + * Pending intent must hold a foreground service, else will be rejected. + * @return true on success, false if any of the suggestions match (See + * {@link WifiNetworkSuggestion#equals(Object)} any previously provided suggestions by the app. + * @throws {@link SecurityException} if the caller is missing required permissions. + */ + public boolean addNetworkSuggestions( + @NonNull List<WifiNetworkSuggestion> networkSuggestions, + @Nullable PendingIntent pendingIntent) { + // TODO(b/115504887): Implementation + return false; + } + + + /** + * Remove a subset of or all of networks from previously provided suggestions by the app to the + * device. + * See {@link WifiNetworkSuggestion} for a detailed explanation of the parameters. + * See {@link WifiNetworkSuggestion#equals(Object)} for the equivalence evaluation used. + * + * @param networkSuggestions List of network suggestions to be removed. Pass an empty list + * to remove all the previous suggestions provided by the app. + * @return true on success, false if any of the suggestions do not match any suggestions + * previously provided by the app. Any matching suggestions are removed from the device and + * will not be considered for any further connection attempts. + */ + public boolean removeNetworkSuggestions( + @NonNull List<WifiNetworkSuggestion> networkSuggestions) { + // TODO(b/115504887): Implementation + return false; + } + + /** * Add or update a Passpoint configuration. The configuration provides a credential * for connecting to Passpoint networks that are operated by the Passpoint * service provider specified in the configuration. @@ -1286,7 +1621,17 @@ public class WifiManager { * @param netId the ID of the network as returned by {@link #addNetwork} or {@link * #getConfiguredNetworks}. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean removeNetwork(int netId) { try { return mService.removeNetwork(netId, mContext.getOpPackageName()); @@ -1301,10 +1646,8 @@ public class WifiManager { * network is initiated. This may result in the asynchronous delivery * of state change events. * <p> - * <b>Note:</b> If an application's target SDK version is - * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network - * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may - * instead be sent through another network, such as cellular data, + * <b>Note:</b> Network communication may not use Wi-Fi even if Wi-Fi is connected; + * traffic may instead be sent through another network, such as cellular data, * Bluetooth tethering, or Ethernet. For example, traffic will never use a * Wi-Fi network that does not provide Internet access (e.g. a wireless * printer), if another network that does offer Internet access (e.g. @@ -1322,29 +1665,24 @@ public class WifiManager { * @param attemptConnect The way to select a particular network to connect to is specify * {@code true} for this parameter. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean enableNetwork(int netId, boolean attemptConnect) { - final boolean pin = attemptConnect && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP; - if (pin) { - NetworkRequest request = new NetworkRequest.Builder() - .clearCapabilities() - .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN) - .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) - .build(); - NetworkPinner.pin(mContext, request); - } - boolean success; try { success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - - if (pin && !success) { - NetworkPinner.unpin(); - } - return success; } @@ -1359,7 +1697,17 @@ public class WifiManager { * @param netId the ID of the network as returned by {@link #addNetwork} or {@link * #getConfiguredNetworks}. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean disableNetwork(int netId) { try { return mService.disableNetwork(netId, mContext.getOpPackageName()); @@ -1372,7 +1720,17 @@ public class WifiManager { * Disassociate from the currently active access point. This may result * in the asynchronous delivery of state change events. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean disconnect() { try { mService.disconnect(mContext.getOpPackageName()); @@ -1387,7 +1745,17 @@ public class WifiManager { * disconnected. This may result in the asynchronous delivery of state * change events. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean reconnect() { try { mService.reconnect(mContext.getOpPackageName()); @@ -1402,7 +1770,17 @@ public class WifiManager { * connected. This may result in the asynchronous delivery of state * change events. * @return {@code true} if the operation succeeded + * + * @deprecated + * a) See {@link WifiNetworkConfigBuilder#buildNetworkSpecifier()} for new + * mechanism to trigger connection to a Wi-Fi network. + * b) See {@link #addNetworkSuggestions(List, PendingIntent)}, + * {@link #removeNetworkSuggestions(List)} for new API to add Wi-Fi networks for consideration + * when auto-connecting to wifi. + * <b>Compatibility Note:</b> For applications targeting + * {@link android.os.Build.VERSION_CODES#Q} or above, this API will always return false. */ + @Deprecated public boolean reassociate() { try { mService.reassociate(mContext.getOpPackageName()); @@ -1477,7 +1855,12 @@ public class WifiManager { public static final int WIFI_FEATURE_SCAN_RAND = 0x2000000; // Random MAC & Probe seq /** @hide */ public static final int WIFI_FEATURE_TX_POWER_LIMIT = 0x4000000; // Set Tx power limit - + /** @hide */ + public static final int WIFI_FEATURE_WPA3_SAE = 0x8000000; // WPA3-Personal SAE + /** @hide */ + public static final int WIFI_FEATURE_WPA3_SUITE_B = 0x10000000; // WPA3-Enterprise Suite-B + /** @hide */ + public static final int WIFI_FEATURE_OWE = 0x20000000; // Enhanced Open private int getSupportedFeatures() { try { @@ -1596,13 +1979,12 @@ public class WifiManager { * Return the record of {@link WifiActivityEnergyInfo} object that * has the activity and energy info. This can be used to ascertain what * the controller has been up to, since the last sample. - * @param updateType Type of info, cached vs refreshed. * * @return a record with {@link WifiActivityEnergyInfo} or null if * report is unavailable or unsupported * @hide */ - public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { + public WifiActivityEnergyInfo getControllerActivityEnergyInfo() { if (mService == null) return null; try { synchronized(this) { @@ -1686,9 +2068,7 @@ public class WifiManager { * @return the list of access points found in the most recent scan. An app must hold * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission - * in order to get valid results. If there is a remote exception (e.g., either a communication - * problem with the system service or an exception within the framework) an empty list will be - * returned. + * in order to get valid results. */ public List<ScanResult> getScanResults() { try { @@ -1705,7 +2085,10 @@ public class WifiManager { * even when Wi-Fi is turned off. * * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}. + * @deprecated The ability for apps to trigger scan requests will be removed in a future + * release. */ + @Deprecated public boolean isScanAlwaysAvailable() { try { return mService.isScanAlwaysAvailable(); @@ -1811,7 +2194,12 @@ public class WifiManager { * @return {@code false} if the request cannot be satisfied; {@code true} indicates that wifi is * either already in the requested state, or in progress toward the requested state. * @throws {@link java.lang.SecurityException} if the caller is missing required permissions. + * + * @deprecated Starting with Build.VERSION_CODES#Q, applications are not allowed to + * enable/disable Wi-Fi regardless of application's target SDK. This API will have no effect + * and will always return false. */ + @Deprecated public boolean setWifiEnabled(boolean enabled) { try { return mService.setWifiEnabled(mContext.getOpPackageName(), enabled); @@ -2465,7 +2853,7 @@ public class WifiManager { * * @hide */ - private static class SoftApCallbackProxy extends ISoftApCallback.Stub { + private class SoftApCallbackProxy extends ISoftApCallback.Stub { private final Handler mHandler; private final SoftApCallback mCallback; @@ -2475,17 +2863,21 @@ public class WifiManager { } @Override - public void onStateChanged(int state, int failureReason) throws RemoteException { - Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + ", failureReason=" + - failureReason); + public void onStateChanged(int state, int failureReason) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SoftApCallbackProxy: onStateChanged: state=" + state + + ", failureReason=" + failureReason); + } mHandler.post(() -> { mCallback.onStateChanged(state, failureReason); }); } @Override - public void onNumClientsChanged(int numClients) throws RemoteException { - Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients); + public void onNumClientsChanged(int numClients) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "SoftApCallbackProxy: onNumClientsChanged: numClients=" + numClients); + } mHandler.post(() -> { mCallback.onNumClientsChanged(numClients); }); @@ -3121,10 +3513,9 @@ public class WifiManager { * an AsyncChannel communication with WifiService * * @return Messenger pointing to the WifiService handler - * @hide */ @UnsupportedAppUsage - public Messenger getWifiServiceMessenger() { + private Messenger getWifiServiceMessenger() { try { return mService.getWifiServiceMessenger(mContext.getOpPackageName()); } catch (RemoteException e) { @@ -3425,7 +3816,7 @@ public class WifiManager { mService.acquireMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { if (mActiveLockCount >= MAX_ACTIVE_LOCKS) { - mService.releaseMulticastLock(); + mService.releaseMulticastLock(mTag); throw new UnsupportedOperationException( "Exceeded maximum number of wifi locks"); } @@ -3467,7 +3858,7 @@ public class WifiManager { synchronized (mBinder) { if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { - mService.releaseMulticastLock(); + mService.releaseMulticastLock(mTag); synchronized (WifiManager.this) { mActiveLockCount--; } @@ -3741,5 +4132,152 @@ public class WifiManager { mCallback.onProvisioningFailure(status); }); } + + @Override + public void onProvisioningComplete() { + mHandler.post(() -> { + mCallback.onProvisioningComplete(); + }); + } + } + + /** + * Base class for Traffic state callback. Should be extended by applications and set when + * calling {@link WifiManager#registerTrafficStateCallback(TrafficStateCallback, Handler)}. + * @hide + */ + public interface TrafficStateCallback { + /** + * Lowest bit indicates data reception and the second lowest + * bit indicates data transmitted + */ + /** @hide */ + int DATA_ACTIVITY_NONE = 0x00; + /** @hide */ + int DATA_ACTIVITY_IN = 0x01; + /** @hide */ + int DATA_ACTIVITY_OUT = 0x02; + /** @hide */ + int DATA_ACTIVITY_INOUT = 0x03; + + /** + * Callback invoked to inform clients about the current traffic state. + * + * @param state One of the values: {@link #DATA_ACTIVITY_NONE}, {@link #DATA_ACTIVITY_IN}, + * {@link #DATA_ACTIVITY_OUT} & {@link #DATA_ACTIVITY_INOUT}. + * @hide + */ + void onStateChanged(int state); + } + + /** + * Callback proxy for TrafficStateCallback objects. + * + * @hide + */ + private class TrafficStateCallbackProxy extends ITrafficStateCallback.Stub { + private final Handler mHandler; + private final TrafficStateCallback mCallback; + + TrafficStateCallbackProxy(Looper looper, TrafficStateCallback callback) { + mHandler = new Handler(looper); + mCallback = callback; + } + + @Override + public void onStateChanged(int state) { + if (mVerboseLoggingEnabled) { + Log.v(TAG, "TrafficStateCallbackProxy: onStateChanged state=" + state); + } + mHandler.post(() -> { + mCallback.onStateChanged(state); + }); + } + } + + /** + * Registers a callback for monitoring traffic state. See {@link TrafficStateCallback}. These + * callbacks will be invoked periodically by platform to inform clients about the current + * traffic state. Caller can unregister a previously registered callback using + * {@link #unregisterTrafficStateCallback(TrafficStateCallback)} + * <p> + * Applications should have the + * {@link android.Manifest.permission#NETWORK_SETTINGS NETWORK_SETTINGS} permission. Callers + * without the permission will trigger a {@link java.lang.SecurityException}. + * <p> + * + * @param callback Callback for traffic state events + * @param handler The Handler on whose thread to execute the callbacks of the {@code callback} + * object. If null, then the application's main thread will be used. + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void registerTrafficStateCallback(@NonNull TrafficStateCallback callback, + @Nullable Handler handler) { + if (callback == null) throw new IllegalArgumentException("callback cannot be null"); + Log.v(TAG, "registerTrafficStateCallback: callback=" + callback + ", handler=" + handler); + + Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper(); + Binder binder = new Binder(); + try { + mService.registerTrafficStateCallback( + binder, new TrafficStateCallbackProxy(looper, callback), callback.hashCode()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Allow callers to unregister a previously registered callback. After calling this method, + * applications will no longer receive traffic state notifications. + * + * @param callback Callback to unregister for traffic state events + * @hide + */ + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void unregisterTrafficStateCallback(@NonNull TrafficStateCallback callback) { + if (callback == null) throw new IllegalArgumentException("callback cannot be null"); + Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback); + + try { + mService.unregisterTrafficStateCallback(callback.hashCode()); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Helper method to update the local verbose logging flag based on the verbose logging + * level from wifi service. + */ + private void updateVerboseLoggingEnabledFromService() { + mVerboseLoggingEnabled = getVerboseLoggingLevel() > 0; + } + + /** + * @return true if this device supports WPA3-Personal SAE + * @hide + */ + @SystemApi + public boolean isWpa3SaeSupported() { + return isFeatureSupported(WIFI_FEATURE_WPA3_SAE); + } + + /** + * @return true if this device supports WPA3-Enterprise Suite-B-192 + * @hide + */ + @SystemApi + public boolean isWpa3SuiteBSupported() { + return isFeatureSupported(WIFI_FEATURE_WPA3_SUITE_B); + } + + /** + * @return true if this device supports Wi-Fi Enhanced Open (OWE) + * @hide + */ + @SystemApi + public boolean isOweSupported() { + return isFeatureSupported(WIFI_FEATURE_OWE); } } diff --git a/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java new file mode 100644 index 000000000000..55fde4ca335e --- /dev/null +++ b/wifi/java/android/net/wifi/WifiNetworkAgentSpecifier.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.internal.util.Preconditions.checkState; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.MacAddress; +import android.net.MatchAllNetworkSpecifier; +import android.net.NetworkAgent; +import android.net.NetworkRequest; +import android.net.NetworkSpecifier; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Network specifier object used by wifi's {@link android.net.NetworkAgent}. + * @hide + */ +public final class WifiNetworkAgentSpecifier extends NetworkSpecifier implements Parcelable { + /** + * Security credentials for the currently connected network. + */ + private final WifiConfiguration mWifiConfiguration; + + /** + * The UID of the app that requested a specific wifi network using {@link WifiNetworkSpecifier}. + * + * Will only be filled when the device connects to a wifi network as a result of a + * {@link NetworkRequest} with {@link WifiNetworkSpecifier}. Will be set to -1 if the device + * auto-connected to a wifi network. + */ + private final int mOriginalRequestorUid; + + public WifiNetworkAgentSpecifier(@NonNull WifiConfiguration wifiConfiguration, + int originalRequestorUid) { + checkNotNull(wifiConfiguration); + + mWifiConfiguration = wifiConfiguration; + mOriginalRequestorUid = originalRequestorUid; + } + + /** + * @hide + */ + public static final Creator<WifiNetworkAgentSpecifier> CREATOR = + new Creator<WifiNetworkAgentSpecifier>() { + @Override + public WifiNetworkAgentSpecifier createFromParcel(@NonNull Parcel in) { + WifiConfiguration wifiConfiguration = in.readParcelable(null); + int originalRequestorUid = in.readInt(); + return new WifiNetworkAgentSpecifier(wifiConfiguration, originalRequestorUid); + } + + @Override + public WifiNetworkAgentSpecifier[] newArray(int size) { + return new WifiNetworkAgentSpecifier[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeParcelable(mWifiConfiguration, flags); + dest.writeInt(mOriginalRequestorUid); + } + + @Override + public boolean satisfiedBy(@Nullable NetworkSpecifier other) { + if (this == other) { + return true; + } + // Any generic requests should be satisifed by a specific wifi network. + if (other == null || other instanceof MatchAllNetworkSpecifier) { + return true; + } + if (other instanceof WifiNetworkSpecifier) { + return satisfiesNetworkSpecifier((WifiNetworkSpecifier) other); + } + if (other instanceof WifiNetworkAgentSpecifier) { + throw new IllegalStateException("WifiNetworkAgentSpecifier instances should never be " + + "compared"); + } + return false; + } + + /** + * Match {@link WifiNetworkSpecifier} in app's {@link NetworkRequest} with the + * {@link WifiNetworkAgentSpecifier} in wifi platform's {@link NetworkAgent}. + */ + public boolean satisfiesNetworkSpecifier(@NonNull WifiNetworkSpecifier ns) { + // None of these should be null by construction. + // {@link WifiNetworkConfigBuilder} enforces non-null in {@link WifiNetworkSpecifier}. + // {@link WifiNetworkFactory} ensures non-null in {@link WifiNetworkAgentSpecifier}. + checkNotNull(ns); + checkNotNull(ns.ssidPatternMatcher); + checkNotNull(ns.bssidPatternMatcher); + checkNotNull(ns.wifiConfiguration.allowedKeyManagement); + checkNotNull(this.mWifiConfiguration.SSID); + checkNotNull(this.mWifiConfiguration.BSSID); + checkNotNull(this.mWifiConfiguration.allowedKeyManagement); + + final String ssidWithQuotes = this.mWifiConfiguration.SSID; + checkState(ssidWithQuotes.startsWith("\"") && ssidWithQuotes.endsWith("\"")); + final String ssidWithoutQuotes = ssidWithQuotes.substring(1, ssidWithQuotes.length() - 1); + if (!ns.ssidPatternMatcher.match(ssidWithoutQuotes)) { + return false; + } + final MacAddress bssid = MacAddress.fromString(this.mWifiConfiguration.BSSID); + final MacAddress matchBaseAddress = ns.bssidPatternMatcher.first; + final MacAddress matchMask = ns.bssidPatternMatcher.second; + if (!bssid.matches(matchBaseAddress, matchMask)) { + return false; + } + if (!ns.wifiConfiguration.allowedKeyManagement.equals( + this.mWifiConfiguration.allowedKeyManagement)) { + return false; + } + if (ns.requestorUid != this.mOriginalRequestorUid) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Objects.hash( + mWifiConfiguration.SSID, + mWifiConfiguration.BSSID, + mWifiConfiguration.allowedKeyManagement, + mOriginalRequestorUid); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof WifiNetworkAgentSpecifier)) { + return false; + } + WifiNetworkAgentSpecifier lhs = (WifiNetworkAgentSpecifier) obj; + return Objects.equals(this.mWifiConfiguration.SSID, lhs.mWifiConfiguration.SSID) + && Objects.equals(this.mWifiConfiguration.BSSID, lhs.mWifiConfiguration.BSSID) + && Objects.equals(this.mWifiConfiguration.allowedKeyManagement, + lhs.mWifiConfiguration.allowedKeyManagement) + && mOriginalRequestorUid == lhs.mOriginalRequestorUid; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("WifiNetworkAgentSpecifier ["); + sb.append(", WifiConfiguration=").append( + mWifiConfiguration == null ? null : mWifiConfiguration.configKey()) + .append(", mOriginalRequestorUid=").append(mOriginalRequestorUid) + .append("]"); + return sb.toString(); + } + + @Override + public void assertValidFromUid(int requestorUid) { + throw new IllegalStateException("WifiNetworkAgentSpecifier should never be used " + + "for requests."); + } +} diff --git a/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java new file mode 100644 index 000000000000..67e218972994 --- /dev/null +++ b/wifi/java/android/net/wifi/WifiNetworkConfigBuilder.java @@ -0,0 +1,511 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.app.PendingIntent; +import android.net.MacAddress; +import android.net.NetworkRequest; +import android.net.NetworkSpecifier; +import android.os.PatternMatcher; +import android.os.Process; +import android.text.TextUtils; +import android.util.Pair; + +import java.nio.charset.CharsetEncoder; +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * WifiNetworkConfigBuilder to use for creating Wi-Fi network configuration. + * <li>See {@link #buildNetworkSpecifier()} for creating a network specifier to use in + * {@link NetworkRequest}.</li> + * <li>See {@link #buildNetworkSuggestion()} for creating a network suggestion to use in + * {@link WifiManager#addNetworkSuggestions(List, PendingIntent)}.</li> + */ +public class WifiNetworkConfigBuilder { + private static final String MATCH_ALL_SSID_PATTERN_PATH = ".*"; + private static final String MATCH_EMPTY_SSID_PATTERN_PATH = ""; + private static final Pair<MacAddress, MacAddress> MATCH_NO_BSSID_PATTERN = + new Pair(MacAddress.BROADCAST_ADDRESS, MacAddress.BROADCAST_ADDRESS); + private static final Pair<MacAddress, MacAddress> MATCH_ALL_BSSID_PATTERN = + new Pair(MacAddress.ALL_ZEROS_ADDRESS, MacAddress.ALL_ZEROS_ADDRESS); + private static final MacAddress MATCH_EXACT_BSSID_PATTERN_MASK = + MacAddress.BROADCAST_ADDRESS; + private static final int UNASSIGNED_PRIORITY = -1; + + /** + * SSID pattern match specified by the app. + */ + private @Nullable PatternMatcher mSsidPatternMatcher; + /** + * BSSID pattern match specified by the app. + * Pair of <BaseAddress, Mask>. + */ + private @Nullable Pair<MacAddress, MacAddress> mBssidPatternMatcher; + /** + * Pre-shared key for use with WPA-PSK networks. + */ + private @Nullable String mPskPassphrase; + /** + * The enterprise configuration details specifying the EAP method, + * certificates and other settings associated with the EAP. + */ + private @Nullable WifiEnterpriseConfig mEnterpriseConfig; + /** + * This is a network that does not broadcast its SSID, so an + * SSID-specific probe request must be used for scans. + */ + private boolean mIsHiddenSSID; + /** + * Whether app needs to log in to captive portal to obtain Internet access. + */ + private boolean mIsAppInteractionRequired; + /** + * Whether user needs to log in to captive portal to obtain Internet access. + */ + private boolean mIsUserInteractionRequired; + /** + * Whether this network is metered or not. + */ + private boolean mIsMetered; + /** + * Priority of this network among other network suggestions provided by the app. + * The lower the number, the higher the priority (i.e value of 0 = highest priority). + */ + private int mPriority; + + public WifiNetworkConfigBuilder() { + mSsidPatternMatcher = null; + mBssidPatternMatcher = null; + mPskPassphrase = null; + mEnterpriseConfig = null; + mIsHiddenSSID = false; + mIsAppInteractionRequired = false; + mIsUserInteractionRequired = false; + mIsMetered = false; + mPriority = UNASSIGNED_PRIORITY; + } + + /** + * Set the unicode SSID match pattern to use for filtering networks from scan results. + * <p> + * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li> + * <li>Overrides any previous value set using {@link #setSsid(String)} or + * {@link #setSsidPattern(PatternMatcher)}.</li> + * + * @param ssidPattern Instance of {@link PatternMatcher} containing the UTF-8 encoded + * string pattern to use for matching the network's SSID. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setSsidPattern(@NonNull PatternMatcher ssidPattern) { + checkNotNull(ssidPattern); + mSsidPatternMatcher = ssidPattern; + return this; + } + + /** + * Set the unicode SSID for the network. + * <p> + * <li>For network requests ({@link NetworkSpecifier}), built using + * {@link #buildNetworkSpecifier}, sets the SSID to use for filtering networks from scan + * results. Will only match networks whose SSID is identical to the UTF-8 encoding of the + * specified value.</li> + * <li>For network suggestions ({@link WifiNetworkSuggestion}), built using + * {@link #buildNetworkSuggestion()}, sets the SSID for the network.</li> + * <li>Overrides any previous value set using {@link #setSsid(String)} or + * {@link #setSsidPattern(PatternMatcher)}.</li> + * + * @param ssid The SSID of the network. It must be valid Unicode. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + * @throws IllegalArgumentException if the SSID is not valid unicode. + */ + public WifiNetworkConfigBuilder setSsid(@NonNull String ssid) { + checkNotNull(ssid); + final CharsetEncoder unicodeEncoder = StandardCharsets.UTF_8.newEncoder(); + if (!unicodeEncoder.canEncode(ssid)) { + throw new IllegalArgumentException("SSID is not a valid unicode string"); + } + mSsidPatternMatcher = new PatternMatcher(ssid, PatternMatcher.PATTERN_LITERAL); + return this; + } + + /** + * Set the BSSID match pattern to use for filtering networks from scan results. + * Will match all networks with BSSID which satisfies the following: + * {@code BSSID & mask == baseAddress}. + * <p> + * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li> + * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or + * {@link #setBssidPattern(MacAddress, MacAddress)}.</li> + * + * @param baseAddress Base address for BSSID pattern. + * @param mask Mask for BSSID pattern. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setBssidPattern( + @NonNull MacAddress baseAddress, @NonNull MacAddress mask) { + checkNotNull(baseAddress, mask); + mBssidPatternMatcher = Pair.create(baseAddress, mask); + return this; + } + + /** + * Set the BSSID to use for filtering networks from scan results. Will only match network whose + * BSSID is identical to the specified value. + * <p> + * <li>Only allowed for creating network specifier, i.e {@link #buildNetworkSpecifier()}. </li> + * <li>Overrides any previous value set using {@link #setBssid(MacAddress)} or + * {@link #setBssidPattern(MacAddress, MacAddress)}.</li> + * + * @param bssid BSSID of the network. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setBssid(@NonNull MacAddress bssid) { + checkNotNull(bssid); + mBssidPatternMatcher = Pair.create(bssid, MATCH_EXACT_BSSID_PATTERN_MASK); + return this; + } + + /** + * Set the ASCII PSK passphrase for this network. Needed for authenticating to + * WPA_PSK networks. + * + * @param pskPassphrase PSK passphrase of the network. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + * @throws IllegalArgumentException if the passphrase is not ASCII encodable. + */ + public WifiNetworkConfigBuilder setPskPassphrase(@NonNull String pskPassphrase) { + checkNotNull(pskPassphrase); + final CharsetEncoder asciiEncoder = StandardCharsets.US_ASCII.newEncoder(); + if (!asciiEncoder.canEncode(pskPassphrase)) { + throw new IllegalArgumentException("passphrase not ASCII encodable"); + } + mPskPassphrase = pskPassphrase; + return this; + } + + /** + * Set the associated enterprise configuration for this network. Needed for authenticating to + * WPA_EAP networks. See {@link WifiEnterpriseConfig} for description. + * + * @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setEnterpriseConfig( + @NonNull WifiEnterpriseConfig enterpriseConfig) { + checkNotNull(enterpriseConfig); + mEnterpriseConfig = new WifiEnterpriseConfig(enterpriseConfig); + return this; + } + + /** + * Specifies whether this represents a hidden network. + * <p> + * <li>For network requests (see {@link NetworkSpecifier}), built using + * {@link #buildNetworkSpecifier}, setting this disallows the usage of + * {@link #setSsidPattern(PatternMatcher)} since hidden networks need to be explicitly + * probed for.</li> + * <li>If not set, defaults to false (i.e not a hidden network).</li> + * + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setIsHiddenSsid() { + mIsHiddenSSID = true; + return this; + } + + /** + * Specifies whether the app needs to log in to a captive portal to obtain Internet access. + * <p> + * This will dictate if the associated pending intent in + * {@link WifiManager#addNetworkSuggestions(List, PendingIntent)} will be sent after + * successfully connecting to the network. + * Use this for captive portal type networks where the app needs to authenticate the user + * before the device can access the network. + * This setting will be ignored if the {@code PendingIntent} used to add this network + * suggestion is null. + * <p> + * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li> + * <li>If not set, defaults to false (i.e no app interaction required).</li> + * + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setIsAppInteractionRequired() { + mIsAppInteractionRequired = true; + return this; + } + + /** + * Specifies whether the user needs to log in to a captive portal to obtain Internet access. + * <p> + * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li> + * <li>If not set, defaults to false (i.e no user interaction required).</li> + * + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setIsUserInteractionRequired() { + mIsUserInteractionRequired = true; + return this; + } + + /** + * Specify the priority of this network among other network suggestions provided by the same app + * (priorities have no impact on suggestions by different apps). The lower the number, the + * higher the priority (i.e value of 0 = highest priority). + * <p> + * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li> + * <li>If not set, defaults to -1 (i.e unassigned priority).</li> + * + * @param priority Integer number representing the priority among suggestions by the app. + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + * @throws IllegalArgumentException if the priority value is negative. + */ + public WifiNetworkConfigBuilder setPriority(int priority) { + if (priority < 0) { + throw new IllegalArgumentException("Invalid priority value " + priority); + } + mPriority = priority; + return this; + } + + /** + * Specifies whether this network is metered. + * <p> + * <li>Only allowed for creating network suggestion, i.e {@link #buildNetworkSuggestion()}.</li> + * <li>If not set, defaults to false (i.e not metered).</li> + * + * @return Instance of {@link WifiNetworkConfigBuilder} to enable chaining of the builder + * method. + */ + public WifiNetworkConfigBuilder setIsMetered() { + mIsMetered = true; + return this; + } + + /** + * Set defaults for the various low level credential type fields in the newly created + * WifiConfiguration object. + * + * See {@link com.android.server.wifi.WifiConfigManager#setDefaultsInWifiConfiguration( + * WifiConfiguration)}. + * + * @param configuration provided WifiConfiguration object. + */ + private static void setDefaultsInWifiConfiguration(@NonNull WifiConfiguration configuration) { + configuration.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN); + configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN); + configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP); + configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP); + } + + private void setKeyMgmtInWifiConfiguration(@NonNull WifiConfiguration configuration) { + if (!TextUtils.isEmpty(mPskPassphrase)) { + // WPA_PSK network. + configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); + } else if (mEnterpriseConfig != null) { + // WPA_EAP network + configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP); + configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.IEEE8021X); + } else { + // Open network + configuration.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); + } + } + + /** + * Helper method to build WifiConfiguration object from the builder. + * @return Instance of {@link WifiConfiguration}. + */ + private WifiConfiguration buildWifiConfiguration() { + final WifiConfiguration wifiConfiguration = new WifiConfiguration(); + setDefaultsInWifiConfiguration(wifiConfiguration); + // WifiConfiguration.SSID needs quotes around unicode SSID. + if (mSsidPatternMatcher.getType() == PatternMatcher.PATTERN_LITERAL) { + wifiConfiguration.SSID = "\"" + mSsidPatternMatcher.getPath() + "\""; + } + setKeyMgmtInWifiConfiguration(wifiConfiguration); + // WifiConfiguration.preSharedKey needs quotes around ASCII password. + if (mPskPassphrase != null) { + wifiConfiguration.preSharedKey = "\"" + mPskPassphrase + "\""; + } + wifiConfiguration.enterpriseConfig = mEnterpriseConfig; + wifiConfiguration.hiddenSSID = mIsHiddenSSID; + wifiConfiguration.priority = mPriority; + wifiConfiguration.meteredOverride = + mIsMetered ? WifiConfiguration.METERED_OVERRIDE_METERED + : WifiConfiguration.METERED_OVERRIDE_NONE; + return wifiConfiguration; + } + + private boolean hasSetAnyPattern() { + return mSsidPatternMatcher != null || mBssidPatternMatcher != null; + } + + private void setMatchAnyPatternIfUnset() { + if (mSsidPatternMatcher == null) { + mSsidPatternMatcher = new PatternMatcher(MATCH_ALL_SSID_PATTERN_PATH, + PatternMatcher.PATTERN_SIMPLE_GLOB); + } + if (mBssidPatternMatcher == null) { + mBssidPatternMatcher = MATCH_ALL_BSSID_PATTERN; + } + } + + private boolean hasSetMatchNonePattern() { + if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_PREFIX + && mSsidPatternMatcher.getPath().equals(MATCH_EMPTY_SSID_PATTERN_PATH)) { + return true; + } + if (mBssidPatternMatcher.equals(MATCH_NO_BSSID_PATTERN)) { + return true; + } + return false; + } + + private boolean hasSetMatchAllPattern() { + if ((mSsidPatternMatcher.match(MATCH_EMPTY_SSID_PATTERN_PATH)) + && mBssidPatternMatcher.equals(MATCH_ALL_BSSID_PATTERN)) { + return true; + } + return false; + } + + /** + * Create a specifier object used to request a Wi-Fi network. The generated + * {@link NetworkSpecifier} should be used in + * {@link NetworkRequest.Builder#setNetworkSpecifier(NetworkSpecifier)} when building + * the {@link NetworkRequest}. + *<p> + * Note: Apps can set a combination of network match params: + * <li> SSID Pattern using {@link #setSsidPattern(PatternMatcher)} OR Specific SSID using + * {@link #setSsid(String)}. </li> + * AND/OR + * <li> BSSID Pattern using {@link #setBssidPattern(MacAddress, MacAddress)} OR Specific BSSID + * using {@link #setBssid(MacAddress)} </li> + * to trigger connection to a network that matches the set params. + * The system will find the set of networks matching the request and present the user + * with a system dialog which will allow the user to select a specific Wi-Fi network to connect + * to or to deny the request. + *</p> + * + * For example: + * To connect to an open network with a SSID prefix of "test" and a BSSID OUI of "10:03:23": + * {@code + * final NetworkSpecifier specifier = + * new WifiNetworkConfigBuilder() + * .setSsidPattern(new PatternMatcher("test", PatterMatcher.PATTERN_PREFIX)) + * .setBssidPattern(MacAddress.fromString("10:03:23:00:00:00"), + * MacAddress.fromString("ff:ff:ff:00:00:00")) + * .buildNetworkSpecifier() + * final NetworkRequest request = + * new NetworkRequest.Builder() + * .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) + * .setNetworkSpecifier(specifier) + * .build(); + * final ConnectivityManager connectivityManager = + * context.getSystemService(Context.CONNECTIVITY_SERVICE); + * final NetworkCallback networkCallback = new NetworkCallback() { + * ... + * {@literal @}Override + * void onAvailable(...) {} + * // etc. + * }; + * connectivityManager.requestNetwork(request, networkCallback); + * } + * + * @return Instance of {@link NetworkSpecifier}. + * @throws IllegalStateException on invalid params set. + */ + public NetworkSpecifier buildNetworkSpecifier() { + if (!hasSetAnyPattern()) { + throw new IllegalStateException("one of setSsidPattern/setSsid/setBssidPattern/setBssid" + + " should be invoked for specifier"); + } + setMatchAnyPatternIfUnset(); + if (hasSetMatchNonePattern()) { + throw new IllegalStateException("cannot set match-none pattern for specifier"); + } + if (hasSetMatchAllPattern()) { + throw new IllegalStateException("cannot set match-all pattern for specifier"); + } + if (mIsHiddenSSID && mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL) { + throw new IllegalStateException("setSsid should also be invoked when " + + "setIsHiddenSsid is invoked for network specifier"); + } + if (mIsAppInteractionRequired || mIsUserInteractionRequired + || mPriority != -1 || mIsMetered) { + throw new IllegalStateException("none of setIsAppInteractionRequired/" + + "setIsUserInteractionRequired/setPriority/setIsMetered are allowed for " + + "specifier"); + } + if (!TextUtils.isEmpty(mPskPassphrase) && mEnterpriseConfig != null) { + throw new IllegalStateException("only one of setPreSharedKey or setEnterpriseConfig can" + + " be invoked for network specifier"); + } + + return new WifiNetworkSpecifier( + mSsidPatternMatcher, + mBssidPatternMatcher, + buildWifiConfiguration(), + Process.myUid()); + } + + /** + * Create a network suggestion object use in + * {@link WifiManager#addNetworkSuggestions(List, PendingIntent)}. + * See {@link WifiNetworkSuggestion}. + * + * @return Instance of {@link WifiNetworkSuggestion}. + * @throws IllegalStateException on invalid params set. + */ + public WifiNetworkSuggestion buildNetworkSuggestion() { + if (mSsidPatternMatcher == null) { + throw new IllegalStateException("setSsid should be invoked for suggestion"); + } + if (mSsidPatternMatcher.getType() != PatternMatcher.PATTERN_LITERAL + || mBssidPatternMatcher != null) { + throw new IllegalStateException("none of setSsidPattern/setBssidPattern/setBssid are" + + " allowed for suggestion"); + } + if (!TextUtils.isEmpty(mPskPassphrase) && mEnterpriseConfig != null) { + throw new IllegalStateException("only one of setPreSharedKey or setEnterpriseConfig can" + + "be invoked for suggestion"); + } + + return new WifiNetworkSuggestion( + buildWifiConfiguration(), + mIsAppInteractionRequired, + mIsUserInteractionRequired, + Process.myUid()); + + } +} diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java new file mode 100644 index 000000000000..4348399b404b --- /dev/null +++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.annotation.NonNull; +import android.net.MacAddress; +import android.net.MatchAllNetworkSpecifier; +import android.net.NetworkSpecifier; +import android.os.Parcel; +import android.os.Parcelable; +import android.os.PatternMatcher; +import android.util.Pair; + +import java.util.Objects; + +/** + * Network specifier object used to request a Wi-Fi network. Apps should use the + * {@link WifiNetworkConfigBuilder} class to create an instance. + * @hide + */ +public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parcelable { + /** + * SSID pattern match specified by the app. + */ + public final PatternMatcher ssidPatternMatcher; + + /** + * BSSID pattern match specified by the app. + * Pair of <BaseAddress, Mask>. + */ + public final Pair<MacAddress, MacAddress> bssidPatternMatcher; + + /** + * Security credentials for the network. + * <p> + * Note: {@link WifiConfiguration#SSID} & {@link WifiConfiguration#BSSID} fields from + * WifiConfiguration are not used. Instead we use the {@link #ssidPatternMatcher} & + * {@link #bssidPatternMatcher} fields embedded directly + * within {@link WifiNetworkSpecifier}. + */ + public final WifiConfiguration wifiConfiguration; + + /** + * The UID of the process initializing this network specifier. Validated by receiver using + * checkUidIfNecessary() and is used by satisfiedBy() to determine whether the specifier + * matches the offered network. + */ + public final int requestorUid; + + public WifiNetworkSpecifier(@NonNull PatternMatcher ssidPatternMatcher, + @NonNull Pair<MacAddress, MacAddress> bssidPatternMatcher, + @NonNull WifiConfiguration wifiConfiguration, + int requestorUid) { + checkNotNull(ssidPatternMatcher); + checkNotNull(bssidPatternMatcher); + checkNotNull(wifiConfiguration); + + this.ssidPatternMatcher = ssidPatternMatcher; + this.bssidPatternMatcher = bssidPatternMatcher; + this.wifiConfiguration = wifiConfiguration; + this.requestorUid = requestorUid; + } + + public static final Creator<WifiNetworkSpecifier> CREATOR = + new Creator<WifiNetworkSpecifier>() { + @Override + public WifiNetworkSpecifier createFromParcel(Parcel in) { + PatternMatcher ssidPatternMatcher = in.readParcelable(/* classLoader */null); + MacAddress baseAddress = in.readParcelable(null); + MacAddress mask = in.readParcelable(null); + Pair<MacAddress, MacAddress> bssidPatternMatcher = + Pair.create(baseAddress, mask); + WifiConfiguration wifiConfiguration = in.readParcelable(null); + int requestorUid = in.readInt(); + return new WifiNetworkSpecifier(ssidPatternMatcher, bssidPatternMatcher, + wifiConfiguration, requestorUid); + } + + @Override + public WifiNetworkSpecifier[] newArray(int size) { + return new WifiNetworkSpecifier[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(ssidPatternMatcher, flags); + dest.writeParcelable(bssidPatternMatcher.first, flags); + dest.writeParcelable(bssidPatternMatcher.second, flags); + dest.writeParcelable(wifiConfiguration, flags); + dest.writeInt(requestorUid); + } + + @Override + public boolean satisfiedBy(NetworkSpecifier other) { + if (this == other) { + return true; + } + // Any generic requests should be satisifed by a specific wifi network. + if (other == null || other instanceof MatchAllNetworkSpecifier) { + return true; + } + if (other instanceof WifiNetworkAgentSpecifier) { + return ((WifiNetworkAgentSpecifier) other).satisfiesNetworkSpecifier(this); + } + // Specific requests are checked for equality although testing for equality of 2 patterns do + // not make much sense! + return equals(other); + } + + @Override + public int hashCode() { + return Objects.hash( + ssidPatternMatcher.getPath(), + ssidPatternMatcher.getType(), + bssidPatternMatcher, + wifiConfiguration.allowedKeyManagement, + requestorUid); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof WifiNetworkSpecifier)) { + return false; + } + WifiNetworkSpecifier lhs = (WifiNetworkSpecifier) obj; + return Objects.equals(this.ssidPatternMatcher.getPath(), + lhs.ssidPatternMatcher.getPath()) + && Objects.equals(this.ssidPatternMatcher.getType(), + lhs.ssidPatternMatcher.getType()) + && Objects.equals(this.bssidPatternMatcher, + lhs.bssidPatternMatcher) + && Objects.equals(this.wifiConfiguration.allowedKeyManagement, + lhs.wifiConfiguration.allowedKeyManagement) + && requestorUid == lhs.requestorUid; + } + + @Override + public String toString() { + return new StringBuilder() + .append("WifiNetworkSpecifierWifiNetworkSpecifier [") + .append(", SSID Match pattern=").append(ssidPatternMatcher) + .append(", BSSID Match pattern=").append(bssidPatternMatcher) + .append(", WifiConfiguration=").append( + wifiConfiguration == null ? null : wifiConfiguration.configKey()) + .append(", requestorUid=").append(requestorUid) + .append("]") + .toString(); + } + + @Override + public void assertValidFromUid(int requestorUid) { + if (this.requestorUid != requestorUid) { + throw new SecurityException("mismatched UIDs"); + } + } +} diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java new file mode 100644 index 000000000000..04b9cb5dfb8d --- /dev/null +++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static com.android.internal.util.Preconditions.checkNotNull; + +import android.app.PendingIntent; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.List; +import java.util.Objects; + +/** + * The Network Suggestion object is used to provide a Wi-Fi network for consideration when + * auto-connecting to networks. Apps cannot directly create this object, they must use + * {@link WifiNetworkConfigBuilder#buildNetworkSuggestion()} to obtain an instance + * of this object. + *<p> + * Apps can provide a list of such networks to the platform using + * {@link WifiManager#addNetworkSuggestions(List, PendingIntent)}. + */ +public final class WifiNetworkSuggestion implements Parcelable { + /** + * Network configuration for the provided network. + * @hide + */ + public final WifiConfiguration wifiConfiguration; + + /** + * Whether app needs to log in to captive portal to obtain Internet access. + * This will dictate if the associated pending intent in + * {@link WifiManager#addNetworkSuggestions(List, PendingIntent)} needs to be sent after + * successfully connecting to the network. + * @hide + */ + public final boolean isAppInteractionRequired; + + /** + * Whether user needs to log in to captive portal to obtain Internet access. + * @hide + */ + public final boolean isUserInteractionRequired; + + /** + * The UID of the process initializing this network suggestion. + * @hide + */ + public final int suggestorUid; + + /** @hide */ + public WifiNetworkSuggestion(WifiConfiguration wifiConfiguration, + boolean isAppInteractionRequired, + boolean isUserInteractionRequired, + int suggestorUid) { + checkNotNull(wifiConfiguration); + + this.wifiConfiguration = wifiConfiguration; + this.isAppInteractionRequired = isAppInteractionRequired; + this.isUserInteractionRequired = isUserInteractionRequired; + this.suggestorUid = suggestorUid; + } + + public static final Creator<WifiNetworkSuggestion> CREATOR = + new Creator<WifiNetworkSuggestion>() { + @Override + public WifiNetworkSuggestion createFromParcel(Parcel in) { + return new WifiNetworkSuggestion( + in.readParcelable(null), // wifiConfiguration + in.readBoolean(), // isAppInteractionRequired + in.readBoolean(), // isUserInteractionRequired + in.readInt() // suggestorUid + ); + } + + @Override + public WifiNetworkSuggestion[] newArray(int size) { + return new WifiNetworkSuggestion[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeParcelable(wifiConfiguration, flags); + dest.writeBoolean(isAppInteractionRequired); + dest.writeBoolean(isUserInteractionRequired); + dest.writeInt(suggestorUid); + } + + @Override + public int hashCode() { + return Objects.hash(wifiConfiguration.SSID, wifiConfiguration.allowedKeyManagement, + suggestorUid); + } + + /** + * Equals for network suggestions. + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof WifiNetworkSuggestion)) { + return false; + } + WifiNetworkSuggestion lhs = (WifiNetworkSuggestion) obj; + return Objects.equals(this.wifiConfiguration.SSID, lhs.wifiConfiguration.SSID) + && Objects.equals(this.wifiConfiguration.allowedKeyManagement, + lhs.wifiConfiguration.allowedKeyManagement) + && suggestorUid == lhs.suggestorUid; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("WifiNetworkSuggestion [") + .append(", WifiConfiguration=").append(wifiConfiguration) + .append(", isAppInteractionRequired=").append(isAppInteractionRequired) + .append(", isUserInteractionRequired=").append(isUserInteractionRequired) + .append(", suggestorUid=").append(suggestorUid) + .append("]"); + return sb.toString(); + } +} diff --git a/wifi/java/android/net/wifi/WifiScanner.java b/wifi/java/android/net/wifi/WifiScanner.java index 928a1da8b51c..529548f1d2b8 100644 --- a/wifi/java/android/net/wifi/WifiScanner.java +++ b/wifi/java/android/net/wifi/WifiScanner.java @@ -16,6 +16,7 @@ package android.net.wifi; +import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.annotation.SystemApi; @@ -593,17 +594,17 @@ public class WifiScanner { /** SSID of the network */ public String ssid; /** Bitmask of the FLAG_XXX */ - public byte flags; + public byte flags = 0; /** Bitmask of the ATUH_XXX */ - public byte authBitField; + public byte authBitField = 0; + /** frequencies on which the particular network needs to be scanned for */ + public int[] frequencies = {}; /** * default constructor for PnoNetwork */ public PnoNetwork(String ssid) { this.ssid = ssid; - flags = 0; - authBitField = 0; } } @@ -650,6 +651,7 @@ public class WifiScanner { dest.writeString(networkList[i].ssid); dest.writeByte(networkList[i].flags); dest.writeByte(networkList[i].authBitField); + dest.writeIntArray(networkList[i].frequencies); } } else { dest.writeInt(0); @@ -676,6 +678,7 @@ public class WifiScanner { PnoNetwork network = new PnoNetwork(ssid); network.flags = in.readByte(); network.authBitField = in.readByte(); + network.frequencies = in.createIntArray(); settings.networkList[i] = network; } return settings; @@ -721,6 +724,17 @@ public class WifiScanner { } /** + * Enable/Disable wifi scanning. + * + * {@hide} + */ + @RequiresPermission(Manifest.permission.NETWORK_STACK) + public void setScanningEnabled(boolean enable) { + validateChannel(); + mAsyncChannel.sendMessage(enable ? CMD_ENABLE : CMD_DISABLE); + } + + /** * Register a listener that will receive results from all single scans * Either the onSuccess/onFailure will be called once when the listener is registered. After * (assuming onSuccess was called) all subsequent single scan results will be delivered to the @@ -916,6 +930,7 @@ public class WifiScanner { * scans should also not share this object. * {@hide} */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void startDisconnectedPnoScan(ScanSettings scanSettings, PnoSettings pnoSettings, PnoScanListener listener) { Preconditions.checkNotNull(listener, "listener cannot be null"); @@ -930,9 +945,9 @@ public class WifiScanner { * Stop an ongoing wifi PNO scan * @param listener specifies which scan to cancel; must be same object as passed in {@link * #startPnoScan} - * TODO(rpius): Check if we can remove pnoSettings param in stop. * {@hide} */ + @RequiresPermission(android.Manifest.permission.NETWORK_STACK) public void stopPnoScan(ScanListener listener) { Preconditions.checkNotNull(listener, "listener cannot be null"); int key = removeListener(listener); @@ -1164,6 +1179,10 @@ public class WifiScanner { public static final int CMD_DEREGISTER_SCAN_LISTENER = BASE + 28; /** @hide */ public static final int CMD_GET_SINGLE_SCAN_RESULTS = BASE + 29; + /** @hide */ + public static final int CMD_ENABLE = BASE + 30; + /** @hide */ + public static final int CMD_DISABLE = BASE + 31; private Context mContext; private IWifiScanner mService; diff --git a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java b/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java deleted file mode 100644 index f5cad139bd23..000000000000 --- a/wifi/java/android/net/wifi/WifiWakeReasonAndCounts.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * 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.net.wifi; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * A class representing wifi wake reason accounting. - */ - -/** @hide */ -public class WifiWakeReasonAndCounts implements Parcelable { - private static final String TAG = "WifiWakeReasonAndCounts"; - /** - * Wlan can wake host, only when it is cmd/event, local driver-fw - * functions(non-data, non cmd/event) and rx data.The first packet - * from wlan that woke up a sleep host is what is accounted here. - * Total wlan wake to application processor would be: - * [cmdEventWake + driverFwLocalWake + totalRxDataWake] - * A further classification is provided for identifying the reasons - * for wakeup. - */ - public int totalCmdEventWake; - public int totalDriverFwLocalWake; - public int totalRxDataWake; - - public int rxUnicast; - public int rxMulticast; - public int rxBroadcast; - - public int icmp; - public int icmp6; - public int icmp6Ra; - public int icmp6Na; - public int icmp6Ns; - - public int ipv4RxMulticast; - public int ipv6Multicast; - public int otherRxMulticast; - public int[] cmdEventWakeCntArray; - public int[] driverFWLocalWakeCntArray; - - /* {@hide} */ - public WifiWakeReasonAndCounts () { - } - - @Override - /* {@hide} */ - public String toString() { - StringBuffer sb = new StringBuffer(); - sb.append(" totalCmdEventWake ").append(totalCmdEventWake); - sb.append(" totalDriverFwLocalWake ").append(totalDriverFwLocalWake); - sb.append(" totalRxDataWake ").append(totalRxDataWake); - - sb.append(" rxUnicast ").append(rxUnicast); - sb.append(" rxMulticast ").append(rxMulticast); - sb.append(" rxBroadcast ").append(rxBroadcast); - - sb.append(" icmp ").append(icmp); - sb.append(" icmp6 ").append(icmp6); - sb.append(" icmp6Ra ").append(icmp6Ra); - sb.append(" icmp6Na ").append(icmp6Na); - sb.append(" icmp6Ns ").append(icmp6Ns); - - sb.append(" ipv4RxMulticast ").append(ipv4RxMulticast); - sb.append(" ipv6Multicast ").append(ipv6Multicast); - sb.append(" otherRxMulticast ").append(otherRxMulticast); - for (int i = 0; i < cmdEventWakeCntArray.length; i++) { - sb.append(" cmdEventWakeCntArray[" + i + "] " + cmdEventWakeCntArray[i]); - } - for (int i = 0; i < driverFWLocalWakeCntArray.length; i++) { - sb.append(" driverFWLocalWakeCntArray[" + i + "] " + driverFWLocalWakeCntArray[i]); - } - - return sb.toString(); - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public int describeContents() { - return 0; - } - - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(totalCmdEventWake); - dest.writeInt(totalDriverFwLocalWake); - dest.writeInt(totalRxDataWake); - - dest.writeInt(rxUnicast); - dest.writeInt(rxMulticast); - dest.writeInt(rxBroadcast); - - dest.writeInt(icmp); - dest.writeInt(icmp6); - dest.writeInt(icmp6Ra); - dest.writeInt(icmp6Na); - dest.writeInt(icmp6Ns); - - dest.writeInt(ipv4RxMulticast); - dest.writeInt(ipv6Multicast); - dest.writeInt(otherRxMulticast); - dest.writeIntArray(cmdEventWakeCntArray); - dest.writeIntArray(driverFWLocalWakeCntArray); - } - - /* Implement the Parcelable interface - * {@hide} - */ - public static final Creator<WifiWakeReasonAndCounts> CREATOR = - new Creator<WifiWakeReasonAndCounts>() { - public WifiWakeReasonAndCounts createFromParcel(Parcel in) { - WifiWakeReasonAndCounts counts = new WifiWakeReasonAndCounts(); - counts.totalCmdEventWake = in.readInt(); - counts.totalDriverFwLocalWake = in.readInt(); - counts.totalRxDataWake = in.readInt(); - - counts.rxUnicast = in.readInt(); - counts.rxMulticast = in.readInt(); - counts.rxBroadcast = in.readInt(); - - counts.icmp = in.readInt(); - counts.icmp6 = in.readInt(); - counts.icmp6Ra = in.readInt(); - counts.icmp6Na = in.readInt(); - counts.icmp6Ns = in.readInt(); - - counts.ipv4RxMulticast = in.readInt(); - counts.ipv6Multicast = in.readInt(); - counts.otherRxMulticast = in.readInt(); - in.readIntArray(counts.cmdEventWakeCntArray); - in.readIntArray(counts.driverFWLocalWakeCntArray); - return counts; - } - /* Implement the Parcelable interface - * {@hide} - */ - @Override - public WifiWakeReasonAndCounts[] newArray(int size) { - return new WifiWakeReasonAndCounts[size]; - } - }; -} diff --git a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java index 7c99c497c54b..14263830660f 100644 --- a/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java +++ b/wifi/java/android/net/wifi/aware/WifiAwareAgentNetworkSpecifier.java @@ -48,7 +48,7 @@ public class WifiAwareAgentNetworkSpecifier extends NetworkSpecifier implements private MessageDigest mDigester; public WifiAwareAgentNetworkSpecifier() { - // do nothing, already initialized to empty + initialize(); } public WifiAwareAgentNetworkSpecifier(WifiAwareNetworkSpecifier ns) { diff --git a/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl index c2cb16ab847c..a6bdd5b6bfff 100644 --- a/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl +++ b/wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl @@ -32,5 +32,10 @@ oneway interface IProvisioningCallback * Service to manager callback providing Provisioning status */ void onProvisioningStatus(int status); + + /** + * Service to manager callback providing completion of Provisioning/Remediation flow + */ + void onProvisioningComplete(); } diff --git a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java index 2ea6e797ec93..5c9db539c8f5 100644 --- a/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java +++ b/wifi/java/android/net/wifi/hotspot2/ProvisioningCallback.java @@ -16,11 +16,12 @@ package android.net.wifi.hotspot2; +import android.net.wifi.WifiManager; import android.os.Handler; /** * Base class for provisioning callbacks. Should be extended by applications and set when calling - * {@link WifiManager#startSubscriptionProvisiong(OsuProvider, ProvisioningCallback, Handler)}. + * {@link WifiManager#startSubscriptionProvisioning(OsuProvider, ProvisioningCallback, Handler)}. * * @hide */ @@ -28,86 +29,199 @@ public abstract class ProvisioningCallback { /** * The reason code for Provisioning Failure due to connection failure to OSU AP. - * @hide */ - public static final int OSU_FAILURE_AP_CONNECTION = 1; + public static final int OSU_FAILURE_AP_CONNECTION = 1; /** - * The reason code for Provisioning Failure due to connection failure to OSU AP. - * @hide + * The reason code for invalid server URL address. */ public static final int OSU_FAILURE_SERVER_URL_INVALID = 2; /** - * The reason code for Provisioning Failure due to connection failure to OSU AP. - * @hide + * The reason code for provisioning failure due to connection failure to the server. */ - public static final int OSU_FAILURE_SERVER_CONNECTION = 3; + public static final int OSU_FAILURE_SERVER_CONNECTION = 3; /** - * The reason code for Provisioning Failure due to connection failure to OSU AP. - * @hide + * The reason code for provisioning failure due to invalid server certificate. */ - public static final int OSU_FAILURE_SERVER_VALIDATION = 4; + public static final int OSU_FAILURE_SERVER_VALIDATION = 4; /** - * The reason code for Provisioning Failure due to connection failure to OSU AP. - * @hide + * The reason code for provisioning failure due to invalid service provider. */ - public static final int OSU_FAILURE_PROVIDER_VERIFICATION = 5; + public static final int OSU_FAILURE_SERVICE_PROVIDER_VERIFICATION = 5; /** - * The reason code for Provisioning Failure when a provisioning flow is aborted. - * @hide + * The reason code for provisioning failure when a provisioning flow is aborted. */ public static final int OSU_FAILURE_PROVISIONING_ABORTED = 6; /** - * The reason code for Provisioning Failure when a provisioning flow is aborted. - * @hide + * The reason code for provisioning failure when a provisioning flow is not possible. */ public static final int OSU_FAILURE_PROVISIONING_NOT_AVAILABLE = 7; /** - * The status code for Provisioning flow to indicate connecting to OSU AP - * @hide + * The reason code for provisioning failure due to invalid server url. + */ + public static final int OSU_FAILURE_INVALID_SERVER_URL = 8; + + /** + * The reason code for provisioning failure when a command received is not the expected command + * type. + */ + public static final int OSU_FAILURE_UNEXPECTED_COMMAND_TYPE = 9; + + /** + * The reason code for provisioning failure when a SOAP message is not the expected message + * type. + */ + public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_TYPE = 10; + + /** + * The reason code for provisioning failure when a SOAP message exchange fails. + */ + public static final int OSU_FAILURE_SOAP_MESSAGE_EXCHANGE = 11; + + /** + * The reason code for provisioning failure when a redirect listener fails to start. + */ + public static final int OSU_FAILURE_START_REDIRECT_LISTENER = 12; + + /** + * The reason code for provisioning failure when a redirect listener timed out to receive a HTTP + * redirect response. + */ + public static final int OSU_FAILURE_TIMED_OUT_REDIRECT_LISTENER = 13; + + /** + * The reason code for provisioning failure when there is no OSU activity to listen to + * {@link WifiManager#ACTION_PASSPOINT_LAUNCH_OSU_VIEW} intent. + */ + public static final int OSU_FAILURE_NO_OSU_ACTIVITY_FOUND = 14; + + /** + * The reason code for provisioning failure when the status of a SOAP message is not the + * expected message status. + */ + public static final int OSU_FAILURE_UNEXPECTED_SOAP_MESSAGE_STATUS = 15; + + /** + * The reason code for provisioning failure when there is no PPS MO. + * MO. + */ + public static final int OSU_FAILURE_NO_PPS_MO = 16; + + /** + * The reason code for provisioning failure when there is no AAAServerTrustRoot node in a PPS + * MO. + */ + public static final int OSU_FAILURE_NO_AAA_SERVER_TRUST_ROOT_NODE = 17; + + /** + * The reason code for provisioning failure when there is no TrustRoot node for remediation + * server in a PPS MO. + */ + public static final int OSU_FAILURE_NO_REMEDIATION_SERVER_TRUST_ROOT_NODE = 18; + + /** + * The reason code for provisioning failure when there is no TrustRoot node for policy server in + * a PPS MO. + */ + public static final int OSU_FAILURE_NO_POLICY_SERVER_TRUST_ROOT_NODE = 19; + + /** + * The reason code for provisioning failure when failing to retrieve trust root certificates + * used for validating server certificate for AAA, Remediation and Policy server. + */ + public static final int OSU_FAILURE_RETRIEVE_TRUST_ROOT_CERTIFICATES = 20; + + /** + * The reason code for provisioning failure when there is no trust root certificate for AAA + * server. + */ + public static final int OSU_FAILURE_NO_AAA_TRUST_ROOT_CERTIFICATE = 21; + + /** + * The reason code for provisioning failure when a {@link PasspointConfiguration} is failed to + * install. + */ + public static final int OSU_FAILURE_ADD_PASSPOINT_CONFIGURATION = 22; + + /** + * The status code for provisioning flow to indicate connecting to OSU AP */ - public static final int OSU_STATUS_AP_CONNECTING = 1; + public static final int OSU_STATUS_AP_CONNECTING = 1; /** - * The status code for Provisioning flow to indicate connected to OSU AP - * @hide + * The status code for provisioning flow to indicate the OSU AP is connected. */ - public static final int OSU_STATUS_AP_CONNECTED = 2; + public static final int OSU_STATUS_AP_CONNECTED = 2; /** - * The status code for Provisioning flow to indicate connecting to OSU AP - * @hide + * The status code for provisioning flow to indicate connecting to the server. */ - public static final int OSU_STATUS_SERVER_CONNECTED = 3; + public static final int OSU_STATUS_SERVER_CONNECTING = 3; /** - * The status code for Provisioning flow to indicate connecting to OSU AP - * @hide + * The status code for provisioning flow to indicate the server certificate is validated. */ - public static final int OSU_STATUS_SERVER_VALIDATED = 4; + public static final int OSU_STATUS_SERVER_VALIDATED = 4; /** - * The status code for Provisioning flow to indicate connecting to OSU AP - * @hide + * The status code for provisioning flow to indicate the server is connected */ - public static final int OSU_STATUS_PROVIDER_VERIFIED = 5; + public static final int OSU_STATUS_SERVER_CONNECTED = 5; + + /** + * The status code for provisioning flow to indicate starting the first SOAP exchange. + */ + public static final int OSU_STATUS_INIT_SOAP_EXCHANGE = 6; + + /** + * The status code for provisioning flow to indicate waiting for a HTTP redirect response. + */ + public static final int OSU_STATUS_WAITING_FOR_REDIRECT_RESPONSE = 7; + + /** + * The status code for provisioning flow to indicate a HTTP redirect response is received. + */ + public static final int OSU_STATUS_REDIRECT_RESPONSE_RECEIVED = 8; + + /** + * The status code for provisioning flow to indicate starting the second SOAP exchange. + */ + public static final int OSU_STATUS_SECOND_SOAP_EXCHANGE = 9; + + /** + * The status code for provisioning flow to indicate starting the third SOAP exchange. + */ + public static final int OSU_STATUS_THIRD_SOAP_EXCHANGE = 10; + + /** + * The status code for provisioning flow to indicate starting a step retrieving trust root + * certs. + */ + public static final int OSU_STATUS_RETRIEVING_TRUST_ROOT_CERTS = 11; /** * Provisioning status for OSU failure + * * @param status indicates error condition */ public abstract void onProvisioningFailure(int status); /** * Provisioning status when OSU is in progress + * * @param status indicates status of OSU flow */ public abstract void onProvisioningStatus(int status); + + /** + * Provisioning complete when provisioning/remediation flow completes + */ + public abstract void onProvisioningComplete(); } diff --git a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java index f6183fa219a1..984cf7d62aa5 100644 --- a/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java +++ b/wifi/java/android/net/wifi/hotspot2/omadm/PpsMoParser.java @@ -136,7 +136,7 @@ public final class PpsMoParser { private static final String NODE_UPDATE_IDENTIFIER = "UpdateIdentifier"; private static final String NODE_AAA_SERVER_TRUST_ROOT = "AAAServerTrustRoot"; private static final String NODE_SUBSCRIPTION_UPDATE = "SubscriptionUpdate"; - private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameter"; + private static final String NODE_SUBSCRIPTION_PARAMETER = "SubscriptionParameters"; private static final String NODE_TYPE_OF_SUBSCRIPTION = "TypeOfSubscription"; private static final String NODE_USAGE_LIMITS = "UsageLimits"; private static final String NODE_DATA_LIMIT = "DataLimit"; diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java index 36a50d615a04..22dc2ed32083 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java @@ -21,6 +21,8 @@ import android.os.Parcelable; import android.os.Parcel; import android.util.Log; +import java.util.Objects; + import java.util.regex.Pattern; import java.util.regex.Matcher; @@ -322,6 +324,11 @@ public class WifiP2pDevice implements Parcelable { } @Override + public int hashCode() { + return Objects.hashCode(deviceAddress); + } + + @Override public String toString() { StringBuffer sbuf = new StringBuffer(); sbuf.append("Device: ").append(deviceName); diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index 5a4c898c0bcd..e6892bea4595 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -16,9 +16,13 @@ package android.net.wifi.p2p; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.annotation.SdkConstant; -import android.annotation.SystemService; import android.annotation.SdkConstant.SdkConstantType; +import android.annotation.SystemApi; +import android.annotation.SystemService; import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.net.wifi.WpsInfo; @@ -480,6 +484,12 @@ public class WifiP2pManager { /** @hide */ public static final int REPORT_NFC_HANDOVER_FAILED = BASE + 81; + /** @hide */ + public static final int FACTORY_RESET = BASE + 82; + /** @hide */ + public static final int FACTORY_RESET_FAILED = BASE + 83; + /** @hide */ + public static final int FACTORY_RESET_SUCCEEDED = BASE + 84; /** * Create a new WifiP2pManager instance. Applications use @@ -776,6 +786,7 @@ public class WifiP2pManager { case STOP_LISTEN_FAILED: case SET_CHANNEL_FAILED: case REPORT_NFC_HANDOVER_FAILED: + case FACTORY_RESET_FAILED: if (listener != null) { ((ActionListener) listener).onFailure(message.arg1); } @@ -802,6 +813,7 @@ public class WifiP2pManager { case STOP_LISTEN_SUCCEEDED: case SET_CHANNEL_SUCCEEDED: case REPORT_NFC_HANDOVER_SUCCEEDED: + case FACTORY_RESET_SUCCEEDED: if (listener != null) { ((ActionListener) listener).onSuccess(); } @@ -1521,4 +1533,21 @@ public class WifiP2pManager { c.mAsyncChannel.sendMessage(RESPONDER_REPORT_NFC_HANDOVER, 0, c.putListener(listener), bundle); } + + /** + * Removes all saved p2p groups. + * @param c is the channel created at {@link #initialize}. + * @param listener for callback on success or failure. Can be null. + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) + public void factoryReset(@NonNull Channel c, @Nullable ActionListener listener) { + checkChannel(c); + Bundle callingPackage = new Bundle(); + callingPackage.putString(CALLING_PACKAGE, c.mContext.getOpPackageName()); + c.mAsyncChannel.sendMessage(FACTORY_RESET, 0, c.putListener(listener), + callingPackage); + } + } diff --git a/wifi/java/com/android/server/wifi/AbstractWifiService.java b/wifi/java/com/android/server/wifi/AbstractWifiService.java new file mode 100644 index 000000000000..eede23b22387 --- /dev/null +++ b/wifi/java/com/android/server/wifi/AbstractWifiService.java @@ -0,0 +1,415 @@ +/** + * Copyright (c) 2018, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License") { + * throw new UnsupportedOperationException(); + } + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wifi; + +import android.content.pm.ParceledListSlice; +import android.net.DhcpInfo; +import android.net.Network; +import android.net.wifi.INetworkRequestMatchCallback; +import android.net.wifi.ISoftApCallback; +import android.net.wifi.ITrafficStateCallback; +import android.net.wifi.IWifiManager; +import android.net.wifi.PasspointManagementObjectDefinition; +import android.net.wifi.ScanResult; +import android.net.wifi.WifiActivityEnergyInfo; +import android.net.wifi.WifiConfiguration; +import android.net.wifi.WifiInfo; +import android.net.wifi.hotspot2.IProvisioningCallback; +import android.net.wifi.hotspot2.OsuProvider; +import android.net.wifi.hotspot2.PasspointConfiguration; +import android.os.IBinder; +import android.os.Messenger; +import android.os.ResultReceiver; +import android.os.WorkSource; +import android.util.Slog; + +import java.util.List; + +/** + * Abstract class implementing IWifiManager with stub methods throwing runtime exceptions. + * + * This class is meant to be extended by real implementations of IWifiManager in order to facilitate + * cross-repo changes to WiFi internal APIs, including the introduction of new APIs, the removal of + * deprecated APIs, or the migration of existing API signatures. + * + * When an existing API is scheduled for removal, it can be removed from IWifiManager.aidl + * immediately and marked as @Deprecated first in this class. Children inheriting this class are + * then given a short grace period to update themselves before the @Deprecated stub is removed for + * good. If the API scheduled for removal has a replacement or an overload (signature change), + * these should be introduced before the stub is removed to allow children to migrate. + */ +public abstract class AbstractWifiService extends IWifiManager.Stub { + + private static final String TAG = AbstractWifiService.class.getSimpleName(); + + @Override + public int getSupportedFeatures() { + throw new UnsupportedOperationException(); + } + + @Override + public WifiActivityEnergyInfo reportActivityInfo() { + throw new UnsupportedOperationException(); + } + + @Override + public void requestActivityInfo(ResultReceiver result) { + throw new UnsupportedOperationException(); + } + + @Override + public ParceledListSlice getConfiguredNetworks() { + throw new UnsupportedOperationException(); + } + + @Override + public ParceledListSlice getPrivilegedConfiguredNetworks() { + throw new UnsupportedOperationException(); + } + + @Override + public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) { + throw new UnsupportedOperationException(); + } + + @Override + public List<WifiConfiguration> getAllMatchingWifiConfigs(ScanResult scanResult) { + throw new UnsupportedOperationException(); + } + + @Override + public List<OsuProvider> getMatchingOsuProviders(ScanResult scanResult) { + throw new UnsupportedOperationException(); + } + + @Override + public int addOrUpdateNetwork(WifiConfiguration config, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean addOrUpdatePasspointConfiguration( + PasspointConfiguration config, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removePasspointConfiguration(String fqdn, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public List<PasspointConfiguration> getPasspointConfigurations() { + throw new UnsupportedOperationException(); + } + + @Override + public void queryPasspointIcon(long bssid, String fileName) { + throw new UnsupportedOperationException(); + } + + @Override + public int matchProviderWithCurrentNetwork(String fqdn) { + throw new UnsupportedOperationException(); + } + + @Override + public void deauthenticateNetwork(long holdoff, boolean ess) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeNetwork(int netId, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean enableNetwork(int netId, boolean disableOthers, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean disableNetwork(int netId, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean startScan(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public List<ScanResult> getScanResults(String callingPackage) { + throw new UnsupportedOperationException(); + } + + @Override + public void disconnect(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void reconnect(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void reassociate(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public WifiInfo getConnectionInfo(String callingPackage) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setWifiEnabled(String packageName, boolean enable) { + throw new UnsupportedOperationException(); + } + + @Override + public int getWifiEnabledState() { + throw new UnsupportedOperationException(); + } + + @Override + public void setCountryCode(String country) { + throw new UnsupportedOperationException(); + } + + @Override + public String getCountryCode() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isDualBandSupported() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean needs5GHzToAnyApBandConversion() { + throw new UnsupportedOperationException(); + } + + @Override + public DhcpInfo getDhcpInfo() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isScanAlwaysAvailable() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean acquireWifiLock(IBinder lock, int lockType, String tag, WorkSource ws) { + throw new UnsupportedOperationException(); + } + + @Override + public void updateWifiLockWorkSource(IBinder lock, WorkSource ws) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean releaseWifiLock(IBinder lock) { + throw new UnsupportedOperationException(); + } + + @Override + public void initializeMulticastFiltering() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isMulticastEnabled() { + throw new UnsupportedOperationException(); + } + + @Override + public void acquireMulticastLock(IBinder binder, String tag) { + throw new UnsupportedOperationException(); + } + + @Override + public void releaseMulticastLock(String tag) { + throw new UnsupportedOperationException(); + } + + @Override + public void updateInterfaceIpState(String ifaceName, int mode) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean startSoftAp(WifiConfiguration wifiConfig) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean stopSoftAp() { + throw new UnsupportedOperationException(); + } + + @Override + public int startLocalOnlyHotspot(Messenger messenger, IBinder binder, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void stopLocalOnlyHotspot() { + throw new UnsupportedOperationException(); + } + + @Override + public void startWatchLocalOnlyHotspot(Messenger messenger, IBinder binder) { + throw new UnsupportedOperationException(); + } + + @Override + public void stopWatchLocalOnlyHotspot() { + throw new UnsupportedOperationException(); + } + + @Override + public int getWifiApEnabledState() { + throw new UnsupportedOperationException(); + } + + @Override + public WifiConfiguration getWifiApConfiguration() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean setWifiApConfiguration(WifiConfiguration wifiConfig, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void notifyUserOfApBandConversion(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public Messenger getWifiServiceMessenger(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void enableTdls(String remoteIPAddress, boolean enable) { + throw new UnsupportedOperationException(); + } + + @Override + public void enableTdlsWithMacAddress(String remoteMacAddress, boolean enable) { + throw new UnsupportedOperationException(); + } + + @Override + public String getCurrentNetworkWpsNfcConfigurationToken() { + throw new UnsupportedOperationException(); + } + + @Override + public void enableVerboseLogging(int verbose) { + throw new UnsupportedOperationException(); + } + + @Override + public int getVerboseLoggingLevel() { + throw new UnsupportedOperationException(); + } + + @Override + public void enableWifiConnectivityManager(boolean enabled) { + throw new UnsupportedOperationException(); + } + + @Override + public void disableEphemeralNetwork(String SSID, String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public void factoryReset(String packageName) { + throw new UnsupportedOperationException(); + } + + @Override + public Network getCurrentNetwork() { + throw new UnsupportedOperationException(); + } + + @Override + public byte[] retrieveBackupData() { + throw new UnsupportedOperationException(); + } + + @Override + public void restoreBackupData(byte[] data) { + throw new UnsupportedOperationException(); + } + + @Override + public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) { + throw new UnsupportedOperationException(); + } + + @Override + public void startSubscriptionProvisioning( + OsuProvider provider, IProvisioningCallback callback) { + throw new UnsupportedOperationException(); + } + + @Override + public void registerSoftApCallback( + IBinder binder, ISoftApCallback callback, int callbackIdentifier) { + throw new UnsupportedOperationException(); + } + + @Override + public void unregisterSoftApCallback(int callbackIdentifier) { + throw new UnsupportedOperationException(); + } + + @Override + public void registerTrafficStateCallback( + IBinder binder, ITrafficStateCallback callback, int callbackIdentifier) { + throw new UnsupportedOperationException(); + } + + @Override + public void unregisterTrafficStateCallback(int callbackIdentifier) { + throw new UnsupportedOperationException(); + } + + @Override + public void registerNetworkRequestMatchCallback( + IBinder binder, INetworkRequestMatchCallback callback, int callbackIdentifier) { + throw new UnsupportedOperationException(); + } + + @Override + public void unregisterNetworkRequestMatchCallback(int callbackIdentifier) { + throw new UnsupportedOperationException(); + } +} |