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