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

Commit 43d10670 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add fullTracking to registerGnssMeasurementsCallback (implementation)"

parents 221588b6 519694b5
Loading
Loading
Loading
Loading
+101 −28
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.Preconditions;

import java.util.Objects;
import java.util.concurrent.Executor;
import java.util.function.Consumer;

@@ -35,26 +36,34 @@ import java.util.function.Consumer;
 *
 * @hide
 */
abstract class AbstractListenerManager<T> {
abstract class AbstractListenerManager<TRequest, TListener> {

    private static class Registration<T> {
    private static class Registration<TRequest, TListener> {
        private final Executor mExecutor;
        @Nullable private volatile T mListener;
        @Nullable private TRequest mRequest;
        @Nullable private volatile TListener mListener;

        private Registration(Executor executor, T listener) {
        private Registration(@Nullable TRequest request, Executor executor, TListener listener) {
            Preconditions.checkArgument(listener != null, "invalid null listener/callback");
            Preconditions.checkArgument(executor != null, "invalid null executor");
            mExecutor = executor;
            mListener = listener;
            mRequest = request;
        }

        @Nullable
        public TRequest getRequest() {
            return mRequest;
        }

        private void unregister() {
            mRequest = null;
            mListener = null;
        }

        private void execute(Consumer<T> operation) {
        private void execute(Consumer<TListener> operation) {
            mExecutor.execute(() -> {
                T listener = mListener;
                TListener listener = mListener;
                if (listener == null) {
                    return;
                }
@@ -71,71 +80,135 @@ abstract class AbstractListenerManager<T> {
    }

    @GuardedBy("mListeners")
    private final ArrayMap<Object, Registration<T>> mListeners = new ArrayMap<>();
    private final ArrayMap<Object, Registration<TRequest, TListener>> mListeners =
            new ArrayMap<>();

    public boolean addListener(@NonNull T listener, @NonNull Handler handler)
    @GuardedBy("mListeners")
    @Nullable
    private TRequest mMergedRequest;

    public boolean addListener(@NonNull TListener listener, @NonNull Handler handler)
            throws RemoteException {
        return addInternal(listener, handler);
        return addInternal(/* request= */ null, listener, handler);
    }

    public boolean addListener(@NonNull T listener, @NonNull Executor executor)
    public boolean addListener(@NonNull TListener listener, @NonNull Executor executor)
            throws RemoteException {
        return addInternal(listener, executor);
        return addInternal(/* request= */ null, listener, executor);
    }

    protected final boolean addInternal(@NonNull Object listener, @NonNull Handler handler)
            throws RemoteException {
        return addInternal(listener, new HandlerExecutor(handler));
    public boolean addListener(@Nullable TRequest request, @NonNull TListener listener,
            @NonNull Handler handler) throws RemoteException {
        return addInternal(request, listener, handler);
    }

    public boolean addListener(@Nullable TRequest request, @NonNull TListener listener,
            @NonNull Executor executor) throws RemoteException {
        return addInternal(request, listener, executor);
    }

    protected final boolean addInternal(@Nullable TRequest request, @NonNull Object listener,
            @NonNull Handler handler) throws RemoteException {
        return addInternal(request, listener, new HandlerExecutor(handler));
    }

    protected final boolean addInternal(@NonNull Object listener, @NonNull Executor executor)
    protected final boolean addInternal(@Nullable TRequest request, @NonNull Object listener,
            @NonNull Executor executor)
            throws RemoteException {
        Preconditions.checkArgument(listener != null, "invalid null listener/callback");
        return addInternal(listener, new Registration<>(executor, convertKey(listener)));
        return addInternal(listener, new Registration<>(request, executor, convertKey(listener)));
    }

    private boolean addInternal(Object key, Registration<T> registration) throws RemoteException {
    private boolean addInternal(Object key, Registration<TRequest, TListener> registration)
            throws RemoteException {
        Preconditions.checkNotNull(registration);

        synchronized (mListeners) {
            if (mListeners.isEmpty() && !registerService()) {
                return false;
            }
            Registration<T> oldRegistration = mListeners.put(key, registration);
            boolean initialRequest = mListeners.isEmpty();

            Registration<TRequest, TListener> oldRegistration = mListeners.put(key, registration);
            if (oldRegistration != null) {
                oldRegistration.unregister();
            }
            TRequest merged = mergeRequests();

            if (initialRequest || !Objects.equals(merged, mMergedRequest)) {
                mMergedRequest = merged;
                if (!initialRequest) {
                    unregisterService();
                }
                registerService(mMergedRequest);
            }

            return true;
        }
    }

    public void removeListener(Object listener) throws RemoteException {
        synchronized (mListeners) {
            Registration<T> oldRegistration = mListeners.remove(listener);
            Registration<TRequest, TListener> oldRegistration = mListeners.remove(listener);
            if (oldRegistration == null) {
                return;
            }
            oldRegistration.unregister();

            if (mListeners.isEmpty()) {
            boolean lastRequest = mListeners.isEmpty();
            TRequest merged = lastRequest ? null : mergeRequests();
            boolean newRequest = !lastRequest && !Objects.equals(merged, mMergedRequest);

            if (lastRequest || newRequest) {
                unregisterService();
                mMergedRequest = merged;
                if (newRequest) {
                    registerService(mMergedRequest);
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    protected T convertKey(@NonNull Object listener) {
        return (T) listener;
    protected TListener convertKey(@NonNull Object listener) {
        return (TListener) listener;
    }

    protected abstract boolean registerService() throws RemoteException;
    protected abstract boolean registerService(TRequest request) throws RemoteException;
    protected abstract void unregisterService() throws RemoteException;

    protected void execute(Consumer<T> operation) {
    @Nullable
    protected TRequest merge(@NonNull TRequest[] requests) {
        for (TRequest request : requests) {
            Preconditions.checkArgument(request == null,
                    "merge() has to be overridden for non-null requests.");
        }
        return null;
    }

    protected void execute(Consumer<TListener> operation) {
        synchronized (mListeners) {
            for (Registration<T> registration : mListeners.values()) {
            for (Registration<TRequest, TListener> registration : mListeners.values()) {
                registration.execute(operation);
            }
        }
    }

    @GuardedBy("mListeners")
    @SuppressWarnings("unchecked")
    @Nullable
    private TRequest mergeRequests() {
        Preconditions.checkState(Thread.holdsLock(mListeners));

        if (mListeners.isEmpty()) {
            return null;
        }

        if (mListeners.size() == 1) {
            return mListeners.valueAt(0).getRequest();
        }

        TRequest[] requests = (TRequest[]) new Object[mListeners.size()];
        for (int index = 0; index < mListeners.size(); index++) {
            requests[index] = mListeners.valueAt(index).getRequest();
        }
        return merge(requests);
    }
}
+5 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssStatusListener;
@@ -69,8 +70,10 @@ interface ILocationManager
        double upperRightLatitude, double upperRightLongitude, int maxResults,
        in GeocoderParams params, out List<Address> addrs);

    boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener,
             String packageName, String featureId, String listenerIdentifier);
    boolean addGnssMeasurementsListener(in GnssRequest request,
            in IGnssMeasurementsListener listener,
            String packageName, String featureId,
            String listenerIdentifier);
    void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
            in String packageName);
    long getGnssCapabilities(in String packageName);
+31 −15
Original line number Diff line number Diff line
@@ -2199,7 +2199,7 @@ public class LocationManager {
     * Registers a GNSS Measurement callback.
     *
     * @param request  extra parameters to pass to GNSS measurement provider. For example, if {@link
     *                 GnssRequest#isFullTrackingEnabled()} is true, GNSS chipset switches off duty
     *                 GnssRequest#isFullTracking()} is true, GNSS chipset switches off duty
     *                 cycling.
     * @param executor the executor that the callback runs on.
     * @param callback a {@link GnssMeasurementsEvent.Callback} object to register.
@@ -2216,7 +2216,12 @@ public class LocationManager {
            @NonNull GnssRequest request,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull GnssMeasurementsEvent.Callback callback) {
        throw new RuntimeException();
        Preconditions.checkArgument(request != null, "invalid null request");
        try {
            return mGnssMeasurementsListenerManager.addListener(request, callback, executor);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
@@ -2763,8 +2768,7 @@ public class LocationManager {
    }

    private class GnssStatusListenerManager extends
            AbstractListenerManager<GnssStatus.Callback> {

            AbstractListenerManager<Void, GnssStatus.Callback> {
        @Nullable
        private IGnssStatusListener mListenerTransport;

@@ -2782,19 +2786,19 @@ public class LocationManager {

        public boolean addListener(@NonNull GpsStatus.Listener listener, @NonNull Executor executor)
                throws RemoteException {
            return addInternal(listener, executor);
            return addInternal(null, listener, executor);
        }

        public boolean addListener(@NonNull OnNmeaMessageListener listener,
                @NonNull Handler handler)
                throws RemoteException {
            return addInternal(listener, handler);
            return addInternal(null, listener, handler);
        }

        public boolean addListener(@NonNull OnNmeaMessageListener listener,
                @NonNull Executor executor)
                throws RemoteException {
            return addInternal(listener, executor);
            return addInternal(null, listener, executor);
        }

        @Override
@@ -2833,7 +2837,7 @@ public class LocationManager {
        }

        @Override
        protected boolean registerService() throws RemoteException {
        protected boolean registerService(Void ignored) throws RemoteException {
            Preconditions.checkState(mListenerTransport == null);

            GnssStatusListener transport = new GnssStatusListener();
@@ -2893,17 +2897,17 @@ public class LocationManager {
    }

    private class GnssMeasurementsListenerManager extends
            AbstractListenerManager<GnssMeasurementsEvent.Callback> {
            AbstractListenerManager<GnssRequest, GnssMeasurementsEvent.Callback> {

        @Nullable
        private IGnssMeasurementsListener mListenerTransport;

        @Override
        protected boolean registerService() throws RemoteException {
        protected boolean registerService(GnssRequest request) throws RemoteException {
            Preconditions.checkState(mListenerTransport == null);

            GnssMeasurementsListener transport = new GnssMeasurementsListener();
            if (mService.addGnssMeasurementsListener(transport, mContext.getPackageName(),
            if (mService.addGnssMeasurementsListener(request, transport, mContext.getPackageName(),
                    mContext.getFeatureId(), "gnss measurement callback")) {
                mListenerTransport = transport;
                return true;
@@ -2920,6 +2924,18 @@ public class LocationManager {
            mListenerTransport = null;
        }

        @Override
        @Nullable
        protected GnssRequest merge(@NonNull GnssRequest[] requests) {
            Preconditions.checkArgument(requests.length > 0);
            for (GnssRequest request : requests) {
                if (request.isFullTracking()) {
                    return request;
                }
            }
            return requests[0];
        }

        private class GnssMeasurementsListener extends IGnssMeasurementsListener.Stub {
            @Override
            public void onGnssMeasurementsReceived(final GnssMeasurementsEvent event) {
@@ -2934,13 +2950,13 @@ public class LocationManager {
    }

    private class GnssNavigationMessageListenerManager extends
            AbstractListenerManager<GnssNavigationMessage.Callback> {
            AbstractListenerManager<Void, GnssNavigationMessage.Callback> {

        @Nullable
        private IGnssNavigationMessageListener mListenerTransport;

        @Override
        protected boolean registerService() throws RemoteException {
        protected boolean registerService(Void ignored) throws RemoteException {
            Preconditions.checkState(mListenerTransport == null);

            GnssNavigationMessageListener transport = new GnssNavigationMessageListener();
@@ -2975,13 +2991,13 @@ public class LocationManager {
    }

    private class BatchedLocationCallbackManager extends
            AbstractListenerManager<BatchedLocationCallback> {
            AbstractListenerManager<Void, BatchedLocationCallback> {

        @Nullable
        private IBatchedLocationCallback mListenerTransport;

        @Override
        protected boolean registerService() throws RemoteException {
        protected boolean registerService(Void ignored) throws RemoteException {
            Preconditions.checkState(mListenerTransport == null);

            BatchedLocationCallback transport = new BatchedLocationCallback();
+6 −3
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.GnssMeasurementCorrections;
import android.location.GnssRequest;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssNavigationMessageListener;
@@ -2287,12 +2288,14 @@ public class LocationManagerService extends ILocationManager.Stub {
    }

    @Override
    public boolean addGnssMeasurementsListener(IGnssMeasurementsListener listener,
            String packageName, String featureId, String listenerIdentifier) {
    public boolean addGnssMeasurementsListener(@Nullable GnssRequest request,
            IGnssMeasurementsListener listener,
            String packageName, String featureId,
            String listenerIdentifier) {
        Objects.requireNonNull(listenerIdentifier);

        return mGnssManagerService != null && mGnssManagerService.addGnssMeasurementsListener(
                listener, packageName, featureId, listenerIdentifier);
                request, listener, packageName, featureId, listenerIdentifier);
    }

    @Override
+11 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@@ -37,22 +38,31 @@ public class LocationManagerServiceUtils {
    /**
     * Listener that can be linked to a binder.
     * @param <TListener> listener type
     * @param <TRequest> request type
     */
    public static class LinkedListener<TListener> extends
    public static class LinkedListener<TRequest, TListener> extends
            LinkedListenerBase {
        @Nullable protected final TRequest mRequest;
        private final TListener mListener;
        private final Consumer<TListener> mBinderDeathCallback;

        public LinkedListener(
                @Nullable TRequest request,
                @NonNull TListener listener,
                String listenerName,
                @NonNull CallerIdentity callerIdentity,
                @NonNull Consumer<TListener> binderDeathCallback) {
            super(callerIdentity, listenerName);
            mListener = listener;
            mRequest = request;
            mBinderDeathCallback = binderDeathCallback;
        }

        @Nullable
        public TRequest getRequest() {
            return mRequest;
        }

        @Override
        public void binderDied() {
            if (D) Log.d(TAG, "Remote " + mListenerName + " died.");
Loading