• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.display.data.repository
18 
19 import android.util.Log
20 import android.view.Display
21 import com.android.app.tracing.coroutines.launchTraced as launch
22 import com.android.systemui.CoreStartable
23 import com.android.systemui.dagger.qualifiers.Background
24 import java.io.PrintWriter
25 import java.util.concurrent.ConcurrentHashMap
26 import kotlinx.coroutines.CoroutineScope
27 
28 /** Provides per display instances of [T]. */
29 @Deprecated("Use PerDisplayInstanceProvider<T> instead")
30 interface PerDisplayStore<T> {
31 
32     /**
33      * The instance for the default/main display of the device. For example, on a phone or a tablet,
34      * the default display is the internal/built-in display of the device.
35      *
36      * Note that the id of the default display is [Display.DEFAULT_DISPLAY].
37      */
38     val defaultDisplay: T
39 
40     /**
41      * Returns an instance for a specific display id, or null if [displayId] doesn't match the id of
42      * any existing displays.
43      */
44     fun forDisplay(displayId: Int): T?
45 }
46 
47 @Deprecated("Use PerDisplayRepository<T> instead")
48 abstract class PerDisplayStoreImpl<T>(
49     @Background private val backgroundApplicationScope: CoroutineScope,
50     private val displayRepository: DisplayRepository,
51 ) : PerDisplayStore<T>, CoreStartable {
52 
53     protected val perDisplayInstances = ConcurrentHashMap<Int, T>()
54 
55     /**
56      * The instance for the default/main display of the device. For example, on a phone or a tablet,
57      * the default display is the internal/built-in display of the device.
58      *
59      * Note that the id of the default display is [Display.DEFAULT_DISPLAY].
60      */
61     override val defaultDisplay: T
62         get() = forDisplay(Display.DEFAULT_DISPLAY)!!
63 
64     /**
65      * Returns an instance for a specific display id.
66      *
67      * @throws IllegalArgumentException if [displayId] doesn't match the id of any existing
68      *   displays.
69      */
forDisplaynull70     override fun forDisplay(displayId: Int): T? {
71         if (displayRepository.getDisplay(displayId)  == null) {
72             Log.e(TAG, "<${instanceClass.simpleName}>: Display with id $displayId doesn't exist.")
73             return null
74         }
75         synchronized(perDisplayInstances) {
76             val existingInstance = perDisplayInstances[displayId]
77             if (existingInstance != null) {
78                 return existingInstance
79             }
80             val newInstance = createInstanceForDisplay(displayId)
81             if (newInstance == null) {
82                 Log.e(
83                     TAG,
84                     "<${instanceClass.simpleName}> returning null because createInstanceForDisplay($displayId) returned null.",
85                 )
86             } else {
87                 perDisplayInstances[displayId] = newInstance
88             }
89             return newInstance
90         }
91     }
92 
createInstanceForDisplaynull93     protected abstract fun createInstanceForDisplay(displayId: Int): T?
94 
95     override fun start() {
96         val instanceType = instanceClass.simpleName
97         backgroundApplicationScope.launch("PerDisplayStore#<$instanceType>start") {
98             displayRepository.displayRemovalEvent.collect { removedDisplayId ->
99                 val removedInstance = perDisplayInstances.remove(removedDisplayId)
100                 removedInstance?.let { onDisplayRemovalAction(it) }
101             }
102         }
103     }
104 
105     abstract val instanceClass: Class<T>
106 
107     /**
108      * Will be called when the display associated with [instance] was removed. It allows to perform
109      * any clean up if needed.
110      */
111     @Deprecated(
112         "Use PerDisplayInstanceProviderWithTeardown instead, and let " +
113             "PerDisplayInstanceRepositoryImpl decide when to destroy the instance (e.g. on " +
114             "display removal or other conditions."
115     )
onDisplayRemovalActionnull116     open suspend fun onDisplayRemovalAction(instance: T) {}
117 
dumpnull118     override fun dump(pw: PrintWriter, args: Array<out String>) {
119         pw.println(perDisplayInstances)
120     }
121 
122     private companion object {
123         const val TAG = "PerDisplayStore"
124     }
125 }
126 
127 class SingleDisplayStore<T>(defaultInstance: T) : PerDisplayStore<T> {
128     override val defaultDisplay: T = defaultInstance
129 
forDisplaynull130     override fun forDisplay(displayId: Int): T = defaultDisplay
131 }
132