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