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

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

DO NOT MERGE Prevent isEnabled from mutating state

When isEnabled sees a user it has not encountered before it may send out
client updates, which can result in the client list and associated state
being mutated unexpectedly, causing ConcurrentModificationExceptions. In
order to prevent this, we now mutate the state asynchronously.

Bug: 171910679
Test: unable to verify this manually, as this is a near impossible bug
to reproduce intentionally

Change-Id: I64ccdcdd50294b875d4ed22de60bff0823812ad7
parent 69f60a90
Loading
Loading
Loading
Loading
+19 −2
Original line number Diff line number Diff line
@@ -906,9 +906,26 @@ public class LocationManagerService extends ILocationManager.Stub {
                if (enabled == null) {
                    // this generally shouldn't occur, but might be possible due to race conditions
                    // on when we are notified of new users

                    // hack to fix b/171910679. mutating the user enabled state within this method
                    // may cause unexpected changes to other state (for instance, this could cause
                    // provider enable/disable notifications to be sent to clients, which could
                    // result in a dead client being detected, which could result in the client
                    // being removed, which means that if this function is called while clients are
                    // being iterated over we have now unexpectedly mutated the iterated
                    // collection). instead, we return a correct value immediately here, and
                    // schedule the actual update for later. this has been completely rewritten and
                    // is no longer a problem in the next version of android.
                    enabled = mProvider.getState().allowed
                            && mUserInfoHelper.isCurrentUserId(userId)
                            && mSettingsHelper.isLocationEnabled(userId);

                    Log.w(TAG, mName + " provider saw user " + userId + " unexpectedly");
                    mHandler.post(() -> {
                        synchronized (mLock) {
                            onEnabledChangedLocked(userId);
                    enabled = Objects.requireNonNull(mEnabled.get(userId));
                        }
                    });
                }

                return enabled;