From 41c104339951e0e5e78240e1f48455c21b3ba5fd Mon Sep 17 00:00:00 2001 From: Robert Greenwalt Date: Wed, 29 Jul 2009 16:18:38 -0700 Subject: Fix MulticastLock API to match WifiLock API. Adds option to make lock refcounted or not. Fixes 2017680. --- api/current.xml | 13 +++++ wifi/java/android/net/wifi/WifiManager.java | 78 ++++++++++++++++++++++++----- 2 files changed, 79 insertions(+), 12 deletions(-) diff --git a/api/current.xml b/api/current.xml index 337a3d3..e0ea966 100644 --- a/api/current.xml +++ b/api/current.xml @@ -79956,6 +79956,19 @@ visibility="public" > + + + + 0) : (!mHeld)) { try { mService.acquireMulticastLock(mBinder, mTag); synchronized (WifiManager.this) { @@ -926,9 +939,9 @@ public class WifiManager { } mActiveLockCount++; } - mHeld = true; } catch (RemoteException ignore) { } + mHeld = true; } } } @@ -937,6 +950,18 @@ public class WifiManager { * Unlocks Wifi Multicast, restoring the filter of packets * not addressed specifically to this device and saving power. * + * If this MulticastLock is reference-counted, each call to + * {@code release} will decrement the reference count, and the + * multicast packets will only stop being received when the reference + * count reaches zero. If the reference count goes below zero (that + * is, if {@code release} is called a greater number of times than + * {@link #acquire}), an exception is thrown. + * + * If this MulticastLock is not reference-counted, the first call to + * {@code release} (after the radio was multicast locked using + * {@linke #acquire}) will unlock the multicast, and subsequent calls + * will be ignored. + * * 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 @@ -947,20 +972,43 @@ public class WifiManager { */ public void release() { synchronized (mBinder) { - if (mHeld) { + if (mRefCounted ? (--mRefCount == 0) : (mHeld)) { try { mService.releaseMulticastLock(); synchronized (WifiManager.this) { mActiveLockCount--; } - mHeld = false; } catch (RemoteException ignore) { } + mHeld = false; + } + if (mRefCount < 0) { + throw new RuntimeException("MulticastLock under-locked " + + mTag); } } } /** + * Controls whether this is a reference-counted or non-reference- + * counted MulticastLock. + * + * Reference-counted MulticastLocks keep track of the number of calls + * to {@link #acquire} and {@link #release}, and only stop the + * reception of multicast packets when every call to {@link #acquire} + * has been balanced with a call to {@link #release}. Non-reference- + * counted MulticastLocks allow the reception of multicast packets + * whenever {@link #acquire} is called and stop accepting multicast + * packets whenever {@link #release} is called. + * + * @param refCounted true if this MulticastLock should keep a reference + * count + */ + public void setReferenceCounted(boolean refCounted) { + mRefCounted = refCounted; + } + + /** * Checks whether this MulticastLock is currently held. * * @return true if this MulticastLock is held, false otherwise @@ -972,17 +1020,23 @@ public class WifiManager { } public String toString() { - String s1, s2; + String s1, s2, s3; synchronized (mBinder) { s1 = Integer.toHexString(System.identityHashCode(this)); s2 = mHeld ? "held; " : ""; - return "MulticastLock{ " + s1 + "; " + s2 + " }"; + if (mRefCounted) { + s3 = "refcounted: refcount = " + mRefCount; + } else { + s3 = "not refcounted"; + } + return "MulticastLock{ " + s1 + "; " + s2 + s3 + " }"; } } @Override protected void finalize() throws Throwable { super.finalize(); + setReferenceCounted(false); release(); } } -- cgit v1.1