FileDocCategorySizeDatePackage
RemoteListenerHelper.javaAPI DocAndroid 5.1 API7780Thu Mar 12 22:22:42 GMT 2015com.android.server.location

RemoteListenerHelper

public abstract class RemoteListenerHelper extends Object
A helper class, that handles operations in remote listeners, and tracks for remote process death.

Fields Summary
protected static final int
RESULT_SUCCESS
protected static final int
RESULT_NOT_AVAILABLE
protected static final int
RESULT_NOT_SUPPORTED
protected static final int
RESULT_GPS_LOCATION_DISABLED
protected static final int
RESULT_INTERNAL_ERROR
private final android.os.Handler
mHandler
private final String
mTag
private final HashMap
mListenerMap
private boolean
mIsRegistered
private boolean
mHasIsSupported
private boolean
mIsSupported
Constructors Summary
protected RemoteListenerHelper(android.os.Handler handler, String name)


         
        Preconditions.checkNotNull(name);
        mHandler = handler;
        mTag = name;
    
Methods Summary
public booleanaddListener(TListener listener)

        Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
        IBinder binder = listener.asBinder();
        LinkedListener deathListener = new LinkedListener(listener);
        synchronized (mListenerMap) {
            if (mListenerMap.containsKey(binder)) {
                // listener already added
                return true;
            }
            try {
                binder.linkToDeath(deathListener, 0 /* flags */);
            } catch (RemoteException e) {
                // if the remote process registering the listener is already death, just swallow the
                // exception and return
                Log.v(mTag, "Remote listener already died.", e);
                return false;
            }
            mListenerMap.put(binder, deathListener);

            // update statuses we already know about, starting from the ones that will never change
            int result;
            if (!isAvailableInPlatform()) {
                result = RESULT_NOT_AVAILABLE;
            } else if (mHasIsSupported && !mIsSupported) {
                result = RESULT_NOT_SUPPORTED;
            } else if (!isGpsEnabled()) {
                result = RESULT_GPS_LOCATION_DISABLED;
            } else if (!tryRegister()) {
                // only attempt to register if GPS is enabled, otherwise we will register once GPS
                // becomes available
                result = RESULT_INTERNAL_ERROR;
            } else if (mHasIsSupported && mIsSupported) {
                result = RESULT_SUCCESS;
            } else {
                // at this point if the supported flag is not set, the notification will be sent
                // asynchronously in the future
                return true;
            }
            post(listener, getHandlerOperation(result));
        }
        return true;
    
protected voidforeach(com.android.server.location.RemoteListenerHelper$ListenerOperation operation)

        synchronized (mListenerMap) {
            foreachUnsafe(operation);
        }
    
private voidforeachUnsafe(com.android.server.location.RemoteListenerHelper$ListenerOperation operation)

        for (LinkedListener linkedListener : mListenerMap.values()) {
            post(linkedListener.getUnderlyingListener(), operation);
        }
    
protected abstract com.android.server.location.RemoteListenerHelper$ListenerOperationgetHandlerOperation(int result)

protected abstract voidhandleGpsEnabledChanged(boolean enabled)

protected abstract booleanisAvailableInPlatform()

protected abstract booleanisGpsEnabled()

public voidonGpsEnabledChanged(boolean enabled)

        // handle first the sub-class implementation, so any error in registration can take
        // precedence
        handleGpsEnabledChanged(enabled);
        synchronized (mListenerMap) {
            if (!enabled) {
                tryUnregister();
                return;
            }
            if (mListenerMap.isEmpty()) {
                return;
            }
            if (tryRegister()) {
                // registration was successful, there is no need to update the state
                return;
            }
            ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
            foreachUnsafe(operation);
        }
    
private voidpost(TListener listener, com.android.server.location.RemoteListenerHelper$ListenerOperation operation)

        if (operation != null) {
            mHandler.post(new HandlerRunnable(listener, operation));
        }
    
protected abstract booleanregisterWithService()

public voidremoveListener(TListener listener)

        Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener.");
        IBinder binder = listener.asBinder();
        LinkedListener linkedListener;
        synchronized (mListenerMap) {
            linkedListener = mListenerMap.remove(binder);
            if (mListenerMap.isEmpty()) {
                tryUnregister();
            }
        }
        if (linkedListener != null) {
            binder.unlinkToDeath(linkedListener, 0 /* flags */);
        }
    
protected voidsetSupported(boolean value, com.android.server.location.RemoteListenerHelper$ListenerOperation notifier)

        synchronized (mListenerMap) {
            mHasIsSupported = true;
            mIsSupported = value;
            foreachUnsafe(notifier);
        }
    
private booleantryRegister()

        if (!mIsRegistered) {
            mIsRegistered = registerWithService();
        }
        return mIsRegistered;
    
private voidtryUnregister()

        if (!mIsRegistered) {
            return;
        }
        unregisterFromService();
        mIsRegistered = false;
    
protected abstract voidunregisterFromService()