Loading packages/SystemUI/res/drawable/ic_do_not_disturb.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2022 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="#ffffff" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM7,11h10v2L7,13z"/> </vector> packages/SystemUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2035,6 +2035,9 @@ <!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] --> <string name="dnd_is_off">Do Not Disturb is off</string> <!-- Label for when Do not disturb is on in lockscreen quick affordance [CHAR LIMIT=NONE] --> <string name="dnd_is_on">Do Not Disturb is on</string> <!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] --> <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>).</string> Loading packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ package com.android.systemui.keyguard.data.quickaffordance object BuiltInKeyguardQuickAffordanceKeys { // Please keep alphabetical order of const names to simplify future maintenance. const val CAMERA = "camera" const val DO_NOT_DISTURB = "do_not_disturb" const val FLASHLIGHT = "flashlight" const val HOME_CONTROLS = "home" const val QR_CODE_SCANNER = "qr_code_scanner" Loading packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.keyguard.data.quickaffordance import android.content.Context import android.net.Uri import android.provider.Settings import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_OFF import android.provider.Settings.Secure.ZEN_DURATION_FOREVER import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import android.service.notification.ZenModeConfig import com.android.settingslib.notification.EnableZenModeDialog import com.android.settingslib.notification.ZenModeDialogMetricsLogger import com.android.systemui.R import com.android.systemui.animation.Expandable import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.ZenModeController import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import javax.inject.Inject @SysUISingleton class DoNotDisturbQuickAffordanceConfig constructor( private val context: Context, private val controller: ZenModeController, private val secureSettings: SecureSettings, private val userTracker: UserTracker, @Background private val backgroundDispatcher: CoroutineDispatcher, private val testConditionId: Uri?, testDialog: EnableZenModeDialog?, ): KeyguardQuickAffordanceConfig { @Inject constructor( context: Context, controller: ZenModeController, secureSettings: SecureSettings, userTracker: UserTracker, @Background backgroundDispatcher: CoroutineDispatcher, ) : this(context, controller, secureSettings, userTracker, backgroundDispatcher, null, null) private var dndMode: Int = 0 private var isAvailable = false private var settingsValue: Int = 0 private val conditionUri: Uri get() = testConditionId ?: ZenModeConfig.toTimeCondition( context, settingsValue, userTracker.userId, true, /* shortVersion */ ).id private val dialog: EnableZenModeDialog by lazy { testDialog ?: EnableZenModeDialog( context, R.style.Theme_SystemUI_Dialog, true, /* cancelIsNeutral */ ZenModeDialogMetricsLogger(context), ) } override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB override val pickerName: String = context.getString(R.string.quick_settings_dnd_label) override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = combine( conflatedCallbackFlow { val callback = object: ZenModeController.Callback { override fun onZenChanged(zen: Int) { dndMode = zen trySendWithFailureLogging(updateState(), TAG) } override fun onZenAvailableChanged(available: Boolean) { isAvailable = available trySendWithFailureLogging(updateState(), TAG) } } dndMode = controller.zen isAvailable = controller.isZenAvailable trySendWithFailureLogging(updateState(), TAG) controller.addCallback(callback) awaitClose { controller.removeCallback(callback) } }, secureSettings .observerFlow(Settings.Secure.ZEN_DURATION) .onStart { emit(Unit) } .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) } .flowOn(backgroundDispatcher) .distinctUntilChanged() .onEach { settingsValue = it } ) { callbackFlowValue, _ -> callbackFlowValue } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { return if (controller.isZenAvailable) { KeyguardQuickAffordanceConfig.PickerScreenState.Default } else { KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice } } override fun onTriggered(expandable: Expandable?): KeyguardQuickAffordanceConfig.OnTriggeredResult { return when { !isAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled dndMode != ZEN_MODE_OFF -> { controller.setZen(ZEN_MODE_OFF, null, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } settingsValue == ZEN_DURATION_PROMPT -> KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( dialog.createDialog(), expandable ) settingsValue == ZEN_DURATION_FOREVER -> { controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } else -> { controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } } } private fun updateState(): KeyguardQuickAffordanceConfig.LockScreenState { return if (!isAvailable) { KeyguardQuickAffordanceConfig.LockScreenState.Hidden } else if (dndMode == ZEN_MODE_OFF) { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_off, ContentDescription.Resource(R.string.dnd_is_off), ), ActivationState.Inactive, ) } else { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_on, ContentDescription.Resource(R.string.dnd_is_on), ), ActivationState.Active, ) } } companion object { const val TAG = "DoNotDisturbQuickAffordanceConfig" } } No newline at end of file packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ interface KeyguardDataQuickAffordanceModule { @Provides @ElementsIntoSet fun quickAffordanceConfigs( doNotDisturb: DoNotDisturbQuickAffordanceConfig, flashlight: FlashlightQuickAffordanceConfig, home: HomeControlsKeyguardQuickAffordanceConfig, quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig, Loading @@ -41,6 +42,7 @@ interface KeyguardDataQuickAffordanceModule { ): Set<KeyguardQuickAffordanceConfig> { return setOf( camera, doNotDisturb, flashlight, home, quickAccessWallet, Loading Loading
packages/SystemUI/res/drawable/ic_do_not_disturb.xml 0 → 100644 +25 −0 Original line number Diff line number Diff line <!-- ~ Copyright (C) 2022 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. --> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:width="24dp" android:viewportHeight="24.0" android:viewportWidth="24.0"> <path android:fillColor="#ffffff" android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM7,11h10v2L7,13z"/> </vector>
packages/SystemUI/res/values/strings.xml +3 −0 Original line number Diff line number Diff line Loading @@ -2035,6 +2035,9 @@ <!-- Label for when Do not disturb is off in QS detail panel [CHAR LIMIT=NONE] --> <string name="dnd_is_off">Do Not Disturb is off</string> <!-- Label for when Do not disturb is on in lockscreen quick affordance [CHAR LIMIT=NONE] --> <string name="dnd_is_on">Do Not Disturb is on</string> <!-- Prompt for when Do not disturb is on from automatic rule in QS [CHAR LIMIT=NONE] --> <string name="qs_dnd_prompt_auto_rule">Do Not Disturb was turned on by an automatic rule (<xliff:g name="rule">%s</xliff:g>).</string> Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/BuiltInKeyguardQuickAffordanceKeys.kt +1 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ package com.android.systemui.keyguard.data.quickaffordance object BuiltInKeyguardQuickAffordanceKeys { // Please keep alphabetical order of const names to simplify future maintenance. const val CAMERA = "camera" const val DO_NOT_DISTURB = "do_not_disturb" const val FLASHLIGHT = "flashlight" const val HOME_CONTROLS = "home" const val QR_CODE_SCANNER = "qr_code_scanner" Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/DoNotDisturbQuickAffordanceConfig.kt 0 → 100644 +190 −0 Original line number Diff line number Diff line /* * Copyright (C) 2022 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.keyguard.data.quickaffordance import android.content.Context import android.net.Uri import android.provider.Settings import android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS import android.provider.Settings.Global.ZEN_MODE_OFF import android.provider.Settings.Secure.ZEN_DURATION_FOREVER import android.provider.Settings.Secure.ZEN_DURATION_PROMPT import android.service.notification.ZenModeConfig import com.android.settingslib.notification.EnableZenModeDialog import com.android.settingslib.notification.ZenModeDialogMetricsLogger import com.android.systemui.R import com.android.systemui.animation.Expandable import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.keyguard.shared.quickaffordance.ActivationState import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.ZenModeController import com.android.systemui.util.settings.SecureSettings import com.android.systemui.util.settings.SettingsProxyExt.observerFlow import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import javax.inject.Inject @SysUISingleton class DoNotDisturbQuickAffordanceConfig constructor( private val context: Context, private val controller: ZenModeController, private val secureSettings: SecureSettings, private val userTracker: UserTracker, @Background private val backgroundDispatcher: CoroutineDispatcher, private val testConditionId: Uri?, testDialog: EnableZenModeDialog?, ): KeyguardQuickAffordanceConfig { @Inject constructor( context: Context, controller: ZenModeController, secureSettings: SecureSettings, userTracker: UserTracker, @Background backgroundDispatcher: CoroutineDispatcher, ) : this(context, controller, secureSettings, userTracker, backgroundDispatcher, null, null) private var dndMode: Int = 0 private var isAvailable = false private var settingsValue: Int = 0 private val conditionUri: Uri get() = testConditionId ?: ZenModeConfig.toTimeCondition( context, settingsValue, userTracker.userId, true, /* shortVersion */ ).id private val dialog: EnableZenModeDialog by lazy { testDialog ?: EnableZenModeDialog( context, R.style.Theme_SystemUI_Dialog, true, /* cancelIsNeutral */ ZenModeDialogMetricsLogger(context), ) } override val key: String = BuiltInKeyguardQuickAffordanceKeys.DO_NOT_DISTURB override val pickerName: String = context.getString(R.string.quick_settings_dnd_label) override val pickerIconResourceId: Int = R.drawable.ic_do_not_disturb override val lockScreenState: Flow<KeyguardQuickAffordanceConfig.LockScreenState> = combine( conflatedCallbackFlow { val callback = object: ZenModeController.Callback { override fun onZenChanged(zen: Int) { dndMode = zen trySendWithFailureLogging(updateState(), TAG) } override fun onZenAvailableChanged(available: Boolean) { isAvailable = available trySendWithFailureLogging(updateState(), TAG) } } dndMode = controller.zen isAvailable = controller.isZenAvailable trySendWithFailureLogging(updateState(), TAG) controller.addCallback(callback) awaitClose { controller.removeCallback(callback) } }, secureSettings .observerFlow(Settings.Secure.ZEN_DURATION) .onStart { emit(Unit) } .map { secureSettings.getInt(Settings.Secure.ZEN_DURATION, ZEN_MODE_OFF) } .flowOn(backgroundDispatcher) .distinctUntilChanged() .onEach { settingsValue = it } ) { callbackFlowValue, _ -> callbackFlowValue } override suspend fun getPickerScreenState(): KeyguardQuickAffordanceConfig.PickerScreenState { return if (controller.isZenAvailable) { KeyguardQuickAffordanceConfig.PickerScreenState.Default } else { KeyguardQuickAffordanceConfig.PickerScreenState.UnavailableOnDevice } } override fun onTriggered(expandable: Expandable?): KeyguardQuickAffordanceConfig.OnTriggeredResult { return when { !isAvailable -> KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled dndMode != ZEN_MODE_OFF -> { controller.setZen(ZEN_MODE_OFF, null, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } settingsValue == ZEN_DURATION_PROMPT -> KeyguardQuickAffordanceConfig.OnTriggeredResult.ShowDialog( dialog.createDialog(), expandable ) settingsValue == ZEN_DURATION_FOREVER -> { controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, null, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } else -> { controller.setZen(ZEN_MODE_IMPORTANT_INTERRUPTIONS, conditionUri, TAG) KeyguardQuickAffordanceConfig.OnTriggeredResult.Handled } } } private fun updateState(): KeyguardQuickAffordanceConfig.LockScreenState { return if (!isAvailable) { KeyguardQuickAffordanceConfig.LockScreenState.Hidden } else if (dndMode == ZEN_MODE_OFF) { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_off, ContentDescription.Resource(R.string.dnd_is_off), ), ActivationState.Inactive, ) } else { KeyguardQuickAffordanceConfig.LockScreenState.Visible( Icon.Resource( R.drawable.qs_dnd_icon_on, ContentDescription.Resource(R.string.dnd_is_on), ), ActivationState.Active, ) } } companion object { const val TAG = "DoNotDisturbQuickAffordanceConfig" } } No newline at end of file
packages/SystemUI/src/com/android/systemui/keyguard/data/quickaffordance/KeyguardDataQuickAffordanceModule.kt +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ interface KeyguardDataQuickAffordanceModule { @Provides @ElementsIntoSet fun quickAffordanceConfigs( doNotDisturb: DoNotDisturbQuickAffordanceConfig, flashlight: FlashlightQuickAffordanceConfig, home: HomeControlsKeyguardQuickAffordanceConfig, quickAccessWallet: QuickAccessWalletKeyguardQuickAffordanceConfig, Loading @@ -41,6 +42,7 @@ interface KeyguardDataQuickAffordanceModule { ): Set<KeyguardQuickAffordanceConfig> { return setOf( camera, doNotDisturb, flashlight, home, quickAccessWallet, Loading