From 8c35dcc7ae956394a6513f4ced8359f56260fbc4 Mon Sep 17 00:00:00 2001 From: Svetoslav Ganov Date: Fri, 17 Jun 2016 15:27:43 -0700 Subject: [PATCH] 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 --- core/java/android/provider/Settings.java | 17 +++++++++++++---- .../providers/settings/GenerationRegistry.java | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ab2506e7e9f74..293eb9ba80aaa 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -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"); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java index 8512dca93e628..f4f7986a753d2 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/GenerationRegistry.java @@ -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));