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