WifiManager.java revision e746f03c6c8b8d0897d322ab524d545ace200fcd
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.net.wifi;
18
19import android.annotation.SdkConstant;
20import android.annotation.SdkConstant.SdkConstantType;
21import android.net.DhcpInfo;
22import android.os.Binder;
23import android.os.IBinder;
24import android.os.Handler;
25import android.os.RemoteException;
26import android.os.WorkSource;
27
28import java.util.List;
29
30/**
31 * This class provides the primary API for managing all aspects of Wi-Fi
32 * connectivity. Get an instance of this class by calling
33 * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
34
35 * It deals with several categories of items:
36 * <ul>
37 * <li>The list of configured networks. The list can be viewed and updated,
38 * and attributes of individual entries can be modified.</li>
39 * <li>The currently active Wi-Fi network, if any. Connectivity can be
40 * established or torn down, and dynamic information about the state of
41 * the network can be queried.</li>
42 * <li>Results of access point scans, containing enough information to
43 * make decisions about what access point to connect to.</li>
44 * <li>It defines the names of various Intent actions that are broadcast
45 * upon any sort of change in Wi-Fi state.
46 * </ul>
47 * This is the API to use when performing Wi-Fi specific operations. To
48 * perform operations that pertain to network connectivity at an abstract
49 * level, use {@link android.net.ConnectivityManager}.
50 */
51public class WifiManager {
52
53    // Supplicant error codes:
54    /**
55     * The error code if there was a problem authenticating.
56     */
57    public static final int ERROR_AUTHENTICATING = 1;
58
59    /**
60     * Broadcast intent action indicating that Wi-Fi has been enabled, disabled,
61     * enabling, disabling, or unknown. One extra provides this state as an int.
62     * Another extra provides the previous state, if available.
63     *
64     * @see #EXTRA_WIFI_STATE
65     * @see #EXTRA_PREVIOUS_WIFI_STATE
66     */
67    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
68    public static final String WIFI_STATE_CHANGED_ACTION =
69        "android.net.wifi.WIFI_STATE_CHANGED";
70    /**
71     * The lookup key for an int that indicates whether Wi-Fi is enabled,
72     * disabled, enabling, disabling, or unknown.  Retrieve it with
73     * {@link android.content.Intent#getIntExtra(String,int)}.
74     *
75     * @see #WIFI_STATE_DISABLED
76     * @see #WIFI_STATE_DISABLING
77     * @see #WIFI_STATE_ENABLED
78     * @see #WIFI_STATE_ENABLING
79     * @see #WIFI_STATE_UNKNOWN
80     */
81    public static final String EXTRA_WIFI_STATE = "wifi_state";
82    /**
83     * The previous Wi-Fi state.
84     *
85     * @see #EXTRA_WIFI_STATE
86     */
87    public static final String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
88
89    /**
90     * Wi-Fi is currently being disabled. The state will change to {@link #WIFI_STATE_DISABLED} if
91     * it finishes successfully.
92     *
93     * @see #WIFI_STATE_CHANGED_ACTION
94     * @see #getWifiState()
95     */
96    public static final int WIFI_STATE_DISABLING = 0;
97    /**
98     * Wi-Fi is disabled.
99     *
100     * @see #WIFI_STATE_CHANGED_ACTION
101     * @see #getWifiState()
102     */
103    public static final int WIFI_STATE_DISABLED = 1;
104    /**
105     * Wi-Fi is currently being enabled. The state will change to {@link #WIFI_STATE_ENABLED} if
106     * it finishes successfully.
107     *
108     * @see #WIFI_STATE_CHANGED_ACTION
109     * @see #getWifiState()
110     */
111    public static final int WIFI_STATE_ENABLING = 2;
112    /**
113     * Wi-Fi is enabled.
114     *
115     * @see #WIFI_STATE_CHANGED_ACTION
116     * @see #getWifiState()
117     */
118    public static final int WIFI_STATE_ENABLED = 3;
119    /**
120     * Wi-Fi is in an unknown state. This state will occur when an error happens while enabling
121     * or disabling.
122     *
123     * @see #WIFI_STATE_CHANGED_ACTION
124     * @see #getWifiState()
125     */
126    public static final int WIFI_STATE_UNKNOWN = 4;
127
128    /**
129     * Broadcast intent action indicating that Wi-Fi AP has been enabled, disabled,
130     * enabling, disabling, or failed.
131     *
132     * @hide
133     */
134    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
135    public static final String WIFI_AP_STATE_CHANGED_ACTION =
136        "android.net.wifi.WIFI_AP_STATE_CHANGED";
137
138    /**
139     * The lookup key for an int that indicates whether Wi-Fi AP is enabled,
140     * disabled, enabling, disabling, or failed.  Retrieve it with
141     * {@link android.content.Intent#getIntExtra(String,int)}.
142     *
143     * @see #WIFI_AP_STATE_DISABLED
144     * @see #WIFI_AP_STATE_DISABLING
145     * @see #WIFI_AP_STATE_ENABLED
146     * @see #WIFI_AP_STATE_ENABLING
147     * @see #WIFI_AP_STATE_FAILED
148     *
149     * @hide
150     */
151    public static final String EXTRA_WIFI_AP_STATE = "wifi_state";
152    /**
153     * The previous Wi-Fi state.
154     *
155     * @see #EXTRA_WIFI_AP_STATE
156     *
157     * @hide
158     */
159    public static final String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
160    /**
161     * Wi-Fi AP is currently being disabled. The state will change to
162     * {@link #WIFI_AP_STATE_DISABLED} if it finishes successfully.
163     *
164     * @see #WIFI_AP_STATE_CHANGED_ACTION
165     * @see #getWifiApState()
166     *
167     * @hide
168     */
169    public static final int WIFI_AP_STATE_DISABLING = 10;
170    /**
171     * Wi-Fi AP is disabled.
172     *
173     * @see #WIFI_AP_STATE_CHANGED_ACTION
174     * @see #getWifiState()
175     *
176     * @hide
177     */
178    public static final int WIFI_AP_STATE_DISABLED = 11;
179    /**
180     * Wi-Fi AP is currently being enabled. The state will change to
181     * {@link #WIFI_AP_STATE_ENABLED} if it finishes successfully.
182     *
183     * @see #WIFI_AP_STATE_CHANGED_ACTION
184     * @see #getWifiApState()
185     *
186     * @hide
187     */
188    public static final int WIFI_AP_STATE_ENABLING = 12;
189    /**
190     * Wi-Fi AP is enabled.
191     *
192     * @see #WIFI_AP_STATE_CHANGED_ACTION
193     * @see #getWifiApState()
194     *
195     * @hide
196     */
197    public static final int WIFI_AP_STATE_ENABLED = 13;
198    /**
199     * Wi-Fi AP is in a failed state. This state will occur when an error occurs during
200     * enabling or disabling
201     *
202     * @see #WIFI_AP_STATE_CHANGED_ACTION
203     * @see #getWifiApState()
204     *
205     * @hide
206     */
207    public static final int WIFI_AP_STATE_FAILED = 14;
208
209    /**
210     * Broadcast intent action indicating that a connection to the supplicant has
211     * been established (and it is now possible
212     * to perform Wi-Fi operations) or the connection to the supplicant has been
213     * lost. One extra provides the connection state as a boolean, where {@code true}
214     * means CONNECTED.
215     * @see #EXTRA_SUPPLICANT_CONNECTED
216     */
217    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
218    public static final String SUPPLICANT_CONNECTION_CHANGE_ACTION =
219        "android.net.wifi.supplicant.CONNECTION_CHANGE";
220    /**
221     * The lookup key for a boolean that indicates whether a connection to
222     * the supplicant daemon has been gained or lost. {@code true} means
223     * a connection now exists.
224     * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
225     */
226    public static final String EXTRA_SUPPLICANT_CONNECTED = "connected";
227    /**
228     * Broadcast intent action indicating that the state of Wi-Fi connectivity
229     * has changed. One extra provides the new state
230     * in the form of a {@link android.net.NetworkInfo} object. If the new state is
231     * CONNECTED, a second extra may provide the BSSID of the access point,
232     * as a {@code String}.
233     * @see #EXTRA_NETWORK_INFO
234     * @see #EXTRA_BSSID
235     */
236    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
237    public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
238    /**
239     * The lookup key for a {@link android.net.NetworkInfo} object associated with the
240     * Wi-Fi network. Retrieve with
241     * {@link android.content.Intent#getParcelableExtra(String)}.
242     */
243    public static final String EXTRA_NETWORK_INFO = "networkInfo";
244    /**
245     * The lookup key for a String giving the BSSID of the access point to which
246     * we are connected. Only present when the new state is CONNECTED.
247     * Retrieve with
248     * {@link android.content.Intent#getStringExtra(String)}.
249     */
250    public static final String EXTRA_BSSID = "bssid";
251    /**
252     * Broadcast intent action indicating that the state of establishing a connection to
253     * an access point has changed.One extra provides the new
254     * {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
255     * is not generally the most useful thing to look at if you are just interested in
256     * the overall state of connectivity.
257     * @see #EXTRA_NEW_STATE
258     * @see #EXTRA_SUPPLICANT_ERROR
259     */
260    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
261    public static final String SUPPLICANT_STATE_CHANGED_ACTION =
262        "android.net.wifi.supplicant.STATE_CHANGE";
263    /**
264     * The lookup key for a {@link SupplicantState} describing the new state
265     * Retrieve with
266     * {@link android.content.Intent#getParcelableExtra(String)}.
267     */
268    public static final String EXTRA_NEW_STATE = "newState";
269
270    /**
271     * The lookup key for a {@link SupplicantState} describing the supplicant
272     * error code if any
273     * Retrieve with
274     * {@link android.content.Intent#getIntExtra(String, int)}.
275     * @see #ERROR_AUTHENTICATING
276     */
277    public static final String EXTRA_SUPPLICANT_ERROR = "supplicantError";
278    /**
279     * Broadcast intent action indicating that the supplicant configuration changed.
280     * This can be as a result of adding/updating/deleting a network
281     * @hide
282     */
283    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
284    public static final String SUPPLICANT_CONFIG_CHANGED_ACTION =
285        "android.net.wifi.supplicant.CONFIG_CHANGE";
286    /**
287     * An access point scan has completed, and results are available from the supplicant.
288     * Call {@link #getScanResults()} to obtain the results.
289     */
290    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
291    public static final String SCAN_RESULTS_AVAILABLE_ACTION = "android.net.wifi.SCAN_RESULTS";
292    /**
293     * The RSSI (signal strength) has changed.
294     * @see #EXTRA_NEW_RSSI
295     */
296    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
297    public static final String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
298    /**
299     * The lookup key for an {@code int} giving the new RSSI in dBm.
300     */
301    public static final String EXTRA_NEW_RSSI = "newRssi";
302
303    /**
304     * Broadcast intent action indicating that the IP configuration
305     * changed on wifi.
306     * @hide
307     */
308    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
309    public static final String CONFIG_CHANGED_ACTION = "android.net.wifi.CONFIG_CHANGED";
310    /**
311     * The lookup key for a {@link android.net.LinkProperties} object associated with the
312     * Wi-Fi network. Retrieve with
313     * {@link android.content.Intent#getParcelableExtra(String)}.
314     * @hide
315     */
316    public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
317
318    /**
319     * The network IDs of the configured networks could have changed.
320     */
321    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
322    public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
323
324    /**
325     * Activity Action: Pick a Wi-Fi network to connect to.
326     * <p>Input: Nothing.
327     * <p>Output: Nothing.
328     */
329    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
330    public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
331
332    /**
333     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
334     * and will behave normally, i.e., it will attempt to automatically
335     * establish a connection to a remembered access point that is
336     * within range, and will do periodic scans if there are remembered
337     * access points but none are in range.
338     */
339    public static final int WIFI_MODE_FULL = 1;
340    /**
341     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
342     * but the only operation that will be supported is initiation of
343     * scans, and the subsequent reporting of scan results. No attempts
344     * will be made to automatically connect to remembered access points,
345     * nor will periodic scans be automatically performed looking for
346     * remembered access points. Scans must be explicitly requested by
347     * an application in this mode.
348     */
349    public static final int WIFI_MODE_SCAN_ONLY = 2;
350
351    /** Anything worse than or equal to this will show 0 bars. */
352    private static final int MIN_RSSI = -100;
353
354    /** Anything better than or equal to this will show the max bars. */
355    private static final int MAX_RSSI = -55;
356
357    IWifiManager mService;
358    Handler mHandler;
359
360    /* Maximum number of active locks we allow.
361     * This limit was added to prevent apps from creating a ridiculous number
362     * of locks and crashing the system by overflowing the global ref table.
363     */
364    private static final int MAX_ACTIVE_LOCKS = 50;
365
366    /* Number of currently active WifiLocks and MulticastLocks */
367    private int mActiveLockCount;
368
369    /**
370     * Create a new WifiManager instance.
371     * Applications will almost always want to use
372     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
373     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
374     * @param service the Binder interface
375     * @param handler target for messages
376     * @hide - hide this because it takes in a parameter of type IWifiManager, which
377     * is a system private class.
378     */
379    public WifiManager(IWifiManager service, Handler handler) {
380        mService = service;
381        mHandler = handler;
382    }
383
384    /**
385     * Return a list of all the networks configured in the supplicant.
386     * Not all fields of WifiConfiguration are returned. Only the following
387     * fields are filled in:
388     * <ul>
389     * <li>networkId</li>
390     * <li>SSID</li>
391     * <li>BSSID</li>
392     * <li>priority</li>
393     * <li>allowedProtocols</li>
394     * <li>allowedKeyManagement</li>
395     * <li>allowedAuthAlgorithms</li>
396     * <li>allowedPairwiseCiphers</li>
397     * <li>allowedGroupCiphers</li>
398     * </ul>
399     * @return a list of network configurations in the form of a list
400     * of {@link WifiConfiguration} objects.
401     */
402    public List<WifiConfiguration> getConfiguredNetworks() {
403        try {
404            return mService.getConfiguredNetworks();
405        } catch (RemoteException e) {
406            return null;
407        }
408    }
409
410    /**
411     * Add a new network description to the set of configured networks.
412     * The {@code networkId} field of the supplied configuration object
413     * is ignored.
414     * <p/>
415     * The new network will be marked DISABLED by default. To enable it,
416     * called {@link #enableNetwork}.
417     *
418     * @param config the set of variables that describe the configuration,
419     *            contained in a {@link WifiConfiguration} object.
420     * @return the ID of the newly created network description. This is used in
421     *         other operations to specified the network to be acted upon.
422     *         Returns {@code -1} on failure.
423     */
424    public int addNetwork(WifiConfiguration config) {
425        if (config == null) {
426            return -1;
427        }
428        config.networkId = -1;
429        return addOrUpdateNetwork(config);
430    }
431
432    /**
433     * Update the network description of an existing configured network.
434     *
435     * @param config the set of variables that describe the configuration,
436     *            contained in a {@link WifiConfiguration} object. It may
437     *            be sparse, so that only the items that are being changed
438     *            are non-<code>null</code>. The {@code networkId} field
439     *            must be set to the ID of the existing network being updated.
440     * @return Returns the {@code networkId} of the supplied
441     *         {@code WifiConfiguration} on success.
442     *         <br/>
443     *         Returns {@code -1} on failure, including when the {@code networkId}
444     *         field of the {@code WifiConfiguration} does not refer to an
445     *         existing network.
446     */
447    public int updateNetwork(WifiConfiguration config) {
448        if (config == null || config.networkId < 0) {
449            return -1;
450        }
451        return addOrUpdateNetwork(config);
452    }
453
454    /**
455     * Internal method for doing the RPC that creates a new network description
456     * or updates an existing one.
457     *
458     * @param config The possibly sparse object containing the variables that
459     *         are to set or updated in the network description.
460     * @return the ID of the network on success, {@code -1} on failure.
461     */
462    private int addOrUpdateNetwork(WifiConfiguration config) {
463        try {
464            return mService.addOrUpdateNetwork(config);
465        } catch (RemoteException e) {
466            return -1;
467        }
468    }
469
470    /**
471     * Remove the specified network from the list of configured networks.
472     * This may result in the asynchronous delivery of state change
473     * events.
474     * @param netId the integer that identifies the network configuration
475     * to the supplicant
476     * @return {@code true} if the operation succeeded
477     */
478    public boolean removeNetwork(int netId) {
479        try {
480            return mService.removeNetwork(netId);
481        } catch (RemoteException e) {
482            return false;
483        }
484    }
485
486    /**
487     * Allow a previously configured network to be associated with. If
488     * <code>disableOthers</code> is true, then all other configured
489     * networks are disabled, and an attempt to connect to the selected
490     * network is initiated. This may result in the asynchronous delivery
491     * of state change events.
492     * @param netId the ID of the network in the list of configured networks
493     * @param disableOthers if true, disable all other networks. The way to
494     * select a particular network to connect to is specify {@code true}
495     * for this parameter.
496     * @return {@code true} if the operation succeeded
497     */
498    public boolean enableNetwork(int netId, boolean disableOthers) {
499        try {
500            return mService.enableNetwork(netId, disableOthers);
501        } catch (RemoteException e) {
502            return false;
503        }
504    }
505
506    /**
507     * Disable a configured network. The specified network will not be
508     * a candidate for associating. This may result in the asynchronous
509     * delivery of state change events.
510     * @param netId the ID of the network as returned by {@link #addNetwork}.
511     * @return {@code true} if the operation succeeded
512     */
513    public boolean disableNetwork(int netId) {
514        try {
515            return mService.disableNetwork(netId);
516        } catch (RemoteException e) {
517            return false;
518        }
519    }
520
521    /**
522     * Disassociate from the currently active access point. This may result
523     * in the asynchronous delivery of state change events.
524     * @return {@code true} if the operation succeeded
525     */
526    public boolean disconnect() {
527        try {
528            mService.disconnect();
529            return true;
530        } catch (RemoteException e) {
531            return false;
532        }
533    }
534
535    /**
536     * Reconnect to the currently active access point, if we are currently
537     * disconnected. This may result in the asynchronous delivery of state
538     * change events.
539     * @return {@code true} if the operation succeeded
540     */
541    public boolean reconnect() {
542        try {
543            mService.reconnect();
544            return true;
545        } catch (RemoteException e) {
546            return false;
547        }
548    }
549
550    /**
551     * Reconnect to the currently active access point, even if we are already
552     * connected. This may result in the asynchronous delivery of state
553     * change events.
554     * @return {@code true} if the operation succeeded
555     */
556    public boolean reassociate() {
557        try {
558            mService.reassociate();
559            return true;
560        } catch (RemoteException e) {
561            return false;
562        }
563    }
564
565    /**
566     * Check that the supplicant daemon is responding to requests.
567     * @return {@code true} if we were able to communicate with the supplicant and
568     * it returned the expected response to the PING message.
569     */
570    public boolean pingSupplicant() {
571        if (mService == null)
572            return false;
573        try {
574            return mService.pingSupplicant();
575        } catch (RemoteException e) {
576            return false;
577        }
578    }
579
580    /**
581     * Request a scan for access points. Returns immediately. The availability
582     * of the results is made known later by means of an asynchronous event sent
583     * on completion of the scan.
584     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
585     */
586    public boolean startScan() {
587        try {
588            mService.startScan(false);
589            return true;
590        } catch (RemoteException e) {
591            return false;
592        }
593    }
594
595    /**
596     * Request a scan for access points. Returns immediately. The availability
597     * of the results is made known later by means of an asynchronous event sent
598     * on completion of the scan.
599     * This is a variant of startScan that forces an active scan, even if passive
600     * scans are the current default
601     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
602     *
603     * @hide
604     */
605    public boolean startScanActive() {
606        try {
607            mService.startScan(true);
608            return true;
609        } catch (RemoteException e) {
610            return false;
611        }
612    }
613
614    /**
615     * Return dynamic information about the current Wi-Fi connection, if any is active.
616     * @return the Wi-Fi information, contained in {@link WifiInfo}.
617     */
618    public WifiInfo getConnectionInfo() {
619        try {
620            return mService.getConnectionInfo();
621        } catch (RemoteException e) {
622            return null;
623        }
624    }
625
626    /**
627     * Return the results of the latest access point scan.
628     * @return the list of access points found in the most recent scan.
629     */
630    public List<ScanResult> getScanResults() {
631        try {
632            return mService.getScanResults();
633        } catch (RemoteException e) {
634            return null;
635        }
636    }
637
638    /**
639     * Tell the supplicant to persist the current list of configured networks.
640     * <p>
641     * Note: It is possible for this method to change the network IDs of
642     * existing networks. You should assume the network IDs can be different
643     * after calling this method.
644     *
645     * @return {@code true} if the operation succeeded
646     */
647    public boolean saveConfiguration() {
648        try {
649            return mService.saveConfiguration();
650        } catch (RemoteException e) {
651            return false;
652        }
653    }
654
655    /**
656     * Return the number of frequency channels that are allowed
657     * to be used in the current regulatory domain.
658     * @return the number of allowed channels, or {@code -1} if an error occurs
659     *
660     * @hide pending API council
661     */
662    public int getNumAllowedChannels() {
663        try {
664            return mService.getNumAllowedChannels();
665        } catch (RemoteException e) {
666            return -1;
667        }
668    }
669
670    /**
671     * Set the number of frequency channels that are allowed to be used
672     * in the current regulatory domain. This method should be used only
673     * if the correct number of channels cannot be determined automatically
674     * for some reason.
675     * @param numChannels the number of allowed channels. Must be greater than 0
676     * and less than or equal to 16.
677     * @param persist {@code true} if you want this remembered
678     * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g.,
679     * {@code numChannels} is out of range.
680     *
681     * @hide pending API council
682     */
683    public boolean setNumAllowedChannels(int numChannels, boolean persist) {
684        try {
685            return mService.setNumAllowedChannels(numChannels, persist);
686        } catch (RemoteException e) {
687            return false;
688        }
689    }
690
691    /**
692     * Return the list of valid values for the number of allowed radio channels
693     * for various regulatory domains.
694     * @return the list of channel counts, or {@code null} if the operation fails
695     *
696     * @hide pending API council review
697     */
698    public int[] getValidChannelCounts() {
699        try {
700            return mService.getValidChannelCounts();
701        } catch (RemoteException e) {
702            return null;
703        }
704   }
705
706    /**
707     * Return the DHCP-assigned addresses from the last successful DHCP request,
708     * if any.
709     * @return the DHCP information
710     */
711    public DhcpInfo getDhcpInfo() {
712        try {
713            return mService.getDhcpInfo();
714        } catch (RemoteException e) {
715            return null;
716        }
717    }
718
719
720    /**
721     * Enable or disable Wi-Fi.
722     * @param enabled {@code true} to enable, {@code false} to disable.
723     * @return {@code true} if the operation succeeds (or if the existing state
724     *         is the same as the requested state).
725     */
726    public boolean setWifiEnabled(boolean enabled) {
727        try {
728            return mService.setWifiEnabled(enabled);
729        } catch (RemoteException e) {
730            return false;
731        }
732    }
733
734    /**
735     * Gets the Wi-Fi enabled state.
736     * @return One of {@link #WIFI_STATE_DISABLED},
737     *         {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
738     *         {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
739     * @see #isWifiEnabled()
740     */
741    public int getWifiState() {
742        try {
743            return mService.getWifiEnabledState();
744        } catch (RemoteException e) {
745            return WIFI_STATE_UNKNOWN;
746        }
747    }
748
749    /**
750     * Return whether Wi-Fi is enabled or disabled.
751     * @return {@code true} if Wi-Fi is enabled
752     * @see #getWifiState()
753     */
754    public boolean isWifiEnabled() {
755        return getWifiState() == WIFI_STATE_ENABLED;
756    }
757
758    /**
759     * Calculates the level of the signal. This should be used any time a signal
760     * is being shown.
761     *
762     * @param rssi The power of the signal measured in RSSI.
763     * @param numLevels The number of levels to consider in the calculated
764     *            level.
765     * @return A level of the signal, given in the range of 0 to numLevels-1
766     *         (both inclusive).
767     */
768    public static int calculateSignalLevel(int rssi, int numLevels) {
769        if (rssi <= MIN_RSSI) {
770            return 0;
771        } else if (rssi >= MAX_RSSI) {
772            return numLevels - 1;
773        } else {
774            float inputRange = (MAX_RSSI - MIN_RSSI);
775            float outputRange = (numLevels - 1);
776            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
777        }
778    }
779
780    /**
781     * Compares two signal strengths.
782     *
783     * @param rssiA The power of the first signal measured in RSSI.
784     * @param rssiB The power of the second signal measured in RSSI.
785     * @return Returns <0 if the first signal is weaker than the second signal,
786     *         0 if the two signals have the same strength, and >0 if the first
787     *         signal is stronger than the second signal.
788     */
789    public static int compareSignalLevel(int rssiA, int rssiB) {
790        return rssiA - rssiB;
791    }
792
793    /**
794     * Start AccessPoint mode with the specified
795     * configuration. If the radio is already running in
796     * AP mode, update the new configuration
797     * Note that starting in access point mode disables station
798     * mode operation
799     * @param wifiConfig SSID, security and channel details as
800     *        part of WifiConfiguration
801     * @return {@code true} if the operation succeeds, {@code false} otherwise
802     *
803     * @hide Dont open up yet
804     */
805    public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
806        try {
807            return mService.setWifiApEnabled(wifiConfig, enabled);
808        } catch (RemoteException e) {
809            return false;
810        }
811    }
812
813    /**
814     * Gets the Wi-Fi enabled state.
815     * @return One of {@link #WIFI_AP_STATE_DISABLED},
816     *         {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
817     *         {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
818     * @see #isWifiApEnabled()
819     *
820     * @hide Dont open yet
821     */
822    public int getWifiApState() {
823        try {
824            return mService.getWifiApEnabledState();
825        } catch (RemoteException e) {
826            return WIFI_AP_STATE_FAILED;
827        }
828    }
829
830    /**
831     * Return whether Wi-Fi AP is enabled or disabled.
832     * @return {@code true} if Wi-Fi AP is enabled
833     * @see #getWifiApState()
834     *
835     * @hide Dont open yet
836     */
837    public boolean isWifiApEnabled() {
838        return getWifiApState() == WIFI_AP_STATE_ENABLED;
839    }
840
841    /**
842     * Gets the Wi-Fi AP Configuration.
843     * @return AP details in WifiConfiguration
844     *
845     * @hide Dont open yet
846     */
847    public WifiConfiguration getWifiApConfiguration() {
848        try {
849            return mService.getWifiApConfiguration();
850        } catch (RemoteException e) {
851            return null;
852        }
853    }
854
855    /**
856     * Sets the Wi-Fi AP Configuration.
857     * @return {@code true} if the operation succeeded, {@code false} otherwise
858     *
859     * @hide Dont open yet
860     */
861    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
862        try {
863            mService.setWifiApConfiguration(wifiConfig);
864            return true;
865        } catch (RemoteException e) {
866            return false;
867        }
868    }
869
870   /**
871     * Start the driver and connect to network.
872     *
873     * This function will over-ride WifiLock and device idle status. For example,
874     * even if the device is idle or there is only a scan-only lock held,
875     * a start wifi would mean that wifi connection is kept active until
876     * a stopWifi() is sent.
877     *
878     * This API is used by WifiStateTracker
879     *
880     * @return {@code true} if the operation succeeds else {@code false}
881     * @hide
882     */
883    public boolean startWifi() {
884        try {
885            mService.startWifi();
886            return true;
887        } catch (RemoteException e) {
888            return false;
889        }
890    }
891
892    /**
893     * Disconnect from a network (if any) and stop the driver.
894     *
895     * This function will over-ride WifiLock and device idle status. Wi-Fi
896     * stays inactive until a startWifi() is issued.
897     *
898     * This API is used by WifiStateTracker
899     *
900     * @return {@code true} if the operation succeeds else {@code false}
901     * @hide
902     */
903    public boolean stopWifi() {
904        try {
905            mService.stopWifi();
906            return true;
907        } catch (RemoteException e) {
908            return false;
909        }
910    }
911
912    /**
913     * Add a bssid to the supplicant blacklist
914     *
915     * This API is used by WifiWatchdogService
916     *
917     * @return {@code true} if the operation succeeds else {@code false}
918     * @hide
919     */
920    public boolean addToBlacklist(String bssid) {
921        try {
922            mService.addToBlacklist(bssid);
923            return true;
924        } catch (RemoteException e) {
925            return false;
926        }
927    }
928
929    /**
930     * Clear the supplicant blacklist
931     *
932     * This API is used by WifiWatchdogService
933     *
934     * @return {@code true} if the operation succeeds else {@code false}
935     * @hide
936     */
937    public boolean clearBlacklist() {
938        try {
939            mService.clearBlacklist();
940            return true;
941        } catch (RemoteException e) {
942            return false;
943        }
944    }
945
946    /* TODO: deprecate synchronous API and open up the following API */
947    /**
948     * Connect to a network with the given configuration. The network also
949     * gets added to the supplicant configuration.
950     *
951     * For a new network, this function is used instead of a
952     * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
953     * reconnect()
954     *
955     * @param config the set of variables that describe the configuration,
956     *            contained in a {@link WifiConfiguration} object.
957     * @hide
958     */
959    public void connectNetwork(WifiConfiguration config) {
960        if (config == null) {
961            return;
962        }
963        try {
964            mService.connectNetworkWithConfig(config);
965        } catch (RemoteException e) { }
966    }
967
968    /**
969     * Connect to a network with the given networkId.
970     *
971     * This function is used instead of a enableNetwork(), saveConfiguration() and
972     * reconnect()
973     *
974     * @param networkId the network id identifiying the network in the
975     *                supplicant configuration list
976     * @hide
977     */
978    public void connectNetwork(int networkId) {
979        if (networkId < 0) {
980            return;
981        }
982        try {
983            mService.connectNetworkWithId(networkId);
984        } catch (RemoteException e) { }
985    }
986
987    /**
988     * Save the given network in the supplicant config. If the network already
989     * exists, the configuration is updated. A new network is enabled
990     * by default.
991     *
992     * For a new network, this function is used instead of a
993     * sequence of addNetwork(), enableNetwork() and saveConfiguration().
994     *
995     * For an existing network, it accomplishes the task of updateNetwork()
996     * and saveConfiguration()
997     *
998     * @param config the set of variables that describe the configuration,
999     *            contained in a {@link WifiConfiguration} object.
1000     * @hide
1001     */
1002    public void saveNetwork(WifiConfiguration config) {
1003        if (config == null) {
1004            return;
1005        }
1006        try {
1007            mService.saveNetwork(config);
1008        } catch (RemoteException e) { }
1009    }
1010
1011    /**
1012     * Delete the network in the supplicant config.
1013     *
1014     * This function is used instead of a sequence of removeNetwork()
1015     * and saveConfiguration().
1016     *
1017     * @param config the set of variables that describe the configuration,
1018     *            contained in a {@link WifiConfiguration} object.
1019     * @hide
1020     */
1021    public void forgetNetwork(int netId) {
1022        if (netId < 0) {
1023            return;
1024        }
1025        try {
1026            mService.forgetNetwork(netId);
1027        } catch (RemoteException e) { }
1028    }
1029
1030    /**
1031     * Allows an application to keep the Wi-Fi radio awake.
1032     * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
1033     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
1034     * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
1035     * WifiLocks are held in any application.
1036     *
1037     * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
1038     * could function over a mobile network, if available.  A program that needs to download large
1039     * files should hold a WifiLock to ensure that the download will complete, but a program whose
1040     * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
1041     * affecting battery life.
1042     *
1043     * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
1044     * Mode.  They simply keep the radio from turning off when Wi-Fi is already on but the device
1045     * is idle.
1046     */
1047    public class WifiLock {
1048        private String mTag;
1049        private final IBinder mBinder;
1050        private int mRefCount;
1051        int mLockType;
1052        private boolean mRefCounted;
1053        private boolean mHeld;
1054        private WorkSource mWorkSource;
1055
1056        private WifiLock(int lockType, String tag) {
1057            mTag = tag;
1058            mLockType = lockType;
1059            mBinder = new Binder();
1060            mRefCount = 0;
1061            mRefCounted = true;
1062            mHeld = false;
1063        }
1064
1065        /**
1066         * Locks the Wi-Fi radio on until {@link #release} is called.
1067         *
1068         * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
1069         * reference count, and the radio will remain locked as long as the reference count is
1070         * above zero.
1071         *
1072         * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
1073         * the radio, but subsequent calls will be ignored.  Only one call to {@link #release}
1074         * will be required, regardless of the number of times that {@code acquire} is called.
1075         */
1076        public void acquire() {
1077            synchronized (mBinder) {
1078                if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) {
1079                    try {
1080                        mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
1081                        synchronized (WifiManager.this) {
1082                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
1083                                mService.releaseWifiLock(mBinder);
1084                                throw new UnsupportedOperationException(
1085                                            "Exceeded maximum number of wifi locks");
1086                            }
1087                            mActiveLockCount++;
1088                        }
1089                    } catch (RemoteException ignore) {
1090                    }
1091                    mHeld = true;
1092                }
1093            }
1094        }
1095
1096        /**
1097         * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle.
1098         *
1099         * If this WifiLock is reference-counted, each call to {@code release} will decrement the
1100         * reference count, and the radio will be unlocked only when the reference count reaches
1101         * zero.  If the reference count goes below zero (that is, if {@code release} is called
1102         * a greater number of times than {@link #acquire}), an exception is thrown.
1103         *
1104         * If this WifiLock is not reference-counted, the first call to {@code release} (after
1105         * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent
1106         * calls will be ignored.
1107         */
1108        public void release() {
1109            synchronized (mBinder) {
1110                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
1111                    try {
1112                        mService.releaseWifiLock(mBinder);
1113                        synchronized (WifiManager.this) {
1114                            mActiveLockCount--;
1115                        }
1116                    } catch (RemoteException ignore) {
1117                    }
1118                    mHeld = false;
1119                }
1120                if (mRefCount < 0) {
1121                    throw new RuntimeException("WifiLock under-locked " + mTag);
1122                }
1123            }
1124        }
1125
1126        /**
1127         * Controls whether this is a reference-counted or non-reference-counted WifiLock.
1128         *
1129         * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and
1130         * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire}
1131         * has been balanced with a call to {@link #release}.  Non-reference-counted WifiLocks
1132         * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the
1133         * radio whenever {@link #release} is called and it is locked.
1134         *
1135         * @param refCounted true if this WifiLock should keep a reference count
1136         */
1137        public void setReferenceCounted(boolean refCounted) {
1138            mRefCounted = refCounted;
1139        }
1140
1141        /**
1142         * Checks whether this WifiLock is currently held.
1143         *
1144         * @return true if this WifiLock is held, false otherwise
1145         */
1146        public boolean isHeld() {
1147            synchronized (mBinder) {
1148                return mHeld;
1149            }
1150        }
1151
1152        public void setWorkSource(WorkSource ws) {
1153            synchronized (mBinder) {
1154                if (ws != null && ws.size() == 0) {
1155                    ws = null;
1156                }
1157                boolean changed = true;
1158                if (ws == null) {
1159                    mWorkSource = null;
1160                } else if (mWorkSource == null) {
1161                    changed = mWorkSource != null;
1162                    mWorkSource = new WorkSource(ws);
1163                } else {
1164                    changed = mWorkSource.diff(ws);
1165                    if (changed) {
1166                        mWorkSource.set(ws);
1167                    }
1168                }
1169                if (changed && mHeld) {
1170                    try {
1171                        mService.updateWifiLockWorkSource(mBinder, mWorkSource);
1172                    } catch (RemoteException e) {
1173                    }
1174                }
1175            }
1176        }
1177
1178        public String toString() {
1179            String s1, s2, s3;
1180            synchronized (mBinder) {
1181                s1 = Integer.toHexString(System.identityHashCode(this));
1182                s2 = mHeld ? "held; " : "";
1183                if (mRefCounted) {
1184                    s3 = "refcounted: refcount = " + mRefCount;
1185                } else {
1186                    s3 = "not refcounted";
1187                }
1188                return "WifiLock{ " + s1 + "; " + s2 + s3 + " }";
1189            }
1190        }
1191
1192        @Override
1193        protected void finalize() throws Throwable {
1194            super.finalize();
1195            synchronized (mBinder) {
1196                if (mHeld) {
1197                    try {
1198                        mService.releaseWifiLock(mBinder);
1199                        synchronized (WifiManager.this) {
1200                            mActiveLockCount--;
1201                        }
1202                    } catch (RemoteException ignore) {
1203                    }
1204                }
1205            }
1206        }
1207    }
1208
1209    /**
1210     * Creates a new WifiLock.
1211     *
1212     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and
1213     * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
1214     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
1215     *            never shown to the user under normal conditions, but should be descriptive
1216     *            enough to identify your application and the specific WifiLock within it, if it
1217     *            holds multiple WifiLocks.
1218     *
1219     * @return a new, unacquired WifiLock with the given tag.
1220     *
1221     * @see WifiLock
1222     */
1223    public WifiLock createWifiLock(int lockType, String tag) {
1224        return new WifiLock(lockType, tag);
1225    }
1226
1227    /**
1228     * Creates a new WifiLock.
1229     *
1230     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
1231     *            never shown to the user under normal conditions, but should be descriptive
1232     *            enough to identify your application and the specific WifiLock within it, if it
1233     *            holds multiple WifiLocks.
1234     *
1235     * @return a new, unacquired WifiLock with the given tag.
1236     *
1237     * @see WifiLock
1238     */
1239    public WifiLock createWifiLock(String tag) {
1240        return new WifiLock(WIFI_MODE_FULL, tag);
1241    }
1242
1243
1244    /**
1245     * Create a new MulticastLock
1246     *
1247     * @param tag a tag for the MulticastLock to identify it in debugging
1248     *            messages.  This string is never shown to the user under
1249     *            normal conditions, but should be descriptive enough to
1250     *            identify your application and the specific MulticastLock
1251     *            within it, if it holds multiple MulticastLocks.
1252     *
1253     * @return a new, unacquired MulticastLock with the given tag.
1254     *
1255     * @see MulticastLock
1256     */
1257    public MulticastLock createMulticastLock(String tag) {
1258        return new MulticastLock(tag);
1259    }
1260
1261    /**
1262     * Allows an application to receive Wifi Multicast packets.
1263     * Normally the Wifi stack filters out packets not explicitly
1264     * addressed to this device.  Acquring a MulticastLock will
1265     * cause the stack to receive packets addressed to multicast
1266     * addresses.  Processing these extra packets can cause a noticable
1267     * battery drain and should be disabled when not needed.
1268     */
1269    public class MulticastLock {
1270        private String mTag;
1271        private final IBinder mBinder;
1272        private int mRefCount;
1273        private boolean mRefCounted;
1274        private boolean mHeld;
1275
1276        private MulticastLock(String tag) {
1277            mTag = tag;
1278            mBinder = new Binder();
1279            mRefCount = 0;
1280            mRefCounted = true;
1281            mHeld = false;
1282        }
1283
1284        /**
1285         * Locks Wifi Multicast on until {@link #release} is called.
1286         *
1287         * If this MulticastLock is reference-counted each call to
1288         * {@code acquire} will increment the reference count, and the
1289         * wifi interface will receive multicast packets as long as the
1290         * reference count is above zero.
1291         *
1292         * If this MulticastLock is not reference-counted, the first call to
1293         * {@code acquire} will turn on the multicast packets, but subsequent
1294         * calls will be ignored.  Only one call to {@link #release} will
1295         * be required, regardless of the number of times that {@code acquire}
1296         * is called.
1297         *
1298         * Note that other applications may also lock Wifi Multicast on.
1299         * Only they can relinquish their lock.
1300         *
1301         * Also note that applications cannot leave Multicast locked on.
1302         * When an app exits or crashes, any Multicast locks will be released.
1303         */
1304        public void acquire() {
1305            synchronized (mBinder) {
1306                if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) {
1307                    try {
1308                        mService.acquireMulticastLock(mBinder, mTag);
1309                        synchronized (WifiManager.this) {
1310                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
1311                                mService.releaseMulticastLock();
1312                                throw new UnsupportedOperationException(
1313                                        "Exceeded maximum number of wifi locks");
1314                            }
1315                            mActiveLockCount++;
1316                        }
1317                    } catch (RemoteException ignore) {
1318                    }
1319                    mHeld = true;
1320                }
1321            }
1322        }
1323
1324        /**
1325         * Unlocks Wifi Multicast, restoring the filter of packets
1326         * not addressed specifically to this device and saving power.
1327         *
1328         * If this MulticastLock is reference-counted, each call to
1329         * {@code release} will decrement the reference count, and the
1330         * multicast packets will only stop being received when the reference
1331         * count reaches zero.  If the reference count goes below zero (that
1332         * is, if {@code release} is called a greater number of times than
1333         * {@link #acquire}), an exception is thrown.
1334         *
1335         * If this MulticastLock is not reference-counted, the first call to
1336         * {@code release} (after the radio was multicast locked using
1337         * {@link #acquire}) will unlock the multicast, and subsequent calls
1338         * will be ignored.
1339         *
1340         * Note that if any other Wifi Multicast Locks are still outstanding
1341         * this {@code release} call will not have an immediate effect.  Only
1342         * when all applications have released all their Multicast Locks will
1343         * the Multicast filter be turned back on.
1344         *
1345         * Also note that when an app exits or crashes all of its Multicast
1346         * Locks will be automatically released.
1347         */
1348        public void release() {
1349            synchronized (mBinder) {
1350                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
1351                    try {
1352                        mService.releaseMulticastLock();
1353                        synchronized (WifiManager.this) {
1354                            mActiveLockCount--;
1355                        }
1356                    } catch (RemoteException ignore) {
1357                    }
1358                    mHeld = false;
1359                }
1360                if (mRefCount < 0) {
1361                    throw new RuntimeException("MulticastLock under-locked "
1362                            + mTag);
1363                }
1364            }
1365        }
1366
1367        /**
1368         * Controls whether this is a reference-counted or non-reference-
1369         * counted MulticastLock.
1370         *
1371         * Reference-counted MulticastLocks keep track of the number of calls
1372         * to {@link #acquire} and {@link #release}, and only stop the
1373         * reception of multicast packets when every call to {@link #acquire}
1374         * has been balanced with a call to {@link #release}.  Non-reference-
1375         * counted MulticastLocks allow the reception of multicast packets
1376         * whenever {@link #acquire} is called and stop accepting multicast
1377         * packets whenever {@link #release} is called.
1378         *
1379         * @param refCounted true if this MulticastLock should keep a reference
1380         * count
1381         */
1382        public void setReferenceCounted(boolean refCounted) {
1383            mRefCounted = refCounted;
1384        }
1385
1386        /**
1387         * Checks whether this MulticastLock is currently held.
1388         *
1389         * @return true if this MulticastLock is held, false otherwise
1390         */
1391        public boolean isHeld() {
1392            synchronized (mBinder) {
1393                return mHeld;
1394            }
1395        }
1396
1397        public String toString() {
1398            String s1, s2, s3;
1399            synchronized (mBinder) {
1400                s1 = Integer.toHexString(System.identityHashCode(this));
1401                s2 = mHeld ? "held; " : "";
1402                if (mRefCounted) {
1403                    s3 = "refcounted: refcount = " + mRefCount;
1404                } else {
1405                    s3 = "not refcounted";
1406                }
1407                return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }";
1408            }
1409        }
1410
1411        @Override
1412        protected void finalize() throws Throwable {
1413            super.finalize();
1414            setReferenceCounted(false);
1415            release();
1416        }
1417    }
1418
1419    /**
1420     * Check multicast filter status.
1421     *
1422     * @return true if multicast packets are allowed.
1423     *
1424     * @hide pending API council approval
1425     */
1426    public boolean isMulticastEnabled() {
1427        try {
1428            return mService.isMulticastEnabled();
1429        } catch (RemoteException e) {
1430            return false;
1431        }
1432    }
1433
1434    /**
1435     * Initialize the multicast filtering to 'on'
1436     * @hide no intent to publish
1437     */
1438    public boolean initializeMulticastFiltering() {
1439        try {
1440            mService.initializeMulticastFiltering();
1441            return true;
1442        } catch (RemoteException e) {
1443             return false;
1444        }
1445    }
1446}
1447