• 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.annotation.SuppressLint
20 import android.content.Context
21 import android.os.Bundle
22 import android.util.Log
23 import android.view.Display
24 import android.view.LayoutInflater
25 import android.view.WindowManager
26 import com.android.app.tracing.coroutines.launchTraced as launch
27 import com.android.systemui.CoreStartable
28 import com.android.systemui.dagger.SysUISingleton
29 import com.android.systemui.dagger.qualifiers.Background
30 import com.android.systemui.display.shared.model.DisplayWindowProperties
31 import com.android.systemui.res.R
32 import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
33 import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
34 import com.android.systemui.utils.windowmanager.WindowManagerUtils
35 import com.google.common.collect.HashBasedTable
36 import com.google.common.collect.Table
37 import java.io.PrintWriter
38 import javax.inject.Inject
39 import kotlinx.coroutines.CoroutineScope
40 
41 /** Provides per display instances of [DisplayWindowProperties]. */
42 interface DisplayWindowPropertiesRepository {
43 
44     /**
45      * Returns a [DisplayWindowProperties] instance for a given display id and window type, or null
46      * if no display with the given display id exists.
47      */
48     fun get(
49         displayId: Int,
50         @WindowManager.LayoutParams.WindowType windowType: Int,
51     ): DisplayWindowProperties?
52 }
53 
54 @SysUISingleton
55 class DisplayWindowPropertiesRepositoryImpl
56 @Inject
57 constructor(
58     @Background private val backgroundApplicationScope: CoroutineScope,
59     private val globalContext: Context,
60     private val globalWindowManager: WindowManager,
61     private val globalLayoutInflater: LayoutInflater,
62     private val displayRepository: DisplayRepository,
63 ) : DisplayWindowPropertiesRepository, CoreStartable {
64 
65     init {
<lambda>null66         check(StatusBarConnectedDisplays.isEnabled || ShadeWindowGoesAround.isEnabled) {
67             "This should be instantiated only when wither StatusBarConnectedDisplays or " +
68                 "ShadeWindowGoesAround are enabled."
69         }
70     }
71 
72     private val properties: Table<Int, Int, DisplayWindowProperties> = HashBasedTable.create()
73 
getnull74     override fun get(
75         displayId: Int,
76         @WindowManager.LayoutParams.WindowType windowType: Int,
77     ): DisplayWindowProperties? {
78         val display = displayRepository.getDisplay(displayId) ?: return null
79         return properties.get(displayId, windowType)
80             ?: create(display, windowType)?.also { properties.put(displayId, windowType, it) }
81     }
82 
startnull83     override fun start() {
84         backgroundApplicationScope.launch("DisplayWindowPropertiesRepositoryImpl#start") {
85             displayRepository.displayRemovalEvent.collect { removedDisplayId ->
86                 properties.row(removedDisplayId).clear()
87             }
88         }
89     }
90 
createnull91     private fun create(display: Display, windowType: Int): DisplayWindowProperties? {
92         val displayId = display.displayId
93         return if (displayId == Display.DEFAULT_DISPLAY) {
94             // For the default display, we can just reuse the global/application properties.
95             // Creating a window context is expensive, therefore we avoid it.
96             DisplayWindowProperties(
97                 displayId = displayId,
98                 windowType = windowType,
99                 context = globalContext,
100                 windowManager = globalWindowManager,
101                 layoutInflater = globalLayoutInflater,
102             )
103         } else {
104             val context = createWindowContext(display, windowType)
105             if (context.displayId != display.displayId) {
106                 Log.e(
107                     TAG,
108                     "Returning null because the new context doesn't have the desired display id " +
109                         "${display.displayId}. Display was already removed.",
110                 )
111                 return null
112             }
113             @SuppressLint("NonInjectedService") // Need to manually get the service
114             val windowManager = WindowManagerUtils.getWindowManager(context)
115             val layoutInflater = LayoutInflater.from(context)
116             DisplayWindowProperties(displayId, windowType, context, windowManager, layoutInflater)
117         }
118     }
119 
createWindowContextnull120     private fun createWindowContext(display: Display, windowType: Int): Context =
121         globalContext.createWindowContext(display, windowType, /* options= */ Bundle.EMPTY).also {
122             it.setTheme(R.style.Theme_SystemUI)
123         }
124 
dumpnull125     override fun dump(pw: PrintWriter, args: Array<out String>) {
126         pw.write("perDisplayContexts: $properties")
127     }
128 
129     private companion object {
130         const val TAG = "DisplayWindowPropsRepo"
131     }
132 }
133