WifiManager.java revision 5ee89800bee7c6c755778795a536e0e2f12b85ff
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    /**
312     * The lookup key for a {@link android.net.LinkProperties} object associated with the
313     * Wi-Fi network. Retrieve with
314     * {@link android.content.Intent#getParcelableExtra(String)}.
315     * @hide
316     */
317    public static final String EXTRA_LINK_PROPERTIES = "linkProperties";
318
319    /**
320     * The lookup key for a {@link android.net.LinkCapabilities} object associated with the
321     * Wi-Fi network. Retrieve with
322     * {@link android.content.Intent#getParcelableExtra(String)}.
323     * @hide
324     */
325    public static final String EXTRA_LINK_CAPABILITIES = "linkCapabilities";
326
327    /**
328     * The network IDs of the configured networks could have changed.
329     */
330    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
331    public static final String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
332
333    /**
334     * Activity Action: Pick a Wi-Fi network to connect to.
335     * <p>Input: Nothing.
336     * <p>Output: Nothing.
337     */
338    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
339    public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
340
341    /**
342     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
343     * and will behave normally, i.e., it will attempt to automatically
344     * establish a connection to a remembered access point that is
345     * within range, and will do periodic scans if there are remembered
346     * access points but none are in range.
347     */
348    public static final int WIFI_MODE_FULL = 1;
349    /**
350     * In this Wi-Fi lock mode, Wi-Fi will be kept active,
351     * but the only operation that will be supported is initiation of
352     * scans, and the subsequent reporting of scan results. No attempts
353     * will be made to automatically connect to remembered access points,
354     * nor will periodic scans be automatically performed looking for
355     * remembered access points. Scans must be explicitly requested by
356     * an application in this mode.
357     */
358    public static final int WIFI_MODE_SCAN_ONLY = 2;
359
360    /** Anything worse than or equal to this will show 0 bars. */
361    private static final int MIN_RSSI = -100;
362
363    /** Anything better than or equal to this will show the max bars. */
364    private static final int MAX_RSSI = -55;
365
366    IWifiManager mService;
367    Handler mHandler;
368
369    /* Maximum number of active locks we allow.
370     * This limit was added to prevent apps from creating a ridiculous number
371     * of locks and crashing the system by overflowing the global ref table.
372     */
373    private static final int MAX_ACTIVE_LOCKS = 50;
374
375    /* Number of currently active WifiLocks and MulticastLocks */
376    private int mActiveLockCount;
377
378    /**
379     * Create a new WifiManager instance.
380     * Applications will almost always want to use
381     * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
382     * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
383     * @param service the Binder interface
384     * @param handler target for messages
385     * @hide - hide this because it takes in a parameter of type IWifiManager, which
386     * is a system private class.
387     */
388    public WifiManager(IWifiManager service, Handler handler) {
389        mService = service;
390        mHandler = handler;
391    }
392
393    /**
394     * Return a list of all the networks configured in the supplicant.
395     * Not all fields of WifiConfiguration are returned. Only the following
396     * fields are filled in:
397     * <ul>
398     * <li>networkId</li>
399     * <li>SSID</li>
400     * <li>BSSID</li>
401     * <li>priority</li>
402     * <li>allowedProtocols</li>
403     * <li>allowedKeyManagement</li>
404     * <li>allowedAuthAlgorithms</li>
405     * <li>allowedPairwiseCiphers</li>
406     * <li>allowedGroupCiphers</li>
407     * </ul>
408     * @return a list of network configurations in the form of a list
409     * of {@link WifiConfiguration} objects.
410     */
411    public List<WifiConfiguration> getConfiguredNetworks() {
412        try {
413            return mService.getConfiguredNetworks();
414        } catch (RemoteException e) {
415            return null;
416        }
417    }
418
419    /**
420     * Add a new network description to the set of configured networks.
421     * The {@code networkId} field of the supplied configuration object
422     * is ignored.
423     * <p/>
424     * The new network will be marked DISABLED by default. To enable it,
425     * called {@link #enableNetwork}.
426     *
427     * @param config the set of variables that describe the configuration,
428     *            contained in a {@link WifiConfiguration} object.
429     * @return the ID of the newly created network description. This is used in
430     *         other operations to specified the network to be acted upon.
431     *         Returns {@code -1} on failure.
432     */
433    public int addNetwork(WifiConfiguration config) {
434        if (config == null) {
435            return -1;
436        }
437        config.networkId = -1;
438        return addOrUpdateNetwork(config);
439    }
440
441    /**
442     * Update the network description of an existing configured network.
443     *
444     * @param config the set of variables that describe the configuration,
445     *            contained in a {@link WifiConfiguration} object. It may
446     *            be sparse, so that only the items that are being changed
447     *            are non-<code>null</code>. The {@code networkId} field
448     *            must be set to the ID of the existing network being updated.
449     * @return Returns the {@code networkId} of the supplied
450     *         {@code WifiConfiguration} on success.
451     *         <br/>
452     *         Returns {@code -1} on failure, including when the {@code networkId}
453     *         field of the {@code WifiConfiguration} does not refer to an
454     *         existing network.
455     */
456    public int updateNetwork(WifiConfiguration config) {
457        if (config == null || config.networkId < 0) {
458            return -1;
459        }
460        return addOrUpdateNetwork(config);
461    }
462
463    /**
464     * Internal method for doing the RPC that creates a new network description
465     * or updates an existing one.
466     *
467     * @param config The possibly sparse object containing the variables that
468     *         are to set or updated in the network description.
469     * @return the ID of the network on success, {@code -1} on failure.
470     */
471    private int addOrUpdateNetwork(WifiConfiguration config) {
472        try {
473            return mService.addOrUpdateNetwork(config);
474        } catch (RemoteException e) {
475            return -1;
476        }
477    }
478
479    /**
480     * Remove the specified network from the list of configured networks.
481     * This may result in the asynchronous delivery of state change
482     * events.
483     * @param netId the integer that identifies the network configuration
484     * to the supplicant
485     * @return {@code true} if the operation succeeded
486     */
487    public boolean removeNetwork(int netId) {
488        try {
489            return mService.removeNetwork(netId);
490        } catch (RemoteException e) {
491            return false;
492        }
493    }
494
495    /**
496     * Allow a previously configured network to be associated with. If
497     * <code>disableOthers</code> is true, then all other configured
498     * networks are disabled, and an attempt to connect to the selected
499     * network is initiated. This may result in the asynchronous delivery
500     * of state change events.
501     * @param netId the ID of the network in the list of configured networks
502     * @param disableOthers if true, disable all other networks. The way to
503     * select a particular network to connect to is specify {@code true}
504     * for this parameter.
505     * @return {@code true} if the operation succeeded
506     */
507    public boolean enableNetwork(int netId, boolean disableOthers) {
508        try {
509            return mService.enableNetwork(netId, disableOthers);
510        } catch (RemoteException e) {
511            return false;
512        }
513    }
514
515    /**
516     * Disable a configured network. The specified network will not be
517     * a candidate for associating. This may result in the asynchronous
518     * delivery of state change events.
519     * @param netId the ID of the network as returned by {@link #addNetwork}.
520     * @return {@code true} if the operation succeeded
521     */
522    public boolean disableNetwork(int netId) {
523        try {
524            return mService.disableNetwork(netId);
525        } catch (RemoteException e) {
526            return false;
527        }
528    }
529
530    /**
531     * Disassociate from the currently active access point. This may result
532     * in the asynchronous delivery of state change events.
533     * @return {@code true} if the operation succeeded
534     */
535    public boolean disconnect() {
536        try {
537            mService.disconnect();
538            return true;
539        } catch (RemoteException e) {
540            return false;
541        }
542    }
543
544    /**
545     * Reconnect to the currently active access point, if we are currently
546     * disconnected. This may result in the asynchronous delivery of state
547     * change events.
548     * @return {@code true} if the operation succeeded
549     */
550    public boolean reconnect() {
551        try {
552            mService.reconnect();
553            return true;
554        } catch (RemoteException e) {
555            return false;
556        }
557    }
558
559    /**
560     * Reconnect to the currently active access point, even if we are already
561     * connected. This may result in the asynchronous delivery of state
562     * change events.
563     * @return {@code true} if the operation succeeded
564     */
565    public boolean reassociate() {
566        try {
567            mService.reassociate();
568            return true;
569        } catch (RemoteException e) {
570            return false;
571        }
572    }
573
574    /**
575     * Check that the supplicant daemon is responding to requests.
576     * @return {@code true} if we were able to communicate with the supplicant and
577     * it returned the expected response to the PING message.
578     */
579    public boolean pingSupplicant() {
580        if (mService == null)
581            return false;
582        try {
583            return mService.pingSupplicant();
584        } catch (RemoteException e) {
585            return false;
586        }
587    }
588
589    /**
590     * Request a scan for access points. Returns immediately. The availability
591     * of the results is made known later by means of an asynchronous event sent
592     * on completion of the scan.
593     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
594     */
595    public boolean startScan() {
596        try {
597            mService.startScan(false);
598            return true;
599        } catch (RemoteException e) {
600            return false;
601        }
602    }
603
604    /**
605     * Request a scan for access points. Returns immediately. The availability
606     * of the results is made known later by means of an asynchronous event sent
607     * on completion of the scan.
608     * This is a variant of startScan that forces an active scan, even if passive
609     * scans are the current default
610     * @return {@code true} if the operation succeeded, i.e., the scan was initiated
611     *
612     * @hide
613     */
614    public boolean startScanActive() {
615        try {
616            mService.startScan(true);
617            return true;
618        } catch (RemoteException e) {
619            return false;
620        }
621    }
622
623    /**
624     * Return dynamic information about the current Wi-Fi connection, if any is active.
625     * @return the Wi-Fi information, contained in {@link WifiInfo}.
626     */
627    public WifiInfo getConnectionInfo() {
628        try {
629            return mService.getConnectionInfo();
630        } catch (RemoteException e) {
631            return null;
632        }
633    }
634
635    /**
636     * Return the results of the latest access point scan.
637     * @return the list of access points found in the most recent scan.
638     */
639    public List<ScanResult> getScanResults() {
640        try {
641            return mService.getScanResults();
642        } catch (RemoteException e) {
643            return null;
644        }
645    }
646
647    /**
648     * Tell the supplicant to persist the current list of configured networks.
649     * <p>
650     * Note: It is possible for this method to change the network IDs of
651     * existing networks. You should assume the network IDs can be different
652     * after calling this method.
653     *
654     * @return {@code true} if the operation succeeded
655     */
656    public boolean saveConfiguration() {
657        try {
658            return mService.saveConfiguration();
659        } catch (RemoteException e) {
660            return false;
661        }
662    }
663
664    /**
665     * Return the number of frequency channels that are allowed
666     * to be used in the current regulatory domain.
667     * @return the number of allowed channels, or {@code -1} if an error occurs
668     *
669     * @hide pending API council
670     */
671    public int getNumAllowedChannels() {
672        try {
673            return mService.getNumAllowedChannels();
674        } catch (RemoteException e) {
675            return -1;
676        }
677    }
678
679    /**
680     * Set the number of frequency channels that are allowed to be used
681     * in the current regulatory domain. This method should be used only
682     * if the correct number of channels cannot be determined automatically
683     * for some reason.
684     * @param numChannels the number of allowed channels. Must be greater than 0
685     * and less than or equal to 16.
686     * @param persist {@code true} if you want this remembered
687     * @return {@code true} if the operation succeeds, {@code false} otherwise, e.g.,
688     * {@code numChannels} is out of range.
689     *
690     * @hide pending API council
691     */
692    public boolean setNumAllowedChannels(int numChannels, boolean persist) {
693        try {
694            return mService.setNumAllowedChannels(numChannels, persist);
695        } catch (RemoteException e) {
696            return false;
697        }
698    }
699
700    /**
701     * Return the list of valid values for the number of allowed radio channels
702     * for various regulatory domains.
703     * @return the list of channel counts, or {@code null} if the operation fails
704     *
705     * @hide pending API council review
706     */
707    public int[] getValidChannelCounts() {
708        try {
709            return mService.getValidChannelCounts();
710        } catch (RemoteException e) {
711            return null;
712        }
713   }
714
715    /**
716     * Return the DHCP-assigned addresses from the last successful DHCP request,
717     * if any.
718     * @return the DHCP information
719     */
720    public DhcpInfo getDhcpInfo() {
721        try {
722            return mService.getDhcpInfo();
723        } catch (RemoteException e) {
724            return null;
725        }
726    }
727
728
729    /**
730     * Enable or disable Wi-Fi.
731     * @param enabled {@code true} to enable, {@code false} to disable.
732     * @return {@code true} if the operation succeeds (or if the existing state
733     *         is the same as the requested state).
734     */
735    public boolean setWifiEnabled(boolean enabled) {
736        try {
737            return mService.setWifiEnabled(enabled);
738        } catch (RemoteException e) {
739            return false;
740        }
741    }
742
743    /**
744     * Gets the Wi-Fi enabled state.
745     * @return One of {@link #WIFI_STATE_DISABLED},
746     *         {@link #WIFI_STATE_DISABLING}, {@link #WIFI_STATE_ENABLED},
747     *         {@link #WIFI_STATE_ENABLING}, {@link #WIFI_STATE_UNKNOWN}
748     * @see #isWifiEnabled()
749     */
750    public int getWifiState() {
751        try {
752            return mService.getWifiEnabledState();
753        } catch (RemoteException e) {
754            return WIFI_STATE_UNKNOWN;
755        }
756    }
757
758    /**
759     * Return whether Wi-Fi is enabled or disabled.
760     * @return {@code true} if Wi-Fi is enabled
761     * @see #getWifiState()
762     */
763    public boolean isWifiEnabled() {
764        return getWifiState() == WIFI_STATE_ENABLED;
765    }
766
767    /**
768     * Calculates the level of the signal. This should be used any time a signal
769     * is being shown.
770     *
771     * @param rssi The power of the signal measured in RSSI.
772     * @param numLevels The number of levels to consider in the calculated
773     *            level.
774     * @return A level of the signal, given in the range of 0 to numLevels-1
775     *         (both inclusive).
776     */
777    public static int calculateSignalLevel(int rssi, int numLevels) {
778        if (rssi <= MIN_RSSI) {
779            return 0;
780        } else if (rssi >= MAX_RSSI) {
781            return numLevels - 1;
782        } else {
783            float inputRange = (MAX_RSSI - MIN_RSSI);
784            float outputRange = (numLevels - 1);
785            return (int)((float)(rssi - MIN_RSSI) * outputRange / inputRange);
786        }
787    }
788
789    /**
790     * Compares two signal strengths.
791     *
792     * @param rssiA The power of the first signal measured in RSSI.
793     * @param rssiB The power of the second signal measured in RSSI.
794     * @return Returns <0 if the first signal is weaker than the second signal,
795     *         0 if the two signals have the same strength, and >0 if the first
796     *         signal is stronger than the second signal.
797     */
798    public static int compareSignalLevel(int rssiA, int rssiB) {
799        return rssiA - rssiB;
800    }
801
802    /**
803     * Start AccessPoint mode with the specified
804     * configuration. If the radio is already running in
805     * AP mode, update the new configuration
806     * Note that starting in access point mode disables station
807     * mode operation
808     * @param wifiConfig SSID, security and channel details as
809     *        part of WifiConfiguration
810     * @return {@code true} if the operation succeeds, {@code false} otherwise
811     *
812     * @hide Dont open up yet
813     */
814    public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
815        try {
816            return mService.setWifiApEnabled(wifiConfig, enabled);
817        } catch (RemoteException e) {
818            return false;
819        }
820    }
821
822    /**
823     * Gets the Wi-Fi enabled state.
824     * @return One of {@link #WIFI_AP_STATE_DISABLED},
825     *         {@link #WIFI_AP_STATE_DISABLING}, {@link #WIFI_AP_STATE_ENABLED},
826     *         {@link #WIFI_AP_STATE_ENABLING}, {@link #WIFI_AP_STATE_FAILED}
827     * @see #isWifiApEnabled()
828     *
829     * @hide Dont open yet
830     */
831    public int getWifiApState() {
832        try {
833            return mService.getWifiApEnabledState();
834        } catch (RemoteException e) {
835            return WIFI_AP_STATE_FAILED;
836        }
837    }
838
839    /**
840     * Return whether Wi-Fi AP is enabled or disabled.
841     * @return {@code true} if Wi-Fi AP is enabled
842     * @see #getWifiApState()
843     *
844     * @hide Dont open yet
845     */
846    public boolean isWifiApEnabled() {
847        return getWifiApState() == WIFI_AP_STATE_ENABLED;
848    }
849
850    /**
851     * Gets the Wi-Fi AP Configuration.
852     * @return AP details in WifiConfiguration
853     *
854     * @hide Dont open yet
855     */
856    public WifiConfiguration getWifiApConfiguration() {
857        try {
858            return mService.getWifiApConfiguration();
859        } catch (RemoteException e) {
860            return null;
861        }
862    }
863
864    /**
865     * Sets the Wi-Fi AP Configuration.
866     * @return {@code true} if the operation succeeded, {@code false} otherwise
867     *
868     * @hide Dont open yet
869     */
870    public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
871        try {
872            mService.setWifiApConfiguration(wifiConfig);
873            return true;
874        } catch (RemoteException e) {
875            return false;
876        }
877    }
878
879   /**
880     * Start the driver and connect to network.
881     *
882     * This function will over-ride WifiLock and device idle status. For example,
883     * even if the device is idle or there is only a scan-only lock held,
884     * a start wifi would mean that wifi connection is kept active until
885     * a stopWifi() is sent.
886     *
887     * This API is used by WifiStateTracker
888     *
889     * @return {@code true} if the operation succeeds else {@code false}
890     * @hide
891     */
892    public boolean startWifi() {
893        try {
894            mService.startWifi();
895            return true;
896        } catch (RemoteException e) {
897            return false;
898        }
899    }
900
901    /**
902     * Disconnect from a network (if any) and stop the driver.
903     *
904     * This function will over-ride WifiLock and device idle status. Wi-Fi
905     * stays inactive until a startWifi() is issued.
906     *
907     * This API is used by WifiStateTracker
908     *
909     * @return {@code true} if the operation succeeds else {@code false}
910     * @hide
911     */
912    public boolean stopWifi() {
913        try {
914            mService.stopWifi();
915            return true;
916        } catch (RemoteException e) {
917            return false;
918        }
919    }
920
921    /**
922     * Add a bssid to the supplicant blacklist
923     *
924     * This API is used by WifiWatchdogService
925     *
926     * @return {@code true} if the operation succeeds else {@code false}
927     * @hide
928     */
929    public boolean addToBlacklist(String bssid) {
930        try {
931            mService.addToBlacklist(bssid);
932            return true;
933        } catch (RemoteException e) {
934            return false;
935        }
936    }
937
938    /**
939     * Clear the supplicant blacklist
940     *
941     * This API is used by WifiWatchdogService
942     *
943     * @return {@code true} if the operation succeeds else {@code false}
944     * @hide
945     */
946    public boolean clearBlacklist() {
947        try {
948            mService.clearBlacklist();
949            return true;
950        } catch (RemoteException e) {
951            return false;
952        }
953    }
954
955    /* TODO: deprecate synchronous API and open up the following API */
956    /**
957     * Connect to a network with the given configuration. The network also
958     * gets added to the supplicant configuration.
959     *
960     * For a new network, this function is used instead of a
961     * sequence of addNetwork(), enableNetwork(), saveConfiguration() and
962     * reconnect()
963     *
964     * @param config the set of variables that describe the configuration,
965     *            contained in a {@link WifiConfiguration} object.
966     * @hide
967     */
968    public void connectNetwork(WifiConfiguration config) {
969        if (config == null) {
970            return;
971        }
972        try {
973            mService.connectNetworkWithConfig(config);
974        } catch (RemoteException e) { }
975    }
976
977    /**
978     * Connect to a network with the given networkId.
979     *
980     * This function is used instead of a enableNetwork(), saveConfiguration() and
981     * reconnect()
982     *
983     * @param networkId the network id identifiying the network in the
984     *                supplicant configuration list
985     * @hide
986     */
987    public void connectNetwork(int networkId) {
988        if (networkId < 0) {
989            return;
990        }
991        try {
992            mService.connectNetworkWithId(networkId);
993        } catch (RemoteException e) { }
994    }
995
996    /**
997     * Save the given network in the supplicant config. If the network already
998     * exists, the configuration is updated. A new network is enabled
999     * by default.
1000     *
1001     * For a new network, this function is used instead of a
1002     * sequence of addNetwork(), enableNetwork() and saveConfiguration().
1003     *
1004     * For an existing network, it accomplishes the task of updateNetwork()
1005     * and saveConfiguration()
1006     *
1007     * @param config the set of variables that describe the configuration,
1008     *            contained in a {@link WifiConfiguration} object.
1009     * @hide
1010     */
1011    public void saveNetwork(WifiConfiguration config) {
1012        if (config == null) {
1013            return;
1014        }
1015        try {
1016            mService.saveNetwork(config);
1017        } catch (RemoteException e) { }
1018    }
1019
1020    /**
1021     * Delete the network in the supplicant config.
1022     *
1023     * This function is used instead of a sequence of removeNetwork()
1024     * and saveConfiguration().
1025     *
1026     * @param config the set of variables that describe the configuration,
1027     *            contained in a {@link WifiConfiguration} object.
1028     * @hide
1029     */
1030    public void forgetNetwork(int netId) {
1031        if (netId < 0) {
1032            return;
1033        }
1034        try {
1035            mService.forgetNetwork(netId);
1036        } catch (RemoteException e) { }
1037    }
1038
1039    /**
1040     * Start Wi-fi protected setup push button Configuration
1041     *
1042     * @param bssid BSSID of the access point
1043     * @hide
1044     */
1045    public void startWpsPbc(String bssid) {
1046        try {
1047            mService.startWpsPbc(bssid);
1048        } catch (RemoteException e) { }
1049    }
1050
1051    /**
1052     * Start Wi-fi Protected Setup pin method configuration
1053     *
1054     * @param bssid BSSID of the access point
1055     * @param apPin PIN issued by the access point
1056     *
1057     * @hide
1058     */
1059    public void startWpsPin(String bssid, int apPin) {
1060        try {
1061            mService.startWpsPin(bssid, apPin);
1062        } catch (RemoteException e) { }
1063    }
1064
1065    /**
1066     * Allows an application to keep the Wi-Fi radio awake.
1067     * Normally the Wi-Fi radio may turn off when the user has not used the device in a while.
1068     * Acquiring a WifiLock will keep the radio on until the lock is released.  Multiple
1069     * applications may hold WifiLocks, and the radio will only be allowed to turn off when no
1070     * WifiLocks are held in any application.
1071     *
1072     * Before using a WifiLock, consider carefully if your application requires Wi-Fi access, or
1073     * could function over a mobile network, if available.  A program that needs to download large
1074     * files should hold a WifiLock to ensure that the download will complete, but a program whose
1075     * network usage is occasional or low-bandwidth should not hold a WifiLock to avoid adversely
1076     * affecting battery life.
1077     *
1078     * Note that WifiLocks cannot override the user-level "Wi-Fi Enabled" setting, nor Airplane
1079     * Mode.  They simply keep the radio from turning off when Wi-Fi is already on but the device
1080     * is idle.
1081     */
1082    public class WifiLock {
1083        private String mTag;
1084        private final IBinder mBinder;
1085        private int mRefCount;
1086        int mLockType;
1087        private boolean mRefCounted;
1088        private boolean mHeld;
1089        private WorkSource mWorkSource;
1090
1091        private WifiLock(int lockType, String tag) {
1092            mTag = tag;
1093            mLockType = lockType;
1094            mBinder = new Binder();
1095            mRefCount = 0;
1096            mRefCounted = true;
1097            mHeld = false;
1098        }
1099
1100        /**
1101         * Locks the Wi-Fi radio on until {@link #release} is called.
1102         *
1103         * If this WifiLock is reference-counted, each call to {@code acquire} will increment the
1104         * reference count, and the radio will remain locked as long as the reference count is
1105         * above zero.
1106         *
1107         * If this WifiLock is not reference-counted, the first call to {@code acquire} will lock
1108         * the radio, but subsequent calls will be ignored.  Only one call to {@link #release}
1109         * will be required, regardless of the number of times that {@code acquire} is called.
1110         */
1111        public void acquire() {
1112            synchronized (mBinder) {
1113                if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) {
1114                    try {
1115                        mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
1116                        synchronized (WifiManager.this) {
1117                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
1118                                mService.releaseWifiLock(mBinder);
1119                                throw new UnsupportedOperationException(
1120                                            "Exceeded maximum number of wifi locks");
1121                            }
1122                            mActiveLockCount++;
1123                        }
1124                    } catch (RemoteException ignore) {
1125                    }
1126                    mHeld = true;
1127                }
1128            }
1129        }
1130
1131        /**
1132         * Unlocks the Wi-Fi radio, allowing it to turn off when the device is idle.
1133         *
1134         * If this WifiLock is reference-counted, each call to {@code release} will decrement the
1135         * reference count, and the radio will be unlocked only when the reference count reaches
1136         * zero.  If the reference count goes below zero (that is, if {@code release} is called
1137         * a greater number of times than {@link #acquire}), an exception is thrown.
1138         *
1139         * If this WifiLock is not reference-counted, the first call to {@code release} (after
1140         * the radio was locked using {@link #acquire}) will unlock the radio, and subsequent
1141         * calls will be ignored.
1142         */
1143        public void release() {
1144            synchronized (mBinder) {
1145                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
1146                    try {
1147                        mService.releaseWifiLock(mBinder);
1148                        synchronized (WifiManager.this) {
1149                            mActiveLockCount--;
1150                        }
1151                    } catch (RemoteException ignore) {
1152                    }
1153                    mHeld = false;
1154                }
1155                if (mRefCount < 0) {
1156                    throw new RuntimeException("WifiLock under-locked " + mTag);
1157                }
1158            }
1159        }
1160
1161        /**
1162         * Controls whether this is a reference-counted or non-reference-counted WifiLock.
1163         *
1164         * Reference-counted WifiLocks keep track of the number of calls to {@link #acquire} and
1165         * {@link #release}, and only allow the radio to sleep when every call to {@link #acquire}
1166         * has been balanced with a call to {@link #release}.  Non-reference-counted WifiLocks
1167         * lock the radio whenever {@link #acquire} is called and it is unlocked, and unlock the
1168         * radio whenever {@link #release} is called and it is locked.
1169         *
1170         * @param refCounted true if this WifiLock should keep a reference count
1171         */
1172        public void setReferenceCounted(boolean refCounted) {
1173            mRefCounted = refCounted;
1174        }
1175
1176        /**
1177         * Checks whether this WifiLock is currently held.
1178         *
1179         * @return true if this WifiLock is held, false otherwise
1180         */
1181        public boolean isHeld() {
1182            synchronized (mBinder) {
1183                return mHeld;
1184            }
1185        }
1186
1187        public void setWorkSource(WorkSource ws) {
1188            synchronized (mBinder) {
1189                if (ws != null && ws.size() == 0) {
1190                    ws = null;
1191                }
1192                boolean changed = true;
1193                if (ws == null) {
1194                    mWorkSource = null;
1195                } else if (mWorkSource == null) {
1196                    changed = mWorkSource != null;
1197                    mWorkSource = new WorkSource(ws);
1198                } else {
1199                    changed = mWorkSource.diff(ws);
1200                    if (changed) {
1201                        mWorkSource.set(ws);
1202                    }
1203                }
1204                if (changed && mHeld) {
1205                    try {
1206                        mService.updateWifiLockWorkSource(mBinder, mWorkSource);
1207                    } catch (RemoteException e) {
1208                    }
1209                }
1210            }
1211        }
1212
1213        public String toString() {
1214            String s1, s2, s3;
1215            synchronized (mBinder) {
1216                s1 = Integer.toHexString(System.identityHashCode(this));
1217                s2 = mHeld ? "held; " : "";
1218                if (mRefCounted) {
1219                    s3 = "refcounted: refcount = " + mRefCount;
1220                } else {
1221                    s3 = "not refcounted";
1222                }
1223                return "WifiLock{ " + s1 + "; " + s2 + s3 + " }";
1224            }
1225        }
1226
1227        @Override
1228        protected void finalize() throws Throwable {
1229            super.finalize();
1230            synchronized (mBinder) {
1231                if (mHeld) {
1232                    try {
1233                        mService.releaseWifiLock(mBinder);
1234                        synchronized (WifiManager.this) {
1235                            mActiveLockCount--;
1236                        }
1237                    } catch (RemoteException ignore) {
1238                    }
1239                }
1240            }
1241        }
1242    }
1243
1244    /**
1245     * Creates a new WifiLock.
1246     *
1247     * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and
1248     * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
1249     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
1250     *            never shown to the user under normal conditions, but should be descriptive
1251     *            enough to identify your application and the specific WifiLock within it, if it
1252     *            holds multiple WifiLocks.
1253     *
1254     * @return a new, unacquired WifiLock with the given tag.
1255     *
1256     * @see WifiLock
1257     */
1258    public WifiLock createWifiLock(int lockType, String tag) {
1259        return new WifiLock(lockType, tag);
1260    }
1261
1262    /**
1263     * Creates a new WifiLock.
1264     *
1265     * @param tag a tag for the WifiLock to identify it in debugging messages.  This string is
1266     *            never shown to the user under normal conditions, but should be descriptive
1267     *            enough to identify your application and the specific WifiLock within it, if it
1268     *            holds multiple WifiLocks.
1269     *
1270     * @return a new, unacquired WifiLock with the given tag.
1271     *
1272     * @see WifiLock
1273     */
1274    public WifiLock createWifiLock(String tag) {
1275        return new WifiLock(WIFI_MODE_FULL, tag);
1276    }
1277
1278
1279    /**
1280     * Create a new MulticastLock
1281     *
1282     * @param tag a tag for the MulticastLock to identify it in debugging
1283     *            messages.  This string is never shown to the user under
1284     *            normal conditions, but should be descriptive enough to
1285     *            identify your application and the specific MulticastLock
1286     *            within it, if it holds multiple MulticastLocks.
1287     *
1288     * @return a new, unacquired MulticastLock with the given tag.
1289     *
1290     * @see MulticastLock
1291     */
1292    public MulticastLock createMulticastLock(String tag) {
1293        return new MulticastLock(tag);
1294    }
1295
1296    /**
1297     * Allows an application to receive Wifi Multicast packets.
1298     * Normally the Wifi stack filters out packets not explicitly
1299     * addressed to this device.  Acquring a MulticastLock will
1300     * cause the stack to receive packets addressed to multicast
1301     * addresses.  Processing these extra packets can cause a noticable
1302     * battery drain and should be disabled when not needed.
1303     */
1304    public class MulticastLock {
1305        private String mTag;
1306        private final IBinder mBinder;
1307        private int mRefCount;
1308        private boolean mRefCounted;
1309        private boolean mHeld;
1310
1311        private MulticastLock(String tag) {
1312            mTag = tag;
1313            mBinder = new Binder();
1314            mRefCount = 0;
1315            mRefCounted = true;
1316            mHeld = false;
1317        }
1318
1319        /**
1320         * Locks Wifi Multicast on until {@link #release} is called.
1321         *
1322         * If this MulticastLock is reference-counted each call to
1323         * {@code acquire} will increment the reference count, and the
1324         * wifi interface will receive multicast packets as long as the
1325         * reference count is above zero.
1326         *
1327         * If this MulticastLock is not reference-counted, the first call to
1328         * {@code acquire} will turn on the multicast packets, but subsequent
1329         * calls will be ignored.  Only one call to {@link #release} will
1330         * be required, regardless of the number of times that {@code acquire}
1331         * is called.
1332         *
1333         * Note that other applications may also lock Wifi Multicast on.
1334         * Only they can relinquish their lock.
1335         *
1336         * Also note that applications cannot leave Multicast locked on.
1337         * When an app exits or crashes, any Multicast locks will be released.
1338         */
1339        public void acquire() {
1340            synchronized (mBinder) {
1341                if (mRefCounted ? (++mRefCount > 0) : (!mHeld)) {
1342                    try {
1343                        mService.acquireMulticastLock(mBinder, mTag);
1344                        synchronized (WifiManager.this) {
1345                            if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
1346                                mService.releaseMulticastLock();
1347                                throw new UnsupportedOperationException(
1348                                        "Exceeded maximum number of wifi locks");
1349                            }
1350                            mActiveLockCount++;
1351                        }
1352                    } catch (RemoteException ignore) {
1353                    }
1354                    mHeld = true;
1355                }
1356            }
1357        }
1358
1359        /**
1360         * Unlocks Wifi Multicast, restoring the filter of packets
1361         * not addressed specifically to this device and saving power.
1362         *
1363         * If this MulticastLock is reference-counted, each call to
1364         * {@code release} will decrement the reference count, and the
1365         * multicast packets will only stop being received when the reference
1366         * count reaches zero.  If the reference count goes below zero (that
1367         * is, if {@code release} is called a greater number of times than
1368         * {@link #acquire}), an exception is thrown.
1369         *
1370         * If this MulticastLock is not reference-counted, the first call to
1371         * {@code release} (after the radio was multicast locked using
1372         * {@link #acquire}) will unlock the multicast, and subsequent calls
1373         * will be ignored.
1374         *
1375         * Note that if any other Wifi Multicast Locks are still outstanding
1376         * this {@code release} call will not have an immediate effect.  Only
1377         * when all applications have released all their Multicast Locks will
1378         * the Multicast filter be turned back on.
1379         *
1380         * Also note that when an app exits or crashes all of its Multicast
1381         * Locks will be automatically released.
1382         */
1383        public void release() {
1384            synchronized (mBinder) {
1385                if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
1386                    try {
1387                        mService.releaseMulticastLock();
1388                        synchronized (WifiManager.this) {
1389                            mActiveLockCount--;
1390                        }
1391                    } catch (RemoteException ignore) {
1392                    }
1393                    mHeld = false;
1394                }
1395                if (mRefCount < 0) {
1396                    throw new RuntimeException("MulticastLock under-locked "
1397                            + mTag);
1398                }
1399            }
1400        }
1401
1402        /**
1403         * Controls whether this is a reference-counted or non-reference-
1404         * counted MulticastLock.
1405         *
1406         * Reference-counted MulticastLocks keep track of the number of calls
1407         * to {@link #acquire} and {@link #release}, and only stop the
1408         * reception of multicast packets when every call to {@link #acquire}
1409         * has been balanced with a call to {@link #release}.  Non-reference-
1410         * counted MulticastLocks allow the reception of multicast packets
1411         * whenever {@link #acquire} is called and stop accepting multicast
1412         * packets whenever {@link #release} is called.
1413         *
1414         * @param refCounted true if this MulticastLock should keep a reference
1415         * count
1416         */
1417        public void setReferenceCounted(boolean refCounted) {
1418            mRefCounted = refCounted;
1419        }
1420
1421        /**
1422         * Checks whether this MulticastLock is currently held.
1423         *
1424         * @return true if this MulticastLock is held, false otherwise
1425         */
1426        public boolean isHeld() {
1427            synchronized (mBinder) {
1428                return mHeld;
1429            }
1430        }
1431
1432        public String toString() {
1433            String s1, s2, s3;
1434            synchronized (mBinder) {
1435                s1 = Integer.toHexString(System.identityHashCode(this));
1436                s2 = mHeld ? "held; " : "";
1437                if (mRefCounted) {
1438                    s3 = "refcounted: refcount = " + mRefCount;
1439                } else {
1440                    s3 = "not refcounted";
1441                }
1442                return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }";
1443            }
1444        }
1445
1446        @Override
1447        protected void finalize() throws Throwable {
1448            super.finalize();
1449            setReferenceCounted(false);
1450            release();
1451        }
1452    }
1453
1454    /**
1455     * Check multicast filter status.
1456     *
1457     * @return true if multicast packets are allowed.
1458     *
1459     * @hide pending API council approval
1460     */
1461    public boolean isMulticastEnabled() {
1462        try {
1463            return mService.isMulticastEnabled();
1464        } catch (RemoteException e) {
1465            return false;
1466        }
1467    }
1468
1469    /**
1470     * Initialize the multicast filtering to 'on'
1471     * @hide no intent to publish
1472     */
1473    public boolean initializeMulticastFiltering() {
1474        try {
1475            mService.initializeMulticastFiltering();
1476            return true;
1477        } catch (RemoteException e) {
1478             return false;
1479        }
1480    }
1481}
1482