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

Commit 4d1174c7 authored by lyn's avatar lyn
Browse files

StateFlow to check isCooldownEnabled in background

Bug: 333119315
Test: NotificationSettingsRepositoryTest
Test: turn settings on/off => feature turns on/off
Flag: com.android.systemui.notification_avalanche_suppression
Change-Id: I3d056ee165138d54230aaaccb8f7de1f0211ddd7
parent e49f5aba
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@ package com.android.systemui.shared.notifications.data.repository

import android.provider.Settings
import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository
import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
@@ -33,6 +35,7 @@ class NotificationSettingsRepository(
    private val scope: CoroutineScope,
    private val backgroundDispatcher: CoroutineDispatcher,
    private val secureSettingsRepository: SecureSettingsRepository,
    private val systemSettingsRepository: SystemSettingsRepository,
) {
    val isNotificationHistoryEnabled: Flow<Boolean> =
        secureSettingsRepository
@@ -60,4 +63,15 @@ class NotificationSettingsRepository(
            )
        }
    }

    val isCooldownEnabled: StateFlow<Boolean> =
        systemSettingsRepository
            .intSetting(name = Settings.System.NOTIFICATION_COOLDOWN_ENABLED)
            .map { it == 1 }
            .flowOn(backgroundDispatcher)
            .stateIn(
                scope = scope,
                started = SharingStarted.Eagerly,
                initialValue = false,
            )
}
+2 −1
Original line number Diff line number Diff line
@@ -38,4 +38,5 @@ class NotificationSettingsInteractor(
        val current = repository.isShowNotificationsOnLockScreenEnabled().value
        repository.setShowNotificationsOnLockscreenEnabled(!current)
    }
}

    val isCooldownEnabled = repository.isCooldownEnabled}
+117 −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.systemui.shared.settings.data.repository

import android.content.ContentResolver
import android.database.ContentObserver
import android.provider.Settings
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext

/**
 * Defines interface for classes that can provide access to data from [Settings.System]. This
 * repository doesn't guarantee to provide value across different users. For that see:
 * [UserAwareSecureSettingsRepository] which does that for secure settings.
 */
interface SystemSettingsRepository {

    /** Returns a [Flow] tracking the value of a setting as an [Int]. */
    fun intSetting(
        name: String,
        defaultValue: Int = 0,
    ): Flow<Int>

    /** Updates the value of the setting with the given name. */
    suspend fun setInt(
        name: String,
        value: Int,
    )

    suspend fun getInt(
        name: String,
        defaultValue: Int = 0,
    ): Int

    suspend fun getString(name: String): String?
}

class SystemSettingsRepositoryImpl(
    private val contentResolver: ContentResolver,
    private val backgroundDispatcher: CoroutineDispatcher,
) : SystemSettingsRepository {

    override fun intSetting(
        name: String,
        defaultValue: Int,
    ): Flow<Int> {
        return callbackFlow {
                val observer =
                    object : ContentObserver(null) {
                        override fun onChange(selfChange: Boolean) {
                            trySend(Unit)
                        }
                    }

                contentResolver.registerContentObserver(
                    Settings.System.getUriFor(name),
                    /* notifyForDescendants= */ false,
                    observer,
                )
                send(Unit)

                awaitClose { contentResolver.unregisterContentObserver(observer) }
            }
            .map { Settings.System.getInt(contentResolver, name, defaultValue) }
            // The above work is done on the background thread (which is important for accessing
            // settings through the content resolver).
            .flowOn(backgroundDispatcher)
    }

    override suspend fun setInt(name: String, value: Int) {
        withContext(backgroundDispatcher) {
            Settings.System.putInt(
                contentResolver,
                name,
                value,
            )
        }
    }

    override suspend fun getInt(name: String, defaultValue: Int): Int {
        return withContext(backgroundDispatcher) {
            Settings.System.getInt(
                contentResolver,
                name,
                defaultValue,
            )
        }
    }

    override suspend fun getString(name: String): String? {
        return withContext(backgroundDispatcher) {
            Settings.System.getString(
                contentResolver,
                name,
            )
        }
    }
}
+42 −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.systemui.shared.settings.data.repository

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.map

class FakeSystemSettingsRepository : SystemSettingsRepository {

    private val settings = MutableStateFlow<Map<String, String>>(mutableMapOf())

    override fun intSetting(name: String, defaultValue: Int): Flow<Int> {
        return settings.map { it.getOrDefault(name, defaultValue.toString()) }.map { it.toInt() }
    }

    override suspend fun setInt(name: String, value: Int) {
        settings.value = settings.value.toMutableMap().apply { this[name] = value.toString() }
    }

    override suspend fun getInt(name: String, defaultValue: Int): Int {
        return settings.value[name]?.toInt() ?: defaultValue
    }

    override suspend fun getString(name: String): String? {
        return settings.value[name]
    }
}
+38 −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.systemui.settings

import android.content.ContentResolver
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.shared.settings.data.repository.SystemSettingsRepository
import com.android.systemui.shared.settings.data.repository.SystemSettingsRepositoryImpl
import dagger.Module
import dagger.Provides
import kotlinx.coroutines.CoroutineDispatcher

@Module
object SystemSettingsRepositoryModule {
    @JvmStatic
    @Provides
    @SysUISingleton
    fun provideSystemSettingsRepository(
        contentResolver: ContentResolver,
        @Background backgroundDispatcher: CoroutineDispatcher,
    ): SystemSettingsRepository =
        SystemSettingsRepositoryImpl(contentResolver, backgroundDispatcher)
}
Loading