2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package android
.net
.wifi
;
19 import android
.annotation
.SdkConstant
;
20 import android
.annotation
.SdkConstant
.SdkConstantType
;
21 import android
.annotation
.SystemApi
;
22 import android
.content
.Context
;
23 import android
.net
.ConnectivityManager
;
24 import android
.net
.ConnectivityManager
.NetworkCallback
;
25 import android
.net
.DhcpInfo
;
26 import android
.net
.Network
;
27 import android
.net
.NetworkCapabilities
;
28 import android
.net
.NetworkRequest
;
29 import android
.net
.wifi
.ScanSettings
;
30 import android
.net
.wifi
.WifiChannel
;
31 import android
.os
.Binder
;
32 import android
.os
.Build
;
33 import android
.os
.IBinder
;
34 import android
.os
.Handler
;
35 import android
.os
.HandlerThread
;
36 import android
.os
.Looper
;
37 import android
.os
.Message
;
38 import android
.os
.RemoteException
;
39 import android
.os
.WorkSource
;
40 import android
.os
.Messenger
;
41 import android
.util
.Log
;
42 import android
.util
.SparseArray
;
44 import java
.net
.InetAddress
;
45 import java
.util
.concurrent
.CountDownLatch
;
47 import com
.android
.internal
.annotations
.GuardedBy
;
48 import com
.android
.internal
.util
.AsyncChannel
;
49 import com
.android
.internal
.util
.Protocol
;
51 import java
.util
.List
;
54 * This class provides the primary API for managing all aspects of Wi-Fi
55 * connectivity. Get an instance of this class by calling
56 * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
58 * It deals with several categories of items:
60 * <li>The list of configured networks. The list can be viewed and updated,
61 * and attributes of individual entries can be modified.</li>
62 * <li>The currently active Wi-Fi network, if any. Connectivity can be
63 * established or torn down, and dynamic information about the state of
64 * the network can be queried.</li>
65 * <li>Results of access point scans, containing enough information to
66 * make decisions about what access point to connect to.</li>
67 * <li>It defines the names of various Intent actions that are broadcast
68 * upon any sort of change in Wi-Fi state.
70 * This is the API to use when performing Wi-Fi specific operations. To
71 * perform operations that pertain to network connectivity at an abstract
72 * level, use {@link android.net.ConnectivityManager}.
74 public class WifiManager
{
76 private static final String TAG
= "WifiManager";
77 // Supplicant error codes:
79 * The error code if there was a problem authenticating.
81 public static final int ERROR_AUTHENTICATING
= 1;
84 * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
87 public static final String WIFI_SCAN_AVAILABLE
= "wifi_scan_available";
90 * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
93 public static final String EXTRA_SCAN_AVAILABLE
= "scan_enabled";
96 * Broadcast intent action indicating that the credential of a Wi-Fi network
97 * has been changed. One extra provides the ssid of the network. Another
98 * extra provides the event type, whether the credential is saved or forgot.
102 public static final String WIFI_CREDENTIAL_CHANGED_ACTION
=
103 "android.net.wifi.WIFI_CREDENTIAL_CHANGED";
106 public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE
= "et";
109 public static final String EXTRA_WIFI_CREDENTIAL_SSID
= "ssid";
112 public static final int WIFI_CREDENTIAL_SAVED
= 0;
115 public static final int WIFI_CREDENTIAL_FORGOT
= 1;
118 * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
119 * enabling, disabling, or unknown. One extra provides this state as an int.
120 * Another extra provides the previous state, if available.
122 * @see #EXTRA_WIFI_STATE
123 * @see #EXTRA_PREVIOUS_WIFI_STATE
125 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
126 public static final String WIFI_STATE_CHANGED_ACTION
=
127 "android.net.wifi.WIFI_STATE_CHANGED";
129 * The lookup key for an int that indicates whether Wi-Fi is enabled,
130 * disabled, enabling, disabling, or unknown. Retrieve it with
131 * {@link android.content.Intent#getIntExtra(String,int)}.
133 * @see #WIFI_STATE_DISABLED
134 * @see #WIFI_STATE_DISABLING
135 * @see #WIFI_STATE_ENABLED
136 * @see #WIFI_STATE_ENABLING
137 * @see #WIFI_STATE_UNKNOWN
139 public static final String EXTRA_WIFI_STATE
= "wifi_state";
141 * The previous Wi-Fi state.
143 * @see #EXTRA_WIFI_STATE
145 public static final String EXTRA_PREVIOUS_WIFI_STATE
= "previous_wifi_state";
148 * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
149 * it finishes successfully.
151 * @see #WIFI_STATE_CHANGED_ACTION
152 * @see #getWifiState()
154 public static final int WIFI_STATE_DISABLING
= 0;
158 * @see #WIFI_STATE_CHANGED_ACTION
159 * @see #getWifiState()
161 public static final int WIFI_STATE_DISABLED
= 1;
163 * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if
164 * it finishes successfully.
166 * @see #WIFI_STATE_CHANGED_ACTION
167 * @see #getWifiState()
169 public static final int WIFI_STATE_ENABLING
= 2;
173 * @see #WIFI_STATE_CHANGED_ACTION
174 * @see #getWifiState()
176 public static final int WIFI_STATE_ENABLED
= 3;
178 * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling
181 * @see #WIFI_STATE_CHANGED_ACTION
182 * @see #getWifiState()
184 public static final int WIFI_STATE_UNKNOWN
= 4;
187 * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
188 * enabling, disabling, or failed.
192 public static final String WIFI_AP_STATE_CHANGED_ACTION
=
193 "android.net.wifi.WIFI_AP_STATE_CHANGED";
196 * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
197 * disabled, enabling, disabling, or failed. Retrieve it with
198 * {@link android.content.Intent#getIntExtra(String,int)}.
200 * @see #WIFI_AP_STATE_DISABLED
201 * @see #WIFI_AP_STATE_DISABLING
202 * @see #WIFI_AP_STATE_ENABLED
203 * @see #WIFI_AP_STATE_ENABLING
204 * @see #WIFI_AP_STATE_FAILED
208 public static final String EXTRA_WIFI_AP_STATE
= "wifi_state";
211 * The look up key for an int that indicates why softAP started failed
212 * currently support general and no_channel
213 * @see #SAP_START_FAILURE_GENERAL
214 * @see #SAP_START_FAILURE_NO_CHANNEL
218 public static final String EXTRA_WIFI_AP_FAILURE_REASON
= "wifi_ap_error_code";
220 * The previous Wi-Fi state.
222 * @see #EXTRA_WIFI_AP_STATE
226 public static final String EXTRA_PREVIOUS_WIFI_AP_STATE
= "previous_wifi_state";
228 * Wi-Fi AP is currently being disabled. The state will change to
229 * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
231 * @see #WIFI_AP_STATE_CHANGED_ACTION
232 * @see #getWifiApState()
236 public static final int WIFI_AP_STATE_DISABLING
= 10;
238 * Wi-Fi AP is disabled.
240 * @see #WIFI_AP_STATE_CHANGED_ACTION
241 * @see #getWifiState()
245 public static final int WIFI_AP_STATE_DISABLED
= 11;
247 * Wi-Fi AP is currently being enabled. The state will change to
248 * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
250 * @see #WIFI_AP_STATE_CHANGED_ACTION
251 * @see #getWifiApState()
255 public static final int WIFI_AP_STATE_ENABLING
= 12;
257 * Wi-Fi AP is enabled.
259 * @see #WIFI_AP_STATE_CHANGED_ACTION
260 * @see #getWifiApState()
264 public static final int WIFI_AP_STATE_ENABLED
= 13;
266 * Wi-Fi AP is in a failed state. This state will occur when an error occurs during
267 * enabling or disabling
269 * @see #WIFI_AP_STATE_CHANGED_ACTION
270 * @see #getWifiApState()
274 public static final int WIFI_AP_STATE_FAILED
= 14;
277 * If WIFI AP start failed, this reason code means there is no legal channel exists on
278 * user selected band by regulatory
282 public static final int SAP_START_FAILURE_GENERAL
= 0;
285 * All other reason for AP start failed besides SAP_START_FAILURE_GENERAL
289 public static final int SAP_START_FAILURE_NO_CHANNEL
= 1;
291 * Broadcast intent action indicating that a connection to the supplicant has
292 * been established (and it is now possible
293 * to perform Wi-Fi operations) or the connection to the supplicant has been
294 * lost. One extra provides the connection state as a boolean, where {@code true}
296 * @see #EXTRA_SUPPLICANT_CONNECTED
298 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
299 public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION
=
300 "android.net.wifi.supplicant.CONNECTION_CHANGE";
302 * The lookup key for a boolean that indicates whether a connection to
303 * the supplicant daemon has been gained or lost. {@code true} means
304 * a connection now exists.
305 * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
307 public static final String EXTRA_SUPPLICANT_CONNECTED
= "connected";
309 * Broadcast intent action indicating that the state of Wi-Fi connectivity
310 * has changed. One extra provides the new state
311 * in the form of a {@link android.net.NetworkInfo} object. If the new
312 * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
314 * as a {@code String}.
315 * @see #EXTRA_NETWORK_INFO
317 * @see #EXTRA_WIFI_INFO
319 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
320 public static final String NETWORK_STATE_CHANGED_ACTION
= "android.net.wifi.STATE_CHANGE";
322 * The lookup key for a {@link android.net.NetworkInfo} object associated with the
323 * Wi-Fi network. Retrieve with
324 * {@link android.content.Intent#getParcelableExtra(String)}.
326 public static final String EXTRA_NETWORK_INFO
= "networkInfo";
328 * The lookup key for a String giving the BSSID of the access point to which
329 * we are connected. Only present when the new state is CONNECTED.
331 * {@link android.content.Intent#getStringExtra(String)}.
333 public static final String EXTRA_BSSID
= "bssid";
335 * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
336 * information about the access point to which we are connected. Only present
337 * when the new state is CONNECTED. Retrieve with
338 * {@link android.content.Intent#getParcelableExtra(String)}.
340 public static final String EXTRA_WIFI_INFO
= "wifiInfo";
342 * Broadcast intent action indicating that the state of establishing a connection to
343 * an access point has changed.One extra provides the new
344 * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
345 * is not generally the most useful thing to look at if you are just interested in
346 * the overall state of connectivity.
347 * @see #EXTRA_NEW_STATE
348 * @see #EXTRA_SUPPLICANT_ERROR
350 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
351 public static final String SUPPLICANT_STATE_CHANGED_ACTION
=
352 "android.net.wifi.supplicant.STATE_CHANGE";
354 * The lookup key for a {@link SupplicantState} describing the new state
356 * {@link android.content.Intent#getParcelableExtra(String)}.
358 public static final String EXTRA_NEW_STATE
= "newState";
361 * The lookup key for a {@link SupplicantState} describing the supplicant
364 * {@link android.content.Intent#getIntExtra(String, int)}.
365 * @see #ERROR_AUTHENTICATING
367 public static final String EXTRA_SUPPLICANT_ERROR
= "supplicantError";
370 * Broadcast intent action indicating that the configured networks changed.
371 * This can be as a result of adding/updating/deleting a network. If
372 * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
373 * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple
374 * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
378 public static final String CONFIGURED_NETWORKS_CHANGED_ACTION
=
379 "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
381 * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing
382 * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
387 public static final String EXTRA_WIFI_CONFIGURATION
= "wifiConfiguration";
389 * Multiple network configurations have changed.
390 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
395 public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED
= "multipleChanges";
397 * The lookup key for an integer indicating the reason a Wi-Fi network configuration
398 * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false}
399 * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
403 public static final String EXTRA_CHANGE_REASON
= "changeReason";
405 * The configuration is new and was added.
409 public static final int CHANGE_REASON_ADDED
= 0;
411 * The configuration was removed and is no longer present in the system's list of
412 * configured networks.
416 public static final int CHANGE_REASON_REMOVED
= 1;
418 * The configuration has changed as a result of explicit action or because the system
419 * took an automated action such as disabling a malfunctioning configuration.
423 public static final int CHANGE_REASON_CONFIG_CHANGE
= 2;
425 * An access point scan has completed, and results are available from the supplicant.
426 * Call {@link #getScanResults()} to obtain the results. {@link #EXTRA_RESULTS_UPDATED}
427 * indicates if the scan was completed successfully.
429 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
430 public static final String SCAN_RESULTS_AVAILABLE_ACTION
= "android.net.wifi.SCAN_RESULTS";
433 * Lookup key for a {@code boolean} representing the result of previous {@link #startScan}
434 * operation, reported with {@link #SCAN_RESULTS_AVAILABLE_ACTION}.
435 * @return true scan was successful, results are updated
436 * @return false scan was not successful, results haven't been updated since previous scan
438 public static final String EXTRA_RESULTS_UPDATED
= "resultsUpdated";
441 * A batch of access point scans has been completed and the results areavailable.
442 * Call {@link #getBatchedScanResults()} to obtain the results.
443 * @hide pending review
445 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
446 public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION
=
447 "android.net.wifi.BATCHED_RESULTS";
449 * The RSSI (signal strength) has changed.
450 * @see #EXTRA_NEW_RSSI
452 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
453 public static final String RSSI_CHANGED_ACTION
= "android.net.wifi.RSSI_CHANGED";
455 * The lookup key for an {@code int} giving the new RSSI in dBm.
457 public static final String EXTRA_NEW_RSSI
= "newRssi";
460 * Broadcast intent action indicating that the link configuration
464 public static final String LINK_CONFIGURATION_CHANGED_ACTION
=
465 "android.net.wifi.LINK_CONFIGURATION_CHANGED";
468 * The lookup key for a {@link android.net.LinkProperties} object associated with the
469 * Wi-Fi network. Retrieve with
470 * {@link android.content.Intent#getParcelableExtra(String)}.
473 public static final String EXTRA_LINK_PROPERTIES
= "linkProperties";
476 * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the
477 * Wi-Fi network. Retrieve with
478 * {@link android.content.Intent#getParcelableExtra(String)}.
481 public static final String EXTRA_NETWORK_CAPABILITIES
= "networkCapabilities";
484 * The network IDs of the configured networks could have changed.
486 @SdkConstant(SdkConstantType
.BROADCAST_INTENT_ACTION
)
487 public static final String NETWORK_IDS_CHANGED_ACTION
= "android.net.wifi.NETWORK_IDS_CHANGED";
490 * Activity Action: Show a system activity that allows the user to enable
491 * scans to be available even with Wi-Fi turned off.
493 * <p>Notification of the result of this activity is posted using the
494 * {@link android.app.Activity#onActivityResult} callback. The
495 * <code>resultCode</code>
496 * will be {@link android.app.Activity#RESULT_OK} if scan always mode has
497 * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
498 * has rejected the request or an error has occurred.
500 @SdkConstant(SdkConstantType
.ACTIVITY_INTENT_ACTION
)
501 public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE
=
502 "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
505 * Activity Action: Pick a Wi-Fi network to connect to.
507 * <p>Output: Nothing.
509 @SdkConstant(SdkConstantType
.ACTIVITY_INTENT_ACTION
)
510 public static final String ACTION_PICK_WIFI_NETWORK
= "android.net.wifi.PICK_WIFI_NETWORK";
513 * In this Wi-Fi lock mode, Wi-Fi will be kept active,
514 * and will behave normally, i.e., it will attempt to automatically
515 * establish a connection to a remembered access point that is
516 * within range, and will do periodic scans if there are remembered
517 * access points but none are in range.
519 public static final int WIFI_MODE_FULL
= 1;
521 * In this Wi-Fi lock mode, Wi-Fi will be kept active,
522 * but the only operation that will be supported is initiation of
523 * scans, and the subsequent reporting of scan results. No attempts
524 * will be made to automatically connect to remembered access points,
525 * nor will periodic scans be automatically performed looking for
526 * remembered access points. Scans must be explicitly requested by
527 * an application in this mode.
529 public static final int WIFI_MODE_SCAN_ONLY
= 2;
531 * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode
532 * {@link #WIFI_MODE_FULL} but it operates at high performance
533 * with minimum packet loss and low packet latency even when
534 * the device screen is off. This mode will consume more power
535 * and hence should be used only when there is a need for such
536 * an active connection.
538 * An example use case is when a voice connection needs to be
539 * kept active even after the device screen goes off. Holding the
540 * regular {@link #WIFI_MODE_FULL} lock will keep the wifi
541 * connection active, but the connection can be lossy.
542 * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the
543 * duration of the voice call will improve the call quality.
545 * When there is no support from the hardware, this lock mode
546 * will have the same behavior as {@link #WIFI_MODE_FULL}
548 public static final int WIFI_MODE_FULL_HIGH_PERF
= 3;
550 /** Anything worse than or equal to this will show 0 bars. */
551 private static final int MIN_RSSI
= -100;
553 /** Anything better than or equal to this will show the max bars. */
554 private static final int MAX_RSSI
= -55;
557 * Number of RSSI levels used in the framework to initiate
558 * {@link #RSSI_CHANGED_ACTION} broadcast
561 public static final int RSSI_LEVELS
= 5;
564 * Auto settings in the driver. The driver could choose to operate on both
565 * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
568 public static final int WIFI_FREQUENCY_BAND_AUTO
= 0;
571 * Operation on 5 GHz alone
574 public static final int WIFI_FREQUENCY_BAND_5GHZ
= 1;
577 * Operation on 2.4 GHz alone
580 public static final int WIFI_FREQUENCY_BAND_2GHZ
= 2;
582 /** List of asyncronous notifications
585 public static final int DATA_ACTIVITY_NOTIFICATION
= 1;
587 //Lowest bit indicates data reception and the second lowest
588 //bit indicates data transmitted
590 public static final int DATA_ACTIVITY_NONE
= 0x00;
592 public static final int DATA_ACTIVITY_IN
= 0x01;
594 public static final int DATA_ACTIVITY_OUT
= 0x02;
596 public static final int DATA_ACTIVITY_INOUT
= 0x03;
599 public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED
= false;
601 /* Maximum number of active locks we allow.
602 * This limit was added to prevent apps from creating a ridiculous number
603 * of locks and crashing the system by overflowing the global ref table.
605 private static final int MAX_ACTIVE_LOCKS
= 50;
607 /* Number of currently active WifiLocks and MulticastLocks */
608 private int mActiveLockCount
;
610 private Context mContext
;
611 IWifiManager mService
;
612 private final int mTargetSdkVersion
;
614 private static final int INVALID_KEY
= 0;
615 private static int sListenerKey
= 1;
616 private static final SparseArray sListenerMap
= new SparseArray();
617 private static final Object sListenerMapLock
= new Object();
619 private static AsyncChannel sAsyncChannel
;
620 private static CountDownLatch sConnected
;
621 private static ConnectivityManager sCM
;
623 private static final Object sThreadRefLock
= new Object();
624 private static int sThreadRefCount
;
625 private static HandlerThread sHandlerThread
;
628 // TODO: Introduce refcounting and make this a per-process static callback, instead of a
629 // per-WifiManager callback.
630 private PinningNetworkCallback mNetworkCallback
;
633 * Create a new WifiManager instance.
634 * Applications will almost always want to use
635 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
636 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
637 * @param context the application context
638 * @param service the Binder interface
639 * @hide - hide this because it takes in a parameter of type IWifiManager, which
640 * is a system private class.
642 public WifiManager(Context context
, IWifiManager service
) {
645 mTargetSdkVersion
= context
.getApplicationInfo().targetSdkVersion
;
650 * Return a list of all the networks configured in the supplicant.
651 * Not all fields of WifiConfiguration are returned. Only the following
652 * fields are filled in:
658 * <li>allowedProtocols</li>
659 * <li>allowedKeyManagement</li>
660 * <li>allowedAuthAlgorithms</li>
661 * <li>allowedPairwiseCiphers</li>
662 * <li>allowedGroupCiphers</li>
664 * @return a list of network configurations in the form of a list
665 * of {@link WifiConfiguration} objects. Upon failure to fetch or
666 * when when Wi-Fi is turned off, it can be null.
668 public List
<WifiConfiguration
> getConfiguredNetworks() {
670 return mService
.getConfiguredNetworks();
671 } catch (RemoteException e
) {
672 Log
.w(TAG
, "Caught RemoteException trying to get configured networks: " + e
);
679 public List
<WifiConfiguration
> getPrivilegedConfiguredNetworks() {
681 return mService
.getPrivilegedConfiguredNetworks();
682 } catch (RemoteException e
) {
689 public WifiConnectionStatistics
getConnectionStatistics() {
691 return mService
.getConnectionStatistics();
692 } catch (RemoteException e
) {
698 * Returns a WifiConfiguration matching this ScanResult
699 * @param scanResult scanResult that represents the BSSID
700 * @return {@link WifiConfiguration} that matches this BSSID or null
703 public WifiConfiguration
getMatchingWifiConfig(ScanResult scanResult
) {
705 return mService
.getMatchingWifiConfig(scanResult
);
706 } catch (RemoteException e
) {
712 * Add a new network description to the set of configured networks.
713 * The {@code networkId} field of the supplied configuration object
716 * The new network will be marked DISABLED by default. To enable it,
717 * called {@link #enableNetwork}.
719 * @param config the set of variables that describe the configuration,
720 * contained in a {@link WifiConfiguration} object.
721 * @return the ID of the newly created network description. This is used in
722 * other operations to specified the network to be acted upon.
723 * Returns {@code -1} on failure.
725 public int addNetwork(WifiConfiguration config
) {
726 if (config
== null) {
729 config
.networkId
= -1;
730 return addOrUpdateNetwork(config
);
734 * Update the network description of an existing configured network.
736 * @param config the set of variables that describe the configuration,
737 * contained in a {@link WifiConfiguration} object. It may
738 * be sparse, so that only the items that are being changed
739 * are non-<code>null</code>. The {@code networkId} field
740 * must be set to the ID of the existing network being updated.
741 * @return Returns the {@code networkId} of the supplied
742 * {@code WifiConfiguration} on success.
744 * Returns {@code -1} on failure, including when the {@code networkId}
745 * field of the {@code WifiConfiguration} does not refer to an
748 public int updateNetwork(WifiConfiguration config
) {
749 if (config
== null || config
.networkId
< 0) {
752 return addOrUpdateNetwork(config
);
756 * Internal method for doing the RPC that creates a new network description
757 * or updates an existing one.
759 * @param config The possibly sparse object containing the variables that
760 * are to set or updated in the network description.
761 * @return the ID of the network on success, {@code -1} on failure.
763 private int addOrUpdateNetwork(WifiConfiguration config
) {
765 return mService
.addOrUpdateNetwork(config
);
766 } catch (RemoteException e
) {
772 * Remove the specified network from the list of configured networks.
773 * This may result in the asynchronous delivery of state change
775 * @param netId the integer that identifies the network configuration
777 * @return {@code true} if the operation succeeded
779 public boolean removeNetwork(int netId
) {
781 return mService
.removeNetwork(netId
);
782 } catch (RemoteException e
) {
788 * Allow a previously configured network to be associated with. If
789 * <code>disableOthers</code> is true, then all other configured
790 * networks are disabled, and an attempt to connect to the selected
791 * network is initiated. This may result in the asynchronous delivery
792 * of state change events.
794 * <b>Note:</b> If an application's target SDK version is
795 * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network
796 * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may
797 * instead be sent through another network, such as cellular data,
798 * Bluetooth tethering, or Ethernet. For example, traffic will never use a
799 * Wi-Fi network that does not provide Internet access (e.g. a wireless
800 * printer), if another network that does offer Internet access (e.g.
801 * cellular data) is available. Applications that need to ensure that their
802 * network traffic uses Wi-Fi should use APIs such as
803 * {@link Network#bindSocket(java.net.Socket)},
804 * {@link Network#openConnection(java.net.URL)}, or
805 * {@link ConnectivityManager#bindProcessToNetwork} to do so.
807 * @param netId the ID of the network in the list of configured networks
808 * @param disableOthers if true, disable all other networks. The way to
809 * select a particular network to connect to is specify {@code true}
810 * for this parameter.
811 * @return {@code true} if the operation succeeded
813 public boolean enableNetwork(int netId
, boolean disableOthers
) {
814 final boolean pin
= disableOthers
&& mTargetSdkVersion
< Build
.VERSION_CODES
.LOLLIPOP
;
816 registerPinningNetworkCallback();
821 success
= mService
.enableNetwork(netId
, disableOthers
);
822 } catch (RemoteException e
) {
826 if (pin
&& !success
) {
827 unregisterPinningNetworkCallback();
834 * Disable a configured network. The specified network will not be
835 * a candidate for associating. This may result in the asynchronous
836 * delivery of state change events.
837 * @param netId the ID of the network as returned by {@link #addNetwork}.
838 * @return {@code true} if the operation succeeded
840 public boolean disableNetwork(int netId
) {
842 return mService
.disableNetwork(netId
);
843 } catch (RemoteException e
) {
849 * Disassociate from the currently active access point. This may result
850 * in the asynchronous delivery of state change events.
851 * @return {@code true} if the operation succeeded
853 public boolean disconnect() {
855 mService
.disconnect();
857 } catch (RemoteException e
) {
863 * Reconnect to the currently active access point, if we are currently
864 * disconnected. This may result in the asynchronous delivery of state
866 * @return {@code true} if the operation succeeded
868 public boolean reconnect() {
870 mService
.reconnect();
872 } catch (RemoteException e
) {
878 * Reconnect to the currently active access point, even if we are already
879 * connected. This may result in the asynchronous delivery of state
881 * @return {@code true} if the operation succeeded
883 public boolean reassociate() {
885 mService
.reassociate();
887 } catch (RemoteException e
) {
893 * Check that the supplicant daemon is responding to requests.
894 * @return {@code true} if we were able to communicate with the supplicant and
895 * it returned the expected response to the PING message.
897 public boolean pingSupplicant() {
898 if (mService
== null)
901 return mService
.pingSupplicant();
902 } catch (RemoteException e
) {
908 * Get a list of available channels for customized scan.
910 * @see {@link WifiChannel}
912 * @return the channel list, or null if not available
915 public List
<WifiChannel
> getChannelList() {
917 return mService
.getChannelList();
918 } catch (RemoteException e
) {
923 /* Keep this list in sync with wifi_hal.h */
925 public static final int WIFI_FEATURE_INFRA
= 0x0001; // Basic infrastructure mode
927 public static final int WIFI_FEATURE_INFRA_5G
= 0x0002; // Support for 5 GHz Band
929 public static final int WIFI_FEATURE_PASSPOINT
= 0x0004; // Support for GAS/ANQP
931 public static final int WIFI_FEATURE_P2P
= 0x0008; // Wifi-Direct
933 public static final int WIFI_FEATURE_MOBILE_HOTSPOT
= 0x0010; // Soft AP
935 public static final int WIFI_FEATURE_SCANNER
= 0x0020; // WifiScanner APIs
937 public static final int WIFI_FEATURE_NAN
= 0x0040; // Neighbor Awareness Networking
939 public static final int WIFI_FEATURE_D2D_RTT
= 0x0080; // Device-to-device RTT
941 public static final int WIFI_FEATURE_D2AP_RTT
= 0x0100; // Device-to-AP RTT
943 public static final int WIFI_FEATURE_BATCH_SCAN
= 0x0200; // Batched Scan (deprecated)
945 public static final int WIFI_FEATURE_PNO
= 0x0400; // Preferred network offload
947 public static final int WIFI_FEATURE_ADDITIONAL_STA
= 0x0800; // Support for two STAs
949 public static final int WIFI_FEATURE_TDLS
= 0x1000; // Tunnel directed link setup
951 public static final int WIFI_FEATURE_TDLS_OFFCHANNEL
= 0x2000; // Support for TDLS off channel
953 public static final int WIFI_FEATURE_EPR
= 0x4000; // Enhanced power reporting
955 public static final int WIFI_FEATURE_AP_STA
= 0x8000; // Support for AP STA Concurrency
957 public static final int WIFI_FEATURE_LINK_LAYER_STATS
= 0x10000; // Link layer stats collection
959 public static final int WIFI_FEATURE_LOGGER
= 0x20000; // WiFi Logger
961 public static final int WIFI_FEATURE_HAL_EPNO
= 0x40000; // WiFi PNO enhanced
963 private int getSupportedFeatures() {
965 return mService
.getSupportedFeatures();
966 } catch (RemoteException e
) {
971 private boolean isFeatureSupported(int feature
) {
972 return (getSupportedFeatures() & feature
) == feature
;
975 * @return true if this adapter supports 5 GHz band
977 public boolean is5GHzBandSupported() {
978 return isFeatureSupported(WIFI_FEATURE_INFRA_5G
);
982 * @return true if this adapter supports passpoint
985 public boolean isPasspointSupported() {
986 return isFeatureSupported(WIFI_FEATURE_PASSPOINT
);
990 * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct)
992 public boolean isP2pSupported() {
993 return isFeatureSupported(WIFI_FEATURE_P2P
);
997 * @return true if this adapter supports portable Wi-Fi hotspot
1001 public boolean isPortableHotspotSupported() {
1002 return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT
);
1006 * @return true if this adapter supports WifiScanner APIs
1010 public boolean isWifiScannerSupported() {
1011 return isFeatureSupported(WIFI_FEATURE_SCANNER
);
1015 * @return true if this adapter supports Neighbour Awareness Network APIs
1018 public boolean isNanSupported() {
1019 return isFeatureSupported(WIFI_FEATURE_NAN
);
1023 * @return true if this adapter supports Device-to-device RTT
1027 public boolean isDeviceToDeviceRttSupported() {
1028 return isFeatureSupported(WIFI_FEATURE_D2D_RTT
);
1032 * @return true if this adapter supports Device-to-AP RTT
1035 public boolean isDeviceToApRttSupported() {
1036 return isFeatureSupported(WIFI_FEATURE_D2AP_RTT
);
1040 * @return true if this adapter supports offloaded connectivity scan
1042 public boolean isPreferredNetworkOffloadSupported() {
1043 return isFeatureSupported(WIFI_FEATURE_PNO
);
1047 * @return true if this adapter supports multiple simultaneous connections
1050 public boolean isAdditionalStaSupported() {
1051 return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA
);
1055 * @return true if this adapter supports Tunnel Directed Link Setup
1057 public boolean isTdlsSupported() {
1058 return isFeatureSupported(WIFI_FEATURE_TDLS
);
1062 * @return true if this adapter supports Off Channel Tunnel Directed Link Setup
1065 public boolean isOffChannelTdlsSupported() {
1066 return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL
);
1070 * @return true if this adapter supports advanced power/performance counters
1072 public boolean isEnhancedPowerReportingSupported() {
1073 return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS
);
1077 * Return the record of {@link WifiActivityEnergyInfo} object that
1078 * has the activity and energy info. This can be used to ascertain what
1079 * the controller has been up to, since the last sample.
1080 * @param updateType Type of info, cached vs refreshed.
1082 * @return a record with {@link WifiActivityEnergyInfo} or null if
1083 * report is unavailable or unsupported
1086 public WifiActivityEnergyInfo
getControllerActivityEnergyInfo(int updateType
) {
1087 if (mService
== null) return null;
1089 WifiActivityEnergyInfo record
;
1090 if (!isEnhancedPowerReportingSupported()) {
1093 synchronized(this) {
1094 record
= mService
.reportActivityInfo();
1095 if (record
!= null && record
.isValid()) {
1101 } catch (RemoteException e
) {
1102 Log
.e(TAG
, "getControllerActivityEnergyInfo: " + e
);
1108 * Request a scan for access points. Returns immediately. The availability
1109 * of the results is made known later by means of an asynchronous event sent
1110 * on completion of the scan.
1111 * @return {@code true} if the operation succeeded, i.e., the scan was initiated
1113 public boolean startScan() {
1115 mService
.startScan(null, null);
1117 } catch (RemoteException e
) {
1124 public boolean startScan(WorkSource workSource
) {
1126 mService
.startScan(null, workSource
);
1128 } catch (RemoteException e
) {
1134 * startLocationRestrictedScan()
1135 * Trigger a scan which will not make use of DFS channels and is thus not suitable for
1136 * establishing wifi connection.
1140 public boolean startLocationRestrictedScan(WorkSource workSource
) {
1142 mService
.startLocationRestrictedScan(workSource
);
1144 } catch (RemoteException e
) {
1150 * Request a scan for access points in specified channel list. Each channel is specified by its
1151 * frequency in MHz, e.g. "5500" (do NOT include "DFS" even though it is). The availability of
1152 * the results is made known later in the same way as {@link #startScan}.
1156 * 1. Customized scan is for non-connection purposes, i.e. it won't trigger a wifi connection
1157 * even though it finds some known networks.
1159 * 2. Customized scan result may include access points that is not specified in the channel
1160 * list. An app will need to do frequency filtering if it wants to get pure results for the
1161 * channel list it specified.
1165 public boolean startCustomizedScan(ScanSettings requested
) {
1167 mService
.startScan(requested
, null);
1169 } catch (RemoteException e
) {
1175 public boolean startCustomizedScan(ScanSettings requested
, WorkSource workSource
) {
1177 mService
.startScan(requested
, workSource
);
1179 } catch (RemoteException e
) {
1185 * Request a batched scan for access points. To end your requested batched scan,
1186 * call stopBatchedScan with the same Settings.
1188 * If there are mulitple requests for batched scans, the more demanding settings will
1191 * @param requested {@link BatchedScanSettings} the scan settings requested.
1192 * @return false on known error
1195 public boolean requestBatchedScan(BatchedScanSettings requested
) {
1197 return mService
.requestBatchedScan(requested
, new Binder(), null);
1198 } catch (RemoteException e
) { return false; }
1201 public boolean requestBatchedScan(BatchedScanSettings requested
, WorkSource workSource
) {
1203 return mService
.requestBatchedScan(requested
, new Binder(), workSource
);
1204 } catch (RemoteException e
) { return false; }
1208 * Check if the Batched Scan feature is supported.
1210 * @return false if not supported.
1214 public boolean isBatchedScanSupported() {
1216 return mService
.isBatchedScanSupported();
1217 } catch (RemoteException e
) { return false; }
1221 * End a requested batch scan for this applicaiton. Note that batched scan may
1222 * still occur if other apps are using them.
1224 * @param requested {@link BatchedScanSettings} the scan settings you previously requested
1225 * and now wish to stop. A value of null here will stop all scans requested by the
1229 public void stopBatchedScan(BatchedScanSettings requested
) {
1231 mService
.stopBatchedScan(requested
);
1232 } catch (RemoteException e
) {}
1236 * Retrieve the latest batched scan result. This should be called immediately after
1237 * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
1241 public List
<BatchedScanResult
> getBatchedScanResults() {
1243 return mService
.getBatchedScanResults(mContext
.getOpPackageName());
1244 } catch (RemoteException e
) {
1250 * Force a re-reading of batched scan results. This will attempt
1251 * to read more information from the chip, but will do so at the expense
1252 * of previous data. Rate limited to the current scan frequency.
1254 * pollBatchedScan will always wait 1 period from the start of the batch
1255 * before trying to read from the chip, so if your #scans/batch == 1 this will
1258 * If you had already waited 1 period before calling, this should have
1259 * immediate (though async) effect.
1261 * If you call before that 1 period is up this will set up a timer and fetch
1262 * results when the 1 period is up.
1264 * Servicing a pollBatchedScan request (immediate or after timed delay) starts a
1265 * new batch, so if you were doing 10 scans/batch and called in the 4th scan, you
1266 * would get data in the 4th and then again 10 scans later.
1269 public void pollBatchedScan() {
1271 mService
.pollBatchedScan();
1272 } catch (RemoteException e
) { }
1276 * Creates a configuration token describing the network referenced by {@code netId}
1277 * of MIME type application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
1279 * @return hex-string encoded configuration token
1282 public String
getWpsNfcConfigurationToken(int netId
) {
1284 return mService
.getWpsNfcConfigurationToken(netId
);
1285 } catch (RemoteException e
) {
1291 * Return dynamic information about the current Wi-Fi connection, if any is active.
1292 * @return the Wi-Fi information, contained in {@link WifiInfo}.
1294 public WifiInfo
getConnectionInfo() {
1296 return mService
.getConnectionInfo();
1297 } catch (RemoteException e
) {
1303 * Return the results of the latest access point scan.
1304 * @return the list of access points found in the most recent scan. An app must hold
1305 * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
1306 * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
1307 * in order to get valid results.
1309 public List
<ScanResult
> getScanResults() {
1311 return mService
.getScanResults(mContext
.getOpPackageName());
1312 } catch (RemoteException e
) {
1318 * Check if scanning is always available.
1320 * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results
1321 * even when Wi-Fi is turned off.
1323 * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
1325 public boolean isScanAlwaysAvailable() {
1327 return mService
.isScanAlwaysAvailable();
1328 } catch (RemoteException e
) {
1334 * Tell the supplicant to persist the current list of configured networks.
1336 * Note: It is possible for this method to change the network IDs of
1337 * existing networks. You should assume the network IDs can be different
1338 * after calling this method.
1340 * @return {@code true} if the operation succeeded
1342 public boolean saveConfiguration() {
1344 return mService
.saveConfiguration();
1345 } catch (RemoteException e
) {
1351 * Set the country code.
1352 * @param countryCode country code in ISO 3166 format.
1353 * @param persist {@code true} if this needs to be remembered
1357 public void setCountryCode(String country
, boolean persist
) {
1359 mService
.setCountryCode(country
, persist
);
1360 } catch (RemoteException e
) { }
1364 * get the country code.
1365 * @return the country code in ISO 3166 format.
1369 public String
getCountryCode() {
1371 String country
= mService
.getCountryCode();
1373 } catch (RemoteException e
) {
1379 * Set the operational frequency band.
1380 * @param band One of
1381 * {@link #WIFI_FREQUENCY_BAND_AUTO},
1382 * {@link #WIFI_FREQUENCY_BAND_5GHZ},
1383 * {@link #WIFI_FREQUENCY_BAND_2GHZ},
1384 * @param persist {@code true} if this needs to be remembered
1387 public void setFrequencyBand(int band
, boolean persist
) {
1389 mService
.setFrequencyBand(band
, persist
);
1390 } catch (RemoteException e
) { }
1394 * Get the operational frequency band.
1396 * {@link #WIFI_FREQUENCY_BAND_AUTO},
1397 * {@link #WIFI_FREQUENCY_BAND_5GHZ},
1398 * {@link #WIFI_FREQUENCY_BAND_2GHZ} or
1399 * {@code -1} on failure.
1402 public int getFrequencyBand() {
1404 return mService
.getFrequencyBand();
1405 } catch (RemoteException e
) {
1411 * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz)
1412 * @return {@code true} if supported, {@code false} otherwise.
1415 public boolean isDualBandSupported() {
1417 return mService
.isDualBandSupported();
1418 } catch (RemoteException e
) {
1424 * Return the DHCP-assigned addresses from the last successful DHCP request,
1426 * @return the DHCP information
1428 public DhcpInfo
getDhcpInfo() {
1430 return mService
.getDhcpInfo();
1431 } catch (RemoteException e
) {
1437 * Enable or disable Wi-Fi.
1438 * @param enabled {@code true} to enable, {@code false} to disable.
1439 * @return {@code true} if the operation succeeds (or if the existing state
1440 * is the same as the requested state).
1442 public boolean setWifiEnabled(boolean enabled
) {
1444 return mService
.setWifiEnabled(enabled
);
1445 } catch (RemoteException e
) {
1451 * Gets the Wi-Fi enabled state.
1452 * @return One of {@link #WIFI_STATE_DISABLED},
1453 * {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
1454 * {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
1455 * @see #isWifiEnabled()
1457 public int getWifiState() {
1459 return mService
.getWifiEnabledState();
1460 } catch (RemoteException e
) {
1461 return WIFI_STATE_UNKNOWN
;
1466 * Return whether Wi-Fi is enabled or disabled.
1467 * @return {@code true} if Wi-Fi is enabled
1468 * @see #getWifiState()
1470 public boolean isWifiEnabled() {
1471 return getWifiState() == WIFI_STATE_ENABLED
;
1475 * Return TX packet counter, for CTS test of WiFi watchdog.
1476 * @param listener is the interface to receive result
1478 * @hide for CTS test only
1480 public void getTxPacketCount(TxPacketCountListener listener
) {
1482 sAsyncChannel
.sendMessage(RSSI_PKTCNT_FETCH
, 0, putListener(listener
));
1486 * Calculates the level of the signal. This should be used any time a signal
1489 * @param rssi The power of the signal measured in RSSI.
1490 * @param numLevels The number of levels to consider in the calculated
1492 * @return A level of the signal, given in the range of 0 to numLevels-1
1495 public static int calculateSignalLevel(int rssi
, int numLevels
) {
1496 if (rssi
<= MIN_RSSI
) {
1498 } else if (rssi
>= MAX_RSSI
) {
1499 return numLevels
- 1;
1501 float inputRange
= (MAX_RSSI
- MIN_RSSI
);
1502 float outputRange
= (numLevels
- 1);
1503 return (int)((float)(rssi
- MIN_RSSI
) * outputRange
/ inputRange
);
1508 * Compares two signal strengths.
1510 * @param rssiA The power of the first signal measured in RSSI.
1511 * @param rssiB The power of the second signal measured in RSSI.
1512 * @return Returns <0 if the first signal is weaker than the second signal,
1513 * 0 if the two signals have the same strength, and >0 if the first
1514 * signal is stronger than the second signal.
1516 public static int compareSignalLevel(int rssiA
, int rssiB
) {
1517 return rssiA
- rssiB
;
1521 * Start AccessPoint mode with the specified
1522 * configuration. If the radio is already running in
1523 * AP mode, update the new configuration
1524 * Note that starting in access point mode disables station
1526 * @param wifiConfig SSID, security and channel details as
1527 * part of WifiConfiguration
1528 * @return {@code true} if the operation succeeds, {@code false} otherwise
1530 * @hide Dont open up yet
1532 public boolean setWifiApEnabled(WifiConfiguration wifiConfig
, boolean enabled
) {
1534 mService
.setWifiApEnabled(wifiConfig
, enabled
);
1536 } catch (RemoteException e
) {
1542 * Gets the Wi-Fi enabled state.
1543 * @return One of {@link #WIFI_AP_STATE_DISABLED},
1544 * {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
1545 * {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
1546 * @see #isWifiApEnabled()
1548 * @hide Dont open yet
1550 public int getWifiApState() {
1552 return mService
.getWifiApEnabledState();
1553 } catch (RemoteException e
) {
1554 return WIFI_AP_STATE_FAILED
;
1559 * Return whether Wi-Fi AP is enabled or disabled.
1560 * @return {@code true} if Wi-Fi AP is enabled
1561 * @see #getWifiApState()
1563 * @hide Dont open yet
1565 public boolean isWifiApEnabled() {
1566 return getWifiApState() == WIFI_AP_STATE_ENABLED
;
1570 * Gets the Wi-Fi AP Configuration.
1571 * @return AP details in WifiConfiguration
1573 * @hide Dont open yet
1575 public WifiConfiguration
getWifiApConfiguration() {
1577 return mService
.getWifiApConfiguration();
1578 } catch (RemoteException e
) {
1584 * Builds a WifiConfiguration from Hotspot 2.0 MIME file.
1585 * @return AP details in WifiConfiguration
1587 * @hide Dont open yet
1589 public WifiConfiguration
buildWifiConfig(String uriString
, String mimeType
, byte[] data
) {
1591 return mService
.buildWifiConfig(uriString
, mimeType
, data
);
1592 } catch (RemoteException e
) {
1593 Log
.w(TAG
, "Caught RemoteException trying to build wifi config: " + e
);
1599 * Sets the Wi-Fi AP Configuration.
1600 * @return {@code true} if the operation succeeded, {@code false} otherwise
1602 * @hide Dont open yet
1604 public boolean setWifiApConfiguration(WifiConfiguration wifiConfig
) {
1606 mService
.setWifiApConfiguration(wifiConfig
);
1608 } catch (RemoteException e
) {
1614 * Start the driver and connect to network.
1616 * This function will over-ride WifiLock and device idle status. For example,
1617 * even if the device is idle or there is only a scan-only lock held,
1618 * a start wifi would mean that wifi connection is kept active until
1619 * a stopWifi() is sent.
1621 * This API is used by WifiStateTracker
1623 * @return {@code true} if the operation succeeds else {@code false}
1626 public boolean startWifi() {
1628 mService
.startWifi();
1630 } catch (RemoteException e
) {
1636 * Disconnect from a network (if any) and stop the driver.
1638 * This function will over-ride WifiLock and device idle status. Wi-Fi
1639 * stays inactive until a startWifi() is issued.
1641 * This API is used by WifiStateTracker
1643 * @return {@code true} if the operation succeeds else {@code false}
1646 public boolean stopWifi() {
1648 mService
.stopWifi();
1650 } catch (RemoteException e
) {
1656 * Add a bssid to the supplicant blacklist
1658 * This API is used by WifiWatchdogService
1660 * @return {@code true} if the operation succeeds else {@code false}
1663 public boolean addToBlacklist(String bssid
) {
1665 mService
.addToBlacklist(bssid
);
1667 } catch (RemoteException e
) {
1673 * Clear the supplicant blacklist
1675 * This API is used by WifiWatchdogService
1677 * @return {@code true} if the operation succeeds else {@code false}
1680 public boolean clearBlacklist() {
1682 mService
.clearBlacklist();
1684 } catch (RemoteException e
) {
1691 * Enable/Disable TDLS on a specific local route.
1694 * TDLS enables two wireless endpoints to talk to each other directly
1695 * without going through the access point that is managing the local
1696 * network. It saves bandwidth and improves quality of the link.
1699 * This API enables/disables the option of using TDLS. If enabled, the
1700 * underlying hardware is free to use TDLS or a hop through the access
1701 * point. If disabled, existing TDLS session is torn down and
1702 * hardware is restricted to use access point for transferring wireless
1703 * packets. Default value for all routes is 'disabled', meaning restricted
1704 * to use access point for transferring packets.
1707 * @param remoteIPAddress IP address of the endpoint to setup TDLS with
1708 * @param enable true = setup and false = tear down TDLS
1710 public void setTdlsEnabled(InetAddress remoteIPAddress
, boolean enable
) {
1712 mService
.enableTdls(remoteIPAddress
.getHostAddress(), enable
);
1713 } catch (RemoteException e
) {
1714 // Just ignore the exception
1719 * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except
1720 * this version allows you to specify remote endpoint with a MAC address.
1721 * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab
1722 * @param enable true = setup and false = tear down TDLS
1724 public void setTdlsEnabledWithMacAddress(String remoteMacAddress
, boolean enable
) {
1726 mService
.enableTdlsWithMacAddress(remoteMacAddress
, enable
);
1727 } catch (RemoteException e
) {
1728 // Just ignore the exception
1732 /* TODO: deprecate synchronous API and open up the following API */
1734 private static final int BASE
= Protocol
.BASE_WIFI_MANAGER
;
1736 /* Commands to WifiService */
1738 public static final int CONNECT_NETWORK
= BASE
+ 1;
1740 public static final int CONNECT_NETWORK_FAILED
= BASE
+ 2;
1742 public static final int CONNECT_NETWORK_SUCCEEDED
= BASE
+ 3;
1745 public static final int FORGET_NETWORK
= BASE
+ 4;
1747 public static final int FORGET_NETWORK_FAILED
= BASE
+ 5;
1749 public static final int FORGET_NETWORK_SUCCEEDED
= BASE
+ 6;
1752 public static final int SAVE_NETWORK
= BASE
+ 7;
1754 public static final int SAVE_NETWORK_FAILED
= BASE
+ 8;
1756 public static final int SAVE_NETWORK_SUCCEEDED
= BASE
+ 9;
1759 public static final int START_WPS
= BASE
+ 10;
1761 public static final int START_WPS_SUCCEEDED
= BASE
+ 11;
1763 public static final int WPS_FAILED
= BASE
+ 12;
1765 public static final int WPS_COMPLETED
= BASE
+ 13;
1768 public static final int CANCEL_WPS
= BASE
+ 14;
1770 public static final int CANCEL_WPS_FAILED
= BASE
+ 15;
1772 public static final int CANCEL_WPS_SUCCEDED
= BASE
+ 16;
1775 public static final int DISABLE_NETWORK
= BASE
+ 17;
1777 public static final int DISABLE_NETWORK_FAILED
= BASE
+ 18;
1779 public static final int DISABLE_NETWORK_SUCCEEDED
= BASE
+ 19;
1782 public static final int RSSI_PKTCNT_FETCH
= BASE
+ 20;
1784 public static final int RSSI_PKTCNT_FETCH_SUCCEEDED
= BASE
+ 21;
1786 public static final int RSSI_PKTCNT_FETCH_FAILED
= BASE
+ 22;
1789 * Passed with {@link ActionListener#onFailure}.
1790 * Indicates that the operation failed due to an internal error.
1793 public static final int ERROR
= 0;
1796 * Passed with {@link ActionListener#onFailure}.
1797 * Indicates that the operation is already in progress
1800 public static final int IN_PROGRESS
= 1;
1803 * Passed with {@link ActionListener#onFailure}.
1804 * Indicates that the operation failed because the framework is busy and
1805 * unable to service the request
1808 public static final int BUSY
= 2;
1810 /* WPS specific errors */
1811 /** WPS overlap detected */
1812 public static final int WPS_OVERLAP_ERROR
= 3;
1813 /** WEP on WPS is prohibited */
1814 public static final int WPS_WEP_PROHIBITED
= 4;
1815 /** TKIP only prohibited */
1816 public static final int WPS_TKIP_ONLY_PROHIBITED
= 5;
1817 /** Authentication failure on WPS */
1818 public static final int WPS_AUTH_FAILURE
= 6;
1819 /** WPS timed out */
1820 public static final int WPS_TIMED_OUT
= 7;
1823 * Passed with {@link ActionListener#onFailure}.
1824 * Indicates that the operation failed due to invalid inputs
1827 public static final int INVALID_ARGS
= 8;
1830 * Passed with {@link ActionListener#onFailure}.
1831 * Indicates that the operation failed due to user permissions.
1834 public static final int NOT_AUTHORIZED
= 9;
1837 * Interface for callback invocation on an application action
1840 public interface ActionListener
{
1841 /** The operation succeeded */
1842 public void onSuccess();
1844 * The operation failed
1845 * @param reason The reason for failure could be one of
1846 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY}
1848 public void onFailure(int reason
);
1851 /** Interface for callback invocation on a start WPS action */
1852 public static abstract class WpsCallback
{
1853 /** WPS start succeeded */
1854 public abstract void onStarted(String pin
);
1856 /** WPS operation completed succesfully */
1857 public abstract void onSucceeded();
1860 * WPS operation failed
1861 * @param reason The reason for failure could be one of
1862 * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR},
1863 * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE}
1864 * and some generic errors.
1866 public abstract void onFailed(int reason
);
1869 /** Interface for callback invocation on a TX packet count poll action {@hide} */
1870 public interface TxPacketCountListener
{
1872 * The operation succeeded
1873 * @param count TX packet counter
1875 public void onSuccess(int count
);
1877 * The operation failed
1878 * @param reason The reason for failure could be one of
1879 * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY}
1881 public void onFailure(int reason
);
1884 private static class ServiceHandler
extends Handler
{
1885 ServiceHandler(Looper looper
) {
1890 public void handleMessage(Message message
) {
1891 Object listener
= removeListener(message
.arg2
);
1892 switch (message
.what
) {
1893 case AsyncChannel
.CMD_CHANNEL_HALF_CONNECTED
:
1894 if (message
.arg1
== AsyncChannel
.STATUS_SUCCESSFUL
) {
1895 sAsyncChannel
.sendMessage(AsyncChannel
.CMD_CHANNEL_FULL_CONNECTION
);
1897 Log
.e(TAG
, "Failed to set up channel connection");
1898 // This will cause all further async API calls on the WifiManager
1899 // to fail and throw an exception
1900 sAsyncChannel
= null;
1902 sConnected
.countDown();
1904 case AsyncChannel
.CMD_CHANNEL_FULLY_CONNECTED
:
1907 case AsyncChannel
.CMD_CHANNEL_DISCONNECTED
:
1908 Log
.e(TAG
, "Channel connection lost");
1909 // This will cause all further async API calls on the WifiManager
1910 // to fail and throw an exception
1911 sAsyncChannel
= null;
1914 /* ActionListeners grouped together */
1915 case WifiManager
.CONNECT_NETWORK_FAILED
:
1916 case WifiManager
.FORGET_NETWORK_FAILED
:
1917 case WifiManager
.SAVE_NETWORK_FAILED
:
1918 case WifiManager
.DISABLE_NETWORK_FAILED
:
1919 if (listener
!= null) {
1920 ((ActionListener
) listener
).onFailure(message
.arg1
);
1923 /* ActionListeners grouped together */
1924 case WifiManager
.CONNECT_NETWORK_SUCCEEDED
:
1925 case WifiManager
.FORGET_NETWORK_SUCCEEDED
:
1926 case WifiManager
.SAVE_NETWORK_SUCCEEDED
:
1927 case WifiManager
.DISABLE_NETWORK_SUCCEEDED
:
1928 if (listener
!= null) {
1929 ((ActionListener
) listener
).onSuccess();
1932 case WifiManager
.START_WPS_SUCCEEDED
:
1933 if (listener
!= null) {
1934 WpsResult result
= (WpsResult
) message
.obj
;
1935 ((WpsCallback
) listener
).onStarted(result
.pin
);
1936 //Listener needs to stay until completion or failure
1937 synchronized(sListenerMapLock
) {
1938 sListenerMap
.put(message
.arg2
, listener
);
1942 case WifiManager
.WPS_COMPLETED
:
1943 if (listener
!= null) {
1944 ((WpsCallback
) listener
).onSucceeded();
1947 case WifiManager
.WPS_FAILED
:
1948 if (listener
!= null) {
1949 ((WpsCallback
) listener
).onFailed(message
.arg1
);
1952 case WifiManager
.CANCEL_WPS_SUCCEDED
:
1953 if (listener
!= null) {
1954 ((WpsCallback
) listener
).onSucceeded();
1957 case WifiManager
.CANCEL_WPS_FAILED
:
1958 if (listener
!= null) {
1959 ((WpsCallback
) listener
).onFailed(message
.arg1
);
1962 case WifiManager
.RSSI_PKTCNT_FETCH_SUCCEEDED
:
1963 if (listener
!= null) {
1964 RssiPacketCountInfo info
= (RssiPacketCountInfo
) message
.obj
;
1966 ((TxPacketCountListener
) listener
).onSuccess(info
.txgood
+ info
.txbad
);
1968 ((TxPacketCountListener
) listener
).onFailure(ERROR
);
1971 case WifiManager
.RSSI_PKTCNT_FETCH_FAILED
:
1972 if (listener
!= null) {
1973 ((TxPacketCountListener
) listener
).onFailure(message
.arg1
);
1983 private static int putListener(Object listener
) {
1984 if (listener
== null) return INVALID_KEY
;
1986 synchronized (sListenerMapLock
) {
1988 key
= sListenerKey
++;
1989 } while (key
== INVALID_KEY
);
1990 sListenerMap
.put(key
, listener
);
1995 private static Object
removeListener(int key
) {
1996 if (key
== INVALID_KEY
) return null;
1997 synchronized (sListenerMapLock
) {
1998 Object listener
= sListenerMap
.get(key
);
1999 sListenerMap
.remove(key
);
2004 private void init() {
2005 synchronized (sThreadRefLock
) {
2006 if (++sThreadRefCount
== 1) {
2007 Messenger messenger
= getWifiServiceMessenger();
2008 if (messenger
== null) {
2009 sAsyncChannel
= null;
2013 sHandlerThread
= new HandlerThread("WifiManager");
2014 sAsyncChannel
= new AsyncChannel();
2015 sConnected
= new CountDownLatch(1);
2017 sHandlerThread
.start();
2018 Handler handler
= new ServiceHandler(sHandlerThread
.getLooper());
2019 sAsyncChannel
.connect(mContext
, handler
, messenger
);
2022 } catch (InterruptedException e
) {
2023 Log
.e(TAG
, "interrupted wait at init");
2029 private void validateChannel() {
2030 if (sAsyncChannel
== null) throw new IllegalStateException(
2031 "No permission to access and change wifi or a bad initialization");
2034 private void initConnectivityManager() {
2035 // TODO: what happens if an app calls a WifiManager API before ConnectivityManager is
2036 // registered? Can we fix this by starting ConnectivityService before WifiService?
2038 sCM
= (ConnectivityManager
) mContext
.getSystemService(Context
.CONNECTIVITY_SERVICE
);
2040 throw new IllegalStateException("Bad luck, ConnectivityService not started.");
2046 * A NetworkCallback that pins the process to the first wifi network to connect.
2048 * We use this to maintain compatibility with pre-M apps that call WifiManager.enableNetwork()
2049 * to connect to a Wi-Fi network that has no Internet access, and then assume that they will be
2050 * able to use that network because it's the system default.
2052 * In order to maintain compatibility with apps that call setProcessDefaultNetwork themselves,
2053 * we try not to set the default network unless they have already done so, and we try not to
2054 * clear the default network unless we set it ourselves.
2056 * This should maintain behaviour that's compatible with L, which would pin the whole system to
2057 * any wifi network that was created via enableNetwork(..., true) until that network
2060 * Note that while this hack allows network traffic to flow, it is quite limited. For example:
2062 * 1. setProcessDefaultNetwork only affects this process, so:
2063 * - Any subprocesses spawned by this process will not be pinned to Wi-Fi.
2064 * - If this app relies on any other apps on the device also being on Wi-Fi, that won't work
2065 * either, because other apps on the device will not be pinned.
2066 * 2. The behaviour of other APIs is not modified. For example:
2067 * - getActiveNetworkInfo will return the system default network, not Wi-Fi.
2068 * - There will be no CONNECTIVITY_ACTION broadcasts about TYPE_WIFI.
2069 * - getProcessDefaultNetwork will not return null, so if any apps are relying on that, they
2070 * will be surprised as well.
2072 private class PinningNetworkCallback
extends NetworkCallback
{
2073 private Network mPinnedNetwork
;
2076 public void onPreCheck(Network network
) {
2077 if (sCM
.getProcessDefaultNetwork() == null && mPinnedNetwork
== null) {
2078 sCM
.setProcessDefaultNetwork(network
);
2079 mPinnedNetwork
= network
;
2080 Log
.d(TAG
, "Wifi alternate reality enabled on network " + network
);
2085 public void onLost(Network network
) {
2086 if (network
.equals(mPinnedNetwork
) && network
.equals(sCM
.getProcessDefaultNetwork())) {
2087 sCM
.setProcessDefaultNetwork(null);
2088 Log
.d(TAG
, "Wifi alternate reality disabled on network " + network
);
2089 mPinnedNetwork
= null;
2090 unregisterPinningNetworkCallback();
2095 private void registerPinningNetworkCallback() {
2096 initConnectivityManager();
2097 synchronized (sCM
) {
2098 if (mNetworkCallback
== null) {
2099 // TODO: clear all capabilities.
2100 NetworkRequest request
= new NetworkRequest
.Builder()
2101 .addTransportType(NetworkCapabilities
.TRANSPORT_WIFI
)
2102 .removeCapability(NetworkCapabilities
.NET_CAPABILITY_INTERNET
)
2104 mNetworkCallback
= new PinningNetworkCallback();
2106 sCM
.registerNetworkCallback(request
, mNetworkCallback
);
2107 } catch (SecurityException e
) {
2108 Log
.d(TAG
, "Failed to register network callback", e
);
2114 private void unregisterPinningNetworkCallback() {
2115 initConnectivityManager();
2116 synchronized (sCM
) {
2117 if (mNetworkCallback
!= null) {
2119 sCM
.unregisterNetworkCallback(mNetworkCallback
);
2120 } catch (SecurityException e
) {
2121 Log
.d(TAG
, "Failed to unregister network callback", e
);
2123 mNetworkCallback
= null;
2129 * Connect to a network with the given configuration. The network also
2130 * gets added to the supplicant configuration.
2132 * For a new network, this function is used instead of a
2133 * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
2136 * @param config the set of variables that describe the configuration,
2137 * contained in a {@link WifiConfiguration} object.
2138 * @param listener for callbacks on success or failure. Can be null.
2139 * @throws IllegalStateException if the WifiManager instance needs to be
2144 public void connect(WifiConfiguration config
, ActionListener listener
) {
2145 if (config
== null) throw new IllegalArgumentException("config cannot be null");
2147 // Use INVALID_NETWORK_ID for arg1 when passing a config object
2148 // arg1 is used to pass network id when the network already exists
2149 sAsyncChannel
.sendMessage(CONNECT_NETWORK
, WifiConfiguration
.INVALID_NETWORK_ID
,
2150 putListener(listener
), config
);
2154 * Connect to a network with the given networkId.
2156 * This function is used instead of a enableNetwork(), saveConfiguration() and
2159 * @param networkId the network id identifiying the network in the
2160 * supplicant configuration list
2161 * @param listener for callbacks on success or failure. Can be null.
2162 * @throws IllegalStateException if the WifiManager instance needs to be
2166 public void connect(int networkId
, ActionListener listener
) {
2167 if (networkId
< 0) throw new IllegalArgumentException("Network id cannot be negative");
2169 sAsyncChannel
.sendMessage(CONNECT_NETWORK
, networkId
, putListener(listener
));
2173 * Save the given network in the supplicant config. If the network already
2174 * exists, the configuration is updated. A new network is enabled
2177 * For a new network, this function is used instead of a
2178 * sequence of addNetwork(), enableNetwork() and saveConfiguration().
2180 * For an existing network, it accomplishes the task of updateNetwork()
2181 * and saveConfiguration()
2183 * @param config the set of variables that describe the configuration,
2184 * contained in a {@link WifiConfiguration} object.
2185 * @param listener for callbacks on success or failure. Can be null.
2186 * @throws IllegalStateException if the WifiManager instance needs to be
2190 public void save(WifiConfiguration config
, ActionListener listener
) {
2191 if (config
== null) throw new IllegalArgumentException("config cannot be null");
2193 sAsyncChannel
.sendMessage(SAVE_NETWORK
, 0, putListener(listener
), config
);
2197 * Delete the network in the supplicant config.
2199 * This function is used instead of a sequence of removeNetwork()
2200 * and saveConfiguration().
2202 * @param config the set of variables that describe the configuration,
2203 * contained in a {@link WifiConfiguration} object.
2204 * @param listener for callbacks on success or failure. Can be null.
2205 * @throws IllegalStateException if the WifiManager instance needs to be
2209 public void forget(int netId
, ActionListener listener
) {
2210 if (netId
< 0) throw new IllegalArgumentException("Network id cannot be negative");
2212 sAsyncChannel
.sendMessage(FORGET_NETWORK
, netId
, putListener(listener
));
2218 * @param netId is the network Id
2219 * @param listener for callbacks on success or failure. Can be null.
2220 * @throws IllegalStateException if the WifiManager instance needs to be
2224 public void disable(int netId
, ActionListener listener
) {
2225 if (netId
< 0) throw new IllegalArgumentException("Network id cannot be negative");
2227 sAsyncChannel
.sendMessage(DISABLE_NETWORK
, netId
, putListener(listener
));
2231 * Disable ephemeral Network
2233 * @param SSID, in the format of WifiConfiguration's SSID.
2236 public void disableEphemeralNetwork(String SSID
) {
2237 if (SSID
== null) throw new IllegalArgumentException("SSID cannot be null");
2239 mService
.disableEphemeralNetwork(SSID
);
2240 } catch (RemoteException e
) {
2245 * Start Wi-fi Protected Setup
2247 * @param config WPS configuration (does not support {@link WpsInfo#LABEL})
2248 * @param listener for callbacks on success or failure. Can be null.
2249 * @throws IllegalStateException if the WifiManager instance needs to be
2252 public void startWps(WpsInfo config
, WpsCallback listener
) {
2253 if (config
== null) throw new IllegalArgumentException("config cannot be null");
2255 sAsyncChannel
.sendMessage(START_WPS
, 0, putListener(listener
), config
);
2259 * Cancel any ongoing Wi-fi Protected Setup
2261 * @param listener for callbacks on success or failure. Can be null.
2262 * @throws IllegalStateException if the WifiManager instance needs to be
2265 public void cancelWps(WpsCallback listener
) {
2267 sAsyncChannel
.sendMessage(CANCEL_WPS
, 0, putListener(listener
));
2271 * Get a reference to WifiService handler. This is used by a client to establish
2272 * an AsyncChannel communication with WifiService
2274 * @return Messenger pointing to the WifiService handler
2277 public Messenger
getWifiServiceMessenger() {
2279 return mService
.getWifiServiceMessenger();
2280 } catch (RemoteException e
) {
2282 } catch (SecurityException e
) {
2289 * Returns the file in which IP and proxy configuration data is stored
2292 public String
getConfigFile() {
2294 return mService
.getConfigFile();
2295 } catch (RemoteException e
) {
2301 * Allows an application to keep the Wi-Fi radio awake.
2302 * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
2303 * Acquiring a WifiLock will keep the radio on until the lock is released. Multiple
2304 * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
2305 * WifiLocks are held in any application.
2307 * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
2308 * could function over a mobile network, if available. A program that needs to download large
2309 * files should hold a WifiLock to ensure that the download will complete, but a program whose
2310 * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
2311 * affecting battery life.
2313 * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
2314 * Mode. They simply keep the radio from turning off when Wi-Fi is already on but the device
2317 * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK}
2318 * permission in an {@code <uses-permission>} element of the application's manifest.
2320 public class WifiLock
{
2321 private String mTag
;
2322 private final IBinder mBinder
;
2323 private int mRefCount
;
2325 private boolean mRefCounted
;
2326 private boolean mHeld
;
2327 private WorkSource mWorkSource
;
2329 private WifiLock(int lockType
, String tag
) {
2331 mLockType
= lockType
;
2332 mBinder
= new Binder();
2339 * Locks the Wi-Fi radio on until {@link #release} is called.
2341 * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
2342 * reference count, and the radio will remain locked as long as the reference count is
2345 * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
2346 * the radio, but subsequent calls will be ignored. Only one call to {@link #release}
2347 * will be required, regardless of the number of times that {@code acquire} is called.
2349 public void acquire() {
2350 synchronized (mBinder
) {
2351 if (mRefCounted ?
(++mRefCount
== 1) : (!mHeld
)) {
2353 mService
.acquireWifiLock(mBinder
, mLockType
, mTag
, mWorkSource
);
2354 synchronized (WifiManager
.this) {
2355 if (mActiveLockCount
>= MAX_ACTIVE_LOCKS
) {
2356 mService
.releaseWifiLock(mBinder
);
2357 throw new UnsupportedOperationException(
2358 "Exceeded maximum number of wifi locks");
2362 } catch (RemoteException ignore
) {
2370 * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle.
2372 * If this WifiLock is reference-counted, each call to {@code release} will decrement the
2373 * reference count, and the radio will be unlocked only when the reference count reaches
2374 * zero. If the reference count goes below zero (that is, if {@code release} is called
2375 * a greater number of times than {@link #acquire}), an exception is thrown.
2377 * If this WifiLock is not reference-counted, the first call to {@code release} (after
2378 * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent
2379 * calls will be ignored.
2381 public void release() {
2382 synchronized (mBinder
) {
2383 if (mRefCounted ?
(--mRefCount
== 0) : (mHeld
)) {
2385 mService
.releaseWifiLock(mBinder
);
2386 synchronized (WifiManager
.this) {
2389 } catch (RemoteException ignore
) {
2393 if (mRefCount
< 0) {
2394 throw new RuntimeException("WifiLock under-locked " + mTag
);
2400 * Controls whether this is a reference-counted or non-reference-counted WifiLock.
2402 * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and
2403 * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire}
2404 * has been balanced with a call to {@link #release}. Non-reference-counted WifiLocks
2405 * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the
2406 * radio whenever {@link #release} is called and it is locked.
2408 * @param refCounted true if this WifiLock should keep a reference count
2410 public void setReferenceCounted(boolean refCounted
) {
2411 mRefCounted
= refCounted
;
2415 * Checks whether this WifiLock is currently held.
2417 * @return true if this WifiLock is held, false otherwise
2419 public boolean isHeld() {
2420 synchronized (mBinder
) {
2425 public void setWorkSource(WorkSource ws
) {
2426 synchronized (mBinder
) {
2427 if (ws
!= null && ws
.size() == 0) {
2430 boolean changed
= true;
2435 if (mWorkSource
== null) {
2436 changed
= mWorkSource
!= null;
2437 mWorkSource
= new WorkSource(ws
);
2439 changed
= mWorkSource
.diff(ws
);
2441 mWorkSource
.set(ws
);
2445 if (changed
&& mHeld
) {
2447 mService
.updateWifiLockWorkSource(mBinder
, mWorkSource
);
2448 } catch (RemoteException e
) {
2454 public String
toString() {
2456 synchronized (mBinder
) {
2457 s1
= Integer
.toHexString(System
.identityHashCode(this));
2458 s2
= mHeld ?
"held; " : "";
2460 s3
= "refcounted: refcount = " + mRefCount
;
2462 s3
= "not refcounted";
2464 return "WifiLock{ " + s1
+ "; " + s2
+ s3
+ " }";
2469 protected void finalize() throws Throwable
{
2471 synchronized (mBinder
) {
2474 mService
.releaseWifiLock(mBinder
);
2475 synchronized (WifiManager
.this) {
2478 } catch (RemoteException ignore
) {
2486 * Creates a new WifiLock.
2488 * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
2489 * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for
2490 * descriptions of the types of Wi-Fi locks.
2491 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is
2492 * never shown to the user under normal conditions, but should be descriptive
2493 * enough to identify your application and the specific WifiLock within it, if it
2494 * holds multiple WifiLocks.
2496 * @return a new, unacquired WifiLock with the given tag.
2500 public WifiLock
createWifiLock(int lockType
, String tag
) {
2501 return new WifiLock(lockType
, tag
);
2505 * Creates a new WifiLock.
2507 * @param tag a tag for the WifiLock to identify it in debugging messages. This string is
2508 * never shown to the user under normal conditions, but should be descriptive
2509 * enough to identify your application and the specific WifiLock within it, if it
2510 * holds multiple WifiLocks.
2512 * @return a new, unacquired WifiLock with the given tag.
2516 public WifiLock
createWifiLock(String tag
) {
2517 return new WifiLock(WIFI_MODE_FULL
, tag
);
2522 * Create a new MulticastLock
2524 * @param tag a tag for the MulticastLock to identify it in debugging
2525 * messages. This string is never shown to the user under
2526 * normal conditions, but should be descriptive enough to
2527 * identify your application and the specific MulticastLock
2528 * within it, if it holds multiple MulticastLocks.
2530 * @return a new, unacquired MulticastLock with the given tag.
2532 * @see MulticastLock
2534 public MulticastLock
createMulticastLock(String tag
) {
2535 return new MulticastLock(tag
);
2539 * Allows an application to receive Wifi Multicast packets.
2540 * Normally the Wifi stack filters out packets not explicitly
2541 * addressed to this device. Acquring a MulticastLock will
2542 * cause the stack to receive packets addressed to multicast
2543 * addresses. Processing these extra packets can cause a noticable
2544 * battery drain and should be disabled when not needed.
2546 public class MulticastLock
{
2547 private String mTag
;
2548 private final IBinder mBinder
;
2549 private int mRefCount
;
2550 private boolean mRefCounted
;
2551 private boolean mHeld
;
2553 private MulticastLock(String tag
) {
2555 mBinder
= new Binder();
2562 * Locks Wifi Multicast on until {@link #release} is called.
2564 * If this MulticastLock is reference-counted each call to
2565 * {@code acquire} will increment the reference count, and the
2566 * wifi interface will receive multicast packets as long as the
2567 * reference count is above zero.
2569 * If this MulticastLock is not reference-counted, the first call to
2570 * {@code acquire} will turn on the multicast packets, but subsequent
2571 * calls will be ignored. Only one call to {@link #release} will
2572 * be required, regardless of the number of times that {@code acquire}
2575 * Note that other applications may also lock Wifi Multicast on.
2576 * Only they can relinquish their lock.
2578 * Also note that applications cannot leave Multicast locked on.
2579 * When an app exits or crashes, any Multicast locks will be released.
2581 public void acquire() {
2582 synchronized (mBinder
) {
2583 if (mRefCounted ?
(++mRefCount
== 1) : (!mHeld
)) {
2585 mService
.acquireMulticastLock(mBinder
, mTag
);
2586 synchronized (WifiManager
.this) {
2587 if (mActiveLockCount
>= MAX_ACTIVE_LOCKS
) {
2588 mService
.releaseMulticastLock();
2589 throw new UnsupportedOperationException(
2590 "Exceeded maximum number of wifi locks");
2594 } catch (RemoteException ignore
) {
2602 * Unlocks Wifi Multicast, restoring the filter of packets
2603 * not addressed specifically to this device and saving power.
2605 * If this MulticastLock is reference-counted, each call to
2606 * {@code release} will decrement the reference count, and the
2607 * multicast packets will only stop being received when the reference
2608 * count reaches zero. If the reference count goes below zero (that
2609 * is, if {@code release} is called a greater number of times than
2610 * {@link #acquire}), an exception is thrown.
2612 * If this MulticastLock is not reference-counted, the first call to
2613 * {@code release} (after the radio was multicast locked using
2614 * {@link #acquire}) will unlock the multicast, and subsequent calls
2617 * Note that if any other Wifi Multicast Locks are still outstanding
2618 * this {@code release} call will not have an immediate effect. Only
2619 * when all applications have released all their Multicast Locks will
2620 * the Multicast filter be turned back on.
2622 * Also note that when an app exits or crashes all of its Multicast
2623 * Locks will be automatically released.
2625 public void release() {
2626 synchronized (mBinder
) {
2627 if (mRefCounted ?
(--mRefCount
== 0) : (mHeld
)) {
2629 mService
.releaseMulticastLock();
2630 synchronized (WifiManager
.this) {
2633 } catch (RemoteException ignore
) {
2637 if (mRefCount
< 0) {
2638 throw new RuntimeException("MulticastLock under-locked "
2645 * Controls whether this is a reference-counted or non-reference-
2646 * counted MulticastLock.
2648 * Reference-counted MulticastLocks keep track of the number of calls
2649 * to {@link #acquire} and {@link #release}, and only stop the
2650 * reception of multicast packets when every call to {@link #acquire}
2651 * has been balanced with a call to {@link #release}. Non-reference-
2652 * counted MulticastLocks allow the reception of multicast packets
2653 * whenever {@link #acquire} is called and stop accepting multicast
2654 * packets whenever {@link #release} is called.
2656 * @param refCounted true if this MulticastLock should keep a reference
2659 public void setReferenceCounted(boolean refCounted
) {
2660 mRefCounted
= refCounted
;
2664 * Checks whether this MulticastLock is currently held.
2666 * @return true if this MulticastLock is held, false otherwise
2668 public boolean isHeld() {
2669 synchronized (mBinder
) {
2674 public String
toString() {
2676 synchronized (mBinder
) {
2677 s1
= Integer
.toHexString(System
.identityHashCode(this));
2678 s2
= mHeld ?
"held; " : "";
2680 s3
= "refcounted: refcount = " + mRefCount
;
2682 s3
= "not refcounted";
2684 return "MulticastLock{ " + s1
+ "; " + s2
+ s3
+ " }";
2689 protected void finalize() throws Throwable
{
2691 setReferenceCounted(false);
2697 * Check multicast filter status.
2699 * @return true if multicast packets are allowed.
2701 * @hide pending API council approval
2703 public boolean isMulticastEnabled() {
2705 return mService
.isMulticastEnabled();
2706 } catch (RemoteException e
) {
2712 * Initialize the multicast filtering to 'on'
2713 * @hide no intent to publish
2715 public boolean initializeMulticastFiltering() {
2717 mService
.initializeMulticastFiltering();
2719 } catch (RemoteException e
) {
2724 protected void finalize() throws Throwable
{
2726 synchronized (sThreadRefLock
) {
2727 if (--sThreadRefCount
== 0 && sAsyncChannel
!= null) {
2728 sAsyncChannel
.disconnect();
2737 * Set wifi verbose log. Called from developer settings.
2740 public void enableVerboseLogging (int verbose
) {
2742 mService
.enableVerboseLogging(verbose
);
2743 } catch (Exception e
) {
2744 //ignore any failure here
2745 Log
.e(TAG
, "enableVerboseLogging " + e
.toString());
2750 * Get the WiFi verbose logging level.This is used by settings
2751 * to decide what to show within the picker.
2754 public int getVerboseLoggingLevel() {
2756 return mService
.getVerboseLoggingLevel();
2757 } catch (RemoteException e
) {
2763 * Set wifi Aggressive Handover. Called from developer settings.
2766 public void enableAggressiveHandover(int enabled
) {
2768 mService
.enableAggressiveHandover(enabled
);
2769 } catch (RemoteException e
) {
2775 * Get the WiFi Handover aggressiveness.This is used by settings
2776 * to decide what to show within the picker.
2779 public int getAggressiveHandover() {
2781 return mService
.getAggressiveHandover();
2782 } catch (RemoteException e
) {
2788 * Set setting for allowing Scans when traffic is ongoing.
2791 public void setAllowScansWithTraffic(int enabled
) {
2793 mService
.setAllowScansWithTraffic(enabled
);
2794 } catch (RemoteException e
) {
2800 * Get setting for allowing Scans when traffic is ongoing.
2803 public int getAllowScansWithTraffic() {
2805 return mService
.getAllowScansWithTraffic();
2806 } catch (RemoteException e
) {
2812 * Resets all wifi manager settings back to factory defaults.
2816 public void factoryReset() {
2818 mService
.factoryReset();
2819 } catch (RemoteException e
) {
2824 * Get Network object of current wifi network
2825 * @return Get Network object of current wifi network
2828 public Network
getCurrentNetwork() {
2830 return mService
.getCurrentNetwork();
2831 } catch (RemoteException e
) {
2837 * Framework layer autojoin enable/disable when device is associated
2838 * this will enable/disable autojoin scan and switch network when connected
2839 * @return true -- if set successful false -- if set failed
2842 public boolean enableAutoJoinWhenAssociated(boolean enabled
) {
2844 return mService
.enableAutoJoinWhenAssociated(enabled
);
2845 } catch (RemoteException e
) {
2851 * Get setting for Framework layer autojoin enable status
2854 public boolean getEnableAutoJoinWhenAssociated() {
2856 return mService
.getEnableAutoJoinWhenAssociated();
2857 } catch (RemoteException e
) {
2862 * Set setting for enabling autojoin Offload thru Wifi HAL layer
2865 public void setHalBasedAutojoinOffload(int enabled
) {
2867 mService
.setHalBasedAutojoinOffload(enabled
);
2868 } catch (RemoteException e
) {
2874 * Get setting for enabling autojoin Offload thru Wifi HAL layer
2877 public int getHalBasedAutojoinOffload() {
2879 return mService
.getHalBasedAutojoinOffload();
2880 } catch (RemoteException e
) {