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

Commit b9085c59 authored by Sunny Shao's avatar Sunny Shao
Browse files

Split ChangeReason and decouple it from Observer

Observer is flexible to be used for other scenarios.

Bug: 325144964
Test: atest SettingsLibDataStoreTest
Change-Id: I8a8ce690edee37bdb1ba20ce06a508fbdddb2c15
parent 633f4509
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -138,7 +138,7 @@ class BackupRestoreStorageManager private constructor(private val application: A
        private fun notifyBackupManager(key: Any?, reason: Int) {
        private fun notifyBackupManager(key: Any?, reason: Int) {
            val name = storage.name
            val name = storage.name
            // prefer not triggering backup immediately after restore
            // prefer not triggering backup immediately after restore
            if (reason == ChangeReason.RESTORE) {
            if (reason == DataChangeReason.RESTORE) {
                Log.d(
                Log.d(
                    LOG_TAG,
                    LOG_TAG,
                    "Notify BackupManager dataChanged ignored for restore: storage=$name key=$key"
                    "Notify BackupManager dataChanged ignored for restore: storage=$name key=$key"
@@ -161,8 +161,8 @@ class BackupRestoreStorageManager private constructor(private val application: A


        fun notifyRestoreFinished() {
        fun notifyRestoreFinished() {
            when (storage) {
            when (storage) {
                is KeyedObservable<*> -> storage.notifyChange(ChangeReason.RESTORE)
                is KeyedObservable<*> -> storage.notifyChange(DataChangeReason.RESTORE)
                is Observable -> storage.notifyChange(ChangeReason.RESTORE)
                is Observable -> storage.notifyChange(DataChangeReason.RESTORE)
            }
            }
        }
        }
    }
    }
+43 −0
Original line number Original line 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 androidx.annotation.IntDef

/** The reason of data change. */
@IntDef(
    DataChangeReason.UNKNOWN,
    DataChangeReason.UPDATE,
    DataChangeReason.DELETE,
    DataChangeReason.RESTORE,
    DataChangeReason.SYNC_ACROSS_PROFILES,
)
@Retention(AnnotationRetention.SOURCE)
annotation class DataChangeReason {
    companion object {
        /** Unknown reason of the change. */
        const val UNKNOWN = 0
        /** Data is updated. */
        const val UPDATE = 1
        /** Data is deleted. */
        const val DELETE = 2
        /** Data is restored from backup/restore framework. */
        const val RESTORE = 3
        /** Data is synced from another profile (e.g. personal profile to work profile). */
        const val SYNC_ACROSS_PROFILES = 4
    }
}
+5 −5
Original line number Original line Diff line number Diff line
@@ -37,7 +37,7 @@ fun interface KeyedObserver<in K> {
     * @param reason the reason of change
     * @param reason the reason of change
     * @see KeyedObservable.addObserver
     * @see KeyedObservable.addObserver
     */
     */
    fun onKeyChanged(key: K, @ChangeReason reason: Int)
    fun onKeyChanged(key: K, reason: Int)
}
}


/**
/**
@@ -89,7 +89,7 @@ interface KeyedObservable<K> {
     *
     *
     * @param reason reason of the change
     * @param reason reason of the change
     */
     */
    fun notifyChange(@ChangeReason reason: Int)
    fun notifyChange(reason: Int)


    /**
    /**
     * Notifies observers that a change occurs on given key.
     * Notifies observers that a change occurs on given key.
@@ -99,7 +99,7 @@ interface KeyedObservable<K> {
     * @param key key of the change
     * @param key key of the change
     * @param reason reason of the change
     * @param reason reason of the change
     */
     */
    fun notifyChange(key: K, @ChangeReason reason: Int)
    fun notifyChange(key: K, reason: Int)
}
}


/** A thread safe implementation of [KeyedObservable]. */
/** A thread safe implementation of [KeyedObservable]. */
@@ -141,7 +141,7 @@ class KeyedDataObservable<K> : KeyedObservable<K> {
        }
        }
    }
    }


    override fun notifyChange(@ChangeReason reason: Int) {
    override fun notifyChange(reason: Int) {
        // make a copy to avoid potential ConcurrentModificationException
        // make a copy to avoid potential ConcurrentModificationException
        val observers = synchronized(observers) { observers.entries.toTypedArray() }
        val observers = synchronized(observers) { observers.entries.toTypedArray() }
        val keyedObservers = synchronized(keyedObservers) { keyedObservers.copy() }
        val keyedObservers = synchronized(keyedObservers) { keyedObservers.copy() }
@@ -165,7 +165,7 @@ class KeyedDataObservable<K> : KeyedObservable<K> {
        return result
        return result
    }
    }


    override fun notifyChange(key: K, @ChangeReason reason: Int) {
    override fun notifyChange(key: K, reason: Int) {
        // make a copy to avoid potential ConcurrentModificationException
        // make a copy to avoid potential ConcurrentModificationException
        val observers = synchronized(observers) { observers.entries.toTypedArray() }
        val observers = synchronized(observers) { observers.entries.toTypedArray() }
        val keyedObservers =
        val keyedObservers =
+3 −28
Original line number Original line Diff line number Diff line
@@ -18,34 +18,9 @@ package com.android.settingslib.datastore


import androidx.annotation.AnyThread
import androidx.annotation.AnyThread
import androidx.annotation.GuardedBy
import androidx.annotation.GuardedBy
import androidx.annotation.IntDef
import java.util.WeakHashMap
import java.util.WeakHashMap
import java.util.concurrent.Executor
import java.util.concurrent.Executor


/** The reason of a change. */
@IntDef(
    ChangeReason.UNKNOWN,
    ChangeReason.UPDATE,
    ChangeReason.DELETE,
    ChangeReason.RESTORE,
    ChangeReason.SYNC_ACROSS_PROFILES,
)
@Retention(AnnotationRetention.SOURCE)
annotation class ChangeReason {
    companion object {
        /** Unknown reason of the change. */
        const val UNKNOWN = 0
        /** Data is updated. */
        const val UPDATE = 1
        /** Data is deleted. */
        const val DELETE = 2
        /** Data is restored from backup/restore framework. */
        const val RESTORE = 3
        /** Data is synced from another profile (e.g. personal profile to work profile). */
        const val SYNC_ACROSS_PROFILES = 4
    }
}

/**
/**
 * Callback to be informed of changes in [Observable] object.
 * Callback to be informed of changes in [Observable] object.
 *
 *
@@ -60,7 +35,7 @@ fun interface Observer {
     * @param reason the reason of change
     * @param reason the reason of change
     * @see [Observable.addObserver] for the notices.
     * @see [Observable.addObserver] for the notices.
     */
     */
    fun onChanged(@ChangeReason reason: Int)
    fun onChanged(reason: Int)
}
}


/** An observable object allows to observe change with [Observer]. */
/** An observable object allows to observe change with [Observer]. */
@@ -90,7 +65,7 @@ interface Observable {
     *
     *
     * @param reason reason of the change
     * @param reason reason of the change
     */
     */
    fun notifyChange(@ChangeReason reason: Int)
    fun notifyChange(reason: Int)
}
}


/** A thread safe implementation of [Observable]. */
/** A thread safe implementation of [Observable]. */
@@ -110,7 +85,7 @@ class DataObservable : Observable {
        synchronized(observers) { observers.remove(observer) }
        synchronized(observers) { observers.remove(observer) }
    }
    }


    override fun notifyChange(@ChangeReason reason: Int) {
    override fun notifyChange(reason: Int) {
        // make a copy to avoid potential ConcurrentModificationException
        // make a copy to avoid potential ConcurrentModificationException
        val entries = synchronized(observers) { observers.entries.toTypedArray() }
        val entries = synchronized(observers) { observers.entries.toTypedArray() }
        for (entry in entries) {
        for (entry in entries) {
+2 −2
Original line number Original line Diff line number Diff line
@@ -83,10 +83,10 @@ constructor(
    private val sharedPreferencesListener =
    private val sharedPreferencesListener =
        SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
        SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
            if (key != null) {
            if (key != null) {
                notifyChange(key, ChangeReason.UPDATE)
                notifyChange(key, DataChangeReason.UPDATE)
            } else {
            } else {
                // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
                // On Android >= R, SharedPreferences.Editor.clear() will trigger this case
                notifyChange(ChangeReason.DELETE)
                notifyChange(DataChangeReason.DELETE)
            }
            }
        }
        }


Loading