1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
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
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17package android.net.wifi;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.annotation.SystemApi;
22import android.bluetooth.BluetoothAdapter;
23import android.content.Context;
24import android.net.ConnectivityManager;
25import android.net.DhcpInfo;
26import android.net.Network;
27import android.net.NetworkCapabilities;
28import android.net.NetworkRequest;
29import android.os.Binder;
30import android.os.Build;
31import android.os.Handler;
32import android.os.IBinder;
33import android.os.Looper;
34import android.os.Message;
35import android.os.Messenger;
36import android.os.RemoteException;
37import android.os.WorkSource;
38import android.util.Log;
39import android.util.SparseArray;
40
41import com.android.internal.util.AsyncChannel;
42import com.android.internal.util.Protocol;
43import com.android.server.net.NetworkPinner;
44
45import java.net.InetAddress;
46import java.util.List;
47import java.util.concurrent.CountDownLatch;
48
49/**
50 * This class provides the primary API for managing all aspects of Wi-Fi
51 * connectivity. Get an instance of this class by calling
52 * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
53 * On releases before NYC, it should only be obtained from an application context, and not from
54 * any other derived context to avoid memory leaks within the calling process.
55
56 * It deals with several categories of items:
57 * <ul>
58 * <li>The list of configured networks. The list can be viewed and updated,
59 * and attributes of individual entries can be modified.</li>
60 * <li>The currently active Wi-Fi network, if any. Connectivity can be
61 * established or torn down, and dynamic information about the state of
62 * the network can be queried.</li>
63 * <li>Results of access point scans, containing enough information to
64 * make decisions about what access point to connect to.</li>
65 * <li>It defines the names of various Intent actions that are broadcast
66 * upon any sort of change in Wi-Fi state.
67 * </ul>
68 * This is the API to use when performing Wi-Fi specific operations. To
69 * perform operations that pertain to network connectivity at an abstract
70 * level, use {@link android.net.ConnectivityManager}.
71 */
72public class WifiManager {
73
74    private static final String TAG = "WifiManager";
75    // Supplicant error codes:
76    /**
77     * The error code if there was a problem authenticating.
78     */
79    public static final int ERROR_AUTHENTICATING = 1;
80
81    /**
82     * Broadcast intent action indicating whether Wi-Fi scanning is allowed currently
83     * @hide
84     */
85    public static final String WIFI_SCAN_AVAILABLE = "wifi_scan_available";
86
87    /**
88     * Extra int indicating scan availability, WIFI_STATE_ENABLED and WIFI_STATE_DISABLED
89     * @hide
90     */
91    public static final String EXTRA_SCAN_AVAILABLE = "scan_enabled";
92
93    /**
94     * Broadcast intent action indicating that the credential of a Wi-Fi network
95     * has been changed. One extra provides the ssid of the network. Another
96     * extra provides the event type, whether the credential is saved or forgot.
97     * @hide
98     */
99    @SystemApi
100    public static final String WIFI_CREDENTIAL_CHANGED_ACTION =
101            "android.net.wifi.WIFI_CREDENTIAL_CHANGED";
102    /** @hide */
103    @SystemApi
104    public static final String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
105    /** @hide */
106    @SystemApi
107    public static final String EXTRA_WIFI_CREDENTIAL_SSID = "ssid";
108    /** @hide */
109    @SystemApi
110    public static final int WIFI_CREDENTIAL_SAVED = 0;
111    /** @hide */
112    @SystemApi
113    public static final int WIFI_CREDENTIAL_FORGOT = 1;
114
115    /**
116     * Broadcast intent action indicating that the a Passpoint release 2 icon has been received.
117     * @hide
118     */
119    public static final String PASSPOINT_ICON_RECEIVED_ACTION =
120            "android.net.wifi.PASSPOINT_ICON_RECEIVED";
121    /** @hide */
122    public static final String EXTRA_PASSPOINT_ICON_BSSID = "bssid";
123    /** @hide */
124    public static final String EXTRA_PASSPOINT_ICON_FILE = "file";
125    /** @hide */
126    public static final String EXTRA_PASSPOINT_ICON_DATA = "icon";
127
128    /**
129     * Broadcast intent action indicating that the a Passpoint release
130     * 2 WNM frame has been received.
131     * @hide
132     */
133    public static final String PASSPOINT_WNM_FRAME_RECEIVED_ACTION =
134            "android.net.wifi.PASSPOINT_WNM_FRAME_RECEIVED";
135    /**
136     * Originating BSS
137     * @hide */
138    public static final String EXTRA_PASSPOINT_WNM_BSSID = "bssid";
139    /**
140     * SOAP-XML or OMA-DM
141     * @hide */
142    public static final String EXTRA_PASSPOINT_WNM_METHOD = "method";
143    /**
144     * Type of Passpoint match
145     * @hide */
146    public static final String EXTRA_PASSPOINT_WNM_PPOINT_MATCH = "match";
147    /**
148     * String
149     * @hide */
150    public static final String EXTRA_PASSPOINT_WNM_URL = "url";
151    /**
152     * Boolean true=ess, false=bss
153     * @hide */
154    public static final String EXTRA_PASSPOINT_WNM_ESS = "ess";
155    /**
156     * Delay in seconds
157     * @hide */
158    public static final String EXTRA_PASSPOINT_WNM_DELAY = "delay";
159
160    /**
161     * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
162     * enabling, disabling, or unknown. One extra provides this state as an int.
163     * Another extra provides the previous state, if available.
164     *
165     * @see #EXTRA_WIFI_STATE
166     * @see #EXTRA_PREVIOUS_WIFI_STATE
167     */
168    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
169    public static final String WIFI_STATE_CHANGED_ACTION =
170        "android.net.wifi.WIFI_STATE_CHANGED";
171    /**
172     * The lookup key for an int that indicates whether Wi-Fi is enabled,
173     * disabled, enabling, disabling, or unknown.  Retrieve it with
174     * {@link android.content.Intent#getIntExtra(String,int)}.
175     *
176     * @see #WIFI_STATE_DISABLED
177     * @see #WIFI_STATE_DISABLING
178     * @see #WIFI_STATE_ENABLED
179     * @see #WIFI_STATE_ENABLING
180     * @see #WIFI_STATE_UNKNOWN
181     */
182    public static final String EXTRA_WIFI_STATE = "wifi_state";
183    /**
184     * The previous Wi-Fi state.
185     *
186     * @see #EXTRA_WIFI_STATE
187     */
188    public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
189
190    /**
191     * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
192     * it finishes successfully.
193     *
194     * @see #WIFI_STATE_CHANGED_ACTION
195     * @see #getWifiState()
196     */
197    public static final int WIFI_STATE_DISABLING = 0;
198    /**
199     * Wi-Fi is disabled.
200     *
201     * @see #WIFI_STATE_CHANGED_ACTION
202     * @see #getWifiState()
203     */
204    public static final int WIFI_STATE_DISABLED = 1;
205    /**
206     * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if
207     * it finishes successfully.
208     *
209     * @see #WIFI_STATE_CHANGED_ACTION
210     * @see #getWifiState()
211     */
212    public static final int WIFI_STATE_ENABLING = 2;
213    /**
214     * Wi-Fi is enabled.
215     *
216     * @see #WIFI_STATE_CHANGED_ACTION
217     * @see #getWifiState()
218     */
219    public static final int WIFI_STATE_ENABLED = 3;
220    /**
221     * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling
222     * or disabling.
223     *
224     * @see #WIFI_STATE_CHANGED_ACTION
225     * @see #getWifiState()
226     */
227    public static final int WIFI_STATE_UNKNOWN = 4;
228
229    /**
230     * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
231     * enabling, disabling, or failed.
232     *
233     * @hide
234     */
235    @SystemApi
236    public static final String WIFI_AP_STATE_CHANGED_ACTION =
237        "android.net.wifi.WIFI_AP_STATE_CHANGED";
238
239    /**
240     * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
241     * disabled, enabling, disabling, or failed.  Retrieve it with
242     * {@link android.content.Intent#getIntExtra(String,int)}.
243     *
244     * @see #WIFI_AP_STATE_DISABLED
245     * @see #WIFI_AP_STATE_DISABLING
246     * @see #WIFI_AP_STATE_ENABLED
247     * @see #WIFI_AP_STATE_ENABLING
248     * @see #WIFI_AP_STATE_FAILED
249     *
250     * @hide
251     */
252    @SystemApi
253    public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
254
255    /**
256     * The look up key for an int that indicates why softAP started failed
257     * currently support general and no_channel
258     * @see #SAP_START_FAILURE_GENERAL
259     * @see #SAP_START_FAILURE_NO_CHANNEL
260     *
261     * @hide
262     */
263    public static final String EXTRA_WIFI_AP_FAILURE_REASON = "wifi_ap_error_code";
264    /**
265     * The previous Wi-Fi state.
266     *
267     * @see #EXTRA_WIFI_AP_STATE
268     *
269     * @hide
270     */
271    @SystemApi
272    public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
273    /**
274     * Wi-Fi AP is currently being disabled. The state will change to
275     * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
276     *
277     * @see #WIFI_AP_STATE_CHANGED_ACTION
278     * @see #getWifiApState()
279     *
280     * @hide
281     */
282    @SystemApi
283    public static final int WIFI_AP_STATE_DISABLING = 10;
284    /**
285     * Wi-Fi AP is disabled.
286     *
287     * @see #WIFI_AP_STATE_CHANGED_ACTION
288     * @see #getWifiState()
289     *
290     * @hide
291     */
292    @SystemApi
293    public static final int WIFI_AP_STATE_DISABLED = 11;
294    /**
295     * Wi-Fi AP is currently being enabled. The state will change to
296     * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
297     *
298     * @see #WIFI_AP_STATE_CHANGED_ACTION
299     * @see #getWifiApState()
300     *
301     * @hide
302     */
303    @SystemApi
304    public static final int WIFI_AP_STATE_ENABLING = 12;
305    /**
306     * Wi-Fi AP is enabled.
307     *
308     * @see #WIFI_AP_STATE_CHANGED_ACTION
309     * @see #getWifiApState()
310     *
311     * @hide
312     */
313    @SystemApi
314    public static final int WIFI_AP_STATE_ENABLED = 13;
315    /**
316     * Wi-Fi AP is in a failed state. This state will occur when an error occurs during
317     * enabling or disabling
318     *
319     * @see #WIFI_AP_STATE_CHANGED_ACTION
320     * @see #getWifiApState()
321     *
322     * @hide
323     */
324    @SystemApi
325    public static final int WIFI_AP_STATE_FAILED = 14;
326
327    /**
328     *  If WIFI AP start failed, this reason code means there is no legal channel exists on
329     *  user selected band by regulatory
330     *
331     *  @hide
332     */
333    public static final int SAP_START_FAILURE_GENERAL= 0;
334
335    /**
336     *  All other reason for AP start failed besides SAP_START_FAILURE_GENERAL
337     *
338     *  @hide
339     */
340    public static final int SAP_START_FAILURE_NO_CHANNEL = 1;
341    /**
342     * Broadcast intent action indicating that a connection to the supplicant has
343     * been established (and it is now possible
344     * to perform Wi-Fi operations) or the connection to the supplicant has been
345     * lost. One extra provides the connection state as a boolean, where {@code true}
346     * means CONNECTED.
347     * @see #EXTRA_SUPPLICANT_CONNECTED
348     */
349    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
350    public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION =
351        "android.net.wifi.supplicant.CONNECTION_CHANGE";
352    /**
353     * The lookup key for a boolean that indicates whether a connection to
354     * the supplicant daemon has been gained or lost. {@code true} means
355     * a connection now exists.
356     * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
357     */
358    public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
359    /**
360     * Broadcast intent action indicating that the state of Wi-Fi connectivity
361     * has changed. One extra provides the new state
362     * in the form of a {@link android.net.NetworkInfo} object. If the new
363     * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
364     * the access point.
365     * as a {@code String}.
366     * @see #EXTRA_NETWORK_INFO
367     * @see #EXTRA_BSSID
368     * @see #EXTRA_WIFI_INFO
369     */
370    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
371    public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
372    /**
373     * The lookup key for a {@link android.net.NetworkInfo} object associated with the
374     * Wi-Fi network. Retrieve with
375     * {@link android.content.Intent#getParcelableExtra(String)}.
376     */
377    public static final String EXTRA_NETWORK_INFO = "networkInfo";
378    /**
379     * The lookup key for a String giving the BSSID of the access point to which
380     * we are connected. Only present when the new state is CONNECTED.
381     * Retrieve with
382     * {@link android.content.Intent#getStringExtra(String)}.
383     */
384    public static final String EXTRA_BSSID = "bssid";
385    /**
386     * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
387     * information about the access point to which we are connected. Only present
388     * when the new state is CONNECTED.  Retrieve with
389     * {@link android.content.Intent#getParcelableExtra(String)}.
390     */
391    public static final String EXTRA_WIFI_INFO = "wifiInfo";
392    /**
393     * Broadcast intent action indicating that the state of establishing a connection to
394     * an access point has changed.One extra provides the new
395     * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
396     * is not generally the most useful thing to look at if you are just interested in
397     * the overall state of connectivity.
398     * @see #EXTRA_NEW_STATE
399     * @see #EXTRA_SUPPLICANT_ERROR
400     */
401    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
402    public static final String SUPPLICANT_STATE_CHANGED_ACTION =
403        "android.net.wifi.supplicant.STATE_CHANGE";
404    /**
405     * The lookup key for a {@link SupplicantState} describing the new state
406     * Retrieve with
407     * {@link android.content.Intent#getParcelableExtra(String)}.
408     */
409    public static final String EXTRA_NEW_STATE = "newState";
410
411    /**
412     * The lookup key for a {@link SupplicantState} describing the supplicant
413     * error code if any
414     * Retrieve with
415     * {@link android.content.Intent#getIntExtra(String, int)}.
416     * @see #ERROR_AUTHENTICATING
417     */
418    public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
419
420    /**
421     * Broadcast intent action indicating that the configured networks changed.
422     * This can be as a result of adding/updating/deleting a network. If
423     * {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is set to true the new configuration
424     * can be retreived with the {@link #EXTRA_WIFI_CONFIGURATION} extra. If multiple
425     * Wi-Fi configurations changed, {@link #EXTRA_WIFI_CONFIGURATION} will not be present.
426     * @hide
427     */
428    @SystemApi
429    public static final String CONFIGURED_NETWORKS_CHANGED_ACTION =
430        "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
431    /**
432     * The lookup key for a (@link android.net.wifi.WifiConfiguration} object representing
433     * the changed Wi-Fi configuration when the {@link #CONFIGURED_NETWORKS_CHANGED_ACTION}
434     * broadcast is sent.
435     * @hide
436     */
437    @SystemApi
438    public static final String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
439    /**
440     * Multiple network configurations have changed.
441     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
442     *
443     * @hide
444     */
445    @SystemApi
446    public static final String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
447    /**
448     * The lookup key for an integer indicating the reason a Wi-Fi network configuration
449     * has changed. Only present if {@link #EXTRA_MULTIPLE_NETWORKS_CHANGED} is {@code false}
450     * @see #CONFIGURED_NETWORKS_CHANGED_ACTION
451     * @hide
452     */
453    @SystemApi
454    public static final String EXTRA_CHANGE_REASON = "changeReason";
455    /**
456     * The configuration is new and was added.
457     * @hide
458     */
459    @SystemApi
460    public static final int CHANGE_REASON_ADDED = 0;
461    /**
462     * The configuration was removed and is no longer present in the system's list of
463     * configured networks.
464     * @hide
465     */
466    @SystemApi
467    public static final int CHANGE_REASON_REMOVED = 1;
468    /**
469     * The configuration has changed as a result of explicit action or because the system
470     * took an automated action such as disabling a malfunctioning configuration.
471     * @hide
472     */
473    @SystemApi
474    public static final int CHANGE_REASON_CONFIG_CHANGE = 2;
475    /**
476     * An access point scan has completed, and results are available from the supplicant.
477     * Call {@link #getScanResults()} to obtain the results. {@link #EXTRA_RESULTS_UPDATED}
478     * indicates if the scan was completed successfully.
479     */
480    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
481    public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
482
483    /**
484     * Lookup key for a {@code boolean} representing the result of previous {@link #startScan}
485     * operation, reported with {@link #SCAN_RESULTS_AVAILABLE_ACTION}.
486     * @return true scan was successful, results are updated
487     * @return false scan was not successful, results haven't been updated since previous scan
488     */
489    public static final String EXTRA_RESULTS_UPDATED = "resultsUpdated";
490
491    /**
492     * A batch of access point scans has been completed and the results areavailable.
493     * Call {@link #getBatchedScanResults()} to obtain the results.
494     * @deprecated This API is nolonger supported.
495     * Use {@link android.net.wifi.WifiScanner} API
496     * @hide
497     */
498    @Deprecated
499    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
500    public static final String BATCHED_SCAN_RESULTS_AVAILABLE_ACTION =
501            "android.net.wifi.BATCHED_RESULTS";
502    /**
503     * The RSSI (signal strength) has changed.
504     * @see #EXTRA_NEW_RSSI
505     */
506    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
507    public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
508    /**
509     * The lookup key for an {@code int} giving the new RSSI in dBm.
510     */
511    public static final String EXTRA_NEW_RSSI = "newRssi";
512
513    /**
514     * Broadcast intent action indicating that the link configuration
515     * changed on wifi.
516     * @hide
517     */
518    public static final String LINK_CONFIGURATION_CHANGED_ACTION =
519        "android.net.wifi.LINK_CONFIGURATION_CHANGED";
520
521    /**
522     * The lookup key for a {@link android.net.LinkProperties} object associated with the
523     * Wi-Fi network. Retrieve with
524     * {@link android.content.Intent#getParcelableExtra(String)}.
525     * @hide
526     */
527    public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
528
529    /**
530     * The lookup key for a {@link android.net.NetworkCapabilities} object associated with the
531     * Wi-Fi network. Retrieve with
532     * {@link android.content.Intent#getParcelableExtra(String)}.
533     * @hide
534     */
535    public static final String EXTRA_NETWORK_CAPABILITIES = "networkCapabilities";
536
537    /**
538     * The network IDs of the configured networks could have changed.
539     */
540    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
541    public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
542
543    /**
544     * Activity Action: Show a system activity that allows the user to enable
545     * scans to be available even with Wi-Fi turned off.
546     *
547     * <p>Notification of the result of this activity is posted using the
548     * {@link android.app.Activity#onActivityResult} callback. The
549     * <code>resultCode</code>
550     * will be {@link android.app.Activity#RESULT_OK} if scan always mode has
551     * been turned on or {@link android.app.Activity#RESULT_CANCELED} if the user
552     * has rejected the request or an error has occurred.
553     */
554    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
555    public static final String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE =
556            "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
557
558    /**
559     * Activity Action: Pick a Wi-Fi network to connect to.
560     * <p>Input: Nothing.
561     * <p>Output: Nothing.
562     */
563    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
564    public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
565
566    /**
567     * Activity Action: Show UI to get user approval to enable WiFi.
568     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
569     *           the name of the app requesting the action.
570     * <p>Output: Nothing.
571     *
572     * @hide
573     */
574    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
575    public static final String ACTION_REQUEST_ENABLE = "android.net.wifi.action.REQUEST_ENABLE";
576
577    /**
578     * Activity Action: Show UI to get user approval to disable WiFi.
579     * <p>Input: {@link android.content.Intent#EXTRA_PACKAGE_NAME} string extra with
580     *           the name of the app requesting the action.
581     * <p>Output: Nothing.
582     *
583     * @hide
584     */
585    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
586    public static final String ACTION_REQUEST_DISABLE = "android.net.wifi.action.REQUEST_DISABLE";
587
588    /**
589     * Internally used Wi-Fi lock mode representing the case were no locks are held.
590     * @hide
591     */
592    public static final int WIFI_MODE_NO_LOCKS_HELD = 0;
593
594    /**
595     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
596     * and will behave normally, i.e., it will attempt to automatically
597     * establish a connection to a remembered access point that is
598     * within range, and will do periodic scans if there are remembered
599     * access points but none are in range.
600     */
601    public static final int WIFI_MODE_FULL = 1;
602    /**
603     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
604     * but the only operation that will be supported is initiation of
605     * scans, and the subsequent reporting of scan results. No attempts
606     * will be made to automatically connect to remembered access points,
607     * nor will periodic scans be automatically performed looking for
608     * remembered access points. Scans must be explicitly requested by
609     * an application in this mode.
610     */
611    public static final int WIFI_MODE_SCAN_ONLY = 2;
612    /**
613     * In this Wi-Fi lock mode, Wi-Fi will be kept active as in mode
614     * {@link #WIFI_MODE_FULL} but it operates at high performance
615     * with minimum packet loss and low packet latency even when
616     * the device screen is off. This mode will consume more power
617     * and hence should be used only when there is a need for such
618     * an active connection.
619     * <p>
620     * An example use case is when a voice connection needs to be
621     * kept active even after the device screen goes off. Holding the
622     * regular {@link #WIFI_MODE_FULL} lock will keep the wifi
623     * connection active, but the connection can be lossy.
624     * Holding a {@link #WIFI_MODE_FULL_HIGH_PERF} lock for the
625     * duration of the voice call will improve the call quality.
626     * <p>
627     * When there is no support from the hardware, this lock mode
628     * will have the same behavior as {@link #WIFI_MODE_FULL}
629     */
630    public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
631
632    /** Anything worse than or equal to this will show 0 bars. */
633    private static final int MIN_RSSI = -100;
634
635    /** Anything better than or equal to this will show the max bars. */
636    private static final int MAX_RSSI = -55;
637
638    /**
639     * Number of RSSI levels used in the framework to initiate
640     * {@link #RSSI_CHANGED_ACTION} broadcast
641     * @hide
642     */
643    public static final int RSSI_LEVELS = 5;
644
645    /**
646     * Auto settings in the driver. The driver could choose to operate on both
647     * 2.4 GHz and 5 GHz or make a dynamic decision on selecting the band.
648     * @hide
649     */
650    public static final int WIFI_FREQUENCY_BAND_AUTO = 0;
651
652    /**
653     * Operation on 5 GHz alone
654     * @hide
655     */
656    public static final int WIFI_FREQUENCY_BAND_5GHZ = 1;
657
658    /**
659     * Operation on 2.4 GHz alone
660     * @hide
661     */
662    public static final int WIFI_FREQUENCY_BAND_2GHZ = 2;
663
664    /** List of asyncronous notifications
665     * @hide
666     */
667    public static final int DATA_ACTIVITY_NOTIFICATION = 1;
668
669    //Lowest bit indicates data reception and the second lowest
670    //bit indicates data transmitted
671    /** @hide */
672    public static final int DATA_ACTIVITY_NONE         = 0x00;
673    /** @hide */
674    public static final int DATA_ACTIVITY_IN           = 0x01;
675    /** @hide */
676    public static final int DATA_ACTIVITY_OUT          = 0x02;
677    /** @hide */
678    public static final int DATA_ACTIVITY_INOUT        = 0x03;
679
680    /** @hide */
681    public static final boolean DEFAULT_POOR_NETWORK_AVOIDANCE_ENABLED = false;
682
683    /* Maximum number of active locks we allow.
684     * This limit was added to prevent apps from creating a ridiculous number
685     * of locks and crashing the system by overflowing the global ref table.
686     */
687    private static final int MAX_ACTIVE_LOCKS = 50;
688
689    /* Number of currently active WifiLocks and MulticastLocks */
690    private int mActiveLockCount;
691
692    private Context mContext;
693    IWifiManager mService;
694    private final int mTargetSdkVersion;
695
696    private static final int INVALID_KEY = 0;
697    private int mListenerKey = 1;
698    private final SparseArray mListenerMap = new SparseArray();
699    private final Object mListenerMapLock = new Object();
700
701    private AsyncChannel mAsyncChannel;
702    private CountDownLatch mConnected;
703    private Looper mLooper;
704
705    /**
706     * Create a new WifiManager instance.
707     * Applications will almost always want to use
708     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
709     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
710     * @param context the application context
711     * @param service the Binder interface
712     * @hide - hide this because it takes in a parameter of type IWifiManager, which
713     * is a system private class.
714     */
715    public WifiManager(Context context, IWifiManager service, Looper looper) {
716        mContext = context;
717        mService = service;
718        mLooper = looper;
719        mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
720    }
721
722    /**
723     * Return a list of all the networks configured in the supplicant.
724     * Not all fields of WifiConfiguration are returned. Only the following
725     * fields are filled in:
726     * <ul>
727     * <li>networkId</li>
728     * <li>SSID</li>
729     * <li>BSSID</li>
730     * <li>priority</li>
731     * <li>allowedProtocols</li>
732     * <li>allowedKeyManagement</li>
733     * <li>allowedAuthAlgorithms</li>
734     * <li>allowedPairwiseCiphers</li>
735     * <li>allowedGroupCiphers</li>
736     * </ul>
737     * @return a list of network configurations in the form of a list
738     * of {@link WifiConfiguration} objects. Upon failure to fetch or
739     * when Wi-Fi is turned off, it can be null.
740     */
741    public List<WifiConfiguration> getConfiguredNetworks() {
742        try {
743            return mService.getConfiguredNetworks();
744        } catch (RemoteException e) {
745            throw e.rethrowFromSystemServer();
746        }
747    }
748
749    /** @hide */
750    public boolean hasCarrierConfiguredNetworks() {
751        try {
752            return mService.hasCarrierConfiguredNetworks();
753        } catch (RemoteException e) {
754            throw e.rethrowFromSystemServer();
755        }
756    }
757
758    /** @hide */
759    @SystemApi
760    public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
761        try {
762            return mService.getPrivilegedConfiguredNetworks();
763        } catch (RemoteException e) {
764            throw e.rethrowFromSystemServer();
765        }
766    }
767
768    /** @hide */
769    @SystemApi
770    public WifiConnectionStatistics getConnectionStatistics() {
771        try {
772            return mService.getConnectionStatistics();
773        } catch (RemoteException e) {
774            throw e.rethrowFromSystemServer();
775        }
776    }
777
778    /**
779     * Returns a WifiConfiguration matching this ScanResult
780     * @param scanResult scanResult that represents the BSSID
781     * @return {@link WifiConfiguration} that matches this BSSID or null
782     * @hide
783     */
784    public WifiConfiguration getMatchingWifiConfig(ScanResult scanResult) {
785        try {
786            return mService.getMatchingWifiConfig(scanResult);
787        } catch (RemoteException e) {
788            throw e.rethrowFromSystemServer();
789        }
790    }
791
792    /**
793     * Add a new network description to the set of configured networks.
794     * The {@code networkId} field of the supplied configuration object
795     * is ignored.
796     * <p/>
797     * The new network will be marked DISABLED by default. To enable it,
798     * called {@link #enableNetwork}.
799     *
800     * @param config the set of variables that describe the configuration,
801     *            contained in a {@link WifiConfiguration} object.
802     * @return the ID of the newly created network description. This is used in
803     *         other operations to specified the network to be acted upon.
804     *         Returns {@code -1} on failure.
805     */
806    public int addNetwork(WifiConfiguration config) {
807        if (config == null) {
808            return -1;
809        }
810        config.networkId = -1;
811        return addOrUpdateNetwork(config);
812    }
813
814    /**
815     * Update the network description of an existing configured network.
816     *
817     * @param config the set of variables that describe the configuration,
818     *            contained in a {@link WifiConfiguration} object. It may
819     *            be sparse, so that only the items that are being changed
820     *            are non-<code>null</code>. The {@code networkId} field
821     *            must be set to the ID of the existing network being updated.
822     * @return Returns the {@code networkId} of the supplied
823     *         {@code WifiConfiguration} on success.
824     *         <br/>
825     *         Returns {@code -1} on failure, including when the {@code networkId}
826     *         field of the {@code WifiConfiguration} does not refer to an
827     *         existing network.
828     */
829    public int updateNetwork(WifiConfiguration config) {
830        if (config == null || config.networkId < 0) {
831            return -1;
832        }
833        return addOrUpdateNetwork(config);
834    }
835
836    /**
837     * Internal method for doing the RPC that creates a new network description
838     * or updates an existing one.
839     *
840     * @param config The possibly sparse object containing the variables that
841     *         are to set or updated in the network description.
842     * @return the ID of the network on success, {@code -1} on failure.
843     */
844    private int addOrUpdateNetwork(WifiConfiguration config) {
845        try {
846            return mService.addOrUpdateNetwork(config);
847        } catch (RemoteException e) {
848            throw e.rethrowFromSystemServer();
849        }
850    }
851
852    /**
853     * Add a Hotspot 2.0 release 2 Management Object
854     * @param mo The MO in XML form
855     * @return -1 for failure
856     * @hide
857     */
858    public int addPasspointManagementObject(String mo) {
859        try {
860            return mService.addPasspointManagementObject(mo);
861        } catch (RemoteException e) {
862            throw e.rethrowFromSystemServer();
863        }
864    }
865
866    /**
867     * Modify a Hotspot 2.0 release 2 Management Object
868     * @param fqdn The FQDN of the service provider
869     * @param mos A List of MO definitions to be updated
870     * @return the number of nodes updated, or -1 for failure
871     * @hide
872     */
873    public int modifyPasspointManagementObject(String fqdn,
874                                               List<PasspointManagementObjectDefinition> mos) {
875        try {
876            return mService.modifyPasspointManagementObject(fqdn, mos);
877        } catch (RemoteException e) {
878            throw e.rethrowFromSystemServer();
879        }
880    }
881
882    /**
883     * Query for a Hotspot 2.0 release 2 OSU icon
884     * @param bssid The BSSID of the AP
885     * @param fileName Icon file name
886     * @hide
887     */
888    public void queryPasspointIcon(long bssid, String fileName) {
889        try {
890            mService.queryPasspointIcon(bssid, fileName);
891        } catch (RemoteException e) {
892            throw e.rethrowFromSystemServer();
893        }
894    }
895
896    /**
897     * Match the currently associated network against the SP matching the given FQDN
898     * @param fqdn FQDN of the SP
899     * @return ordinal [HomeProvider, RoamingProvider, Incomplete, None, Declined]
900     * @hide
901     */
902    public int matchProviderWithCurrentNetwork(String fqdn) {
903        try {
904            return mService.matchProviderWithCurrentNetwork(fqdn);
905        } catch (RemoteException e) {
906            throw e.rethrowFromSystemServer();
907        }
908    }
909
910    /**
911     * Deauthenticate and set the re-authentication hold off time for the current network
912     * @param holdoff hold off time in milliseconds
913     * @param ess set if the hold off pertains to an ESS rather than a BSS
914     * @hide
915     */
916    public void deauthenticateNetwork(long holdoff, boolean ess) {
917        try {
918            mService.deauthenticateNetwork(holdoff, ess);
919        } catch (RemoteException e) {
920            throw e.rethrowFromSystemServer();
921        }
922    }
923
924    /**
925     * Remove the specified network from the list of configured networks.
926     * This may result in the asynchronous delivery of state change
927     * events.
928     * @param netId the integer that identifies the network configuration
929     * to the supplicant
930     * @return {@code true} if the operation succeeded
931     */
932    public boolean removeNetwork(int netId) {
933        try {
934            return mService.removeNetwork(netId);
935        } catch (RemoteException e) {
936            throw e.rethrowFromSystemServer();
937        }
938    }
939
940    /**
941     * Allow a previously configured network to be associated with. If
942     * <code>disableOthers</code> is true, then all other configured
943     * networks are disabled, and an attempt to connect to the selected
944     * network is initiated. This may result in the asynchronous delivery
945     * of state change events.
946     * <p>
947     * <b>Note:</b> If an application's target SDK version is
948     * {@link android.os.Build.VERSION_CODES#LOLLIPOP} or newer, network
949     * communication may not use Wi-Fi even if Wi-Fi is connected; traffic may
950     * instead be sent through another network, such as cellular data,
951     * Bluetooth tethering, or Ethernet. For example, traffic will never use a
952     * Wi-Fi network that does not provide Internet access (e.g. a wireless
953     * printer), if another network that does offer Internet access (e.g.
954     * cellular data) is available. Applications that need to ensure that their
955     * network traffic uses Wi-Fi should use APIs such as
956     * {@link Network#bindSocket(java.net.Socket)},
957     * {@link Network#openConnection(java.net.URL)}, or
958     * {@link ConnectivityManager#bindProcessToNetwork} to do so.
959     *
960     * @param netId the ID of the network in the list of configured networks
961     * @param disableOthers if true, disable all other networks. The way to
962     * select a particular network to connect to is specify {@code true}
963     * for this parameter.
964     * @return {@code true} if the operation succeeded
965     */
966    public boolean enableNetwork(int netId, boolean disableOthers) {
967        final boolean pin = disableOthers && mTargetSdkVersion < Build.VERSION_CODES.LOLLIPOP;
968        if (pin) {
969            NetworkRequest request = new NetworkRequest.Builder()
970                    .clearCapabilities()
971                    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
972                    .build();
973            NetworkPinner.pin(mContext, request);
974        }
975
976        boolean success;
977        try {
978            success = mService.enableNetwork(netId, disableOthers);
979        } catch (RemoteException e) {
980            throw e.rethrowFromSystemServer();
981        }
982
983        if (pin && !success) {
984            NetworkPinner.unpin();
985        }
986
987        return success;
988    }
989
990    /**
991     * Disable a configured network. The specified network will not be
992     * a candidate for associating. This may result in the asynchronous
993     * delivery of state change events.
994     * @param netId the ID of the network as returned by {@link #addNetwork}.
995     * @return {@code true} if the operation succeeded
996     */
997    public boolean disableNetwork(int netId) {
998        try {
999            return mService.disableNetwork(netId);
1000        } catch (RemoteException e) {
1001            throw e.rethrowFromSystemServer();
1002        }
1003    }
1004
1005    /**
1006     * Disassociate from the currently active access point. This may result
1007     * in the asynchronous delivery of state change events.
1008     * @return {@code true} if the operation succeeded
1009     */
1010    public boolean disconnect() {
1011        try {
1012            mService.disconnect();
1013            return true;
1014        } catch (RemoteException e) {
1015            throw e.rethrowFromSystemServer();
1016        }
1017    }
1018
1019    /**
1020     * Reconnect to the currently active access point, if we are currently
1021     * disconnected. This may result in the asynchronous delivery of state
1022     * change events.
1023     * @return {@code true} if the operation succeeded
1024     */
1025    public boolean reconnect() {
1026        try {
1027            mService.reconnect();
1028            return true;
1029        } catch (RemoteException e) {
1030            throw e.rethrowFromSystemServer();
1031        }
1032    }
1033
1034    /**
1035     * Reconnect to the currently active access point, even if we are already
1036     * connected. This may result in the asynchronous delivery of state
1037     * change events.
1038     * @return {@code true} if the operation succeeded
1039     */
1040    public boolean reassociate() {
1041        try {
1042            mService.reassociate();
1043            return true;
1044        } catch (RemoteException e) {
1045            throw e.rethrowFromSystemServer();
1046        }
1047    }
1048
1049    /**
1050     * Check that the supplicant daemon is responding to requests.
1051     * @return {@code true} if we were able to communicate with the supplicant and
1052     * it returned the expected response to the PING message.
1053     */
1054    public boolean pingSupplicant() {
1055        if (mService == null)
1056            return false;
1057        try {
1058            return mService.pingSupplicant();
1059        } catch (RemoteException e) {
1060            throw e.rethrowFromSystemServer();
1061        }
1062    }
1063
1064    /* Keep this list in sync with wifi_hal.h */
1065    /** @hide */
1066    public static final int WIFI_FEATURE_INFRA            = 0x0001;  // Basic infrastructure mode
1067    /** @hide */
1068    public static final int WIFI_FEATURE_INFRA_5G         = 0x0002;  // Support for 5 GHz Band
1069    /** @hide */
1070    public static final int WIFI_FEATURE_PASSPOINT        = 0x0004;  // Support for GAS/ANQP
1071    /** @hide */
1072    public static final int WIFI_FEATURE_P2P              = 0x0008;  // Wifi-Direct
1073    /** @hide */
1074    public static final int WIFI_FEATURE_MOBILE_HOTSPOT   = 0x0010;  // Soft AP
1075    /** @hide */
1076    public static final int WIFI_FEATURE_SCANNER          = 0x0020;  // WifiScanner APIs
1077    /** @hide */
1078    public static final int WIFI_FEATURE_NAN              = 0x0040;  // Neighbor Awareness Networking
1079    /** @hide */
1080    public static final int WIFI_FEATURE_D2D_RTT          = 0x0080;  // Device-to-device RTT
1081    /** @hide */
1082    public static final int WIFI_FEATURE_D2AP_RTT         = 0x0100;  // Device-to-AP RTT
1083    /** @hide */
1084    public static final int WIFI_FEATURE_BATCH_SCAN       = 0x0200;  // Batched Scan (deprecated)
1085    /** @hide */
1086    public static final int WIFI_FEATURE_PNO              = 0x0400;  // Preferred network offload
1087    /** @hide */
1088    public static final int WIFI_FEATURE_ADDITIONAL_STA   = 0x0800;  // Support for two STAs
1089    /** @hide */
1090    public static final int WIFI_FEATURE_TDLS             = 0x1000;  // Tunnel directed link setup
1091    /** @hide */
1092    public static final int WIFI_FEATURE_TDLS_OFFCHANNEL  = 0x2000;  // Support for TDLS off channel
1093    /** @hide */
1094    public static final int WIFI_FEATURE_EPR              = 0x4000;  // Enhanced power reporting
1095    /** @hide */
1096    public static final int WIFI_FEATURE_AP_STA            = 0x8000;  // Support for AP STA Concurrency
1097    /** @hide */
1098    public static final int WIFI_FEATURE_LINK_LAYER_STATS  = 0x10000; // Link layer stats collection
1099    /** @hide */
1100    public static final int WIFI_FEATURE_LOGGER            = 0x20000; // WiFi Logger
1101    /** @hide */
1102    public static final int WIFI_FEATURE_HAL_EPNO          = 0x40000; // WiFi PNO enhanced
1103
1104    private int getSupportedFeatures() {
1105        try {
1106            return mService.getSupportedFeatures();
1107        } catch (RemoteException e) {
1108            throw e.rethrowFromSystemServer();
1109        }
1110    }
1111
1112    private boolean isFeatureSupported(int feature) {
1113        return (getSupportedFeatures() & feature) == feature;
1114    }
1115    /**
1116     * @return true if this adapter supports 5 GHz band
1117     */
1118    public boolean is5GHzBandSupported() {
1119        return isFeatureSupported(WIFI_FEATURE_INFRA_5G);
1120    }
1121
1122    /**
1123     * @return true if this adapter supports passpoint
1124     * @hide
1125     */
1126    public boolean isPasspointSupported() {
1127        return isFeatureSupported(WIFI_FEATURE_PASSPOINT);
1128    }
1129
1130    /**
1131     * @return true if this adapter supports WifiP2pManager (Wi-Fi Direct)
1132     */
1133    public boolean isP2pSupported() {
1134        return isFeatureSupported(WIFI_FEATURE_P2P);
1135    }
1136
1137    /**
1138     * @return true if this adapter supports portable Wi-Fi hotspot
1139     * @hide
1140     */
1141    @SystemApi
1142    public boolean isPortableHotspotSupported() {
1143        return isFeatureSupported(WIFI_FEATURE_MOBILE_HOTSPOT);
1144    }
1145
1146    /**
1147     * @return true if this adapter supports WifiScanner APIs
1148     * @hide
1149     */
1150    @SystemApi
1151    public boolean isWifiScannerSupported() {
1152        return isFeatureSupported(WIFI_FEATURE_SCANNER);
1153    }
1154
1155    /**
1156     * @return true if this adapter supports Neighbour Awareness Network APIs
1157     * @hide PROPOSED_NAN_API
1158     */
1159    public boolean isNanSupported() {
1160        return isFeatureSupported(WIFI_FEATURE_NAN);
1161    }
1162
1163    /**
1164     * @return true if this adapter supports Device-to-device RTT
1165     * @hide
1166     */
1167    @SystemApi
1168    public boolean isDeviceToDeviceRttSupported() {
1169        return isFeatureSupported(WIFI_FEATURE_D2D_RTT);
1170    }
1171
1172    /**
1173     * @return true if this adapter supports Device-to-AP RTT
1174     */
1175    @SystemApi
1176    public boolean isDeviceToApRttSupported() {
1177        return isFeatureSupported(WIFI_FEATURE_D2AP_RTT);
1178    }
1179
1180    /**
1181     * @return true if this adapter supports offloaded connectivity scan
1182     */
1183    public boolean isPreferredNetworkOffloadSupported() {
1184        return isFeatureSupported(WIFI_FEATURE_PNO);
1185    }
1186
1187    /**
1188     * @return true if this adapter supports multiple simultaneous connections
1189     * @hide
1190     */
1191    public boolean isAdditionalStaSupported() {
1192        return isFeatureSupported(WIFI_FEATURE_ADDITIONAL_STA);
1193    }
1194
1195    /**
1196     * @return true if this adapter supports Tunnel Directed Link Setup
1197     */
1198    public boolean isTdlsSupported() {
1199        return isFeatureSupported(WIFI_FEATURE_TDLS);
1200    }
1201
1202    /**
1203     * @return true if this adapter supports Off Channel Tunnel Directed Link Setup
1204     * @hide
1205     */
1206    public boolean isOffChannelTdlsSupported() {
1207        return isFeatureSupported(WIFI_FEATURE_TDLS_OFFCHANNEL);
1208    }
1209
1210    /**
1211     * @return true if this adapter supports advanced power/performance counters
1212     */
1213    public boolean isEnhancedPowerReportingSupported() {
1214        return isFeatureSupported(WIFI_FEATURE_LINK_LAYER_STATS);
1215    }
1216
1217    /**
1218     * Return the record of {@link WifiActivityEnergyInfo} object that
1219     * has the activity and energy info. This can be used to ascertain what
1220     * the controller has been up to, since the last sample.
1221     * @param updateType Type of info, cached vs refreshed.
1222     *
1223     * @return a record with {@link WifiActivityEnergyInfo} or null if
1224     * report is unavailable or unsupported
1225     * @hide
1226     */
1227    public WifiActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
1228        if (mService == null) return null;
1229        try {
1230            synchronized(this) {
1231                return mService.reportActivityInfo();
1232            }
1233        } catch (RemoteException e) {
1234            throw e.rethrowFromSystemServer();
1235        }
1236    }
1237
1238    /**
1239     * Request a scan for access points. Returns immediately. The availability
1240     * of the results is made known later by means of an asynchronous event sent
1241     * on completion of the scan.
1242     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
1243     */
1244    public boolean startScan() {
1245        try {
1246            mService.startScan(null, null);
1247            return true;
1248        } catch (RemoteException e) {
1249            throw e.rethrowFromSystemServer();
1250        }
1251    }
1252
1253    /** @hide */
1254    @SystemApi
1255    public boolean startScan(WorkSource workSource) {
1256        try {
1257            mService.startScan(null, workSource);
1258            return true;
1259        } catch (RemoteException e) {
1260            throw e.rethrowFromSystemServer();
1261        }
1262    }
1263
1264    /**
1265     * startLocationRestrictedScan()
1266     * Trigger a scan which will not make use of DFS channels and is thus not suitable for
1267     * establishing wifi connection.
1268     * @deprecated This API is nolonger supported.
1269     * Use {@link android.net.wifi.WifiScanner} API
1270     * @hide
1271     */
1272    @Deprecated
1273    @SystemApi
1274    public boolean startLocationRestrictedScan(WorkSource workSource) {
1275        return false;
1276    }
1277
1278    /**
1279     * Check if the Batched Scan feature is supported.
1280     *
1281     * @return false if not supported.
1282     * @deprecated This API is nolonger supported.
1283     * Use {@link android.net.wifi.WifiScanner} API
1284     * @hide
1285     */
1286    @Deprecated
1287    @SystemApi
1288    public boolean isBatchedScanSupported() {
1289        return false;
1290    }
1291
1292    /**
1293     * Retrieve the latest batched scan result.  This should be called immediately after
1294     * {@link BATCHED_SCAN_RESULTS_AVAILABLE_ACTION} is received.
1295     * @deprecated This API is nolonger supported.
1296     * Use {@link android.net.wifi.WifiScanner} API
1297     * @hide
1298     */
1299    @Deprecated
1300    @SystemApi
1301    public List<BatchedScanResult> getBatchedScanResults() {
1302        return null;
1303    }
1304
1305    /**
1306     * Creates a configuration token describing the network referenced by {@code netId}
1307     * of MIME type application/vnd.wfa.wsc. Can be used to configure WiFi networks via NFC.
1308     *
1309     * @return hex-string encoded configuration token
1310     * @hide
1311     */
1312    public String getWpsNfcConfigurationToken(int netId) {
1313        try {
1314            return mService.getWpsNfcConfigurationToken(netId);
1315        } catch (RemoteException e) {
1316            throw e.rethrowFromSystemServer();
1317        }
1318    }
1319
1320    /**
1321     * Return dynamic information about the current Wi-Fi connection, if any is active.
1322     * @return the Wi-Fi information, contained in {@link WifiInfo}.
1323     */
1324    public WifiInfo getConnectionInfo() {
1325        try {
1326            return mService.getConnectionInfo();
1327        } catch (RemoteException e) {
1328            throw e.rethrowFromSystemServer();
1329        }
1330    }
1331
1332    /**
1333     * Return the results of the latest access point scan.
1334     * @return the list of access points found in the most recent scan. An app must hold
1335     * {@link android.Manifest.permission#ACCESS_COARSE_LOCATION ACCESS_COARSE_LOCATION} or
1336     * {@link android.Manifest.permission#ACCESS_FINE_LOCATION ACCESS_FINE_LOCATION} permission
1337     * in order to get valid results.  If there is a remote exception (e.g., either a communication
1338     * problem with the system service or an exception within the framework) an empty list will be
1339     * returned.
1340     */
1341    public List<ScanResult> getScanResults() {
1342        try {
1343            return mService.getScanResults(mContext.getOpPackageName());
1344        } catch (RemoteException e) {
1345            throw e.rethrowFromSystemServer();
1346        }
1347    }
1348
1349    /**
1350     * Check if scanning is always available.
1351     *
1352     * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results
1353     * even when Wi-Fi is turned off.
1354     *
1355     * To change this setting, see {@link #ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE}.
1356     */
1357    public boolean isScanAlwaysAvailable() {
1358        try {
1359            return mService.isScanAlwaysAvailable();
1360        } catch (RemoteException e) {
1361            throw e.rethrowFromSystemServer();
1362        }
1363    }
1364
1365    /**
1366     * Tell the supplicant to persist the current list of configured networks.
1367     * <p>
1368     * Note: It is possible for this method to change the network IDs of
1369     * existing networks. You should assume the network IDs can be different
1370     * after calling this method.
1371     *
1372     * @return {@code true} if the operation succeeded
1373     */
1374    public boolean saveConfiguration() {
1375        try {
1376            return mService.saveConfiguration();
1377        } catch (RemoteException e) {
1378            throw e.rethrowFromSystemServer();
1379        }
1380    }
1381
1382    /**
1383     * Set the country code.
1384     * @param countryCode country code in ISO 3166 format.
1385     * @param persist {@code true} if this needs to be remembered
1386     *
1387     * @hide
1388     */
1389    public void setCountryCode(String country, boolean persist) {
1390        try {
1391            mService.setCountryCode(country, persist);
1392        } catch (RemoteException e) {
1393            throw e.rethrowFromSystemServer();
1394        }
1395    }
1396
1397    /**
1398    * get the country code.
1399    * @return the country code in ISO 3166 format.
1400    *
1401    * @hide
1402    */
1403    public String getCountryCode() {
1404       try {
1405           String country = mService.getCountryCode();
1406           return country;
1407       } catch (RemoteException e) {
1408           throw e.rethrowFromSystemServer();
1409       }
1410    }
1411
1412    /**
1413     * Set the operational frequency band.
1414     * @param band  One of
1415     *     {@link #WIFI_FREQUENCY_BAND_AUTO},
1416     *     {@link #WIFI_FREQUENCY_BAND_5GHZ},
1417     *     {@link #WIFI_FREQUENCY_BAND_2GHZ},
1418     * @param persist {@code true} if this needs to be remembered
1419     * @hide
1420     */
1421    public void setFrequencyBand(int band, boolean persist) {
1422        try {
1423            mService.setFrequencyBand(band, persist);
1424        } catch (RemoteException e) {
1425            throw e.rethrowFromSystemServer();
1426        }
1427    }
1428
1429    /**
1430     * Get the operational frequency band.
1431     * @return One of
1432     *     {@link #WIFI_FREQUENCY_BAND_AUTO},
1433     *     {@link #WIFI_FREQUENCY_BAND_5GHZ},
1434     *     {@link #WIFI_FREQUENCY_BAND_2GHZ} or
1435     *     {@code -1} on failure.
1436     * @hide
1437     */
1438    public int getFrequencyBand() {
1439        try {
1440            return mService.getFrequencyBand();
1441        } catch (RemoteException e) {
1442            throw e.rethrowFromSystemServer();
1443        }
1444    }
1445
1446    /**
1447     * Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz)
1448     * @return {@code true} if supported, {@code false} otherwise.
1449     * @hide
1450     */
1451    public boolean isDualBandSupported() {
1452        try {
1453            return mService.isDualBandSupported();
1454        } catch (RemoteException e) {
1455            throw e.rethrowFromSystemServer();
1456        }
1457    }
1458
1459    /**
1460     * Return the DHCP-assigned addresses from the last successful DHCP request,
1461     * if any.
1462     * @return the DHCP information
1463     */
1464    public DhcpInfo getDhcpInfo() {
1465        try {
1466            return mService.getDhcpInfo();
1467        } catch (RemoteException e) {
1468            throw e.rethrowFromSystemServer();
1469        }
1470    }
1471
1472    /**
1473     * Enable or disable Wi-Fi.
1474     * @param enabled {@code true} to enable, {@code false} to disable.
1475     * @return {@code true} if the operation succeeds (or if the existing state
1476     *         is the same as the requested state).
1477     */
1478    public boolean setWifiEnabled(boolean enabled) {
1479        try {
1480            return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
1481        } catch (RemoteException e) {
1482            throw e.rethrowFromSystemServer();
1483        }
1484    }
1485
1486    /**
1487     * Gets the Wi-Fi enabled state.
1488     * @return One of {@link #WIFI_STATE_DISABLED},
1489     *         {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
1490     *         {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
1491     * @see #isWifiEnabled()
1492     */
1493    public int getWifiState() {
1494        try {
1495            return mService.getWifiEnabledState();
1496        } catch (RemoteException e) {
1497            throw e.rethrowFromSystemServer();
1498        }
1499    }
1500
1501    /**
1502     * Return whether Wi-Fi is enabled or disabled.
1503     * @return {@code true} if Wi-Fi is enabled
1504     * @see #getWifiState()
1505     */
1506    public boolean isWifiEnabled() {
1507        return getWifiState() == WIFI_STATE_ENABLED;
1508    }
1509
1510    /**
1511     * Return TX packet counter, for CTS test of WiFi watchdog.
1512     * @param listener is the interface to receive result
1513     *
1514     * @hide for CTS test only
1515     */
1516    public void getTxPacketCount(TxPacketCountListener listener) {
1517        getChannel().sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
1518    }
1519
1520    /**
1521     * Calculates the level of the signal. This should be used any time a signal
1522     * is being shown.
1523     *
1524     * @param rssi The power of the signal measured in RSSI.
1525     * @param numLevels The number of levels to consider in the calculated
1526     *            level.
1527     * @return A level of the signal, given in the range of 0 to numLevels-1
1528     *         (both inclusive).
1529     */
1530    public static int calculateSignalLevel(int rssi, int numLevels) {
1531        if (rssi <= MIN_RSSI) {
1532            return 0;
1533        } else if (rssi >= MAX_RSSI) {
1534            return numLevels - 1;
1535        } else {
1536            float inputRange = (MAX_RSSI - MIN_RSSI);
1537            float outputRange = (numLevels - 1);
1538            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
1539        }
1540    }
1541
1542    /**
1543     * Compares two signal strengths.
1544     *
1545     * @param rssiA The power of the first signal measured in RSSI.
1546     * @param rssiB The power of the second signal measured in RSSI.
1547     * @return Returns <0 if the first signal is weaker than the second signal,
1548     *         0 if the two signals have the same strength, and >0 if the first
1549     *         signal is stronger than the second signal.
1550     */
1551    public static int compareSignalLevel(int rssiA, int rssiB) {
1552        return rssiA - rssiB;
1553    }
1554
1555    /**
1556     * Start AccessPoint mode with the specified
1557     * configuration. If the radio is already running in
1558     * AP mode, update the new configuration
1559     * Note that starting in access point mode disables station
1560     * mode operation
1561     * @param wifiConfig SSID, security and channel details as
1562     *        part of WifiConfiguration
1563     * @return {@code true} if the operation succeeds, {@code false} otherwise
1564     *
1565     * @hide
1566     */
1567    @SystemApi
1568    public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
1569        try {
1570            mService.setWifiApEnabled(wifiConfig, enabled);
1571            return true;
1572        } catch (RemoteException e) {
1573            throw e.rethrowFromSystemServer();
1574        }
1575    }
1576
1577    /**
1578     * Gets the Wi-Fi enabled state.
1579     * @return One of {@link #WIFI_AP_STATE_DISABLED},
1580     *         {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
1581     *         {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
1582     * @see #isWifiApEnabled()
1583     *
1584     * @hide
1585     */
1586    @SystemApi
1587    public int getWifiApState() {
1588        try {
1589            return mService.getWifiApEnabledState();
1590        } catch (RemoteException e) {
1591            throw e.rethrowFromSystemServer();
1592        }
1593    }
1594
1595    /**
1596     * Return whether Wi-Fi AP is enabled or disabled.
1597     * @return {@code true} if Wi-Fi AP is enabled
1598     * @see #getWifiApState()
1599     *
1600     * @hide
1601     */
1602    @SystemApi
1603    public boolean isWifiApEnabled() {
1604        return getWifiApState() == WIFI_AP_STATE_ENABLED;
1605    }
1606
1607    /**
1608     * Gets the Wi-Fi AP Configuration.
1609     * @return AP details in WifiConfiguration
1610     *
1611     * @hide
1612     */
1613    @SystemApi
1614    public WifiConfiguration getWifiApConfiguration() {
1615        try {
1616            return mService.getWifiApConfiguration();
1617        } catch (RemoteException e) {
1618            throw e.rethrowFromSystemServer();
1619        }
1620    }
1621
1622    /**
1623     * Builds a WifiConfiguration from Hotspot 2.0 MIME file.
1624     * @return AP details in WifiConfiguration
1625     *
1626     * @hide Dont open yet
1627     */
1628    public WifiConfiguration buildWifiConfig(String uriString, String mimeType, byte[] data) {
1629        try {
1630            return mService.buildWifiConfig(uriString, mimeType, data);
1631        } catch (RemoteException e) {
1632            throw e.rethrowFromSystemServer();
1633        }
1634    }
1635
1636    /**
1637     * Sets the Wi-Fi AP Configuration.
1638     * @return {@code true} if the operation succeeded, {@code false} otherwise
1639     *
1640     * @hide
1641     */
1642    @SystemApi
1643    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
1644        try {
1645            mService.setWifiApConfiguration(wifiConfig);
1646            return true;
1647        } catch (RemoteException e) {
1648            throw e.rethrowFromSystemServer();
1649        }
1650    }
1651
1652    /**
1653     * Add a bssid to the supplicant blacklist
1654     *
1655     * This API is used by WifiWatchdogService
1656     *
1657     * @return {@code true} if the operation succeeds else {@code false}
1658     * @hide
1659     */
1660    public boolean addToBlacklist(String bssid) {
1661        try {
1662            mService.addToBlacklist(bssid);
1663            return true;
1664        } catch (RemoteException e) {
1665            throw e.rethrowFromSystemServer();
1666        }
1667    }
1668
1669    /**
1670     * Clear the supplicant blacklist
1671     *
1672     * This API is used by WifiWatchdogService
1673     *
1674     * @return {@code true} if the operation succeeds else {@code false}
1675     * @hide
1676     */
1677    public boolean clearBlacklist() {
1678        try {
1679            mService.clearBlacklist();
1680            return true;
1681        } catch (RemoteException e) {
1682            throw e.rethrowFromSystemServer();
1683        }
1684    }
1685
1686
1687    /**
1688     * Enable/Disable TDLS on a specific local route.
1689     *
1690     * <p>
1691     * TDLS enables two wireless endpoints to talk to each other directly
1692     * without going through the access point that is managing the local
1693     * network. It saves bandwidth and improves quality of the link.
1694     * </p>
1695     * <p>
1696     * This API enables/disables the option of using TDLS. If enabled, the
1697     * underlying hardware is free to use TDLS or a hop through the access
1698     * point. If disabled, existing TDLS session is torn down and
1699     * hardware is restricted to use access point for transferring wireless
1700     * packets. Default value for all routes is 'disabled', meaning restricted
1701     * to use access point for transferring packets.
1702     * </p>
1703     *
1704     * @param remoteIPAddress IP address of the endpoint to setup TDLS with
1705     * @param enable true = setup and false = tear down TDLS
1706     */
1707    public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) {
1708        try {
1709            mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
1710        } catch (RemoteException e) {
1711            throw e.rethrowFromSystemServer();
1712        }
1713    }
1714
1715    /**
1716     * Similar to {@link #setTdlsEnabled(InetAddress, boolean) }, except
1717     * this version allows you to specify remote endpoint with a MAC address.
1718     * @param remoteMacAddress MAC address of the remote endpoint such as 00:00:0c:9f:f2:ab
1719     * @param enable true = setup and false = tear down TDLS
1720     */
1721    public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) {
1722        try {
1723            mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
1724        } catch (RemoteException e) {
1725            throw e.rethrowFromSystemServer();
1726        }
1727    }
1728
1729    /* TODO: deprecate synchronous API and open up the following API */
1730
1731    private static final int BASE = Protocol.BASE_WIFI_MANAGER;
1732
1733    /* Commands to WifiService */
1734    /** @hide */
1735    public static final int CONNECT_NETWORK                 = BASE + 1;
1736    /** @hide */
1737    public static final int CONNECT_NETWORK_FAILED          = BASE + 2;
1738    /** @hide */
1739    public static final int CONNECT_NETWORK_SUCCEEDED       = BASE + 3;
1740
1741    /** @hide */
1742    public static final int FORGET_NETWORK                  = BASE + 4;
1743    /** @hide */
1744    public static final int FORGET_NETWORK_FAILED           = BASE + 5;
1745    /** @hide */
1746    public static final int FORGET_NETWORK_SUCCEEDED        = BASE + 6;
1747
1748    /** @hide */
1749    public static final int SAVE_NETWORK                    = BASE + 7;
1750    /** @hide */
1751    public static final int SAVE_NETWORK_FAILED             = BASE + 8;
1752    /** @hide */
1753    public static final int SAVE_NETWORK_SUCCEEDED          = BASE + 9;
1754
1755    /** @hide */
1756    public static final int START_WPS                       = BASE + 10;
1757    /** @hide */
1758    public static final int START_WPS_SUCCEEDED             = BASE + 11;
1759    /** @hide */
1760    public static final int WPS_FAILED                      = BASE + 12;
1761    /** @hide */
1762    public static final int WPS_COMPLETED                   = BASE + 13;
1763
1764    /** @hide */
1765    public static final int CANCEL_WPS                      = BASE + 14;
1766    /** @hide */
1767    public static final int CANCEL_WPS_FAILED               = BASE + 15;
1768    /** @hide */
1769    public static final int CANCEL_WPS_SUCCEDED             = BASE + 16;
1770
1771    /** @hide */
1772    public static final int DISABLE_NETWORK                 = BASE + 17;
1773    /** @hide */
1774    public static final int DISABLE_NETWORK_FAILED          = BASE + 18;
1775    /** @hide */
1776    public static final int DISABLE_NETWORK_SUCCEEDED       = BASE + 19;
1777
1778    /** @hide */
1779    public static final int RSSI_PKTCNT_FETCH               = BASE + 20;
1780    /** @hide */
1781    public static final int RSSI_PKTCNT_FETCH_SUCCEEDED     = BASE + 21;
1782    /** @hide */
1783    public static final int RSSI_PKTCNT_FETCH_FAILED        = BASE + 22;
1784
1785    /**
1786     * Passed with {@link ActionListener#onFailure}.
1787     * Indicates that the operation failed due to an internal error.
1788     * @hide
1789     */
1790    public static final int ERROR                       = 0;
1791
1792    /**
1793     * Passed with {@link ActionListener#onFailure}.
1794     * Indicates that the operation is already in progress
1795     * @hide
1796     */
1797    public static final int IN_PROGRESS                 = 1;
1798
1799    /**
1800     * Passed with {@link ActionListener#onFailure}.
1801     * Indicates that the operation failed because the framework is busy and
1802     * unable to service the request
1803     * @hide
1804     */
1805    public static final int BUSY                        = 2;
1806
1807    /* WPS specific errors */
1808    /** WPS overlap detected */
1809    public static final int WPS_OVERLAP_ERROR           = 3;
1810    /** WEP on WPS is prohibited */
1811    public static final int WPS_WEP_PROHIBITED          = 4;
1812    /** TKIP only prohibited */
1813    public static final int WPS_TKIP_ONLY_PROHIBITED    = 5;
1814    /** Authentication failure on WPS */
1815    public static final int WPS_AUTH_FAILURE            = 6;
1816    /** WPS timed out */
1817    public static final int WPS_TIMED_OUT               = 7;
1818
1819    /**
1820     * Passed with {@link ActionListener#onFailure}.
1821     * Indicates that the operation failed due to invalid inputs
1822     * @hide
1823     */
1824    public static final int INVALID_ARGS                = 8;
1825
1826    /**
1827     * Passed with {@link ActionListener#onFailure}.
1828     * Indicates that the operation failed due to user permissions.
1829     * @hide
1830     */
1831    public static final int NOT_AUTHORIZED              = 9;
1832
1833    /**
1834     * Interface for callback invocation on an application action
1835     * @hide
1836     */
1837    public interface ActionListener {
1838        /** The operation succeeded */
1839        public void onSuccess();
1840        /**
1841         * The operation failed
1842         * @param reason The reason for failure could be one of
1843         * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY}
1844         */
1845        public void onFailure(int reason);
1846    }
1847
1848    /** Interface for callback invocation on a start WPS action */
1849    public static abstract class WpsCallback {
1850        /** WPS start succeeded */
1851        public abstract void onStarted(String pin);
1852
1853        /** WPS operation completed succesfully */
1854        public abstract void onSucceeded();
1855
1856        /**
1857         * WPS operation failed
1858         * @param reason The reason for failure could be one of
1859         * {@link #WPS_TKIP_ONLY_PROHIBITED}, {@link #WPS_OVERLAP_ERROR},
1860         * {@link #WPS_WEP_PROHIBITED}, {@link #WPS_TIMED_OUT} or {@link #WPS_AUTH_FAILURE}
1861         * and some generic errors.
1862         */
1863        public abstract void onFailed(int reason);
1864    }
1865
1866    /** Interface for callback invocation on a TX packet count poll action {@hide} */
1867    public interface TxPacketCountListener {
1868        /**
1869         * The operation succeeded
1870         * @param count TX packet counter
1871         */
1872        public void onSuccess(int count);
1873        /**
1874         * The operation failed
1875         * @param reason The reason for failure could be one of
1876         * {@link #ERROR}, {@link #IN_PROGRESS} or {@link #BUSY}
1877         */
1878        public void onFailure(int reason);
1879    }
1880
1881    // Ensure that multiple ServiceHandler threads do not interleave message dispatch.
1882    private static final Object sServiceHandlerDispatchLock = new Object();
1883
1884    private class ServiceHandler extends Handler {
1885        ServiceHandler(Looper looper) {
1886            super(looper);
1887        }
1888
1889        @Override
1890        public void handleMessage(Message message) {
1891            synchronized (sServiceHandlerDispatchLock) {
1892                dispatchMessageToListeners(message);
1893            }
1894        }
1895
1896        private void dispatchMessageToListeners(Message message) {
1897            Object listener = removeListener(message.arg2);
1898            switch (message.what) {
1899                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
1900                    if (message.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
1901                        mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
1902                    } else {
1903                        Log.e(TAG, "Failed to set up channel connection");
1904                        // This will cause all further async API calls on the WifiManager
1905                        // to fail and throw an exception
1906                        mAsyncChannel = null;
1907                    }
1908                    mConnected.countDown();
1909                    break;
1910                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
1911                    // Ignore
1912                    break;
1913                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
1914                    Log.e(TAG, "Channel connection lost");
1915                    // This will cause all further async API calls on the WifiManager
1916                    // to fail and throw an exception
1917                    mAsyncChannel = null;
1918                    getLooper().quit();
1919                    break;
1920                    /* ActionListeners grouped together */
1921                case WifiManager.CONNECT_NETWORK_FAILED:
1922                case WifiManager.FORGET_NETWORK_FAILED:
1923                case WifiManager.SAVE_NETWORK_FAILED:
1924                case WifiManager.DISABLE_NETWORK_FAILED:
1925                    if (listener != null) {
1926                        ((ActionListener) listener).onFailure(message.arg1);
1927                    }
1928                    break;
1929                    /* ActionListeners grouped together */
1930                case WifiManager.CONNECT_NETWORK_SUCCEEDED:
1931                case WifiManager.FORGET_NETWORK_SUCCEEDED:
1932                case WifiManager.SAVE_NETWORK_SUCCEEDED:
1933                case WifiManager.DISABLE_NETWORK_SUCCEEDED:
1934                    if (listener != null) {
1935                        ((ActionListener) listener).onSuccess();
1936                    }
1937                    break;
1938                case WifiManager.START_WPS_SUCCEEDED:
1939                    if (listener != null) {
1940                        WpsResult result = (WpsResult) message.obj;
1941                        ((WpsCallback) listener).onStarted(result.pin);
1942                        //Listener needs to stay until completion or failure
1943                        synchronized (mListenerMapLock) {
1944                            mListenerMap.put(message.arg2, listener);
1945                        }
1946                    }
1947                    break;
1948                case WifiManager.WPS_COMPLETED:
1949                    if (listener != null) {
1950                        ((WpsCallback) listener).onSucceeded();
1951                    }
1952                    break;
1953                case WifiManager.WPS_FAILED:
1954                    if (listener != null) {
1955                        ((WpsCallback) listener).onFailed(message.arg1);
1956                    }
1957                    break;
1958                case WifiManager.CANCEL_WPS_SUCCEDED:
1959                    if (listener != null) {
1960                        ((WpsCallback) listener).onSucceeded();
1961                    }
1962                    break;
1963                case WifiManager.CANCEL_WPS_FAILED:
1964                    if (listener != null) {
1965                        ((WpsCallback) listener).onFailed(message.arg1);
1966                    }
1967                    break;
1968                case WifiManager.RSSI_PKTCNT_FETCH_SUCCEEDED:
1969                    if (listener != null) {
1970                        RssiPacketCountInfo info = (RssiPacketCountInfo) message.obj;
1971                        if (info != null)
1972                            ((TxPacketCountListener) listener).onSuccess(info.txgood + info.txbad);
1973                        else
1974                            ((TxPacketCountListener) listener).onFailure(ERROR);
1975                    }
1976                    break;
1977                case WifiManager.RSSI_PKTCNT_FETCH_FAILED:
1978                    if (listener != null) {
1979                        ((TxPacketCountListener) listener).onFailure(message.arg1);
1980                    }
1981                    break;
1982                default:
1983                    //ignore
1984                    break;
1985            }
1986        }
1987    }
1988
1989    private int putListener(Object listener) {
1990        if (listener == null) return INVALID_KEY;
1991        int key;
1992        synchronized (mListenerMapLock) {
1993            do {
1994                key = mListenerKey++;
1995            } while (key == INVALID_KEY);
1996            mListenerMap.put(key, listener);
1997        }
1998        return key;
1999    }
2000
2001    private Object removeListener(int key) {
2002        if (key == INVALID_KEY) return null;
2003        synchronized (mListenerMapLock) {
2004            Object listener = mListenerMap.get(key);
2005            mListenerMap.remove(key);
2006            return listener;
2007        }
2008    }
2009
2010    private synchronized AsyncChannel getChannel() {
2011        if (mAsyncChannel == null) {
2012            Messenger messenger = getWifiServiceMessenger();
2013            if (messenger == null) {
2014                throw new IllegalStateException(
2015                        "getWifiServiceMessenger() returned null!  This is invalid.");
2016            }
2017
2018            mAsyncChannel = new AsyncChannel();
2019            mConnected = new CountDownLatch(1);
2020
2021            Handler handler = new ServiceHandler(mLooper);
2022            mAsyncChannel.connect(mContext, handler, messenger);
2023            try {
2024                mConnected.await();
2025            } catch (InterruptedException e) {
2026                Log.e(TAG, "interrupted wait at init");
2027            }
2028        }
2029        return mAsyncChannel;
2030    }
2031
2032    /**
2033     * Connect to a network with the given configuration. The network also
2034     * gets added to the supplicant configuration.
2035     *
2036     * For a new network, this function is used instead of a
2037     * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
2038     * reconnect()
2039     *
2040     * @param config the set of variables that describe the configuration,
2041     *            contained in a {@link WifiConfiguration} object.
2042     * @param listener for callbacks on success or failure. Can be null.
2043     * @throws IllegalStateException if the WifiManager instance needs to be
2044     * initialized again
2045     *
2046     * @hide
2047     */
2048    public void connect(WifiConfiguration config, ActionListener listener) {
2049        if (config == null) throw new IllegalArgumentException("config cannot be null");
2050        // Use INVALID_NETWORK_ID for arg1 when passing a config object
2051        // arg1 is used to pass network id when the network already exists
2052        getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
2053                putListener(listener), config);
2054    }
2055
2056    /**
2057     * Connect to a network with the given networkId.
2058     *
2059     * This function is used instead of a enableNetwork(), saveConfiguration() and
2060     * reconnect()
2061     *
2062     * @param networkId the network id identifiying the network in the
2063     *                supplicant configuration list
2064     * @param listener for callbacks on success or failure. Can be null.
2065     * @throws IllegalStateException if the WifiManager instance needs to be
2066     * initialized again
2067     * @hide
2068     */
2069    public void connect(int networkId, ActionListener listener) {
2070        if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
2071        getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
2072    }
2073
2074    /**
2075     * Save the given network in the supplicant config. If the network already
2076     * exists, the configuration is updated. A new network is enabled
2077     * by default.
2078     *
2079     * For a new network, this function is used instead of a
2080     * sequence of addNetwork(), enableNetwork() and saveConfiguration().
2081     *
2082     * For an existing network, it accomplishes the task of updateNetwork()
2083     * and saveConfiguration()
2084     *
2085     * @param config the set of variables that describe the configuration,
2086     *            contained in a {@link WifiConfiguration} object.
2087     * @param listener for callbacks on success or failure. Can be null.
2088     * @throws IllegalStateException if the WifiManager instance needs to be
2089     * initialized again
2090     * @hide
2091     */
2092    public void save(WifiConfiguration config, ActionListener listener) {
2093        if (config == null) throw new IllegalArgumentException("config cannot be null");
2094        getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
2095    }
2096
2097    /**
2098     * Delete the network in the supplicant config.
2099     *
2100     * This function is used instead of a sequence of removeNetwork()
2101     * and saveConfiguration().
2102     *
2103     * @param config the set of variables that describe the configuration,
2104     *            contained in a {@link WifiConfiguration} object.
2105     * @param listener for callbacks on success or failure. Can be null.
2106     * @throws IllegalStateException if the WifiManager instance needs to be
2107     * initialized again
2108     * @hide
2109     */
2110    public void forget(int netId, ActionListener listener) {
2111        if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
2112        getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
2113    }
2114
2115    /**
2116     * Disable network
2117     *
2118     * @param netId is the network Id
2119     * @param listener for callbacks on success or failure. Can be null.
2120     * @throws IllegalStateException if the WifiManager instance needs to be
2121     * initialized again
2122     * @hide
2123     */
2124    public void disable(int netId, ActionListener listener) {
2125        if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
2126        getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
2127    }
2128
2129    /**
2130     * Disable ephemeral Network
2131     *
2132     * @param SSID, in the format of WifiConfiguration's SSID.
2133     * @hide
2134     */
2135    public void disableEphemeralNetwork(String SSID) {
2136        if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
2137        try {
2138            mService.disableEphemeralNetwork(SSID);
2139        } catch (RemoteException e) {
2140            throw e.rethrowFromSystemServer();
2141        }
2142    }
2143
2144    /**
2145     * Start Wi-fi Protected Setup
2146     *
2147     * @param config WPS configuration (does not support {@link WpsInfo#LABEL})
2148     * @param listener for callbacks on success or failure. Can be null.
2149     * @throws IllegalStateException if the WifiManager instance needs to be
2150     * initialized again
2151     */
2152    public void startWps(WpsInfo config, WpsCallback listener) {
2153        if (config == null) throw new IllegalArgumentException("config cannot be null");
2154        getChannel().sendMessage(START_WPS, 0, putListener(listener), config);
2155    }
2156
2157    /**
2158     * Cancel any ongoing Wi-fi Protected Setup
2159     *
2160     * @param listener for callbacks on success or failure. Can be null.
2161     * @throws IllegalStateException if the WifiManager instance needs to be
2162     * initialized again
2163     */
2164    public void cancelWps(WpsCallback listener) {
2165        getChannel().sendMessage(CANCEL_WPS, 0, putListener(listener));
2166    }
2167
2168    /**
2169     * Get a reference to WifiService handler. This is used by a client to establish
2170     * an AsyncChannel communication with WifiService
2171     *
2172     * @return Messenger pointing to the WifiService handler
2173     * @hide
2174     */
2175    public Messenger getWifiServiceMessenger() {
2176        try {
2177            return mService.getWifiServiceMessenger();
2178        } catch (RemoteException e) {
2179            throw e.rethrowFromSystemServer();
2180        }
2181    }
2182
2183
2184    /**
2185     * Returns the file in which IP and proxy configuration data is stored
2186     * @hide
2187     */
2188    public String getConfigFile() {
2189        try {
2190            return mService.getConfigFile();
2191        } catch (RemoteException e) {
2192            throw e.rethrowFromSystemServer();
2193        }
2194    }
2195
2196    /**
2197     * Allows an application to keep the Wi-Fi radio awake.
2198     * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
2199     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
2200     * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
2201     * WifiLocks are held in any application.
2202     * <p>
2203     * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
2204     * could function over a mobile network, if available.  A program that needs to download large
2205     * files should hold a WifiLock to ensure that the download will complete, but a program whose
2206     * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
2207     * affecting battery life.
2208     * <p>
2209     * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
2210     * Mode.  They simply keep the radio from turning off when Wi-Fi is already on but the device
2211     * is idle.
2212     * <p>
2213     * Any application using a WifiLock must request the {@code android.permission.WAKE_LOCK}
2214     * permission in an {@code <uses-permission>} element of the application's manifest.
2215     */
2216    public class WifiLock {
2217        private String mTag;
2218        private final IBinder mBinder;
2219        private int mRefCount;
2220        int mLockType;
2221        private boolean mRefCounted;
2222        private boolean mHeld;
2223        private WorkSource mWorkSource;
2224
2225        private WifiLock(int lockType, String tag) {
2226            mTag = tag;
2227            mLockType = lockType;
2228            mBinder = new Binder();
2229            mRefCount = 0;
2230            mRefCounted = true;
2231            mHeld = false;
2232        }
2233
2234        /**
2235         * Locks the Wi-Fi radio on until {@link #release} is called.
2236         *
2237         * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
2238         * reference count, and the radio will remain locked as long as the reference count is
2239         * above zero.
2240         *
2241         * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
2242         * the radio, but subsequent calls will be ignored.  Only one call to {@link #release}
2243         * will be required, regardless of the number of times that {@code acquire} is called.
2244         */
2245        public void acquire() {
2246            synchronized (mBinder) {
2247                if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
2248                    try {
2249                        mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
2250                        synchronized (WifiManager.this) {
2251                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
2252                                mService.releaseWifiLock(mBinder);
2253                                throw new UnsupportedOperationException(
2254                                            "Exceeded maximum number of wifi locks");
2255                            }
2256                            mActiveLockCount++;
2257                        }
2258                    } catch (RemoteException e) {
2259                        throw e.rethrowFromSystemServer();
2260                    }
2261                    mHeld = true;
2262                }
2263            }
2264        }
2265
2266        /**
2267         * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle.
2268         *
2269         * If this WifiLock is reference-counted, each call to {@code release} will decrement the
2270         * reference count, and the radio will be unlocked only when the reference count reaches
2271         * zero.  If the reference count goes below zero (that is, if {@code release} is called
2272         * a greater number of times than {@link #acquire}), an exception is thrown.
2273         *
2274         * If this WifiLock is not reference-counted, the first call to {@code release} (after
2275         * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent
2276         * calls will be ignored.
2277         */
2278        public void release() {
2279            synchronized (mBinder) {
2280                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
2281                    try {
2282                        mService.releaseWifiLock(mBinder);
2283                        synchronized (WifiManager.this) {
2284                            mActiveLockCount--;
2285                        }
2286                    } catch (RemoteException e) {
2287                        throw e.rethrowFromSystemServer();
2288                    }
2289                    mHeld = false;
2290                }
2291                if (mRefCount < 0) {
2292                    throw new RuntimeException("WifiLock under-locked " + mTag);
2293                }
2294            }
2295        }
2296
2297        /**
2298         * Controls whether this is a reference-counted or non-reference-counted WifiLock.
2299         *
2300         * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and
2301         * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire}
2302         * has been balanced with a call to {@link #release}.  Non-reference-counted WifiLocks
2303         * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the
2304         * radio whenever {@link #release} is called and it is locked.
2305         *
2306         * @param refCounted true if this WifiLock should keep a reference count
2307         */
2308        public void setReferenceCounted(boolean refCounted) {
2309            mRefCounted = refCounted;
2310        }
2311
2312        /**
2313         * Checks whether this WifiLock is currently held.
2314         *
2315         * @return true if this WifiLock is held, false otherwise
2316         */
2317        public boolean isHeld() {
2318            synchronized (mBinder) {
2319                return mHeld;
2320            }
2321        }
2322
2323        public void setWorkSource(WorkSource ws) {
2324            synchronized (mBinder) {
2325                if (ws != null && ws.size() == 0) {
2326                    ws = null;
2327                }
2328                boolean changed = true;
2329                if (ws == null) {
2330                    mWorkSource = null;
2331                } else {
2332                    ws.clearNames();
2333                    if (mWorkSource == null) {
2334                        changed = mWorkSource != null;
2335                        mWorkSource = new WorkSource(ws);
2336                    } else {
2337                        changed = mWorkSource.diff(ws);
2338                        if (changed) {
2339                            mWorkSource.set(ws);
2340                        }
2341                    }
2342                }
2343                if (changed && mHeld) {
2344                    try {
2345                        mService.updateWifiLockWorkSource(mBinder, mWorkSource);
2346                    } catch (RemoteException e) {
2347                        throw e.rethrowFromSystemServer();
2348                    }
2349                }
2350            }
2351        }
2352
2353        public String toString() {
2354            String s1, s2, s3;
2355            synchronized (mBinder) {
2356                s1 = Integer.toHexString(System.identityHashCode(this));
2357                s2 = mHeld ? "held; " : "";
2358                if (mRefCounted) {
2359                    s3 = "refcounted: refcount = " + mRefCount;
2360                } else {
2361                    s3 = "not refcounted";
2362                }
2363                return "WifiLock{ " + s1 + "; " + s2 + s3 + " }";
2364            }
2365        }
2366
2367        @Override
2368        protected void finalize() throws Throwable {
2369            super.finalize();
2370            synchronized (mBinder) {
2371                if (mHeld) {
2372                    try {
2373                        mService.releaseWifiLock(mBinder);
2374                        synchronized (WifiManager.this) {
2375                            mActiveLockCount--;
2376                        }
2377                    } catch (RemoteException e) {
2378                        throw e.rethrowFromSystemServer();
2379                    }
2380                }
2381            }
2382        }
2383    }
2384
2385    /**
2386     * Creates a new WifiLock.
2387     *
2388     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
2389     * {@link #WIFI_MODE_FULL_HIGH_PERF} and {@link #WIFI_MODE_SCAN_ONLY} for
2390     * descriptions of the types of Wi-Fi locks.
2391     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
2392     *            never shown to the user under normal conditions, but should be descriptive
2393     *            enough to identify your application and the specific WifiLock within it, if it
2394     *            holds multiple WifiLocks.
2395     *
2396     * @return a new, unacquired WifiLock with the given tag.
2397     *
2398     * @see WifiLock
2399     */
2400    public WifiLock createWifiLock(int lockType, String tag) {
2401        return new WifiLock(lockType, tag);
2402    }
2403
2404    /**
2405     * Creates a new WifiLock.
2406     *
2407     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
2408     *            never shown to the user under normal conditions, but should be descriptive
2409     *            enough to identify your application and the specific WifiLock within it, if it
2410     *            holds multiple WifiLocks.
2411     *
2412     * @return a new, unacquired WifiLock with the given tag.
2413     *
2414     * @see WifiLock
2415     */
2416    public WifiLock createWifiLock(String tag) {
2417        return new WifiLock(WIFI_MODE_FULL, tag);
2418    }
2419
2420
2421    /**
2422     * Create a new MulticastLock
2423     *
2424     * @param tag a tag for the MulticastLock to identify it in debugging
2425     *            messages.  This string is never shown to the user under
2426     *            normal conditions, but should be descriptive enough to
2427     *            identify your application and the specific MulticastLock
2428     *            within it, if it holds multiple MulticastLocks.
2429     *
2430     * @return a new, unacquired MulticastLock with the given tag.
2431     *
2432     * @see MulticastLock
2433     */
2434    public MulticastLock createMulticastLock(String tag) {
2435        return new MulticastLock(tag);
2436    }
2437
2438    /**
2439     * Allows an application to receive Wifi Multicast packets.
2440     * Normally the Wifi stack filters out packets not explicitly
2441     * addressed to this device.  Acquring a MulticastLock will
2442     * cause the stack to receive packets addressed to multicast
2443     * addresses.  Processing these extra packets can cause a noticable
2444     * battery drain and should be disabled when not needed.
2445     */
2446    public class MulticastLock {
2447        private String mTag;
2448        private final IBinder mBinder;
2449        private int mRefCount;
2450        private boolean mRefCounted;
2451        private boolean mHeld;
2452
2453        private MulticastLock(String tag) {
2454            mTag = tag;
2455            mBinder = new Binder();
2456            mRefCount = 0;
2457            mRefCounted = true;
2458            mHeld = false;
2459        }
2460
2461        /**
2462         * Locks Wifi Multicast on until {@link #release} is called.
2463         *
2464         * If this MulticastLock is reference-counted each call to
2465         * {@code acquire} will increment the reference count, and the
2466         * wifi interface will receive multicast packets as long as the
2467         * reference count is above zero.
2468         *
2469         * If this MulticastLock is not reference-counted, the first call to
2470         * {@code acquire} will turn on the multicast packets, but subsequent
2471         * calls will be ignored.  Only one call to {@link #release} will
2472         * be required, regardless of the number of times that {@code acquire}
2473         * is called.
2474         *
2475         * Note that other applications may also lock Wifi Multicast on.
2476         * Only they can relinquish their lock.
2477         *
2478         * Also note that applications cannot leave Multicast locked on.
2479         * When an app exits or crashes, any Multicast locks will be released.
2480         */
2481        public void acquire() {
2482            synchronized (mBinder) {
2483                if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
2484                    try {
2485                        mService.acquireMulticastLock(mBinder, mTag);
2486                        synchronized (WifiManager.this) {
2487                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
2488                                mService.releaseMulticastLock();
2489                                throw new UnsupportedOperationException(
2490                                        "Exceeded maximum number of wifi locks");
2491                            }
2492                            mActiveLockCount++;
2493                        }
2494                    } catch (RemoteException e) {
2495                        throw e.rethrowFromSystemServer();
2496                    }
2497                    mHeld = true;
2498                }
2499            }
2500        }
2501
2502        /**
2503         * Unlocks Wifi Multicast, restoring the filter of packets
2504         * not addressed specifically to this device and saving power.
2505         *
2506         * If this MulticastLock is reference-counted, each call to
2507         * {@code release} will decrement the reference count, and the
2508         * multicast packets will only stop being received when the reference
2509         * count reaches zero.  If the reference count goes below zero (that
2510         * is, if {@code release} is called a greater number of times than
2511         * {@link #acquire}), an exception is thrown.
2512         *
2513         * If this MulticastLock is not reference-counted, the first call to
2514         * {@code release} (after the radio was multicast locked using
2515         * {@link #acquire}) will unlock the multicast, and subsequent calls
2516         * will be ignored.
2517         *
2518         * Note that if any other Wifi Multicast Locks are still outstanding
2519         * this {@code release} call will not have an immediate effect.  Only
2520         * when all applications have released all their Multicast Locks will
2521         * the Multicast filter be turned back on.
2522         *
2523         * Also note that when an app exits or crashes all of its Multicast
2524         * Locks will be automatically released.
2525         */
2526        public void release() {
2527            synchronized (mBinder) {
2528                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
2529                    try {
2530                        mService.releaseMulticastLock();
2531                        synchronized (WifiManager.this) {
2532                            mActiveLockCount--;
2533                        }
2534                    } catch (RemoteException e) {
2535                        throw e.rethrowFromSystemServer();
2536                    }
2537                    mHeld = false;
2538                }
2539                if (mRefCount < 0) {
2540                    throw new RuntimeException("MulticastLock under-locked "
2541                            + mTag);
2542                }
2543            }
2544        }
2545
2546        /**
2547         * Controls whether this is a reference-counted or non-reference-
2548         * counted MulticastLock.
2549         *
2550         * Reference-counted MulticastLocks keep track of the number of calls
2551         * to {@link #acquire} and {@link #release}, and only stop the
2552         * reception of multicast packets when every call to {@link #acquire}
2553         * has been balanced with a call to {@link #release}.  Non-reference-
2554         * counted MulticastLocks allow the reception of multicast packets
2555         * whenever {@link #acquire} is called and stop accepting multicast
2556         * packets whenever {@link #release} is called.
2557         *
2558         * @param refCounted true if this MulticastLock should keep a reference
2559         * count
2560         */
2561        public void setReferenceCounted(boolean refCounted) {
2562            mRefCounted = refCounted;
2563        }
2564
2565        /**
2566         * Checks whether this MulticastLock is currently held.
2567         *
2568         * @return true if this MulticastLock is held, false otherwise
2569         */
2570        public boolean isHeld() {
2571            synchronized (mBinder) {
2572                return mHeld;
2573            }
2574        }
2575
2576        public String toString() {
2577            String s1, s2, s3;
2578            synchronized (mBinder) {
2579                s1 = Integer.toHexString(System.identityHashCode(this));
2580                s2 = mHeld ? "held; " : "";
2581                if (mRefCounted) {
2582                    s3 = "refcounted: refcount = " + mRefCount;
2583                } else {
2584                    s3 = "not refcounted";
2585                }
2586                return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }";
2587            }
2588        }
2589
2590        @Override
2591        protected void finalize() throws Throwable {
2592            super.finalize();
2593            setReferenceCounted(false);
2594            release();
2595        }
2596    }
2597
2598    /**
2599     * Check multicast filter status.
2600     *
2601     * @return true if multicast packets are allowed.
2602     *
2603     * @hide pending API council approval
2604     */
2605    public boolean isMulticastEnabled() {
2606        try {
2607            return mService.isMulticastEnabled();
2608        } catch (RemoteException e) {
2609            throw e.rethrowFromSystemServer();
2610        }
2611    }
2612
2613    /**
2614     * Initialize the multicast filtering to 'on'
2615     * @hide no intent to publish
2616     */
2617    public boolean initializeMulticastFiltering() {
2618        try {
2619            mService.initializeMulticastFiltering();
2620            return true;
2621        } catch (RemoteException e) {
2622            throw e.rethrowFromSystemServer();
2623        }
2624    }
2625
2626    protected void finalize() throws Throwable {
2627        try {
2628            if (mAsyncChannel != null) {
2629                mAsyncChannel.disconnect();
2630            }
2631        } finally {
2632            super.finalize();
2633        }
2634    }
2635
2636    /**
2637     * Set wifi verbose log. Called from developer settings.
2638     * @hide
2639     */
2640    public void enableVerboseLogging (int verbose) {
2641        try {
2642            mService.enableVerboseLogging(verbose);
2643        } catch (Exception e) {
2644            //ignore any failure here
2645            Log.e(TAG, "enableVerboseLogging " + e.toString());
2646        }
2647    }
2648
2649    /**
2650     * Get the WiFi verbose logging level.This is used by settings
2651     * to decide what to show within the picker.
2652     * @hide
2653     */
2654    public int getVerboseLoggingLevel() {
2655        try {
2656            return mService.getVerboseLoggingLevel();
2657        } catch (RemoteException e) {
2658            throw e.rethrowFromSystemServer();
2659        }
2660    }
2661
2662    /**
2663     * Set wifi Aggressive Handover. Called from developer settings.
2664     * @hide
2665     */
2666    public void enableAggressiveHandover(int enabled) {
2667        try {
2668            mService.enableAggressiveHandover(enabled);
2669        } catch (RemoteException e) {
2670            throw e.rethrowFromSystemServer();
2671        }
2672    }
2673
2674    /**
2675     * Get the WiFi Handover aggressiveness.This is used by settings
2676     * to decide what to show within the picker.
2677     * @hide
2678     */
2679    public int getAggressiveHandover() {
2680        try {
2681            return mService.getAggressiveHandover();
2682        } catch (RemoteException e) {
2683            throw e.rethrowFromSystemServer();
2684        }
2685    }
2686
2687    /**
2688     * Set setting for allowing Scans when traffic is ongoing.
2689     * @hide
2690     */
2691    public void setAllowScansWithTraffic(int enabled) {
2692        try {
2693            mService.setAllowScansWithTraffic(enabled);
2694        } catch (RemoteException e) {
2695            throw e.rethrowFromSystemServer();
2696        }
2697    }
2698
2699    /**
2700     * Get setting for allowing Scans when traffic is ongoing.
2701     * @hide
2702     */
2703    public int getAllowScansWithTraffic() {
2704        try {
2705            return mService.getAllowScansWithTraffic();
2706        } catch (RemoteException e) {
2707            throw e.rethrowFromSystemServer();
2708        }
2709    }
2710
2711    /**
2712     * Resets all wifi manager settings back to factory defaults.
2713     *
2714     * @hide
2715     */
2716    public void factoryReset() {
2717        try {
2718            mService.factoryReset();
2719        } catch (RemoteException e) {
2720            throw e.rethrowFromSystemServer();
2721        }
2722    }
2723
2724    /**
2725     * Get Network object of current wifi network
2726     * @return Get Network object of current wifi network
2727     * @hide
2728     */
2729    public Network getCurrentNetwork() {
2730        try {
2731            return mService.getCurrentNetwork();
2732        } catch (RemoteException e) {
2733            throw e.rethrowFromSystemServer();
2734        }
2735    }
2736
2737    /**
2738     * Framework layer autojoin enable/disable when device is associated
2739     * this will enable/disable autojoin scan and switch network when connected
2740     * @return true -- if set successful false -- if set failed
2741     * @hide
2742     */
2743    public boolean setEnableAutoJoinWhenAssociated(boolean enabled) {
2744        try {
2745            return mService.setEnableAutoJoinWhenAssociated(enabled);
2746        } catch (RemoteException e) {
2747            throw e.rethrowFromSystemServer();
2748        }
2749    }
2750
2751    /**
2752     * Get setting for Framework layer autojoin enable status
2753     * @hide
2754     */
2755    public boolean getEnableAutoJoinWhenAssociated() {
2756        try {
2757            return mService.getEnableAutoJoinWhenAssociated();
2758        } catch (RemoteException e) {
2759            throw e.rethrowFromSystemServer();
2760        }
2761    }
2762
2763    /**
2764     * Enable/disable WifiConnectivityManager
2765     * @hide
2766     */
2767    public void enableWifiConnectivityManager(boolean enabled) {
2768        try {
2769            mService.enableWifiConnectivityManager(enabled);
2770        } catch (RemoteException e) {
2771            throw e.rethrowFromSystemServer();
2772        }
2773    }
2774}
2775