Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a983cb9 authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Make ListenerMultiplexer more flexible

Previously ListenerMultiplexer attempted to be perscriptive about when
individual listener invocations should be allowed, but this is not
proving flexible enough. So, we allow registrations to invoke listeners
at any time without being perscriptive about it instead.

Test: manual + presubmit
Change-Id: I6ff8c6bd4f3e3af15d6ebc4b484b971df5a8c0e2
parent e30e78ff
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -52,9 +52,11 @@ interface ILocationManager
    void registerLocationListener(String provider, in LocationRequest request, in ILocationListener listener, String packageName, String attributionTag, String listenerId);
    void unregisterLocationListener(in ILocationListener listener);

    void registerLocationPendingIntent(String provider, in LocationRequest request, in PendingIntent intent, String packageName, String attributionTag);
    void registerLocationPendingIntent(String provider, in LocationRequest request, in PendingIntent pendingIntent, String packageName, String attributionTag);
    void unregisterLocationPendingIntent(in PendingIntent intent);

    void injectLocation(in Location location);

    void requestGeofence(in Geofence geofence, in PendingIntent intent, String packageName, String attributionTag);
    void removeGeofence(in PendingIntent intent);

@@ -89,7 +91,6 @@ interface ILocationManager
    void startGnssBatch(long periodNanos, boolean wakeOnFifoFull, String packageName, String attributionTag);
    void flushGnssBatch();
    void stopGnssBatch();
    void injectLocation(in Location location);

    List<String> getAllProviders();
    List<String> getProviders(in Criteria criteria, boolean enabledOnly);
+6 −5
Original line number Diff line number Diff line
@@ -19,12 +19,11 @@ package android.location;
import android.annotation.NonNull;
import android.os.Bundle;

import java.util.concurrent.Executor;

/**
 * Used for receiving notifications from the LocationManager when
 * the location has changed. These methods are called if the
 * LocationListener has been registered with the location manager service
 * using the {@link LocationManager#requestLocationUpdates(String, long, float, LocationListener)}
 * method.
 * Used for receiving notifications when the device location has changed. These methods are called
 * when the listener has been registered with the LocationManager.
 *
 * <div class="special reference">
 * <h3>Developer Guides</h3>
@@ -32,6 +31,8 @@ import android.os.Bundle;
 * <a href="{@docRoot}guide/topics/location/obtaining-user-location.html">Obtaining User
 * Location</a> developer guide.</p>
 * </div>
 *
 * @see LocationManager#requestLocationUpdates(String, LocationRequest, Executor, LocationListener)
 */
public interface LocationListener {

+32 −35
Original line number Diff line number Diff line
@@ -216,15 +216,15 @@ public class LocationManager {
     * Key used for an extra holding a boolean enabled/disabled status value when a provider
     * enabled/disabled event is broadcast using a PendingIntent.
     *
     * @see #requestLocationUpdates(String, long, float, PendingIntent)
     * @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
     */
    public static final String KEY_PROVIDER_ENABLED = "providerEnabled";

    /**
     * Key used for an extra holding a {@link Location} value when a location change is broadcast
     * using a PendingIntent.
     * Key used for an extra holding a {@link Location} value when a location change is sent using
     * a PendingIntent.
     *
     * @see #requestLocationUpdates(String, long, float, PendingIntent)
     * @see #requestLocationUpdates(String, LocationRequest, PendingIntent)
     */
    public static final String KEY_LOCATION_CHANGED = "location";

@@ -1322,29 +1322,28 @@ public class LocationManager {
        Preconditions.checkArgument(provider != null, "invalid null provider");
        Preconditions.checkArgument(locationRequest != null, "invalid null location request");

        try {
            synchronized (sLocationListeners) {
            WeakReference<LocationListenerTransport> reference = sLocationListeners.get(listener);
                WeakReference<LocationListenerTransport> reference = sLocationListeners.get(
                        listener);
                LocationListenerTransport transport = reference != null ? reference.get() : null;
                if (transport == null) {
                    transport = new LocationListenerTransport(listener, executor);
                sLocationListeners.put(listener, new WeakReference<>(transport));
                } else {
                    Preconditions.checkState(transport.isRegistered());
                    transport.setExecutor(executor);
                }

            try {
                // making the service call while under lock is less than ideal since LMS must
                // make sure that callbacks are not made on the same thread - however it is the
                // easiest way to guarantee that clients will not receive callbacks after
                // unregistration is complete.
                mService.registerLocationListener(provider, locationRequest, transport,
                        mContext.getPackageName(), mContext.getAttributionTag(),
                        AppOpsManager.toReceiverId(listener));

                sLocationListeners.put(listener, new WeakReference<>(transport));
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }
    }

    /**
     * Register for location updates from the specified provider, using a {@link LocationRequest},
@@ -1429,23 +1428,17 @@ public class LocationManager {
    public void removeUpdates(@NonNull LocationListener listener) {
        Preconditions.checkArgument(listener != null, "invalid null listener");

        try {
            synchronized (sLocationListeners) {
            WeakReference<LocationListenerTransport> reference = sLocationListeners.remove(
                    listener);
            LocationListenerTransport transport = reference != null ? reference.get() : null;
                WeakReference<LocationListenerTransport> ref = sLocationListeners.remove(listener);
                LocationListenerTransport transport = ref != null ? ref.get() : null;
                if (transport != null) {
                    transport.unregister();

                try {
                    // making the service call while under lock is less than ideal since LMS must
                    // make sure that callbacks are not made on the same thread - however it is the
                    // easiest way to guarantee that clients will not receive callbacks after
                    // unregistration is complete.
                    mService.unregisterLocationListener(transport);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                }
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

@@ -2568,7 +2561,7 @@ public class LocationManager {
        @Nullable private volatile LocationListener mListener;

        LocationListenerTransport(LocationListener listener, Executor executor) {
            Preconditions.checkArgument(listener != null, "invalid null listener/callback");
            Preconditions.checkArgument(listener != null, "invalid null listener");
            mListener = listener;
            setExecutor(executor);
        }
@@ -2578,6 +2571,10 @@ public class LocationManager {
            mExecutor = executor;
        }

        boolean isRegistered() {
            return mListener != null;
        }

        void unregister() {
            mListener = null;
        }
+11 −3
Original line number Diff line number Diff line
@@ -171,7 +171,9 @@ public abstract class LocationProviderBase {
        if (manager != null) {
            try {
                manager.onSetAllowed(mAllowed);
            } catch (RemoteException | RuntimeException e) {
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } catch (RuntimeException e) {
                Log.w(mTag, e);
            }
        }
@@ -191,7 +193,9 @@ public abstract class LocationProviderBase {
        if (manager != null) {
            try {
                manager.onSetProperties(mProperties);
            } catch (RemoteException | RuntimeException e) {
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } catch (RuntimeException e) {
                Log.w(mTag, e);
            }
        }
@@ -248,7 +252,9 @@ public abstract class LocationProviderBase {

            try {
                manager.onReportLocation(location);
            } catch (RemoteException | RuntimeException e) {
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            } catch (RuntimeException e) {
                Log.w(mTag, e);
            }
        }
@@ -339,6 +345,8 @@ public abstract class LocationProviderBase {
                    manager.onSetProperties(mProperties);
                    manager.onSetAllowed(mAllowed);
                } catch (RemoteException e) {
                    throw e.rethrowFromSystemServer();
                } catch (RuntimeException e) {
                    Log.w(mTag, e);
                }

+3 −3
Original line number Diff line number Diff line
@@ -556,8 +556,8 @@ public class LocationManagerService extends ILocationManager.Stub {

    @Override
    public void registerLocationListener(String provider, LocationRequest request,
            ILocationListener listener, String packageName, String attributionTag,
            String listenerId) {
            ILocationListener listener, String packageName, @Nullable String attributionTag,
            @Nullable String listenerId) {
        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
                listenerId);
        int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
@@ -582,7 +582,7 @@ public class LocationManagerService extends ILocationManager.Stub {

    @Override
    public void registerLocationPendingIntent(String provider, LocationRequest request,
            PendingIntent pendingIntent, String packageName, String attributionTag) {
            PendingIntent pendingIntent, String packageName, @Nullable String attributionTag) {
        CallerIdentity identity = CallerIdentity.fromBinder(mContext, packageName, attributionTag,
                AppOpsManager.toReceiverId(pendingIntent));
        int permissionLevel = LocationPermissions.getPermissionLevel(mContext, identity.getUid(),
Loading