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 onMediaDataLoadednull30 override fun onMediaDataLoaded( 31 key: String, 32 oldKey: String?, 33 data: MediaData, 34 immediately: Boolean, 35 isSsReactivated: Boolean 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 onSmartspaceMediaDataLoadednull46 override fun onSmartspaceMediaDataLoaded( 47 key: String, 48 data: SmartspaceMediaData, 49 shouldPrioritize: Boolean 50 ) { 51 listeners.toSet().forEach { it.onSmartspaceMediaDataLoaded(key, data) } 52 } 53 onMediaDataRemovednull54 override fun onMediaDataRemoved(key: String) { 55 remove(key) 56 } 57 onSmartspaceMediaDataRemovednull58 override fun onSmartspaceMediaDataRemoved(key: String, immediately: Boolean) { 59 listeners.toSet().forEach { it.onSmartspaceMediaDataRemoved(key, immediately) } 60 } 61 onMediaDeviceChangednull62 override fun onMediaDeviceChanged( 63 key: String, 64 oldKey: String?, 65 data: MediaDeviceData? 66 ) { 67 if (oldKey != null && oldKey != key && entries.contains(oldKey)) { 68 entries[key] = entries.remove(oldKey)?.first to data 69 update(key, oldKey) 70 } else { 71 entries[key] = entries[key]?.first to data 72 update(key, key) 73 } 74 } 75 onKeyRemovednull76 override fun onKeyRemoved(key: String) { 77 remove(key) 78 } 79 80 /** 81 * Add a listener for [MediaData] changes that has been combined with latest [MediaDeviceData]. 82 */ addListenernull83 fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener) 84 85 /** 86 * Remove a listener registered with addListener. 87 */ 88 fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener) 89 90 private fun update(key: String, oldKey: String?) { 91 val (entry, device) = entries[key] ?: null to null 92 if (entry != null && device != null) { 93 val data = entry.copy(device = device) 94 val listenersCopy = listeners.toSet() 95 listenersCopy.forEach { 96 it.onMediaDataLoaded(key, oldKey, data) 97 } 98 } 99 } 100 removenull101 private fun remove(key: String) { 102 entries.remove(key)?.let { 103 val listenersCopy = listeners.toSet() 104 listenersCopy.forEach { 105 it.onMediaDataRemoved(key) 106 } 107 } 108 } 109 } 110