diff options
-rw-r--r-- | api/current.xml | 66 | ||||
-rw-r--r-- | core/res/AndroidManifest.xml | 7 | ||||
-rw-r--r-- | core/res/res/values/strings.xml | 9 | ||||
-rw-r--r-- | services/java/com/android/server/WifiService.java | 14 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/IWifiManager.aidl | 4 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiManager.java | 143 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateTracker.java | 6 |
7 files changed, 202 insertions, 47 deletions
diff --git a/api/current.xml b/api/current.xml index ce1b726..bf3044e 100644 --- a/api/current.xml +++ b/api/current.xml @@ -309,6 +309,17 @@ visibility="public" > </field> +<field name="CHANGE_WIFI_MULTICAST_STATE" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.permission.CHANGE_WIFI_MULTICAST_STATE"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="CHANGE_WIFI_STATE" type="java.lang.String" transient="false" @@ -77087,6 +77098,19 @@ <parameter name="rssiB" type="int"> </parameter> </method> +<method name="createMulticastLock" + return="android.net.wifi.WifiManager.MulticastLock" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="tag" type="java.lang.String"> +</parameter> +</method> <method name="createWifiLock" return="android.net.wifi.WifiManager.WifiLock" abstract="false" @@ -77579,6 +77603,48 @@ > </field> </class> +<class name="WifiManager.MulticastLock" + extends="java.lang.Object" + abstract="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="acquire" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="isHeld" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +<method name="release" + return="void" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +</method> +</class> <class name="WifiManager.WifiLock" extends="java.lang.Object" abstract="false" diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index fbaef5f..36f7dfb 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -644,6 +644,13 @@ android:description="@string/permdesc_changeWifiState" android:label="@string/permlab_changeWifiState" /> + <!-- Allows applications to enter Wi-Fi Multicast mode --> + <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" + android:permissionGroup="android.permission-group.SYSTEM_TOOLS" + android:protectionLevel="dangerous" + android:description="@string/permdesc_changeWifiMulticastState" + android:label="@string/permlab_changeWifiMulticastState" /> + <!-- Allows applications to discover and pair bluetooth devices --> <permission android:name="android.permission.BLUETOOTH_ADMIN" android:permissionGroup="android.permission-group.SYSTEM_TOOLS" diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 8b2689b..e311abd 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1005,6 +1005,15 @@ configured Wi-Fi networks.</string> <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permlab_changeWifiMulticastState">allow Wi-Fi Multicast + reception</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> + <string name="permdesc_changeWifiMulticastState">Allows an application to + receive packets not directly addressed to your device. This can be + useful when discovering services offered near by. It uses more power + than the non-multicast mode.</string> + + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_bluetoothAdmin">bluetooth administration</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permdesc_bluetoothAdmin">Allows an application to configure diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 5fa8701..1528ba3 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -588,6 +588,12 @@ public class WifiService extends IWifiManager.Stub { } + private void enforceMulticastChangePermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, + "WifiService"); + } + /** * see {@link WifiManager#getWifiState()} * @return One of {@link WifiManager#WIFI_STATE_DISABLED}, @@ -1930,8 +1936,8 @@ public class WifiService extends IWifiManager.Stub { } } - public void enableMulticast(IBinder binder, String tag) { - enforceChangePermission(); + public void acquireMulticastLock(IBinder binder, String tag) { + enforceMulticastChangePermission(); synchronized (mMulticasters) { mMulticastEnabled++; @@ -1953,8 +1959,8 @@ public class WifiService extends IWifiManager.Stub { } } - public void disableMulticast() { - enforceChangePermission(); + public void releaseMulticastLock() { + enforceMulticastChangePermission(); int uid = Binder.getCallingUid(); synchronized (mMulticasters) { diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index 7c3af69..3d65d3c 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -72,8 +72,8 @@ interface IWifiManager boolean isMulticastEnabled(); - void enableMulticast(IBinder binder, String tag); + void acquireMulticastLock(IBinder binder, String tag); - void disableMulticast(); + void releaseMulticastLock(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index 1a7caef..5b8ced6 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -824,62 +824,127 @@ public class WifiManager { return new WifiLock(WIFI_MODE_FULL, tag); } + /** - * Check multicast filter status. + * Create a new MulticastLock * - * @return true if multicast packets are allowed. + * @param tag a tag for the MulticastLock to identify it in debugging + * messages. * - * @hide pending API council approval + * @return a new, unacquired MulticastLock with the given tag. + * + * @see MulticastLock */ - public boolean isMulticastEnabled() { - try { - return mService.isMulticastEnabled(); - } catch (RemoteException e) { - return false; - } + public MulticastLock createMulticastLock(String tag) { + return new MulticastLock(tag); } /** - * Turn on the reception of multicast packets. - * The default behavior is to disable multicast packets as they - * have a noticable negative effect on battery life. An - * application can turn them on, but should not leave it on for longer - * than needed. When the app quits (or crashes) its request will - * be reverted. - * - * @param tag a string associated with this request for debugging. - * - * @return true on success - * - * @see #disableMulticast - * - * @hide pending API council approval + * Allows an application to receive Wifi Multicast packets. + * Normally the Wifi stack filters out packets not explicitly + * addressed to this device. Acquring a MulticastLock will + * cause the stack to receive packets addressed to multicast + * addresses. Processing these extra packets can cause a noticable + * battery drain and should be disabled when not needed */ - public boolean enableMulticast(String tag) { - try { - mService.enableMulticast(new Binder(), tag); - return true; - } catch (RemoteException e) { - return false; + public class MulticastLock { + private String mTag; + private final IBinder mBinder; + private boolean mHeld; + + private MulticastLock(String tag) { + mTag = tag; + mBinder = new Binder(); + mHeld = false; + } + + /** + * Locks Wifi Multicast on until {@link #release} is called. + * + * The first call to {@code acquire} will lock the Multicast on + * but subsequent calls will be ignored. Only one call to + * {@link #release} will be required, regardless of the number of + * times that {@code acquire} is called. + * + * Note that other applications may also lock Wifi Multicast on. + * Only they can relinquish their lock. + * + * Also note that applications cannot leave Multicast locked on. + * When an app exits or crashes, any Multicast locks will be released. + */ + public void acquire() { + synchronized (mBinder) { + if (!mHeld) { + try { + mService.acquireMulticastLock(mBinder, mTag); + mHeld = true; + } catch (RemoteException ignore) { + } + } + } + } + + /** + * Unlocks Wifi Multicast, restoring the filter of packets + * not addressed specifically to this device and saving power. + * + * Note that if any other Wifi Multicast Locks are still outstanding + * this {@code release} call will not have an immediate effect. Only + * when all applications have released all their Multicast Locks will + * the Multicast filter be turned back on. + * + * Also note that when an app exits or crashes all of its Multicast + * Locks will be automatically released. + */ + public void release() { + synchronized (mBinder) { + if (mHeld) { + try { + mService.releaseMulticastLock(); + mHeld = false; + } catch (RemoteException ignore) { + } + } + } + } + + /** + * Checks whether this MulticastLock is currently held. + * + * @return true if this MulticastLock is held, false otherwise + */ + public boolean isHeld() { + synchronized (mBinder) { + return mHeld; + } + } + + public String toString() { + String s1, s2; + synchronized (mBinder) { + s1 = Integer.toHexString(System.identityHashCode(this)); + s2 = mHeld ? "held; " : ""; + return "MulticastLock{ " + s1 + "; " + s2 + " }"; + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + release(); } } /** - * Return to the default multicast-off setting. - * Note that if others had turned on Multicast reception, your - * call will not turn it back off - they must also turn off their - * request for multicast reception. - * - * @return true on success + * Check multicast filter status. * - * @see #enableMulticast + * @return true if multicast packets are allowed. * * @hide pending API council approval */ - public boolean disableMulticast() { + public boolean isMulticastEnabled() { try { - mService.disableMulticast(); - return true; + return mService.isMulticastEnabled(); } catch (RemoteException e) { return false; } diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 6771136..2fbc779 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -747,8 +747,10 @@ public class WifiStateTracker extends NetworkStateTracker { * first and then off.. if nobody else wants it on it'll be * off then and it's all synchronized within the API. */ - mWM.enableMulticast("WifiStateTracker"); - mWM.disableMulticast(); + WifiManager.MulticastLock l = + mWM.createMulticastLock("WifiStateTracker"); + l.acquire(); + l.release(); if (mBluetoothA2dp == null) { mBluetoothA2dp = new BluetoothA2dp(mContext); |