xref: /aosp_15_r20/frameworks/base/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsActivity.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright (C) 2021 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.controls.ui
18 
19 import android.app.Activity
20 import android.content.BroadcastReceiver
21 import android.content.Context
22 import android.content.Intent
23 import android.content.IntentFilter
24 import android.content.pm.ActivityInfo
25 import android.content.res.Configuration
26 import android.os.Bundle
27 import android.os.RemoteException
28 import android.service.dreams.IDreamManager
29 import android.view.ViewGroup
30 import android.view.WindowManager
31 import androidx.activity.ComponentActivity
32 import com.android.systemui.broadcast.BroadcastDispatcher
33 import com.android.systemui.controls.management.ControlsAnimations
34 import com.android.systemui.controls.management.ControlsManagementActivity
35 import com.android.systemui.controls.management.applyInsets
36 import com.android.systemui.controls.settings.ControlsSettingsDialogManager
37 import com.android.systemui.flags.FeatureFlags
38 import com.android.systemui.res.R
39 import com.android.systemui.statusbar.policy.KeyguardStateController
40 import javax.inject.Inject
41 
42 /**
43  * Displays Device Controls inside an activity. This activity is available to be displayed over the
44  * lockscreen if the user has allowed it via
45  * [android.provider.Settings.Secure.LOCKSCREEN_SHOW_CONTROLS]. This activity will be destroyed on
46  * SCREEN_OFF events, due to issues with occluded activities over lockscreen as well as user
47  * expectations for the activity to not continue running.
48  */
49 // Open for testing
50 open class ControlsActivity
51 @Inject
52 constructor(
53     private val uiController: ControlsUiController,
54     private val broadcastDispatcher: BroadcastDispatcher,
55     private val dreamManager: IDreamManager,
56     private val featureFlags: FeatureFlags,
57     private val controlsSettingsDialogManager: ControlsSettingsDialogManager,
58     private val keyguardStateController: KeyguardStateController,
59 ) : ComponentActivity(), ControlsManagementActivity {
60 
61     override val activity: Activity
62         get() = this
63 
64     private val lastConfiguration = Configuration()
65 
66     private lateinit var parent: ViewGroup
67     private lateinit var broadcastReceiver: BroadcastReceiver
68     private var mExitToDream: Boolean = false
69 
onCreatenull70     override fun onCreate(savedInstanceState: Bundle?) {
71         super.onCreate(savedInstanceState)
72         lastConfiguration.setTo(resources.configuration)
73         window.addPrivateFlags(WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY)
74 
75         setContentView(R.layout.controls_fullscreen)
76 
77         applyInsets(R.id.control_detail_root)
78 
79         lifecycle.addObserver(
80             ControlsAnimations.observerForAnimations(
81                 requireViewById(R.id.control_detail_root),
82                 window,
83                 intent,
84                 false,
85             )
86         )
87 
88         initBroadcastReceiver()
89     }
90 
onConfigurationChangednull91     override fun onConfigurationChanged(newConfig: Configuration) {
92         super.onConfigurationChanged(newConfig)
93         val interestingFlags =
94             ActivityInfo.CONFIG_ORIENTATION or
95                 ActivityInfo.CONFIG_SCREEN_SIZE or
96                 ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE
97         if (lastConfiguration.diff(newConfig) and interestingFlags != 0) {
98             uiController.onSizeChange()
99         }
100         lastConfiguration.setTo(newConfig)
101     }
102 
onStartnull103     override fun onStart() {
104         super.onStart()
105 
106         parent = requireViewById(R.id.control_detail_root)
107         parent.alpha = 0f
108         if (!keyguardStateController.isUnlocked) {
109             controlsSettingsDialogManager.maybeShowDialog(this) {
110                 uiController.show(parent, { finishOrReturnToDream() }, this)
111             }
112         } else {
113             uiController.show(parent, { finishOrReturnToDream() }, this)
114         }
115 
116         ControlsAnimations.enterAnimation(parent).start()
117     }
118 
onResumenull119     override fun onResume() {
120         super.onResume()
121         mExitToDream = intent.getBooleanExtra(ControlsUiController.EXIT_TO_DREAM, false)
122     }
123 
finishOrReturnToDreamnull124     fun finishOrReturnToDream() {
125         if (mExitToDream) {
126             try {
127                 mExitToDream = false
128                 dreamManager.dream()
129                 return
130             } catch (e: RemoteException) {
131                 // Fall through
132             }
133         }
134         finish()
135     }
136 
onBackPressednull137     override fun onBackPressed() {
138         finishOrReturnToDream()
139     }
140 
onStopnull141     override fun onStop() {
142         super.onStop()
143         mExitToDream = false
144 
145         // parent is set in onStart, so the field is initialized when we get here
146         uiController.hide(parent)
147         controlsSettingsDialogManager.closeDialog()
148     }
149 
onDestroynull150     override fun onDestroy() {
151         super.onDestroy()
152 
153         unregisterReceiver()
154     }
155 
unregisterReceivernull156     protected open fun unregisterReceiver() {
157         broadcastDispatcher.unregisterReceiver(broadcastReceiver)
158     }
159 
initBroadcastReceivernull160     private fun initBroadcastReceiver() {
161         broadcastReceiver =
162             object : BroadcastReceiver() {
163                 override fun onReceive(context: Context, intent: Intent) {
164                     val action = intent.getAction()
165                     if (
166                         action == Intent.ACTION_SCREEN_OFF ||
167                             action == Intent.ACTION_DREAMING_STARTED
168                     ) {
169                         finish()
170                     }
171                 }
172             }
173 
174         val filter = IntentFilter()
175         filter.addAction(Intent.ACTION_SCREEN_OFF)
176         filter.addAction(Intent.ACTION_DREAMING_STARTED)
177         broadcastDispatcher.registerReceiver(broadcastReceiver, filter)
178     }
179 }
180