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