1 /*
<lambda>null2  * Copyright 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 androidx.window.layout.adapter.extensions
18 
19 import android.content.Context
20 import androidx.annotation.GuardedBy
21 import androidx.core.util.Consumer
22 import androidx.window.extensions.layout.WindowLayoutInfo as OEMWindowLayoutInfo
23 import androidx.window.layout.WindowLayoutInfo
24 import java.util.concurrent.locks.ReentrantLock
25 import kotlin.concurrent.withLock
26 
27 /** A [Consumer] that handles multicasting to multiple [Consumer]s downstream. */
28 internal class MulticastConsumer(private val context: Context) : Consumer<OEMWindowLayoutInfo> {
29     private val globalLock = ReentrantLock()
30 
31     @GuardedBy("globalLock") private var lastKnownValue: WindowLayoutInfo? = null
32     @GuardedBy("globalLock")
33     private val registeredListeners = mutableSetOf<Consumer<WindowLayoutInfo>>()
34 
35     override fun accept(value: OEMWindowLayoutInfo) {
36         globalLock.withLock {
37             val newValue = ExtensionsWindowLayoutInfoAdapter.translate(context, value)
38             lastKnownValue = newValue
39             registeredListeners.forEach { consumer -> consumer.accept(newValue) }
40         }
41     }
42 
43     fun addListener(listener: Consumer<WindowLayoutInfo>) {
44         globalLock.withLock {
45             lastKnownValue?.let { value -> listener.accept(value) }
46             registeredListeners.add(listener)
47         }
48     }
49 
50     fun removeListener(listener: Consumer<WindowLayoutInfo>) {
51         globalLock.withLock { registeredListeners.remove(listener) }
52     }
53 
54     fun isEmpty(): Boolean {
55         return registeredListeners.isEmpty()
56     }
57 }
58