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

Commit 4335af56 authored by Ioana Alexandru's avatar Ioana Alexandru Committed by Android (Google) Code Review
Browse files

Merge changes from topic "one_zenrepository" into main

* changes:
  Fix ZenModeRepository using the wrong broadcast.
  Merge NotificationsSoundPolicyRepository and ZenModeRepository
parents 0ab853e2 4a02c225
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -89,3 +89,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "volume_panel_broadcast_fix"
    namespace: "systemui"
    description: "Make the volume panel's repository listen for the new ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED broadcast instead of ACTION_NOTIFICATION_POLICY_CHANGED"
    bug: "347707024"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+0 −39
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.statusbar.notification.data.model

import android.provider.Settings.Global

/** Validating wrapper for [android.app.NotificationManager.getZenMode] values. */
@JvmInline
value class ZenMode(val zenMode: Int) {

    init {
        require(zenMode in supportedModes) { "Unsupported zenMode=$zenMode" }
    }

    private companion object {

        val supportedModes =
            listOf(
                Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
                Global.ZEN_MODE_NO_INTERRUPTIONS,
                Global.ZEN_MODE_ALARMS,
                Global.ZEN_MODE_OFF,
            )
    }
}
+6 −7
Original line number Diff line number Diff line
@@ -18,19 +18,18 @@ package com.android.settingslib.statusbar.notification.data.repository

import android.app.NotificationManager
import android.provider.Settings
import com.android.settingslib.statusbar.notification.data.model.ZenMode
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow

class FakeNotificationsSoundPolicyRepository : NotificationsSoundPolicyRepository {
class FakeZenModeRepository : ZenModeRepository {

    private val mutableNotificationPolicy = MutableStateFlow<NotificationManager.Policy?>(null)
    override val notificationPolicy: StateFlow<NotificationManager.Policy?>
    override val consolidatedNotificationPolicy: StateFlow<NotificationManager.Policy?>
        get() = mutableNotificationPolicy.asStateFlow()

    private val mutableZenMode = MutableStateFlow<ZenMode?>(ZenMode(Settings.Global.ZEN_MODE_OFF))
    override val zenMode: StateFlow<ZenMode?>
    private val mutableZenMode = MutableStateFlow(Settings.Global.ZEN_MODE_OFF)
    override val globalZenMode: StateFlow<Int>
        get() = mutableZenMode.asStateFlow()

    init {
@@ -41,12 +40,12 @@ class FakeNotificationsSoundPolicyRepository : NotificationsSoundPolicyRepositor
        mutableNotificationPolicy.value = policy
    }

    fun updateZenMode(zenMode: ZenMode?) {
    fun updateZenMode(zenMode: Int) {
        mutableZenMode.value = zenMode
    }
}

fun FakeNotificationsSoundPolicyRepository.updateNotificationPolicy(
fun FakeZenModeRepository.updateNotificationPolicy(
    priorityCategories: Int = 0,
    priorityCallSenders: Int = NotificationManager.Policy.PRIORITY_SENDERS_ANY,
    priorityMessageSenders: Int = NotificationManager.Policy.CONVERSATION_SENDERS_NONE,
+42 −27
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import com.android.settingslib.statusbar.notification.data.model.ZenMode
import com.android.settingslib.flags.Flags
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
@@ -37,21 +37,20 @@ import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

/** Provides state of volume policy and restrictions imposed by notifications. */
interface NotificationsSoundPolicyRepository {

    /** @see NotificationManager.getNotificationPolicy */
    val notificationPolicy: StateFlow<NotificationManager.Policy?>
interface ZenModeRepository {
    /** @see NotificationManager.getConsolidatedNotificationPolicy */
    val consolidatedNotificationPolicy: StateFlow<NotificationManager.Policy?>

    /** @see NotificationManager.getZenMode */
    val zenMode: StateFlow<ZenMode?>
    val globalZenMode: StateFlow<Int?>
}

class NotificationsSoundPolicyRepositoryImpl(
class ZenModeRepositoryImpl(
    private val context: Context,
    private val notificationManager: NotificationManager,
    scope: CoroutineScope,
    backgroundCoroutineContext: CoroutineContext,
) : NotificationsSoundPolicyRepository {
    val scope: CoroutineScope,
    val backgroundCoroutineContext: CoroutineContext,
) : ZenModeRepository {

    private val notificationBroadcasts =
        callbackFlow {
@@ -67,29 +66,45 @@ class NotificationsSoundPolicyRepositoryImpl(
                    IntentFilter().apply {
                        addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED)
                        addAction(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED)
                    }
                )
                        if (Flags.volumePanelBroadcastFix() && android.app.Flags.modesApi())
                            addAction(
                                NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED)
                    })

                awaitClose { context.unregisterReceiver(receiver) }
            }
            .shareIn(
            .apply {
                if (Flags.volumePanelBroadcastFix()) {
                    flowOn(backgroundCoroutineContext)
                    stateIn(scope, SharingStarted.WhileSubscribed(), null)
                } else {
                    shareIn(
                        started = SharingStarted.WhileSubscribed(),
                        scope = scope,
                    )
                }
            }

    override val notificationPolicy: StateFlow<NotificationManager.Policy?> =
        notificationBroadcasts
            .filter { NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED == it }
            .map { notificationManager.consolidatedNotificationPolicy }
            .onStart { emit(notificationManager.consolidatedNotificationPolicy) }
            .flowOn(backgroundCoroutineContext)
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
    override val consolidatedNotificationPolicy: StateFlow<NotificationManager.Policy?> =
        if (Flags.volumePanelBroadcastFix() && android.app.Flags.modesApi())
            flowFromBroadcast(NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED) {
                notificationManager.consolidatedNotificationPolicy
            }
        else
            flowFromBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED) {
                notificationManager.consolidatedNotificationPolicy
            }

    override val globalZenMode: StateFlow<Int?> =
        flowFromBroadcast(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED) {
            notificationManager.zenMode
        }

    override val zenMode: StateFlow<ZenMode?> =
    private fun <T> flowFromBroadcast(intentAction: String, mapper: () -> T) =
        notificationBroadcasts
            .filter { NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED == it }
            .map { ZenMode(notificationManager.zenMode) }
            .onStart { emit(ZenMode(notificationManager.zenMode)) }
            .filter { intentAction == it }
            .map { mapper() }
            .onStart { emit(mapper()) }
            .flowOn(backgroundCoroutineContext)
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)
}
+7 −10
Original line number Diff line number Diff line
@@ -20,8 +20,7 @@ import android.app.NotificationManager
import android.media.AudioManager
import android.provider.Settings
import android.service.notification.ZenModeConfig
import com.android.settingslib.statusbar.notification.data.model.ZenMode
import com.android.settingslib.statusbar.notification.data.repository.NotificationsSoundPolicyRepository
import com.android.settingslib.statusbar.notification.data.repository.ZenModeRepository
import com.android.settingslib.volume.shared.model.AudioStream
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
@@ -30,17 +29,15 @@ import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map

/** Determines notification sounds state and limitations. */
class NotificationsSoundPolicyInteractor(
    private val repository: NotificationsSoundPolicyRepository
) {
class NotificationsSoundPolicyInteractor(private val repository: ZenModeRepository) {

    /** @see NotificationManager.getNotificationPolicy */
    val notificationPolicy: StateFlow<NotificationManager.Policy?>
        get() = repository.notificationPolicy
    private val notificationPolicy: StateFlow<NotificationManager.Policy?>
        get() = repository.consolidatedNotificationPolicy

    /** @see NotificationManager.getZenMode */
    val zenMode: StateFlow<ZenMode?>
        get() = repository.zenMode
    val zenMode: StateFlow<Int?>
        get() = repository.globalZenMode

    /** Checks if [notificationPolicy] allows alarms. */
    val areAlarmsAllowed: Flow<Boolean?> = notificationPolicy.map { it?.allowAlarms() }
@@ -67,7 +64,7 @@ class NotificationsSoundPolicyInteractor(
            isRingerAllowed.filterNotNull(),
            isSystemAllowed.filterNotNull(),
        ) { zenMode, areAlarmsAllowed, isMediaAllowed, isRingerAllowed, isSystemAllowed ->
            when (zenMode.zenMode) {
            when (zenMode) {
                // Everything is muted
                Settings.Global.ZEN_MODE_NO_INTERRUPTIONS -> return@combine true
                Settings.Global.ZEN_MODE_ALARMS ->
Loading