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

Commit 93ff5b8c authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Ameliorate geocoder causing ANRs

-Move geocoder onto background thread since it's network bound.
-Add timeout for blocking binder operations to help release binder
threads for old APIs that still use this deprecated functionality.

Bug: 140252195
Test: atest GeocoderTest
Change-Id: I32221a1edd16c0e891fc7ddf28ae214c14c4da90
parent cabc32d2
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * Find the best Service, and bind to it.
@@ -64,6 +66,7 @@ public class ServiceWatcher implements ServiceConnection {
    public static final String EXTRA_SERVICE_VERSION = "serviceVersion";
    public static final String EXTRA_SERVICE_IS_MULTIUSER = "serviceIsMultiuser";

    private static final long BLOCKING_BINDER_TIMEOUT_MS = 30 * 1000;

    /** Function to run on binder interface. */
    public interface BinderRunner {
@@ -402,7 +405,7 @@ public class ServiceWatcher implements ServiceConnection {
                    return defaultValue;
                }
            });
        } catch (InterruptedException e) {
        } catch (InterruptedException | TimeoutException e) {
            return defaultValue;
        }
    }
@@ -439,7 +442,8 @@ public class ServiceWatcher implements ServiceConnection {
        }
    }

    private <T> T runOnHandlerBlocking(Callable<T> c) throws InterruptedException {
    private <T> T runOnHandlerBlocking(Callable<T> c)
            throws InterruptedException, TimeoutException {
        if (Looper.myLooper() == mHandler.getLooper()) {
            try {
                return c.call();
@@ -451,7 +455,12 @@ public class ServiceWatcher implements ServiceConnection {
            FutureTask<T> task = new FutureTask<>(c);
            mHandler.post(task);
            try {
                return task.get();
                // timeout will unblock callers, in particular if the caller is a binder thread to
                // help reduce binder contention. this will still result in blocking the handler
                // thread which may result in ANRs, but should make problems slightly more rare.
                // the underlying solution is simply not to use this API at all, but that would
                // require large refactors to very legacy code.
                return task.get(BLOCKING_BINDER_TIMEOUT_MS, TimeUnit.MILLISECONDS);
            } catch (ExecutionException e) {
                // Function cannot throw exception, this should never happen
                throw new IllegalStateException(e);
+2 −2
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import android.location.Address;
import android.location.GeocoderParams;
import android.location.IGeocodeProvider;

import com.android.server.FgThread;
import com.android.internal.os.BackgroundThread;
import com.android.server.ServiceWatcher;

import java.util.List;
@@ -53,7 +53,7 @@ public class GeocoderProxy {
            int initialPackageNamesResId) {
        mServiceWatcher = new ServiceWatcher(context, TAG, SERVICE_ACTION, overlaySwitchResId,
                defaultServicePackageNameResId, initialPackageNamesResId,
                FgThread.getHandler());
                BackgroundThread.getHandler());
    }

    private boolean bind() {