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

Commit 13a60b0d authored by destradaa's avatar destradaa
Browse files

Fix race condition generating READY and NOT_SUPPORTED statuses.

The race condition only affects when the client registers for several (all) location listeners.
And the side efects are benign: only the measurement and navigation message status are incurrectly
being sent to the application, but there are no crashes or any real data from GPS being
misscommunicated.
Also:
- cache the last reported status to filter sending notifications when no changes have occurred
- do some cleanup and refactoring in the code changed

Change-Id: I0692e6b70847dc1ee092d7a05a2c6ba3cd9fa147
parent 34efbced
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -36,18 +36,18 @@ public class GpsNavigationMessageEvent implements Parcelable {
     * The system does not support tracking of GPS Navigation Messages. This status will not change
     * in the future.
     */
    public static int STATUS_NOT_SUPPORTED = 0;
    public static final int STATUS_NOT_SUPPORTED = 0;

    /**
     * GPS Navigation Messages are successfully being tracked, it will receive updates once they are
     * available.
     */
    public static int STATUS_READY = 1;
    public static final int STATUS_READY = 1;

    /**
     * GPS provider or Location is disabled, updated will not be received until they are enabled.
     */
    public static int STATUS_GPS_LOCATION_DISABLED = 2;
    public static final int STATUS_GPS_LOCATION_DISABLED = 2;

    private final GpsNavigationMessage mNavigationMessage;

+9 −8
Original line number Diff line number Diff line
@@ -25,7 +25,6 @@ import com.android.internal.location.ProviderRequest;
import com.android.internal.R;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyIntents;

import android.app.AlarmManager;
import android.app.AppOpsManager;
@@ -72,7 +71,6 @@ import android.provider.Settings;
import android.provider.Telephony.Carriers;
import android.provider.Telephony.Sms.Intents;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
import android.telephony.TelephonyManager;
@@ -91,7 +89,6 @@ import java.io.StringReader;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;

@@ -395,7 +392,7 @@ public class GpsLocationProvider implements LocationProviderInterface {

    private final IGpsStatusProvider mGpsStatusProvider = new IGpsStatusProvider.Stub() {
        @Override
        public void addGpsStatusListener(IGpsStatusListener listener) throws RemoteException {
        public void addGpsStatusListener(IGpsStatusListener listener) {
            mListenerHelper.addListener(listener);
        }

@@ -681,7 +678,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
        mListenerHelper = new GpsStatusListenerHelper(mHandler) {
            @Override
            protected boolean isAvailableInPlatform() {
                return GpsLocationProvider.isSupported();
                return isSupported();
            }

            @Override
@@ -1027,6 +1024,9 @@ public class GpsLocationProvider implements LocationProviderInterface {
            if (mC2KServerHost != null) {
                native_set_agps_server(AGPS_TYPE_C2K, mC2KServerHost, mC2KServerPort);
            }

            mGpsMeasurementsProvider.onGpsEnabledChanged();
            mGpsNavigationMessageProvider.onGpsEnabledChanged();
        } else {
            synchronized (mLock) {
                mEnabled = false;
@@ -1060,6 +1060,9 @@ public class GpsLocationProvider implements LocationProviderInterface {

        // do this before releasing wakelock
        native_cleanup();

        mGpsMeasurementsProvider.onGpsEnabledChanged();
        mGpsNavigationMessageProvider.onGpsEnabledChanged();
    }

    @Override
@@ -1479,9 +1482,7 @@ public class GpsLocationProvider implements LocationProviderInterface {
        }

        if (wasNavigating != mNavigating) {
            mListenerHelper.onGpsEnabledChanged(mNavigating);
            mGpsMeasurementsProvider.onGpsEnabledChanged(mNavigating);
            mGpsNavigationMessageProvider.onGpsEnabledChanged(mNavigating);
            mListenerHelper.onStatusChanged(mNavigating);

            // send an intent to notify that the GPS has been enabled or disabled
            Intent intent = new Intent(LocationManager.GPS_ENABLED_CHANGE_ACTION);
+14 −15
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ public abstract class GpsMeasurementsProvider
        extends RemoteListenerHelper<IGpsMeasurementsListener> {
    private static final String TAG = "GpsMeasurementsProvider";

    public GpsMeasurementsProvider(Handler handler) {
    protected GpsMeasurementsProvider(Handler handler) {
        super(handler, TAG);
    }

@@ -49,15 +49,19 @@ public abstract class GpsMeasurementsProvider
    }

    public void onCapabilitiesUpdated(boolean isGpsMeasurementsSupported) {
        int status = isGpsMeasurementsSupported ?
                GpsMeasurementsEvent.STATUS_READY :
                GpsMeasurementsEvent.STATUS_NOT_SUPPORTED;
        setSupported(isGpsMeasurementsSupported, new StatusChangedOperation(status));
        setSupported(isGpsMeasurementsSupported);
        updateResult();
    }

    public void onGpsEnabledChanged() {
        if (tryUpdateRegistrationWithService()) {
            updateResult();
        }
    }

    @Override
    protected ListenerOperation<IGpsMeasurementsListener> getHandlerOperation(int result) {
        final int status;
        int status;
        switch (result) {
            case RESULT_SUCCESS:
                status = GpsMeasurementsEvent.STATUS_READY;
@@ -70,6 +74,8 @@ public abstract class GpsMeasurementsProvider
            case RESULT_GPS_LOCATION_DISABLED:
                status = GpsMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
                break;
            case RESULT_UNKNOWN:
                return null;
            default:
                Log.v(TAG, "Unhandled addListener result: " + result);
                return null;
@@ -77,15 +83,8 @@ public abstract class GpsMeasurementsProvider
        return new StatusChangedOperation(status);
    }

    @Override
    protected void handleGpsEnabledChanged(boolean enabled) {
        int status = enabled ?
                GpsMeasurementsEvent.STATUS_READY :
                GpsMeasurementsEvent.STATUS_GPS_LOCATION_DISABLED;
        foreach(new StatusChangedOperation(status));
    }

    private class StatusChangedOperation implements ListenerOperation<IGpsMeasurementsListener> {
    private static class StatusChangedOperation
            implements ListenerOperation<IGpsMeasurementsListener> {
        private final int mStatus;

        public StatusChangedOperation(int status) {
+13 −15
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ public abstract class GpsNavigationMessageProvider
        extends RemoteListenerHelper<IGpsNavigationMessageListener> {
    private static final String TAG = "GpsNavigationMessageProvider";

    public GpsNavigationMessageProvider(Handler handler) {
    protected GpsNavigationMessageProvider(Handler handler) {
        super(handler, TAG);
    }

@@ -50,15 +50,19 @@ public abstract class GpsNavigationMessageProvider
    }

    public void onCapabilitiesUpdated(boolean isGpsNavigationMessageSupported) {
        int status = isGpsNavigationMessageSupported ?
                GpsNavigationMessageEvent.STATUS_READY :
                GpsNavigationMessageEvent.STATUS_NOT_SUPPORTED;
        setSupported(isGpsNavigationMessageSupported, new StatusChangedOperation(status));
        setSupported(isGpsNavigationMessageSupported);
        updateResult();
    }

    public void onGpsEnabledChanged() {
        if (tryUpdateRegistrationWithService()) {
            updateResult();
        }
    }

    @Override
    protected ListenerOperation<IGpsNavigationMessageListener> getHandlerOperation(int result) {
        final int status;
        int status;
        switch (result) {
            case RESULT_SUCCESS:
                status = GpsNavigationMessageEvent.STATUS_READY;
@@ -71,6 +75,8 @@ public abstract class GpsNavigationMessageProvider
            case RESULT_GPS_LOCATION_DISABLED:
                status = GpsNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
                break;
            case RESULT_UNKNOWN:
                return null;
            default:
                Log.v(TAG, "Unhandled addListener result: " + result);
                return null;
@@ -78,15 +84,7 @@ public abstract class GpsNavigationMessageProvider
        return new StatusChangedOperation(status);
    }

    @Override
    protected void handleGpsEnabledChanged(boolean enabled) {
        int status = enabled ?
                GpsNavigationMessageEvent.STATUS_READY :
                GpsNavigationMessageEvent.STATUS_GPS_LOCATION_DISABLED;
        foreach(new StatusChangedOperation(status));
    }

    private class StatusChangedOperation
    private static class StatusChangedOperation
            implements ListenerOperation<IGpsNavigationMessageListener> {
        private final int mStatus;

+5 −11
Original line number Diff line number Diff line
@@ -24,14 +24,9 @@ import android.os.RemoteException;
 * Implementation of a handler for {@link IGpsStatusListener}.
 */
abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusListener> {
    public GpsStatusListenerHelper(Handler handler) {
    protected GpsStatusListenerHelper(Handler handler) {
        super(handler, "GpsStatusListenerHelper");

        Operation nullOperation = new Operation() {
            @Override
            public void execute(IGpsStatusListener iGpsStatusListener) throws RemoteException {}
        };
        setSupported(GpsLocationProvider.isSupported(), nullOperation);
        setSupported(GpsLocationProvider.isSupported());
    }

    @Override
@@ -47,10 +42,9 @@ abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusLi
        return null;
    }

    @Override
    protected void handleGpsEnabledChanged(boolean enabled) {
    public void onStatusChanged(boolean isNavigating) {
        Operation operation;
        if (enabled) {
        if (isNavigating) {
            operation = new Operation() {
                @Override
                public void execute(IGpsStatusListener listener) throws RemoteException {
@@ -114,5 +108,5 @@ abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusLi
        foreach(operation);
    }

    private abstract class Operation implements ListenerOperation<IGpsStatusListener> { }
    private interface Operation extends ListenerOperation<IGpsStatusListener> {}
}
Loading