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

Commit d58d9e98 authored by Soonil Nagarkar's avatar Soonil Nagarkar
Browse files

Prevent ConcurrentModificationExceptions in log

Guard iteration within lock to prevent changes.

Test: manual
Change-Id: I7fed514aeb3f81b0af21bbf23d98fd7c23338409
parent 3131ab32
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -1212,9 +1212,7 @@ public class LocationManagerService extends ILocationManager.Stub {

        ipw.println("Event Log:");
        ipw.increaseIndent();
        for (String log : mInjector.getLocationEventLog()) {
            ipw.println(log);
        }
        mInjector.getLocationEventLog().iterate(ipw::println);
        ipw.decreaseIndent();
    }

+9 −9
Original line number Diff line number Diff line
@@ -59,46 +59,46 @@ public class LocationEventLog extends LocalEventLog {
    }

    /** Logs a location enabled/disabled event. */
    public synchronized void logLocationEnabled(int userId, boolean enabled) {
    public void logLocationEnabled(int userId, boolean enabled) {
        addLogEvent(EVENT_LOCATION_POWER_SAVE_MODE_CHANGE, userId, enabled);
    }

    /** Logs a location provider enabled/disabled event. */
    public synchronized void logProviderEnabled(String provider, int userId, boolean enabled) {
    public void logProviderEnabled(String provider, int userId, boolean enabled) {
        addLogEvent(EVENT_PROVIDER_ENABLED, provider, userId, enabled);
    }

    /** Logs a location provider being replaced/unreplaced by a mock provider. */
    public synchronized void logProviderMocked(String provider, boolean mocked) {
    public void logProviderMocked(String provider, boolean mocked) {
        addLogEvent(EVENT_PROVIDER_MOCKED, provider, mocked);
    }

    /** Logs a new client registration for a location provider. */
    public synchronized void logProviderClientRegistered(String provider, CallerIdentity identity,
    public void logProviderClientRegistered(String provider, CallerIdentity identity,
            LocationRequest request) {
        addLogEvent(EVENT_PROVIDER_REGISTER_CLIENT, provider, identity, request);
    }

    /** Logs a client unregistration for a location provider. */
    public synchronized void logProviderClientUnregistered(String provider,
    public void logProviderClientUnregistered(String provider,
            CallerIdentity identity) {
        addLogEvent(EVENT_PROVIDER_UNREGISTER_CLIENT, provider, identity);
    }

    /** Logs a change to the provider request for a location provider. */
    public synchronized void logProviderUpdateRequest(String provider, ProviderRequest request) {
    public void logProviderUpdateRequest(String provider, ProviderRequest request) {
        addLogEvent(EVENT_PROVIDER_UPDATE_REQUEST, provider, request);
    }

    /** Logs a new incoming location for a location provider. */
    public synchronized void logProviderReceivedLocations(String provider, int numLocations) {
    public void logProviderReceivedLocations(String provider, int numLocations) {
        if (Build.IS_DEBUGGABLE || D) {
            addLogEvent(EVENT_PROVIDER_RECEIVE_LOCATION, provider, numLocations);
        }
    }

    /** Logs a location deliver for a client of a location provider. */
    public synchronized void logProviderDeliveredLocations(String provider, int numLocations,
    public void logProviderDeliveredLocations(String provider, int numLocations,
            CallerIdentity identity) {
        if (Build.IS_DEBUGGABLE || D) {
            addLogEvent(EVENT_PROVIDER_DELIVER_LOCATION, provider, numLocations, identity);
@@ -106,7 +106,7 @@ public class LocationEventLog extends LocalEventLog {
    }

    /** Logs that the location power save mode has changed. */
    public synchronized void logLocationPowerSaveMode(
    public void logLocationPowerSaveMode(
            @LocationPowerSaveMode int locationPowerSaveMode) {
        addLogEvent(EVENT_LOCATION_POWER_SAVE_MODE_CHANGE, locationPowerSaveMode);
    }
+11 −26
Original line number Diff line number Diff line
@@ -21,14 +21,14 @@ import android.util.TimeUtils;

import com.android.internal.util.Preconditions;

import java.util.ConcurrentModificationException;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.function.Consumer;

/**
 * An in-memory event log to support historical event information.
 */
public abstract class LocalEventLog implements Iterable<String> {
public abstract class LocalEventLog {

    private interface Log {
        // true if this is a filler element that should not be queried
@@ -93,7 +93,6 @@ public abstract class LocalEventLog implements Iterable<String> {
    private final Log[] mLog;
    private int mLogSize;
    private int mLogEndIndex;
    private int mModificationCount;

    // invalid if log is empty
    private long mStartRealtimeMs;
@@ -103,7 +102,6 @@ public abstract class LocalEventLog implements Iterable<String> {
        mLog = new Log[size];
        mLogSize = 0;
        mLogEndIndex = 0;
        mModificationCount = 0;

        mStartRealtimeMs = -1;
        mLastLogRealtimeMs = -1;
@@ -128,7 +126,7 @@ public abstract class LocalEventLog implements Iterable<String> {
     * into {@link #createLogEvent(long, int, Object...)} in addition to a time delta, and should be
     * used to construct an appropriate {@link LogEvent} object.
     */
    public void addLogEvent(int event, Object... args) {
    public synchronized void addLogEvent(int event, Object... args) {
        long timeMs = SystemClock.elapsedRealtime();

        // calculate delta
@@ -175,28 +173,28 @@ public abstract class LocalEventLog implements Iterable<String> {
        mLog[mLogEndIndex] = event;
        mLogEndIndex = incrementIndex(mLogEndIndex);
        mLastLogRealtimeMs = mLastLogRealtimeMs + event.getTimeDeltaMs();

        mModificationCount++;
    }

    /** Clears the log of all entries. */
    public void clear() {
    public synchronized void clear() {
        mLogEndIndex = 0;
        mLogSize = 0;
        mModificationCount++;

        mStartRealtimeMs = -1;
        mLastLogRealtimeMs = -1;
    }

    // checks if the log is empty (if empty, times are invalid)
    private boolean isEmpty() {
    private synchronized boolean isEmpty() {
        return mLogSize == 0;
    }

    @Override
    public ListIterator<String> iterator() {
        return new LogIterator();
    /** Iterates over the event log, passing each log string to the given consumer. */
    public synchronized void iterate(Consumer<String> consumer) {
        LogIterator it = new LogIterator();
        while (it.hasNext()) {
            consumer.accept(it.next());
        }
    }

    // returns the index of the first element
@@ -222,8 +220,6 @@ public abstract class LocalEventLog implements Iterable<String> {

    private class LogIterator implements ListIterator<String> {

        private final int mModificationGuard;

        private final long mSystemTimeDeltaMs;

        private long mCurrentRealtimeMs;
@@ -231,7 +227,6 @@ public abstract class LocalEventLog implements Iterable<String> {
        private int mCount;

        LogIterator() {
            mModificationGuard = mModificationCount;
            mSystemTimeDeltaMs = System.currentTimeMillis() - SystemClock.elapsedRealtime();
            mCurrentRealtimeMs = mStartRealtimeMs;
            mIndex = startIndex();
@@ -251,8 +246,6 @@ public abstract class LocalEventLog implements Iterable<String> {
        @Override
        // return then increment
        public String next() {
            checkModifications();

            if (!hasNext()) {
                throw new NoSuchElementException();
            }
@@ -276,8 +269,6 @@ public abstract class LocalEventLog implements Iterable<String> {
        @Override
        // decrement then return
        public String previous() {
            checkModifications();

            Log log;
            long currentDeltaMs;
            long realtimeMs;
@@ -303,12 +294,6 @@ public abstract class LocalEventLog implements Iterable<String> {
            return getTimePrefix(realtimeMs + mSystemTimeDeltaMs) + log.getLogString();
        }

        private void checkModifications() {
            if (mModificationGuard != mModificationCount) {
                throw new ConcurrentModificationException();
            }
        }

        @Override
        public int nextIndex() {
            throw new UnsupportedOperationException();