• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2022 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.flags
18 
19 import java.io.PrintWriter
20 
21 class FakeFeatureFlags : FeatureFlags {
22     private val booleanFlags = mutableMapOf<Int, Boolean>()
23     private val stringFlags = mutableMapOf<Int, String>()
24     private val intFlags = mutableMapOf<Int, Int>()
25     private val knownFlagNames = mutableMapOf<Int, String>()
26     private val flagListeners = mutableMapOf<Int, MutableSet<FlagListenable.Listener>>()
27     private val listenerFlagIds = mutableMapOf<FlagListenable.Listener, MutableSet<Int>>()
28 
29     init {
30         FlagsFactory.knownFlags.forEach { entry: Map.Entry<String, Flag<*>> ->
31             knownFlagNames[entry.value.id] = entry.key
32         }
33     }
34 
35     fun set(flag: BooleanFlag, value: Boolean) {
36         if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
37             notifyFlagChanged(flag)
38         }
39     }
40 
41     fun set(flag: ResourceBooleanFlag, value: Boolean) {
42         if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
43             notifyFlagChanged(flag)
44         }
45     }
46 
47     fun set(flag: SysPropBooleanFlag, value: Boolean) {
48         if (booleanFlags.put(flag.id, value)?.let { value != it } != false) {
49             notifyFlagChanged(flag)
50         }
51     }
52 
53     fun set(flag: StringFlag, value: String) {
54         if (stringFlags.put(flag.id, value)?.let { value != it } == null) {
55             notifyFlagChanged(flag)
56         }
57     }
58 
59     fun set(flag: ResourceStringFlag, value: String) {
60         if (stringFlags.put(flag.id, value)?.let { value != it } == null) {
61             notifyFlagChanged(flag)
62         }
63     }
64 
65     private fun notifyFlagChanged(flag: Flag<*>) {
66         flagListeners[flag.id]?.let { listeners ->
67             listeners.forEach { listener ->
68                 listener.onFlagChanged(
69                     object : FlagListenable.FlagEvent {
70                         override val flagName = flag.name
71                         override fun requestNoRestart() {}
72                     }
73                 )
74             }
75         }
76     }
77 
78     override fun isEnabled(flag: UnreleasedFlag): Boolean = requireBooleanValue(flag.id)
79 
80     override fun isEnabled(flag: ReleasedFlag): Boolean = requireBooleanValue(flag.id)
81 
82     override fun isEnabled(flag: ResourceBooleanFlag): Boolean = requireBooleanValue(flag.id)
83 
84     override fun isEnabled(flag: SysPropBooleanFlag): Boolean = requireBooleanValue(flag.id)
85 
86     override fun getString(flag: StringFlag): String = requireStringValue(flag.id)
87 
88     override fun getString(flag: ResourceStringFlag): String = requireStringValue(flag.id)
89 
90     override fun getInt(flag: IntFlag): Int = requireIntValue(flag.id)
91 
92     override fun getInt(flag: ResourceIntFlag): Int = requireIntValue(flag.id)
93 
94     override fun addListener(flag: Flag<*>, listener: FlagListenable.Listener) {
95         flagListeners.getOrPut(flag.id) { mutableSetOf() }.add(listener)
96         listenerFlagIds.getOrPut(listener) { mutableSetOf() }.add(flag.id)
97     }
98 
99     override fun removeListener(listener: FlagListenable.Listener) {
100         listenerFlagIds.remove(listener)?.let {
101                 flagIds -> flagIds.forEach {
102                         id -> flagListeners[id]?.remove(listener)
103                 }
104         }
105     }
106 
107     override fun dump(writer: PrintWriter, args: Array<out String>?) {
108         // no-op
109     }
110 
111     private fun flagName(flagId: Int): String {
112         return knownFlagNames[flagId] ?: "UNKNOWN(id=$flagId)"
113     }
114 
115     private fun requireBooleanValue(flagId: Int): Boolean {
116         return booleanFlags[flagId]
117             ?: error("Flag ${flagName(flagId)} was accessed as boolean but not specified.")
118     }
119 
120     private fun requireStringValue(flagId: Int): String {
121         return stringFlags[flagId]
122             ?: error("Flag ${flagName(flagId)} was accessed as string but not specified.")
123     }
124 
125     private fun requireIntValue(flagId: Int): Int {
126         return intFlags[flagId]
127             ?: error("Flag ${flagName(flagId)} was accessed as int but not specified.")
128     }
129 }
130