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

Commit 51095e26 authored by Song Chun Fan's avatar Song Chun Fan Committed by Android (Google) Code Review
Browse files

Merge "Revert "Revert "SettingsProvider enhanced cache""" into udc-dev

parents 77ec4fab 42e1e6d7
Loading
Loading
Loading
Loading
+129 −121
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
 * The Settings provider contains global system-level device preferences.
@@ -2977,19 +2978,22 @@ public final class Settings {
    }
    private static final class GenerationTracker {
        private final MemoryIntArray mArray;
        private final Runnable mErrorHandler;
        @NonNull private final String mName;
        @NonNull private final MemoryIntArray mArray;
        @NonNull private final Consumer<String> mErrorHandler;
        private final int mIndex;
        private int mCurrentGeneration;
        public GenerationTracker(@NonNull MemoryIntArray array, int index,
                int generation, Runnable errorHandler) {
        GenerationTracker(@NonNull String name, @NonNull MemoryIntArray array, int index,
                int generation, Consumer<String> errorHandler) {
            mName = name;
            mArray = array;
            mIndex = index;
            mErrorHandler = errorHandler;
            mCurrentGeneration = generation;
        }
        // This method also updates the obsolete generation code stored locally
        public boolean isGenerationChanged() {
            final int currentGeneration = readCurrentGeneration();
            if (currentGeneration >= 0) {
@@ -3010,9 +3014,7 @@ public final class Settings {
                return mArray.get(mIndex);
            } catch (IOException e) {
                Log.e(TAG, "Error getting current generation", e);
                if (mErrorHandler != null) {
                    mErrorHandler.run();
                }
                mErrorHandler.accept(mName);
            }
            return -1;
        }
@@ -3022,9 +3024,6 @@ public final class Settings {
                mArray.close();
            } catch (IOException e) {
                Log.e(TAG, "Error closing backing array", e);
                if (mErrorHandler != null) {
                    mErrorHandler.run();
                }
            }
        }
    }
@@ -3087,8 +3086,21 @@ public final class Settings {
        private final ArraySet<String> mAllFields;
        private final ArrayMap<String, Integer> mReadableFieldsWithMaxTargetSdk;
        // Mapping from the name of a setting (or the prefix of a namespace) to a generation tracker
        @GuardedBy("this")
        private GenerationTracker mGenerationTracker;
        private ArrayMap<String, GenerationTracker> mGenerationTrackers = new ArrayMap<>();
        private Consumer<String> mGenerationTrackerErrorHandler = (String name) -> {
            synchronized (NameValueCache.this) {
                Log.e(TAG, "Error accessing generation tracker - removing");
                final GenerationTracker tracker = mGenerationTrackers.get(name);
                if (tracker != null) {
                    tracker.destroy();
                    mGenerationTrackers.remove(name);
                }
                mValues.remove(name);
            }
        };
        <T extends NameValueTable> NameValueCache(Uri uri, String getCommand,
                String setCommand, String deleteCommand, ContentProviderHolder providerHolder,
@@ -3177,6 +3189,43 @@ public final class Settings {
        @UnsupportedAppUsage
        public String getStringForUser(ContentResolver cr, String name, final int userHandle) {
            final boolean isSelf = (userHandle == UserHandle.myUserId());
            int currentGeneration = -1;
            boolean needsGenerationTracker = false;
            if (isSelf) {
                synchronized (NameValueCache.this) {
                    final GenerationTracker generationTracker = mGenerationTrackers.get(name);
                    if (generationTracker != null) {
                        if (generationTracker.isGenerationChanged()) {
                            if (DEBUG) {
                                Log.i(TAG, "Generation changed for setting:" + name
                                        + " type:" + mUri.getPath()
                                        + " in package:" + cr.getPackageName()
                                        + " and user:" + userHandle);
                            }
                            mValues.remove(name);
                        } else if (mValues.containsKey(name)) {
                            if (DEBUG) {
                                Log.i(TAG, "Cache hit for setting:" + name);
                            }
                            return mValues.get(name);
                        }
                        currentGeneration = generationTracker.getCurrentGeneration();
                    } else {
                        needsGenerationTracker = true;
                    }
                }
            } else {
                if (DEBUG || LOCAL_LOGV) {
                    Log.v(TAG, "get setting for user " + userHandle
                            + " by user " + UserHandle.myUserId() + " so skipping cache");
                }
            }
            if (DEBUG) {
                Log.i(TAG, "Cache miss for setting:" + name + " for user:" + userHandle);
            }
            // Check if the target settings key is readable. Reject if the caller is not system and
            // is trying to access a settings key defined in the Settings.Secure, Settings.System or
            // Settings.Global and is not annotated as @Readable.
@@ -3210,31 +3259,6 @@ public final class Settings {
                }
            }
            final boolean isSelf = (userHandle == UserHandle.myUserId());
            int currentGeneration = -1;
            if (isSelf) {
                synchronized (NameValueCache.this) {
                    if (mGenerationTracker != null) {
                        if (mGenerationTracker.isGenerationChanged()) {
                            if (DEBUG) {
                                Log.i(TAG, "Generation changed for type:"
                                        + mUri.getPath() + " in package:"
                                        + cr.getPackageName() +" and user:" + userHandle);
                            }
                            mValues.clear();
                        } else if (mValues.containsKey(name)) {
                            return mValues.get(name);
                        }
                        if (mGenerationTracker != null) {
                            currentGeneration = mGenerationTracker.getCurrentGeneration();
                        }
                    }
                }
            } else {
                if (LOCAL_LOGV) Log.v(TAG, "get setting for user " + userHandle
                        + " by user " + UserHandle.myUserId() + " so skipping cache");
            }
            IContentProvider cp = mProviderHolder.getProvider(cr);
            // Try the fast path first, not using query().  If this
@@ -3243,24 +3267,17 @@ public final class Settings {
            // interface.
            if (mCallGetCommand != null) {
                try {
                    Bundle args = null;
                    Bundle args = new Bundle();
                    if (!isSelf) {
                        args = new Bundle();
                        args.putInt(CALL_METHOD_USER_KEY, userHandle);
                    }
                    boolean needsGenerationTracker = false;
                    synchronized (NameValueCache.this) {
                        if (isSelf && mGenerationTracker == null) {
                            needsGenerationTracker = true;
                            if (args == null) {
                                args = new Bundle();
                            }
                    if (needsGenerationTracker) {
                        args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
                        if (DEBUG) {
                                Log.i(TAG, "Requested generation tracker for type: "+ mUri.getPath()
                                        + " in package:" + cr.getPackageName() +" and user:"
                                        + userHandle);
                            }
                            Log.i(TAG, "Requested generation tracker for setting:" + name
                                    + " type:" + mUri.getPath()
                                    + " in package:" + cr.getPackageName()
                                    + " and user:" + userHandle);
                        }
                    }
                    Bundle b;
@@ -3297,33 +3314,24 @@ public final class Settings {
                                        final int generation = b.getInt(
                                                CALL_METHOD_GENERATION_KEY, 0);
                                        if (DEBUG) {
                                            Log.i(TAG, "Received generation tracker for type:"
                                                    + mUri.getPath() + " in package:"
                                                    + cr.getPackageName() + " and user:"
                                                    + userHandle + " with index:" + index);
                                        }
                                        if (mGenerationTracker != null) {
                                            mGenerationTracker.destroy();
                                        }
                                        mGenerationTracker = new GenerationTracker(array, index,
                                                generation, () -> {
                                            synchronized (NameValueCache.this) {
                                                Log.e(TAG, "Error accessing generation"
                                                        + " tracker - removing");
                                                if (mGenerationTracker != null) {
                                                    GenerationTracker generationTracker =
                                                            mGenerationTracker;
                                                    mGenerationTracker = null;
                                                    generationTracker.destroy();
                                                    mValues.clear();
                                                }
                                            }
                                        });
                                            Log.i(TAG, "Received generation tracker for setting:"
                                                    + name
                                                    + " type:" + mUri.getPath()
                                                    + " in package:" + cr.getPackageName()
                                                    + " and user:" + userHandle
                                                    + " with index:" + index);
                                        }
                                        mGenerationTrackers.put(name, new GenerationTracker(name,
                                                array, index, generation,
                                                mGenerationTrackerErrorHandler));
                                        currentGeneration = generation;
                                    }
                                }
                                if (mGenerationTracker != null && currentGeneration ==
                                        mGenerationTracker.getCurrentGeneration()) {
                                if (mGenerationTrackers.get(name) != null && currentGeneration
                                        == mGenerationTrackers.get(name).getCurrentGeneration()) {
                                    if (DEBUG) {
                                        Log.i(TAG, "Updating cache for setting:" + name);
                                    }
                                    mValues.put(name, value);
                                }
                            }
@@ -3366,14 +3374,13 @@ public final class Settings {
                String value = c.moveToNext() ? c.getString(0) : null;
                synchronized (NameValueCache.this) {
                    if (mGenerationTracker != null
                            && currentGeneration == mGenerationTracker.getCurrentGeneration()) {
                        mValues.put(name, value);
                    if (mGenerationTrackers.get(name) != null && currentGeneration
                            == mGenerationTrackers.get(name).getCurrentGeneration()) {
                        if (DEBUG) {
                            Log.i(TAG, "Updating cache for setting:" + name + " using query");
                        }
                        mValues.put(name, value);
                    }
                if (LOCAL_LOGV) {
                    Log.v(TAG, "cache miss [" + mUri.getLastPathSegment() + "]: " +
                            name + " = " + (value == null ? "(null)" : value));
                }
                return value;
            } catch (RemoteException e) {
@@ -3408,18 +3415,29 @@ public final class Settings {
            Config.enforceReadPermission(namespace);
            ArrayMap<String, String> keyValues = new ArrayMap<>();
            int currentGeneration = -1;
            boolean needsGenerationTracker = false;
            synchronized (NameValueCache.this) {
                if (mGenerationTracker != null) {
                    if (mGenerationTracker.isGenerationChanged()) {
                final GenerationTracker generationTracker = mGenerationTrackers.get(prefix);
                if (generationTracker != null) {
                    if (generationTracker.isGenerationChanged()) {
                        if (DEBUG) {
                            Log.i(TAG, "Generation changed for type:" + mUri.getPath()
                            Log.i(TAG, "Generation changed for prefix:" + prefix
                                    + " type:" + mUri.getPath()
                                    + " in package:" + cr.getPackageName());
                        }
                        mValues.clear();
                        for (int i = 0; i < mValues.size(); ++i) {
                            String key = mValues.keyAt(i);
                            if (key.startsWith(prefix)) {
                                mValues.remove(key);
                            }
                        }
                    } else {
                        boolean prefixCached = mValues.containsKey(prefix);
                        if (prefixCached) {
                            if (DEBUG) {
                                Log.i(TAG, "Cache hit for prefix:" + prefix);
                            }
                            if (!names.isEmpty()) {
                                for (String name : names) {
                                    if (mValues.containsKey(name)) {
@@ -3439,9 +3457,9 @@ public final class Settings {
                            return keyValues;
                        }
                    }
                    if (mGenerationTracker != null) {
                        currentGeneration = mGenerationTracker.getCurrentGeneration();
                    }
                    currentGeneration = generationTracker.getCurrentGeneration();
                } else {
                    needsGenerationTracker = true;
                }
            }
@@ -3449,20 +3467,20 @@ public final class Settings {
                // No list command specified, return empty map
                return keyValues;
            }
            if (DEBUG) {
                Log.i(TAG, "Cache miss for prefix:" + prefix);
            }
            IContentProvider cp = mProviderHolder.getProvider(cr);
            try {
                Bundle args = new Bundle();
                args.putString(Settings.CALL_METHOD_PREFIX_KEY, prefix);
                boolean needsGenerationTracker = false;
                synchronized (NameValueCache.this) {
                    if (mGenerationTracker == null) {
                        needsGenerationTracker = true;
                if (needsGenerationTracker) {
                    args.putString(CALL_METHOD_TRACK_GENERATION_KEY, null);
                    if (DEBUG) {
                            Log.i(TAG, "Requested generation tracker for type: "
                                    + mUri.getPath() + " in package:" + cr.getPackageName());
                        }
                        Log.i(TAG, "Requested generation tracker for prefix:" + prefix
                                + " type: " + mUri.getPath()
                                + " in package:" + cr.getPackageName());
                    }
                }
@@ -3515,32 +3533,22 @@ public final class Settings {
                            final int generation = b.getInt(
                                    CALL_METHOD_GENERATION_KEY, 0);
                            if (DEBUG) {
                                Log.i(TAG, "Received generation tracker for type:"
                                        + mUri.getPath() + " in package:"
                                        + cr.getPackageName() + " with index:" + index);
                            }
                            if (mGenerationTracker != null) {
                                mGenerationTracker.destroy();
                            }
                            mGenerationTracker = new GenerationTracker(array, index,
                                    generation, () -> {
                                synchronized (NameValueCache.this) {
                                    Log.e(TAG, "Error accessing generation tracker"
                                            + " - removing");
                                    if (mGenerationTracker != null) {
                                        GenerationTracker generationTracker =
                                                mGenerationTracker;
                                        mGenerationTracker = null;
                                        generationTracker.destroy();
                                        mValues.clear();
                                    }
                                }
                            });
                                Log.i(TAG, "Received generation tracker for prefix:" + prefix
                                        + " type:" + mUri.getPath()
                                        + " in package:" + cr.getPackageName()
                                        + " with index:" + index);
                            }
                            mGenerationTrackers.put(prefix,
                                    new GenerationTracker(prefix, array, index, generation,
                                            mGenerationTrackerErrorHandler));
                            currentGeneration = generation;
                        }
                    }
                    if (mGenerationTracker != null && currentGeneration
                            == mGenerationTracker.getCurrentGeneration()) {
                    if (mGenerationTrackers.get(prefix) != null && currentGeneration
                            == mGenerationTrackers.get(prefix).getCurrentGeneration()) {
                        if (DEBUG) {
                            Log.i(TAG, "Updating cache for prefix:" + prefix);
                        }
                        // cache the complete list of flags for the namespace
                        mValues.putAll(flagsToValues);
                        // Adding the prefix as a signal that the prefix is cached.
@@ -3556,11 +3564,11 @@ public final class Settings {
        public void clearGenerationTrackerForTest() {
            synchronized (NameValueCache.this) {
                if (mGenerationTracker != null) {
                    mGenerationTracker.destroy();
                for (int i = 0; i < mGenerationTrackers.size(); i++) {
                    mGenerationTrackers.valueAt(i).destroy();
                }
                mGenerationTrackers.clear();
                mValues.clear();
                mGenerationTracker = null;
            }
        }
    }
+200 −59

File changed.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ android_test {
        "test/**/*.java",
        "src/android/provider/settings/backup/*",
        "src/android/provider/settings/validators/*",
        "src/com/android/providers/settings/GenerationRegistry.java",
        "src/com/android/providers/settings/SettingsBackupAgent.java",
        "src/com/android/providers/settings/SettingsState.java",
        "src/com/android/providers/settings/SettingsHelper.java",
+129 −80

File changed.

Preview size limit exceeded, changes collapsed.

+41 −22

File changed.

Preview size limit exceeded, changes collapsed.

Loading