1 /* <lambda>null2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.qs.footer.domain.interactor 18 19 import android.app.admin.DevicePolicyEventLogger 20 import android.app.admin.DevicePolicyManager 21 import android.content.Context 22 import android.content.Intent 23 import android.content.IntentFilter 24 import android.os.UserHandle 25 import android.provider.Settings 26 import com.android.internal.jank.InteractionJankMonitor 27 import com.android.internal.logging.MetricsLogger 28 import com.android.internal.logging.UiEventLogger 29 import com.android.internal.logging.nano.MetricsProto 30 import com.android.internal.util.FrameworkStatsLog 31 import com.android.systemui.animation.Expandable 32 import com.android.systemui.broadcast.BroadcastDispatcher 33 import com.android.systemui.dagger.SysUISingleton 34 import com.android.systemui.dagger.qualifiers.Background 35 import com.android.systemui.globalactions.GlobalActionsDialogLite 36 import com.android.systemui.plugins.ActivityStarter 37 import com.android.systemui.qs.FgsManagerController 38 import com.android.systemui.qs.QSSecurityFooterUtils 39 import com.android.systemui.qs.footer.data.model.UserSwitcherStatusModel 40 import com.android.systemui.qs.footer.data.repository.ForegroundServicesRepository 41 import com.android.systemui.qs.footer.domain.model.SecurityButtonConfig 42 import com.android.systemui.security.data.repository.SecurityRepository 43 import com.android.systemui.shade.ShadeDisplayAware 44 import com.android.systemui.statusbar.policy.DeviceProvisionedController 45 import com.android.systemui.user.data.repository.UserSwitcherRepository 46 import com.android.systemui.user.domain.interactor.UserSwitcherInteractor 47 import javax.inject.Inject 48 import kotlinx.coroutines.CoroutineDispatcher 49 import kotlinx.coroutines.flow.Flow 50 import kotlinx.coroutines.flow.map 51 import kotlinx.coroutines.withContext 52 53 /** Interactor for the footer actions business logic. */ 54 interface FooterActionsInteractor { 55 /** The current [SecurityButtonConfig]. */ 56 val securityButtonConfig: Flow<SecurityButtonConfig?> 57 58 /** The number of packages with a service running in the foreground. */ 59 val foregroundServicesCount: Flow<Int> 60 61 /** Whether there are new packages with a service running in the foreground. */ 62 val hasNewForegroundServices: Flow<Boolean> 63 64 /** The current [UserSwitcherStatusModel]. */ 65 val userSwitcherStatus: Flow<UserSwitcherStatusModel> 66 67 /** 68 * The flow emitting `Unit` whenever a request to show the device monitoring dialog is fired. 69 */ 70 val deviceMonitoringDialogRequests: Flow<Unit> 71 72 /** 73 * Show the device monitoring dialog, expanded from [expandable] if it's not null. 74 * 75 * Important: [quickSettingsContext] *must* be the [Context] associated to the 76 * [Quick Settings fragment][com.android.systemui.qs.QSFragmentLegacy]. 77 */ 78 fun showDeviceMonitoringDialog(quickSettingsContext: Context, expandable: Expandable?) 79 80 /** Show the foreground services dialog. */ 81 fun showForegroundServicesDialog(expandable: Expandable) 82 83 /** Show the power menu dialog. */ 84 fun showPowerMenuDialog( 85 globalActionsDialogLite: GlobalActionsDialogLite, 86 expandable: Expandable, 87 ) 88 89 /** Show the settings. */ 90 fun showSettings(expandable: Expandable) 91 92 /** Show the user switcher. */ 93 fun showUserSwitcher(expandable: Expandable) 94 } 95 96 @SysUISingleton 97 class FooterActionsInteractorImpl 98 @Inject 99 constructor( 100 private val activityStarter: ActivityStarter, 101 private val metricsLogger: MetricsLogger, 102 private val uiEventLogger: UiEventLogger, 103 private val deviceProvisionedController: DeviceProvisionedController, 104 private val qsSecurityFooterUtils: QSSecurityFooterUtils, 105 private val fgsManagerController: FgsManagerController, 106 private val userSwitcherInteractor: UserSwitcherInteractor, 107 securityRepository: SecurityRepository, 108 foregroundServicesRepository: ForegroundServicesRepository, 109 userSwitcherRepository: UserSwitcherRepository, 110 broadcastDispatcher: BroadcastDispatcher, 111 @Background bgDispatcher: CoroutineDispatcher, 112 @ShadeDisplayAware private val context: Context, 113 ) : FooterActionsInteractor { 114 override val securityButtonConfig: Flow<SecurityButtonConfig?> = securitynull115 securityRepository.security.map { security -> 116 withContext(bgDispatcher) { qsSecurityFooterUtils.getButtonConfig(security) } 117 } 118 119 override val foregroundServicesCount: Flow<Int> = 120 foregroundServicesRepository.foregroundServicesCount 121 122 override val hasNewForegroundServices: Flow<Boolean> = 123 foregroundServicesRepository.hasNewChanges 124 125 override val userSwitcherStatus: Flow<UserSwitcherStatusModel> = 126 userSwitcherRepository.userSwitcherStatus 127 128 override val deviceMonitoringDialogRequests: Flow<Unit> = 129 broadcastDispatcher.broadcastFlow( 130 IntentFilter(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG), 131 UserHandle.ALL, 132 Context.RECEIVER_EXPORTED, 133 null, 134 ) 135 showDeviceMonitoringDialognull136 override fun showDeviceMonitoringDialog( 137 quickSettingsContext: Context, 138 expandable: Expandable?, 139 ) { 140 qsSecurityFooterUtils.showDeviceMonitoringDialog(quickSettingsContext, expandable) 141 if (expandable != null) { 142 DevicePolicyEventLogger.createEvent( 143 FrameworkStatsLog.DEVICE_POLICY_EVENT__EVENT_ID__DO_USER_INFO_CLICKED 144 ) 145 .write() 146 } 147 } 148 showForegroundServicesDialognull149 override fun showForegroundServicesDialog(expandable: Expandable) { 150 fgsManagerController.showDialog(expandable) 151 } 152 showPowerMenuDialognull153 override fun showPowerMenuDialog( 154 globalActionsDialogLite: GlobalActionsDialogLite, 155 expandable: Expandable, 156 ) { 157 uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS) 158 globalActionsDialogLite.showOrHideDialog( 159 /* keyguardShowing= */ false, 160 /* isDeviceProvisioned= */ true, 161 expandable, 162 context.displayId, 163 ) 164 } 165 showSettingsnull166 override fun showSettings(expandable: Expandable) { 167 if (!deviceProvisionedController.isCurrentUserSetup) { 168 // If user isn't setup just unlock the device and dump them back at SUW. 169 activityStarter.postQSRunnableDismissingKeyguard {} 170 return 171 } 172 173 metricsLogger.action(MetricsProto.MetricsEvent.ACTION_QS_EXPANDED_SETTINGS_LAUNCH) 174 activityStarter.startActivity( 175 Intent(Settings.ACTION_SETTINGS), 176 true /* dismissShade */, 177 expandable.activityTransitionController( 178 InteractionJankMonitor.CUJ_SHADE_APP_LAUNCH_FROM_SETTINGS_BUTTON 179 ), 180 ) 181 } 182 showUserSwitchernull183 override fun showUserSwitcher(expandable: Expandable) { 184 userSwitcherInteractor.showUserSwitcher(expandable) 185 } 186 } 187