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