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

Commit bc288caf authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Sync settingslib/datastore library" into main

parents c3da1590 5cd51ac8
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ class BackupRestoreStorageManager private constructor(private val application: A
            }
        }

        override fun onChanged(reason: Int) = onKeyChanged(null, reason)
        override fun onChanged(observable: Observable, reason: Int) = onKeyChanged(null, reason)

        override fun onKeyChanged(key: Any?, reason: Int) {
            notifyBackupManager(key, reason)
+1 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ interface KeyedObservable<K> {
}

/** A thread safe implementation of [KeyedObservable]. */
class KeyedDataObservable<K> : KeyedObservable<K> {
open class KeyedDataObservable<K> : KeyedObservable<K> {
    // Instead of @GuardedBy("this"), guarded by itself because KeyedDataObservable object could be
    // synchronized outside by the holder
    @GuardedBy("itself") private val observers = WeakHashMap<KeyedObserver<K?>, Executor>()
+4 −2
Original line number Diff line number Diff line
@@ -21,5 +21,7 @@ package com.android.settingslib.datastore
 *
 * This class provides the [Observable] implementations on top of [DataObservable] by delegation.
 */
abstract class ObservableBackupRestoreStorage :
    BackupRestoreStorage(), Observable by DataObservable()
abstract class ObservableBackupRestoreStorage : BackupRestoreStorage(), ObservableDelegation {

    final override val observableDelegate: Observable = DataObservable(this)
}
+17 −3
Original line number Diff line number Diff line
@@ -32,10 +32,11 @@ fun interface Observer {
     *
     * This callback will run in the given [Executor] when observer is added.
     *
     * @param observable observable of the change
     * @param reason the reason of change
     * @see [Observable.addObserver] for the notices.
     */
    fun onChanged(reason: Int)
    fun onChanged(observable: Observable, reason: Int)
}

/** An observable object allows to observe change with [Observer]. */
@@ -68,8 +69,21 @@ interface Observable {
    fun notifyChange(reason: Int)
}

/** Delegation of [Observable]. */
interface ObservableDelegation : Observable {
    /** [Observable] to delegate. */
    val observableDelegate: Observable

    override fun addObserver(observer: Observer, executor: Executor) =
        observableDelegate.addObserver(observer, executor)

    override fun removeObserver(observer: Observer) = observableDelegate.removeObserver(observer)

    override fun notifyChange(reason: Int) = observableDelegate.notifyChange(reason)
}

/** A thread safe implementation of [Observable]. */
class DataObservable : Observable {
class DataObservable(private val observable: Observable) : Observable {
    // Instead of @GuardedBy("this"), guarded by itself because DataObservable object could be
    // synchronized outside by the holder
    @GuardedBy("itself") private val observers = WeakHashMap<Observer, Executor>()
@@ -90,7 +104,7 @@ class DataObservable : Observable {
        val entries = synchronized(observers) { observers.entries.toTypedArray() }
        for (entry in entries) {
            val observer = entry.key // avoid reference "entry"
            entry.value.execute { observer.onChanged(reason) }
            entry.value.execute { observer.onChanged(observable, reason) }
        }
    }
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.settingslib.datastore

import android.content.SharedPreferences

/** [SharedPreferences] based [KeyedDataObservable]. */
class SharedPreferencesObservable(private val sharedPreferences: SharedPreferences) :
    KeyedDataObservable<String>(), AutoCloseable {

    private val listener = createSharedPreferenceListener()

    init {
        sharedPreferences.registerOnSharedPreferenceChangeListener(listener)
    }

    override fun close() {
        sharedPreferences.unregisterOnSharedPreferenceChangeListener(listener)
    }
}

/** Creates [SharedPreferences.OnSharedPreferenceChangeListener] for [KeyedObservable]. */
internal fun KeyedObservable<String>.createSharedPreferenceListener() =
    SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
        if (key != null) {
            notifyChange(key, DataChangeReason.UPDATE)
        } else {
            // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
            notifyChange(DataChangeReason.DELETE)
        }
    }
Loading