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