FileDocCategorySizeDatePackage
TokenWatcher.javaAPI DocAndroid 1.5 API5536Wed May 06 22:41:56 BST 2009android.os

TokenWatcher

public abstract class TokenWatcher extends Object
Helper class that helps you use IBinder objects as reference counted tokens. IBinders make good tokens because we find out when they are removed

Fields Summary
private Runnable
mNotificationTask
private WeakHashMap
mTokens
private Handler
mHandler
private String
mTag
private int
mNotificationQueue
private volatile boolean
mAcquired
Constructors Summary
public TokenWatcher(Handler h, String tag)
Construct the TokenWatcher

param
h A handler to call {@link #acquired} and {@link #released} on. If you don't care, just call it like this, although your thread will have to be a Looper thread. new TokenWatcher(new Handler())
param
tag A debugging tag for this TokenWatcher

        mHandler = h;
        mTag = tag != null ? tag : "TokenWatcher";
    
Methods Summary
public voidacquire(IBinder token, java.lang.String tag)
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.
param
tag A string used by the {@link #dump} method for debugging, to see who has references.

        synchronized (mTokens) {
            // explicitly checked to avoid bogus sendNotification calls because
            // of the WeakHashMap and the GC
            int oldSize = mTokens.size();

            Death d = new Death(token, tag);
            try {
                token.linkToDeath(d, 0);
            } catch (RemoteException e) {
                return;
            }
            mTokens.put(token, d);

            if (oldSize == 0 && !mAcquired) {
                sendNotificationLocked(true);
                mAcquired = true;
            }
        }
    
public abstract voidacquired()
Called when the number of active tokens goes from 0 to 1.

public voidcleanup(IBinder token, boolean unlink)

        synchronized (mTokens) {
            Death d = mTokens.remove(token);
            if (unlink && d != null) {
                d.token.unlinkToDeath(d, 0);
                d.token = null;
            }

            if (mTokens.size() == 0 && mAcquired) {
                sendNotificationLocked(false);
                mAcquired = false;
            }
        }
    
public voiddump()

        synchronized (mTokens) {
            Set<IBinder> keys = mTokens.keySet();
            Log.i(mTag, "Token count: " + mTokens.size());
            int i = 0;
            for (IBinder b: keys) {
                Log.i(mTag, "[" + i + "] " + mTokens.get(b).tag + " - " + b);
                i++;
            }
        }
    
public booleanisAcquired()

        synchronized (mTokens) {
            return mAcquired;
        }
    
public voidrelease(IBinder token)

        cleanup(token, true);
    
public abstract voidreleased()
Called when the number of active tokens goes from 1 to 0.

private voidsendNotificationLocked(boolean on)


       
    
        int value = on ? 1 : 0;
        if (mNotificationQueue == -1) {
            // empty
            mNotificationQueue = value;
            mHandler.post(mNotificationTask);
        }
        else if (mNotificationQueue != value) {
            // it's a pair, so cancel it
            mNotificationQueue = -1;
            mHandler.removeCallbacks(mNotificationTask);
        }
        // else, same so do nothing -- maybe we should warn?