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

Commit 10909fd3 authored by Varun Shah's avatar Varun Shah Committed by Android (Google) Code Review
Browse files

Merge "Add OnSharedPreferencesClearListener for Editor#clear."

parents 713b809f 72511ead
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -10834,7 +10834,9 @@ package android.content {
    method @Nullable public String getString(String, @Nullable String);
    method @Nullable public String getString(String, @Nullable String);
    method @Nullable public java.util.Set<java.lang.String> getStringSet(String, @Nullable java.util.Set<java.lang.String>);
    method @Nullable public java.util.Set<java.lang.String> getStringSet(String, @Nullable java.util.Set<java.lang.String>);
    method public void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
    method public void registerOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
    method public default void registerOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener);
    method public void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
    method public void unregisterOnSharedPreferenceChangeListener(android.content.SharedPreferences.OnSharedPreferenceChangeListener);
    method public default void unregisterOnSharedPreferencesClearListener(@NonNull android.content.SharedPreferences.OnSharedPreferencesClearListener);
  }
  }
  public static interface SharedPreferences.Editor {
  public static interface SharedPreferences.Editor {
@@ -10854,6 +10856,10 @@ package android.content {
    method public void onSharedPreferenceChanged(android.content.SharedPreferences, String);
    method public void onSharedPreferenceChanged(android.content.SharedPreferences, String);
  }
  }
  public static interface SharedPreferences.OnSharedPreferencesClearListener {
    method public void onSharedPreferencesClear(@NonNull android.content.SharedPreferences, @NonNull java.util.Set<java.lang.String>);
  }
  public class SyncAdapterType implements android.os.Parcelable {
  public class SyncAdapterType implements android.os.Parcelable {
    ctor public SyncAdapterType(String, String, boolean, boolean);
    ctor public SyncAdapterType(String, String, boolean, boolean);
    ctor public SyncAdapterType(android.os.Parcel);
    ctor public SyncAdapterType(android.os.Parcel);
+65 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.app;
package android.app;


import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UnsupportedAppUsage;
import android.content.SharedPreferences;
import android.content.SharedPreferences;
@@ -25,6 +26,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.system.Os;
import android.system.StructStat;
import android.system.StructStat;
import android.system.StructTimespec;
import android.system.StructTimespec;
import android.util.ArraySet;
import android.util.Log;
import android.util.Log;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
@@ -92,6 +94,10 @@ final class SharedPreferencesImpl implements SharedPreferences {
    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
    private final WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners =
            new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
            new WeakHashMap<OnSharedPreferenceChangeListener, Object>();


    @GuardedBy("mLock")
    private final WeakHashMap<OnSharedPreferencesClearListener, Object> mClearListeners =
            new WeakHashMap<>();

    /** Current memory state (always increasing) */
    /** Current memory state (always increasing) */
    @GuardedBy("this")
    @GuardedBy("this")
    private long mCurrentMemoryStateGeneration;
    private long mCurrentMemoryStateGeneration;
@@ -252,6 +258,28 @@ final class SharedPreferencesImpl implements SharedPreferences {
        }
        }
    }
    }


    @Override
    public void registerOnSharedPreferencesClearListener(
            @NonNull OnSharedPreferencesClearListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener cannot be null.");
        }
        synchronized (mLock) {
            mClearListeners.put(listener, CONTENT);
        }
    }

    @Override
    public void unregisterOnSharedPreferencesClearListener(
            @NonNull OnSharedPreferencesClearListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("listener cannot be null.");
        }
        synchronized (mLock) {
            mClearListeners.remove(listener);
        }
    }

    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void awaitLoadedLocked() {
    private void awaitLoadedLocked() {
        if (!mLoaded) {
        if (!mLoaded) {
@@ -361,7 +389,9 @@ final class SharedPreferencesImpl implements SharedPreferences {
    private static class MemoryCommitResult {
    private static class MemoryCommitResult {
        final long memoryStateGeneration;
        final long memoryStateGeneration;
        @Nullable final List<String> keysModified;
        @Nullable final List<String> keysModified;
        @Nullable final Set<String> keysCleared;
        @Nullable final Set<OnSharedPreferenceChangeListener> listeners;
        @Nullable final Set<OnSharedPreferenceChangeListener> listeners;
        @Nullable final Set<OnSharedPreferencesClearListener> clearListeners;
        final Map<String, Object> mapToWriteToDisk;
        final Map<String, Object> mapToWriteToDisk;
        final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);
        final CountDownLatch writtenToDiskLatch = new CountDownLatch(1);


@@ -371,10 +401,14 @@ final class SharedPreferencesImpl implements SharedPreferences {


        private MemoryCommitResult(long memoryStateGeneration, @Nullable List<String> keysModified,
        private MemoryCommitResult(long memoryStateGeneration, @Nullable List<String> keysModified,
                @Nullable Set<OnSharedPreferenceChangeListener> listeners,
                @Nullable Set<OnSharedPreferenceChangeListener> listeners,
                @Nullable Set<String> keysCleared,
                @Nullable Set<OnSharedPreferencesClearListener> clearListeners,
                Map<String, Object> mapToWriteToDisk) {
                Map<String, Object> mapToWriteToDisk) {
            this.memoryStateGeneration = memoryStateGeneration;
            this.memoryStateGeneration = memoryStateGeneration;
            this.keysModified = keysModified;
            this.keysModified = keysModified;
            this.listeners = listeners;
            this.listeners = listeners;
            this.keysCleared = keysCleared;
            this.clearListeners = clearListeners;
            this.mapToWriteToDisk = mapToWriteToDisk;
            this.mapToWriteToDisk = mapToWriteToDisk;
        }
        }


@@ -492,13 +526,16 @@ final class SharedPreferencesImpl implements SharedPreferences {
            // SharedPreferences instance back, which has the
            // SharedPreferences instance back, which has the
            // changes reflected in memory.
            // changes reflected in memory.
            notifyListeners(mcr);
            notifyListeners(mcr);
            notifyClearListeners(mcr);
        }
        }


        // Returns true if any changes were made
        // Returns true if any changes were made
        private MemoryCommitResult commitToMemory() {
        private MemoryCommitResult commitToMemory() {
            long memoryStateGeneration;
            long memoryStateGeneration;
            List<String> keysModified = null;
            List<String> keysModified = null;
            Set<String> keysCleared = null;
            Set<OnSharedPreferenceChangeListener> listeners = null;
            Set<OnSharedPreferenceChangeListener> listeners = null;
            Set<OnSharedPreferencesClearListener> clearListeners = null;
            Map<String, Object> mapToWriteToDisk;
            Map<String, Object> mapToWriteToDisk;


            synchronized (SharedPreferencesImpl.this.mLock) {
            synchronized (SharedPreferencesImpl.this.mLock) {
@@ -520,12 +557,20 @@ final class SharedPreferencesImpl implements SharedPreferences {
                    keysModified = new ArrayList<String>();
                    keysModified = new ArrayList<String>();
                    listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
                    listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
                }
                }
                boolean hasClearListeners = !mClearListeners.isEmpty();
                if (hasClearListeners) {
                    keysCleared = new ArraySet<>();
                    clearListeners = new HashSet<>(mClearListeners.keySet());
                }


                synchronized (mEditorLock) {
                synchronized (mEditorLock) {
                    boolean changesMade = false;
                    boolean changesMade = false;


                    if (mClear) {
                    if (mClear) {
                        if (!mapToWriteToDisk.isEmpty()) {
                        if (!mapToWriteToDisk.isEmpty()) {
                            if (hasClearListeners) {
                                keysCleared.addAll(mapToWriteToDisk.keySet());
                            }
                            changesMade = true;
                            changesMade = true;
                            mapToWriteToDisk.clear();
                            mapToWriteToDisk.clear();
                        }
                        }
@@ -569,7 +614,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
                }
                }
            }
            }
            return new MemoryCommitResult(memoryStateGeneration, keysModified, listeners,
            return new MemoryCommitResult(memoryStateGeneration, keysModified, listeners,
                    mapToWriteToDisk);
                    keysCleared, clearListeners, mapToWriteToDisk);
        }
        }


        @Override
        @Override
@@ -596,6 +641,7 @@ final class SharedPreferencesImpl implements SharedPreferences {
                }
                }
            }
            }
            notifyListeners(mcr);
            notifyListeners(mcr);
            notifyClearListeners(mcr);
            return mcr.writeToDiskResult;
            return mcr.writeToDiskResult;
        }
        }


@@ -618,6 +664,24 @@ final class SharedPreferencesImpl implements SharedPreferences {
                ActivityThread.sMainThreadHandler.post(() -> notifyListeners(mcr));
                ActivityThread.sMainThreadHandler.post(() -> notifyListeners(mcr));
            }
            }
        }
        }

        private void notifyClearListeners(final MemoryCommitResult mcr) {
            if (mcr.clearListeners == null || mcr.keysCleared == null
                    || mcr.keysCleared.isEmpty()) {
                return;
            }
            if (Looper.myLooper() == Looper.getMainLooper()) {
                for (OnSharedPreferencesClearListener listener : mcr.clearListeners) {
                    if (listener != null) {
                        listener.onSharedPreferencesClear(SharedPreferencesImpl.this,
                                mcr.keysCleared);
                    }
                }
            } else {
                // Run this function on the main thread.
                ActivityThread.sMainThreadHandler.post(() -> notifyClearListeners(mcr));
            }
        }
    }
    }


    /**
    /**
+54 −4
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package android.content;
package android.content;


import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;


import java.util.Map;
import java.util.Map;
@@ -58,7 +59,9 @@ public interface SharedPreferences {
         * <p>This callback will be run on your main thread.
         * <p>This callback will be run on your main thread.
         *
         *
         * <p><em>Note: This callback will not be triggered when preferences are cleared via
         * <p><em>Note: This callback will not be triggered when preferences are cleared via
         * {@link Editor#clear()}.</em>
         * {@link Editor#clear()}. However, from {@link android.os.Build.VERSION_CODES#R Android R}
         * onwards, you can use {@link OnSharedPreferencesClearListener} to register for
         * {@link Editor#clear()} callbacks.</em>
         *
         *
         * @param sharedPreferences The {@link SharedPreferences} that received
         * @param sharedPreferences The {@link SharedPreferences} that received
         *            the change.
         *            the change.
@@ -68,6 +71,22 @@ public interface SharedPreferences {
        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
        void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key);
    }
    }


    /**
     * Interface definition for a callback to be invoked when shared preferences are cleared.
     */
    public interface OnSharedPreferencesClearListener {
        /**
         * Called when shared preferences are cleared via {@link Editor#clear()}.
         *
         * <p>This callback will be run on your main thread.
         *
         * @param sharedPreferences The {@link SharedPreferences} that received the change.
         * @param keys The set of keys that were cleared.
         */
        void onSharedPreferencesClear(@NonNull SharedPreferences sharedPreferences,
                @NonNull Set<String> keys);
    }

    /**
    /**
     * Interface used for modifying values in a {@link SharedPreferences}
     * Interface used for modifying values in a {@link SharedPreferences}
     * object.  All changes you make in an editor are batched, and not copied
     * object.  All changes you make in an editor are batched, and not copied
@@ -386,4 +405,35 @@ public interface SharedPreferences {
     * @see #registerOnSharedPreferenceChangeListener
     * @see #registerOnSharedPreferenceChangeListener
     */
     */
    void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);
    void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener);

    /**
     * Registers a callback to be invoked when preferences are cleared via {@link Editor#clear()}.
     *
     * <p class="caution"><strong>Caution:</strong> The preference manager does
     * not currently store a strong reference to the listener. You must store a
     * strong reference to the listener, or it will be susceptible to garbage
     * collection. We recommend you keep a reference to the listener in the
     * instance data of an object that will exist as long as you need the
     * listener.</p>
     *
     * @param listener The callback that will run.
     * @see #unregisterOnSharedPreferencesClearListener
     */
    default void registerOnSharedPreferencesClearListener(
            @NonNull OnSharedPreferencesClearListener listener) {
        throw new UnsupportedOperationException(
                "registerOnSharedPreferencesClearListener not implemented");
    }

    /**
     * Unregisters a previous callback for {@link Editor#clear()}.
     *
     * @param listener The callback that should be unregistered.
     * @see #registerOnSharedPreferencesClearListener
     */
    default void unregisterOnSharedPreferencesClearListener(
            @NonNull OnSharedPreferencesClearListener listener) {
        throw new UnsupportedOperationException(
                "unregisterOnSharedPreferencesClearListener not implemented");
    }
}
}