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