summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
authorCharles He <qiurui@google.com>2017-10-31 09:35:15 +0000
committerCharles He <qiurui@google.com>2017-11-01 09:43:14 +0000
commitcdef147ac370d5bd6206c632c47570a9e024ad8a (patch)
treee4e3c2bb9d683fc2a274f310e1618acc34dab91b /core/java/android
parent01c9c0e4ba3912907030a53123d6a37325cfb646 (diff)
TokenWatcher: fix bug in repeated calls to acquire().
The javadoc of TokenWatcher promised to implement repeated calls to acquire() with the same token as a no-op, but this wasn't the case. When acquire() is called repeatedly with the same token, its associated DeathRecipient object is replaced by a new one. The old DeathRecipient can therefore be destroyed. This is problematic because the finalizer of this DeathRecipient implementation calls release() on the same token, resulting in the token being released unexpectedly. In this CL we properly implement the documented no-op behavior. Bug: 68368071 Test: (First, cherry-pick to internal master) Test: cts-tradefed run cts-dev -m OsTest -t android.os.cts.TokenWatcherTest Test: CTS verifier > Managed provisioning > Device owner tests > LockTask UI Change-Id: Idfad7c88075a510ea1f8527b5a8620121a5dd7bb
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/os/TokenWatcher.java30
1 files changed, 22 insertions, 8 deletions
diff --git a/core/java/android/os/TokenWatcher.java b/core/java/android/os/TokenWatcher.java
index 9b3a2d689693..00333dad1a17 100644
--- a/core/java/android/os/TokenWatcher.java
+++ b/core/java/android/os/TokenWatcher.java
@@ -16,17 +16,23 @@
package android.os;
+import android.util.Log;
+
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.WeakHashMap;
import java.util.Set;
-import android.util.Log;
+import java.util.WeakHashMap;
/**
- * Helper class that helps you use IBinder objects as reference counted
- * tokens. IBinders make good tokens because we find out when they are
- * removed
+ * A TokenWatcher watches a collection of {@link IBinder}s. IBinders are added
+ * to the collection by calling {@link #acquire}, and removed by calling {@link
+ * #release}. IBinders are also implicitly removed when they become weakly
+ * reachable. Each IBinder may be added at most once.
*
+ * The {@link #acquired} method is invoked by posting to the specified handler
+ * whenever the size of the watched collection becomes nonzero. The {@link
+ * #released} method is invoked on the specified handler whenever the size of
+ * the watched collection becomes zero.
*/
public abstract class TokenWatcher
{
@@ -59,15 +65,23 @@ public abstract class TokenWatcher
* Record that this token has been acquired. When acquire is called, and
* the current count is 0, the acquired method is called on the given
* handler.
- *
- * @param token An IBinder object. If this token has already been acquired,
- * no action is taken.
+ *
+ * Note that the same {@code token} can only be acquired once. If this
+ * {@code token} has already been acquired, no action is taken. The first
+ * subsequent call to {@link #release} will release this {@code token}
+ * immediately.
+ *
+ * @param token An IBinder object.
* @param tag A string used by the {@link #dump} method for debugging,
* to see who has references.
*/
public void acquire(IBinder token, String tag)
{
synchronized (mTokens) {
+ if (mTokens.containsKey(token)) {
+ return;
+ }
+
// explicitly checked to avoid bogus sendNotification calls because
// of the WeakHashMap and the GC
int oldSize = mTokens.size();