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.qs 18 19 import android.content.ComponentName 20 import android.content.Context 21 import androidx.annotation.GuardedBy 22 import com.android.systemui.dagger.SysUISingleton 23 import com.android.systemui.dagger.qualifiers.Application 24 import com.android.systemui.dump.DumpManager 25 import com.android.systemui.plugins.qs.QSTile 26 import com.android.systemui.qs.external.TileServiceRequestController 27 import com.android.systemui.qs.pipeline.data.repository.TileSpecRepository.Companion.POSITION_AT_END 28 import com.android.systemui.qs.pipeline.domain.interactor.CurrentTilesInteractor 29 import com.android.systemui.qs.pipeline.shared.QSPipelineFlagsRepository 30 import com.android.systemui.qs.pipeline.shared.TileSpec 31 import javax.inject.Inject 32 import kotlinx.coroutines.CoroutineScope 33 import kotlinx.coroutines.Job 34 import kotlinx.coroutines.launch 35 36 /** 37 * Adapter to determine what real class to use for classes that depend on [QSHost]. 38 * * When [QSPipelineFlagsRepository.pipelineEnabled] is false, all calls will be routed to 39 * [QSTileHost]. 40 * * When [QSPipelineFlagsRepository.pipelineEnabled] is true, calls regarding the current set of 41 * tiles will be routed to [CurrentTilesInteractor]. Other calls (like [createTileView]) will 42 * still be routed to [QSTileHost]. 43 * 44 * This routing also includes dumps. 45 */ 46 @SysUISingleton 47 class QSHostAdapter 48 @Inject 49 constructor( 50 private val qsTileHost: QSTileHost, 51 private val interactor: CurrentTilesInteractor, 52 private val context: Context, 53 private val tileServiceRequestControllerBuilder: TileServiceRequestController.Builder, 54 @Application private val scope: CoroutineScope, 55 flags: QSPipelineFlagsRepository, 56 dumpManager: DumpManager, 57 ) : QSHost { 58 59 companion object { 60 private const val TAG = "QSTileHost" 61 } 62 63 private val useNewHost = flags.pipelineEnabled 64 65 @GuardedBy("callbacksMap") private val callbacksMap = mutableMapOf<QSHost.Callback, Job>() 66 67 init { <lambda>null68 scope.launch { tileServiceRequestControllerBuilder.create(this@QSHostAdapter).init() } 69 // Redirect dump to the correct host (needed for CTS tests) 70 dumpManager.registerCriticalDumpable(TAG, if (useNewHost) interactor else qsTileHost) 71 } 72 getTilesnull73 override fun getTiles(): Collection<QSTile> { 74 return if (useNewHost) { 75 interactor.currentQSTiles 76 } else { 77 qsTileHost.getTiles() 78 } 79 } 80 getSpecsnull81 override fun getSpecs(): List<String> { 82 return if (useNewHost) { 83 interactor.currentTilesSpecs.map { it.spec } 84 } else { 85 qsTileHost.getSpecs() 86 } 87 } 88 removeTilenull89 override fun removeTile(spec: String) { 90 if (useNewHost) { 91 interactor.removeTiles(listOf(TileSpec.create(spec))) 92 } else { 93 qsTileHost.removeTile(spec) 94 } 95 } 96 addCallbacknull97 override fun addCallback(callback: QSHost.Callback) { 98 if (useNewHost) { 99 val job = scope.launch { interactor.currentTiles.collect { callback.onTilesChanged() } } 100 synchronized(callbacksMap) { callbacksMap.put(callback, job) } 101 } else { 102 qsTileHost.addCallback(callback) 103 } 104 } 105 removeCallbacknull106 override fun removeCallback(callback: QSHost.Callback) { 107 if (useNewHost) { 108 synchronized(callbacksMap) { callbacksMap.remove(callback)?.cancel() } 109 } else { 110 qsTileHost.removeCallback(callback) 111 } 112 } 113 removeTilesnull114 override fun removeTiles(specs: Collection<String>) { 115 if (useNewHost) { 116 interactor.removeTiles(specs.map(TileSpec::create)) 117 } else { 118 qsTileHost.removeTiles(specs) 119 } 120 } 121 removeTileByUsernull122 override fun removeTileByUser(component: ComponentName) { 123 if (useNewHost) { 124 interactor.removeTiles(listOf(TileSpec.create(component))) 125 } else { 126 qsTileHost.removeTileByUser(component) 127 } 128 } 129 addTilenull130 override fun addTile(spec: String, position: Int) { 131 if (useNewHost) { 132 interactor.addTile(TileSpec.create(spec), position) 133 } else { 134 qsTileHost.addTile(spec, position) 135 } 136 } 137 addTilenull138 override fun addTile(component: ComponentName, end: Boolean) { 139 if (useNewHost) { 140 interactor.addTile(TileSpec.create(component), if (end) POSITION_AT_END else 0) 141 } else { 142 qsTileHost.addTile(component, end) 143 } 144 } 145 changeTilesByUsernull146 override fun changeTilesByUser(previousTiles: List<String>, newTiles: List<String>) { 147 if (useNewHost) { 148 interactor.setTiles(newTiles.map(TileSpec::create)) 149 } else { 150 qsTileHost.changeTilesByUser(previousTiles, newTiles) 151 } 152 } 153 getContextnull154 override fun getContext(): Context { 155 return if (useNewHost) { 156 context 157 } else { 158 qsTileHost.context 159 } 160 } 161 getUserContextnull162 override fun getUserContext(): Context { 163 return if (useNewHost) { 164 interactor.userContext.value 165 } else { 166 qsTileHost.userContext 167 } 168 } 169 getUserIdnull170 override fun getUserId(): Int { 171 return if (useNewHost) { 172 interactor.userId.value 173 } else { 174 qsTileHost.userId 175 } 176 } 177 createTilenull178 override fun createTile(tileSpec: String): QSTile? { 179 return qsTileHost.createTile(tileSpec) 180 } 181 addTilenull182 override fun addTile(spec: String) { 183 return addTile(spec, QSHost.POSITION_AT_END) 184 } 185 addTilenull186 override fun addTile(tile: ComponentName) { 187 return addTile(tile, false) 188 } 189 indexOfnull190 override fun indexOf(tileSpec: String): Int { 191 return specs.indexOf(tileSpec) 192 } 193 } 194