1 /*
2  * Copyright (C) 2020 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.media.controls.domain.pipeline
18 
19 import com.android.systemui.media.controls.shared.model.MediaData
20 import com.android.systemui.media.controls.shared.model.MediaDeviceData
21 import com.android.systemui.media.controls.shared.model.SmartspaceMediaData
22 import javax.inject.Inject
23 
24 /** Combines [MediaDataManager.Listener] events with [MediaDeviceManager.Listener] events. */
25 class MediaDataCombineLatest @Inject constructor() :
26     MediaDataManager.Listener, MediaDeviceManager.Listener {
27 
28     private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
29     private val entries: MutableMap<String, Pair<MediaData?, MediaDeviceData?>> = mutableMapOf()
30 
onMediaDataLoadednull31     override fun onMediaDataLoaded(
32         key: String,
33         oldKey: String?,
34         data: MediaData,
35         immediately: Boolean,
36         receivedSmartspaceCardLatency: Int,
37         isSsReactivated: Boolean
38     ) {
39         if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
40             entries[key] = data to entries.remove(oldKey)?.second
41             update(key, oldKey)
42         } else {
43             entries[key] = data to entries[key]?.second
44             update(key, key)
45         }
46     }
47 
onSmartspaceMediaDataLoadednull48     override fun onSmartspaceMediaDataLoaded(
49         key: String,
50         data: SmartspaceMediaData,
51         shouldPrioritize: Boolean
52     ) {
53         listeners.toSet().forEach { it.onSmartspaceMediaDataLoaded(key, data) }
54     }
55 
onMediaDataRemovednull56     override fun onMediaDataRemoved(key: String, userInitiated: Boolean) {
57         remove(key, userInitiated)
58     }
59 
onSmartspaceMediaDataRemovednull60     override fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean) {
61         listeners.toSet().forEach { it.onSmartspaceMediaDataRemoved(key, immediately) }
62     }
63 
onMediaDeviceChangednull64     override fun onMediaDeviceChanged(key: String, oldKey: String?, data: MediaDeviceData?) {
65         if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
66             entries[key] = entries.remove(oldKey)?.first to data
67             update(key, oldKey)
68         } else {
69             entries[key] = entries[key]?.first to data
70             update(key, key)
71         }
72     }
73 
onKeyRemovednull74     override fun onKeyRemoved(key: String, userInitiated: Boolean) {
75         remove(key, userInitiated)
76     }
77 
78     /**
79      * Add a listener for [MediaData] changes that has been combined with latest [MediaDeviceData].
80      */
addListenernull81     fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener)
82 
83     /** Remove a listener registered with addListener. */
84     fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener)
85 
86     private fun update(key: String, oldKey: String?) {
87         val (entry, device) = entries[key] ?: null to null
88         if (entry != null && device != null) {
89             val data = entry.copy(device = device)
90             val listenersCopy = listeners.toSet()
91             listenersCopy.forEach { it.onMediaDataLoaded(key, oldKey, data) }
92         }
93     }
94 
removenull95     private fun remove(key: String, userInitiated: Boolean) {
96         entries.remove(key)?.let {
97             val listenersCopy = listeners.toSet()
98             listenersCopy.forEach { it.onMediaDataRemoved(key, userInitiated) }
99         }
100     }
101 }
102