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

Commit 87b8cc38 authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Refactor ListenerMultiplexer with new capabilities

-Store tag string in multiplexer rather than duplicating in every
registration.
-Add support for failure callbacks at listener operation submission
time, in addition to within the listener operation itself.
-Extract request out of ListenerRegistration and into subclass, so that
the multiplexer does not need to have any knowledge of requests.
-New multiplexer specific execute and failure callbacks within
registrations objects, with strongly typed listener operation objects.
-Fixed resetService() to work properly even if the service is still
registered.
-Added registration info as an argument to registerWithService() so that
this doesn't need to be duplicated if a client wants access to this
information.
-Narrow exception handling so that only the proper exception
(RemoteException for binder calls for instance) results in registration
removal, and other unexpected checked exceptions should still crash the
process.
-Various other minor fixes.

Test: manual + presubmit
Change-Id: I6fdec313222ff1ef01a1aa4d27d8ee56b4be25d4
parent 559bf655
Loading
Loading
Loading
Loading
+52 −34
Original line number Diff line number Diff line
@@ -38,71 +38,86 @@ public interface ListenerExecutor {
        void operate(TListener listener) throws Exception;

        /**
         * Called before this operation is to be run. Some operations may be canceled before they
         * are run, in which case this method may not be called. {@link #onPostExecute(boolean)}
         * will only be run if this method was run. This callback is invoked on the calling thread.
         * Called before this operation is to be run. An operation may be canceled before it is run,
         * in which case this method may not be invoked. {@link #onPostExecute(boolean)} will only
         * be invoked if this method was previously invoked. This callback is invoked on the
         * calling thread.
         */
        default void onPreExecute() {}

        /**
         * Called if the operation fails while running. Will not be invoked in the event of a
         * RuntimeException, which will propagate normally. Implementations of
         * {@link ListenerExecutor} have the option to override
         * {@link ListenerExecutor#onOperationFailure(ListenerOperation, Exception)} instead to
         * intercept failures at the class level. This callback is invoked on the executor thread.
         * unchecked exception, which will propagate normally. This callback is invoked on the
         * executor thread.
         */
        default void onFailure(Exception e) {
            // implementations should handle any exceptions that may be thrown
            throw new AssertionError(e);
        }
        default void onFailure(Exception e) {}

        /**
         * Called after the operation is run. This method will always be called if
         * {@link #onPreExecute()} is called. Success implies that the operation was run to
         * completion with no failures. This callback may be invoked on the calling thread or
         * executor thread.
         * Called after the operation may have been run. Will always be invoked for every operation
         * which has previously had {@link #onPreExecute()} invoked. Success implies that the
         * operation was run to completion with no failures. If {@code success} is true, this
         * callback will always be invoked on the executor thread. If {@code success} is false, this
         * callback may be invoked on the calling thread or executor thread.
         */
        default void onPostExecute(boolean success) {}

        /**
         * Called after this operation is complete (which does not imply that it was necessarily
         * run). Will always be called once per operation, no matter if the operation was run or
         * not. Success implies that the operation was run to completion with no failures. This
         * callback may be invoked on the calling thread or executor thread.
         * Will always be called once for every operation submitted to
         * {@link #executeSafely(Executor, Supplier, ListenerOperation)}, no matter if the operation
         * was run or not. This method is always invoked last, after every other callback. Success
         * implies that the operation was run to completion with no failures. If {@code success}
         * is true, this callback will always be invoked on the executor thread. If {@code success}
         * is false, this callback may be invoked on the calling thread or executor thread.
         */
        default void onComplete(boolean success) {}
    }

    /**
     * May be override to handle operation failures at a class level. Will not be invoked in the
     * event of a RuntimeException, which will propagate normally. This callback is invoked on the
     * executor thread.
     * An callback for listener operation failure.
     *
     * @param <TListenerOperation> listener operation type
     */
    default <TListener> void onOperationFailure(ListenerOperation<TListener> operation,
            Exception exception) {
        operation.onFailure(exception);
    interface FailureCallback<TListenerOperation extends ListenerOperation<?>> {

        /**
         * Called if a listener operation fails while running with a checked exception. This
         * callback is invoked on the executor thread.
         */
        void onFailure(TListenerOperation operation, Exception exception);
    }

    /**
     * See {@link #executeSafely(Executor, Supplier, ListenerOperation, FailureCallback)}.
     */
    default <TListener> void executeSafely(Executor executor, Supplier<TListener> listenerSupplier,
            @Nullable ListenerOperation<TListener> operation) {
        executeSafely(executor, listenerSupplier, operation, null);
    }

    /**
     * Executes the given listener operation on the given executor, using the provided listener
     * supplier. If the supplier returns a null value, or a value during the operation that does not
     * match the value prior to the operation, then the operation is considered canceled. If a null
     * operation is supplied, nothing happens.
     * operation is supplied, nothing happens. If a failure callback is supplied, this will be
     * invoked on the executor thread in the event a checked exception is thrown from the listener
     * operation.
     */
    default <TListener> void executeSafely(Executor executor, Supplier<TListener> listenerSupplier,
            @Nullable ListenerOperation<TListener> operation) {
    default <TListener, TListenerOperation extends ListenerOperation<TListener>> void executeSafely(
            Executor executor, Supplier<TListener> listenerSupplier,
            @Nullable TListenerOperation operation,
            @Nullable FailureCallback<TListenerOperation> failureCallback) {
        if (operation == null) {
            return;
        }

        boolean executing = false;
        boolean preexecute = false;
        try {
        TListener listener = listenerSupplier.get();
        if (listener == null) {
            return;
        }

        boolean executing = false;
        boolean preexecute = false;
        try {
            operation.onPreExecute();
            preexecute = true;
            executor.execute(() -> {
@@ -116,7 +131,10 @@ public interface ListenerExecutor {
                    if (e instanceof RuntimeException) {
                        throw (RuntimeException) e;
                    } else {
                        onOperationFailure(operation, e);
                        operation.onFailure(e);
                        if (failureCallback != null) {
                            failureCallback.onFailure(operation, e);
                        }
                    }
                } finally {
                    operation.onPostExecute(success);
+7 −7
Original line number Diff line number Diff line
@@ -475,7 +475,7 @@ public final class LocationRequest implements Parcelable {

    /**
     * Returns the minimum update interval. If location updates are available faster than the
     * request interval then locations will only be delivered if the minimum update interval has
     * request interval then locations will only be updated if the minimum update interval has
     * expired since the last location update.
     *
     * <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
@@ -951,9 +951,9 @@ public final class LocationRequest implements Parcelable {

        /**
         * Sets an explicit minimum update interval. If location updates are available faster than
         * the request interval then locations will only be delivered if the minimum update interval
         * has expired since the last location update. Defaults to no explicit minimum update
         * interval set, which means the minimum update interval is the same as the interval.
         * the request interval then an update will only occur if the minimum update interval has
         * expired since the last location update. Defaults to no explicit minimum update interval
         * set, which means the minimum update interval is the same as the interval.
         *
         * <p class=note><strong>Note:</strong> Some allowance for jitter is already built into the
         * minimum update interval, so you need not worry about updates blocked simply because they
@@ -972,7 +972,7 @@ public final class LocationRequest implements Parcelable {

        /**
         * Clears an explicitly set minimum update interval and reverts to an implicit minimum
         * update interval (ie, the minimum update interval is same value as the interval).
         * update interval (ie, the minimum update interval is the same value as the interval).
         */
        public @NonNull Builder clearMinUpdateIntervalMillis() {
            mMinUpdateIntervalMillis = IMPLICIT_MIN_UPDATE_INTERVAL;
@@ -980,8 +980,8 @@ public final class LocationRequest implements Parcelable {
        }

        /**
         * Sets the minimum update distance between delivered locations. If a potential location
         * update is closer to the last delivered location than the minimum update distance, then
         * Sets the minimum update distance between location updates. If a potential location
         * update is closer to the last location update than the minimum update distance, then
         * the potential location update will not occur. Defaults to 0, which represents no minimum
         * update distance.
         */
+2 −11
Original line number Diff line number Diff line
@@ -16,8 +16,6 @@

package com.android.server.location;

import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;

import android.annotation.Nullable;
import android.location.Location;
import android.location.util.identity.CallerIdentity;
@@ -342,8 +340,7 @@ public abstract class AbstractLocationProvider {
     */
    public final void setRequest(ProviderRequest request) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock
        mExecutor.execute(obtainRunnable(AbstractLocationProvider::onSetRequest, this, request)
                .recycleOnUse());
        mExecutor.execute(() -> onSetRequest(request));
    }

    /**
@@ -356,13 +353,7 @@ public abstract class AbstractLocationProvider {
     */
    public final void sendExtraCommand(int uid, int pid, String command, Bundle extras) {
        // all calls into the provider must be moved onto the provider thread to prevent deadlock

        // the integer boxing done here likely cancels out any gains from removing lambda
        // allocation, but since this an infrequently used api with no real performance needs, we
        // we use pooled lambdas anyways for consistency.
        mExecutor.execute(
                obtainRunnable(AbstractLocationProvider::onExtraCommand, this, uid, pid, command,
                        extras).recycleOnUse());
        mExecutor.execute(() -> onExtraCommand(uid, pid, command, extras));
    }

    /**
+162 −59

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ class PassiveLocationProviderManager extends LocationProviderManager {
    }

    @Override
    protected ProviderRequest mergeRequests(Collection<Registration> registrations) {
    protected ProviderRequest mergeRegistrations(Collection<Registration> registrations) {
        ProviderRequest.Builder providerRequest = new ProviderRequest.Builder()
                .setIntervalMillis(0);

Loading