diff options
| author | Charles He <qiurui@google.com> | 2017-10-31 09:35:15 +0000 |
|---|---|---|
| committer | Charles He <qiurui@google.com> | 2017-11-01 09:43:14 +0000 |
| commit | cdef147ac370d5bd6206c632c47570a9e024ad8a (patch) | |
| tree | e4e3c2bb9d683fc2a274f310e1618acc34dab91b /core/java/android | |
| parent | 01c9c0e4ba3912907030a53123d6a37325cfb646 (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.java | 30 |
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(); |
