1 /*
2  * Copyright (C) 2023 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.statusbar.phone
18 
19 import android.annotation.CallSuper
20 import android.content.Context
21 import android.os.Bundle
22 import android.view.View
23 import android.view.ViewGroup
24 import androidx.activity.OnBackPressedDispatcher
25 import androidx.activity.OnBackPressedDispatcherOwner
26 import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
27 import androidx.lifecycle.Lifecycle
28 import androidx.lifecycle.LifecycleOwner
29 import androidx.lifecycle.LifecycleRegistry
30 import androidx.lifecycle.setViewTreeLifecycleOwner
31 import androidx.savedstate.SavedStateRegistry
32 import androidx.savedstate.SavedStateRegistryController
33 import androidx.savedstate.SavedStateRegistryOwner
34 import androidx.savedstate.setViewTreeSavedStateRegistryOwner
35 import com.android.systemui.animation.DialogTransitionAnimator
36 import com.android.systemui.broadcast.BroadcastDispatcher
37 import com.android.systemui.model.SysUiState
38 
39 /**
40  * A [SystemUIDialog] that implements [LifecycleOwner], [SavedStateRegistryOwner] and
41  * [OnBackPressedDispatcherOwner].
42  *
43  * This class was forked from [androidx.activity.ComponentDialog] and can be used to easily create
44  * SystemUI dialogs without the need to subclass [SystemUIDialog]. You should call
45  * [SystemUIDialogFactory.create] to easily instantiate this class.
46  *
47  * Important: [ComponentSystemUIDialog] should be created and shown on the main thread.
48  *
49  * @see SystemUIDialogFactory.create
50  */
51 class ComponentSystemUIDialog(
52     context: Context,
53     theme: Int,
54     dismissOnDeviceLock: Boolean,
55     dialogManager: SystemUIDialogManager,
56     sysUiState: SysUiState,
57     broadcastDispatcher: BroadcastDispatcher,
58     dialogTransitionAnimator: DialogTransitionAnimator,
59     delegate: DialogDelegate<SystemUIDialog>,
60 ) :
61     SystemUIDialog(
62         context,
63         theme,
64         dismissOnDeviceLock,
65         dialogManager,
66         sysUiState,
67         broadcastDispatcher,
68         dialogTransitionAnimator,
69         delegate,
70     ),
71     LifecycleOwner,
72     SavedStateRegistryOwner,
73     OnBackPressedDispatcherOwner {
74     private var _lifecycleRegistry: LifecycleRegistry? = null
75     private val lifecycleRegistry: LifecycleRegistry
<lambda>null76         get() = _lifecycleRegistry ?: LifecycleRegistry(this).also { _lifecycleRegistry = it }
77 
78     private val savedStateRegistryController: SavedStateRegistryController =
79         SavedStateRegistryController.create(this)
80     override val savedStateRegistry: SavedStateRegistry
81         get() = savedStateRegistryController.savedStateRegistry
82 
83     override val lifecycle: Lifecycle
84         get() = lifecycleRegistry
85 
onSaveInstanceStatenull86     override fun onSaveInstanceState(): Bundle {
87         val bundle = super.onSaveInstanceState()
88         savedStateRegistryController.performSave(bundle)
89         return bundle
90     }
91 
92     @CallSuper
onCreatenull93     override fun onCreate(savedInstanceState: Bundle?) {
94         super.onCreate(savedInstanceState)
95         onBackPressedDispatcher.setOnBackInvokedDispatcher(onBackInvokedDispatcher)
96         savedStateRegistryController.performRestore(savedInstanceState)
97         lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
98     }
99 
100     @CallSuper
startnull101     override fun start() {
102         lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
103     }
104 
105     @CallSuper
stopnull106     override fun stop() {
107         // This is the closest thing to onDestroy that a Dialog has
108         // TODO(b/296180426): Make SystemUIDialog.onStop() and onStart() open again (annotated with
109         // @CallSuper) and do this *before* calling super.onStop(), like AndroidX ComponentDialog
110         // does.
111         lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY)
112         _lifecycleRegistry = null
113     }
114 
115     @Suppress("DEPRECATION")
<lambda>null116     override val onBackPressedDispatcher = OnBackPressedDispatcher { super.onBackPressed() }
117 
118     @CallSuper
onBackPressednull119     override fun onBackPressed() {
120         onBackPressedDispatcher.onBackPressed()
121     }
122 
setContentViewnull123     override fun setContentView(layoutResID: Int) {
124         initializeViewTreeOwners()
125         super.setContentView(layoutResID)
126     }
127 
setContentViewnull128     override fun setContentView(view: View) {
129         initializeViewTreeOwners()
130         super.setContentView(view)
131     }
132 
setContentViewnull133     override fun setContentView(view: View, params: ViewGroup.LayoutParams?) {
134         initializeViewTreeOwners()
135         super.setContentView(view, params)
136     }
137 
addContentViewnull138     override fun addContentView(view: View, params: ViewGroup.LayoutParams?) {
139         initializeViewTreeOwners()
140         super.addContentView(view, params)
141     }
142 
143     /**
144      * Sets the view tree owners before setting the content view so that the inflation process and
145      * attach listeners will see them already present.
146      */
147     @CallSuper
initializeViewTreeOwnersnull148     open fun initializeViewTreeOwners() {
149         window!!.decorView.setViewTreeLifecycleOwner(this)
150         window!!.decorView.setViewTreeOnBackPressedDispatcherOwner(this)
151         window!!.decorView.setViewTreeSavedStateRegistryOwner(this)
152     }
153 }
154