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

Commit 6049b651 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 8016260 from e56fbfa9 to sc-v2-release

Change-Id: I57a4d1abb788658b695450a0a0705a867fa51ce2
parents e49a7863 e56fbfa9
Loading
Loading
Loading
Loading
+74 −17
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import static android.os.PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF
import static android.os.PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
import static android.os.PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF;
import static android.os.PowerManager.LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF;
import static android.os.UserHandle.USER_CURRENT;

import static com.android.server.location.LocationManagerService.D;
import static com.android.server.location.LocationManagerService.TAG;
@@ -177,7 +178,7 @@ public class LocationProviderManager extends
    protected interface LocationTransport {

        void deliverOnLocationChanged(LocationResult locationResult,
                @Nullable Runnable onCompleteCallback) throws Exception;
                @Nullable IRemoteCallback onCompleteCallback) throws Exception;
        void deliverOnFlushComplete(int requestCode) throws Exception;
    }

@@ -197,9 +198,8 @@ public class LocationProviderManager extends

        @Override
        public void deliverOnLocationChanged(LocationResult locationResult,
                @Nullable Runnable onCompleteCallback) throws RemoteException {
            mListener.onLocationChanged(locationResult.asList(),
                    SingleUseCallback.wrap(onCompleteCallback));
                @Nullable IRemoteCallback onCompleteCallback) throws RemoteException {
            mListener.onLocationChanged(locationResult.asList(), onCompleteCallback);
        }

        @Override
@@ -227,7 +227,7 @@ public class LocationProviderManager extends

        @Override
        public void deliverOnLocationChanged(LocationResult locationResult,
                @Nullable Runnable onCompleteCallback)
                @Nullable IRemoteCallback onCompleteCallback)
                throws PendingIntent.CanceledException {
            BroadcastOptions options = BroadcastOptions.makeBasic();
            options.setDontSendToRestrictedApps(true);
@@ -243,20 +243,34 @@ public class LocationProviderManager extends
                intent.putExtra(KEY_LOCATIONS, locationResult.asList().toArray(new Location[0]));
            }

            PendingIntent.OnFinished onFinished = null;

            // send() SHOULD only run the completion callback if it completes successfully. however,
            // b/199464864 (which could not be fixed in the S timeframe) means that it's possible
            // b/201299281 (which could not be fixed in the S timeframe) means that it's possible
            // for send() to throw an exception AND run the completion callback. if this happens, we
            // would over-release the wakelock... we take matters into our own hands to ensure that
            // the completion callback can only be run if send() completes successfully. this means
            // the completion callback may be run inline - but as we've never specified what thread
            // the callback is run on, this is fine.
            GatedCallback gatedCallback = new GatedCallback(onCompleteCallback);
            GatedCallback gatedCallback;
            if (onCompleteCallback != null) {
                gatedCallback = new GatedCallback(() -> {
                    try {
                        onCompleteCallback.sendResult(null);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                });
                onFinished = (pI, i, rC, rD, rE) -> gatedCallback.run();
            } else {
                gatedCallback = new GatedCallback(null);
            }

            mPendingIntent.send(
                    mContext,
                    0,
                    intent,
                    (pI, i, rC, rD, rE) -> gatedCallback.run(),
                    onFinished,
                    null,
                    null,
                    options.toBundle());
@@ -293,7 +307,7 @@ public class LocationProviderManager extends

        @Override
        public void deliverOnLocationChanged(@Nullable LocationResult locationResult,
                @Nullable Runnable onCompleteCallback)
                @Nullable IRemoteCallback onCompleteCallback)
                throws RemoteException {
            // ILocationCallback doesn't currently support completion callbacks
            Preconditions.checkState(onCompleteCallback == null);
@@ -714,6 +728,13 @@ public class LocationProviderManager extends

        final PowerManager.WakeLock mWakeLock;

        // b/206340085 - if we allocate a new wakelock releaser object for every delivery we
        // increase the risk of resource starvation. if a client stops processing deliveries the
        // system server binder allocation pool will be starved as we continue to queue up
        // deliveries, each with a new allocation. in order to mitigate this, we use a single
        // releaser object per registration rather than per delivery.
        final ExternalWakeLockReleaser mWakeLockReleaser;

        private volatile ProviderTransport mProviderTransport;
        private int mNumLocationsDelivered = 0;
        private long mExpirationRealtimeMs = Long.MAX_VALUE;
@@ -727,6 +748,7 @@ public class LocationProviderManager extends
                    .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_TAG);
            mWakeLock.setReferenceCounted(true);
            mWakeLock.setWorkSource(request.getWorkSource());
            mWakeLockReleaser = new ExternalWakeLockReleaser(identity, mWakeLock);
        }

        @Override
@@ -872,6 +894,10 @@ public class LocationProviderManager extends
                                        MAX_FASTEST_INTERVAL_JITTER_MS);
                                if (deltaMs
                                        < getRequest().getMinUpdateIntervalMillis() - maxJitterMs) {
                                    if (D) {
                                        Log.v(TAG, mName + " provider registration " + getIdentity()
                                                + " dropped delivery - too fast");
                                    }
                                    return false;
                                }

@@ -881,6 +907,10 @@ public class LocationProviderManager extends
                                if (smallestDisplacementM > 0.0 && location.distanceTo(
                                        mPreviousLocation)
                                        <= smallestDisplacementM) {
                                    if (D) {
                                        Log.v(TAG, mName + " provider registration " + getIdentity()
                                                + " dropped delivery - too close");
                                    }
                                    return false;
                                }
                            }
@@ -898,7 +928,8 @@ public class LocationProviderManager extends
            if (!mAppOpsHelper.noteOpNoThrow(LocationPermissions.asAppOp(getPermissionLevel()),
                    getIdentity())) {
                if (D) {
                    Log.w(TAG, "noteOp denied for " + getIdentity());
                    Log.w(TAG,
                            mName + " provider registration " + getIdentity() + " noteOp denied");
                }
                return null;
            }
@@ -943,7 +974,7 @@ public class LocationProviderManager extends
                    }

                    listener.deliverOnLocationChanged(deliverLocationResult,
                            mUseWakeLock ? mWakeLock::release : null);
                            mUseWakeLock ? mWakeLockReleaser : null);
                    EVENT_LOG.logProviderDeliveredLocations(mName, locationResult.size(),
                            getIdentity());
                }
@@ -1482,7 +1513,7 @@ public class LocationProviderManager extends
    public boolean isEnabled(int userId) {
        if (userId == UserHandle.USER_NULL) {
            return false;
        } else if (userId == UserHandle.USER_CURRENT) {
        } else if (userId == USER_CURRENT) {
            return isEnabled(mUserHelper.getCurrentUserId());
        }

@@ -1655,7 +1686,7 @@ public class LocationProviderManager extends
                }
            }
            return lastLocation;
        } else if (userId == UserHandle.USER_CURRENT) {
        } else if (userId == USER_CURRENT) {
            return getLastLocationUnsafe(mUserHelper.getCurrentUserId(), permissionLevel,
                    isBypass, maximumAgeMs);
        }
@@ -1700,7 +1731,7 @@ public class LocationProviderManager extends
                setLastLocation(location, runningUserIds[i]);
            }
            return;
        } else if (userId == UserHandle.USER_CURRENT) {
        } else if (userId == USER_CURRENT) {
            setLastLocation(location, mUserHelper.getCurrentUserId());
            return;
        }
@@ -2383,13 +2414,13 @@ public class LocationProviderManager extends
            filtered = locationResult.filter(location -> {
                if (!location.isMock()) {
                    if (location.getLatitude() == 0 && location.getLongitude() == 0) {
                        Log.w(TAG, "blocking 0,0 location from " + mName + " provider");
                        Log.e(TAG, "blocking 0,0 location from " + mName + " provider");
                        return false;
                    }
                }

                if (!location.isComplete()) {
                    Log.w(TAG, "blocking incomplete location from " + mName + " provider");
                    Log.e(TAG, "blocking incomplete location from " + mName + " provider");
                    return false;
                }

@@ -2407,6 +2438,12 @@ public class LocationProviderManager extends
            filtered = locationResult;
        }

        Location last = getLastLocationUnsafe(USER_CURRENT, PERMISSION_FINE, true, Long.MAX_VALUE);
        if (last != null && locationResult.get(0).getElapsedRealtimeNanos()
                < last.getElapsedRealtimeNanos()) {
            Log.e(TAG, "non-monotonic location received from " + mName + " provider");
        }

        // update last location
        setLastLocation(filtered.getLastLocation(), UserHandle.USER_ALL);

@@ -2761,7 +2798,7 @@ public class LocationProviderManager extends
        @GuardedBy("this")
        private boolean mRun;

        GatedCallback(Runnable callback) {
        GatedCallback(@Nullable Runnable callback) {
            mCallback = callback;
        }

@@ -2796,4 +2833,24 @@ public class LocationProviderManager extends
            }
        }
    }

    private static class ExternalWakeLockReleaser extends IRemoteCallback.Stub {

        private final CallerIdentity mIdentity;
        private final PowerManager.WakeLock mWakeLock;

        ExternalWakeLockReleaser(CallerIdentity identity, PowerManager.WakeLock wakeLock) {
            mIdentity = identity;
            mWakeLock = Objects.requireNonNull(wakeLock);
        }

        @Override
        public void sendResult(Bundle data) {
            try {
                mWakeLock.release();
            } catch (RuntimeException e) {
                Log.e(TAG, "wakelock over-released by " + mIdentity, e);
            }
        }
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import static com.android.server.location.LocationManagerService.D;
import static com.android.server.location.LocationManagerService.TAG;
import static com.android.server.location.eventlog.LocationEventLog.EVENT_LOG;

import static java.lang.Math.max;

import android.annotation.Nullable;
import android.location.Location;
import android.location.LocationResult;
@@ -53,6 +55,7 @@ public final class StationaryThrottlingLocationProvider extends DelegateLocation
        implements DeviceIdleHelper.DeviceIdleListener, DeviceIdleInternal.StationaryListener {

    private static final long MAX_STATIONARY_LOCATION_AGE_MS = 30000;
    private static final long MIN_INTERVAL_MS = 1000;

    final Object mLock = new Object();

@@ -179,7 +182,7 @@ public final class StationaryThrottlingLocationProvider extends DelegateLocation
                && mLastLocation != null
                && mLastLocation.getElapsedRealtimeAgeMillis(mDeviceStationaryRealtimeMs)
                <= MAX_STATIONARY_LOCATION_AGE_MS) {
            throttlingIntervalMs = mIncomingRequest.getIntervalMillis();
            throttlingIntervalMs = max(mIncomingRequest.getIntervalMillis(), MIN_INTERVAL_MS);
        }

        ProviderRequest newRequest;
+21 −10
Original line number Diff line number Diff line
@@ -89,6 +89,19 @@ public class StationaryThrottlingLocationProviderTest {
        mProvider.getController().stop();
    }

    @Test
    public void testThrottle_lowInterval() {
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(0).build();

        mProvider.getController().setRequest(request);
        mDelegateProvider.reportLocation(createLocationResult("test_provider", mRandom));
        verify(mListener, times(1)).onReportLocation(any(LocationResult.class));

        mInjector.getDeviceStationaryHelper().setStationary(true);
        mInjector.getDeviceIdleHelper().setIdle(true);
        verify(mListener, after(1500).times(2)).onReportLocation(any(LocationResult.class));
    }

    @Test
    public void testThrottle_stationaryExit() {
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build();
@@ -104,17 +117,16 @@ public class StationaryThrottlingLocationProviderTest {

        mInjector.getDeviceIdleHelper().setIdle(true);
        verify(mDelegate).onSetRequest(ProviderRequest.EMPTY_REQUEST);
        verify(mListener, timeout(75).times(2)).onReportLocation(any(LocationResult.class));
        verify(mListener, timeout(75).times(3)).onReportLocation(any(LocationResult.class));
        verify(mListener, timeout(1100).times(2)).onReportLocation(any(LocationResult.class));

        mInjector.getDeviceStationaryHelper().setStationary(false);
        verify(mDelegate, times(2)).onSetRequest(request);
        verify(mListener, after(75).times(3)).onReportLocation(any(LocationResult.class));
        verify(mListener, after(1000).times(2)).onReportLocation(any(LocationResult.class));
    }

    @Test
    public void testThrottle_idleExit() {
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build();
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(1000).build();

        mProvider.getController().setRequest(request);
        verify(mDelegate).onSetRequest(request);
@@ -127,17 +139,16 @@ public class StationaryThrottlingLocationProviderTest {

        mInjector.getDeviceStationaryHelper().setStationary(true);
        verify(mDelegate).onSetRequest(ProviderRequest.EMPTY_REQUEST);
        verify(mListener, timeout(75).times(2)).onReportLocation(any(LocationResult.class));
        verify(mListener, timeout(75).times(3)).onReportLocation(any(LocationResult.class));
        verify(mListener, timeout(1100).times(2)).onReportLocation(any(LocationResult.class));

        mInjector.getDeviceIdleHelper().setIdle(false);
        verify(mDelegate, times(2)).onSetRequest(request);
        verify(mListener, after(75).times(3)).onReportLocation(any(LocationResult.class));
        verify(mListener, after(1000).times(2)).onReportLocation(any(LocationResult.class));
    }

    @Test
    public void testThrottle_NoInitialLocation() {
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(50).build();
        ProviderRequest request = new ProviderRequest.Builder().setIntervalMillis(1000).build();

        mProvider.getController().setRequest(request);
        verify(mDelegate).onSetRequest(request);
@@ -149,11 +160,11 @@ public class StationaryThrottlingLocationProviderTest {
        mDelegateProvider.reportLocation(createLocationResult("test_provider", mRandom));
        verify(mListener, times(1)).onReportLocation(any(LocationResult.class));
        verify(mDelegate, times(1)).onSetRequest(ProviderRequest.EMPTY_REQUEST);
        verify(mListener, timeout(75).times(2)).onReportLocation(any(LocationResult.class));
        verify(mListener, timeout(1100).times(2)).onReportLocation(any(LocationResult.class));

        mInjector.getDeviceStationaryHelper().setStationary(false);
        verify(mDelegate, times(2)).onSetRequest(request);
        verify(mListener, after(75).times(2)).onReportLocation(any(LocationResult.class));
        verify(mListener, after(1000).times(2)).onReportLocation(any(LocationResult.class));
    }

    @Test