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

Commit 8c35dcc7 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Fix a race in local settings caches

We send a handle to the generation tracker along with the first accessed
setting but don't send the generation id of when the setting was
actually looked up. So by the time the client gets the setting with the
generation tracker from which to get and cache the last generation the
setting may have changed. We need to pass the generation id along with
the value and the generation tracker.

bug:29458487

Change-Id: I0ac4955ba5b10b547f8fe653a7c28e048a4691eb
parent 8e8fb7dd
Loading
Loading
Loading
Loading
+13 −4
Original line number Diff line number Diff line
@@ -1311,12 +1311,19 @@ public final class Settings {

    /**
     * @hide Key with the location in the {@link android.util.MemoryIntArray} where
     * to look up the generation id of the backing table.
     * to look up the generation id of the backing table. The value is an integer.
     *
     * @see #CALL_METHOD_TRACK_GENERATION_KEY
     */
    public static final String CALL_METHOD_GENERATION_INDEX_KEY = "_generation_index";

    /**
     * @hide Key with the settings table generation. The value is an integer.
     *
     * @see #CALL_METHOD_TRACK_GENERATION_KEY
     */
    public static final String CALL_METHOD_GENERATION_KEY = "_generation";

    /**
     * @hide - User handle argument extra to the fast-path call()-based requests
     */
@@ -1467,11 +1474,11 @@ public final class Settings {
        private int mCurrentGeneration;

        public GenerationTracker(@NonNull MemoryIntArray array, int index,
                Runnable errorHandler) {
                int generation, Runnable errorHandler) {
            mArray = array;
            mIndex = index;
            mErrorHandler = errorHandler;
            mCurrentGeneration = readCurrentGeneration();
            mCurrentGeneration = generation;
        }

        public boolean isGenerationChanged() {
@@ -1627,6 +1634,8 @@ public final class Settings {
                                    final int index = b.getInt(
                                            CALL_METHOD_GENERATION_INDEX_KEY, -1);
                                    if (array != null && index >= 0) {
                                        final int generation = b.getInt(
                                                CALL_METHOD_GENERATION_KEY, 0);
                                        if (DEBUG) {
                                            Log.i(TAG, "Received generation tracker for type:"
                                                    + mUri.getPath() + " in package:"
@@ -1634,7 +1643,7 @@ public final class Settings {
                                                    + userHandle + " with index:" + index);
                                        }
                                        mGenerationTracker = new GenerationTracker(array, index,
                                                () -> {
                                                generation, () -> {
                                            synchronized (this) {
                                                Log.e(TAG, "Error accessing generation"
                                                        + " tracker - removing");
+2 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ final class GenerationRegistry {
                        bundle.putParcelable(Settings.CALL_METHOD_TRACK_GENERATION_KEY,
                                backingStore);
                        bundle.putInt(Settings.CALL_METHOD_GENERATION_INDEX_KEY, index);
                        bundle.putInt(Settings.CALL_METHOD_GENERATION_KEY,
                                backingStore.get(index));
                        if (DEBUG) {
                            Slog.i(LOG_TAG, "Exported index:" + index + " for key:"
                                    + SettingsProvider.keyToString(key));