1 /* 2 * Copyright (C) 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 com.android.systemui.statusbar.pipeline.mobile.data.model 18 19 import android.os.PersistableBundle 20 import android.telephony.CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL 21 import android.telephony.CarrierConfigManager.KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL 22 import androidx.annotation.VisibleForTesting 23 import kotlinx.coroutines.flow.MutableStateFlow 24 import kotlinx.coroutines.flow.StateFlow 25 import kotlinx.coroutines.flow.asStateFlow 26 27 /** 28 * Represents, for a given subscription ID, the set of keys about which SystemUI cares. 29 * 30 * Upon first creation, this config represents only the default configuration (see 31 * [android.telephony.CarrierConfigManager.getDefaultConfig]). 32 * 33 * Upon request (see 34 * [com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository]), an 35 * instance of this class may be created for a given subscription Id, and will default to 36 * representing the default carrier configuration. However, once a carrier config is received for 37 * this [subId], all fields will reflect those in the received config, using [PersistableBundle]'s 38 * default of false for any config that is not present in the override. 39 * 40 * To keep things relatively simple, this class defines a wrapper around each config key which 41 * exposes a StateFlow<Boolean> for each config we care about. It also tracks whether or not it is 42 * using the default config for logging purposes. 43 * 44 * NOTE to add new keys to be tracked: 45 * 1. Define a new `private val` wrapping the key using [BooleanCarrierConfig] 46 * 2. Define a public `val` exposing the wrapped flow using [BooleanCarrierConfig.config] 47 * 3. Add the new [BooleanCarrierConfig] to the list of tracked configs, so they are properly 48 * updated when a new carrier config comes down 49 */ 50 class SystemUiCarrierConfig 51 internal constructor( 52 val subId: Int, 53 defaultConfig: PersistableBundle, 54 ) { 55 @VisibleForTesting 56 var isUsingDefault = true 57 private set 58 59 private val inflateSignalStrength = 60 BooleanCarrierConfig(KEY_INFLATE_SIGNAL_STRENGTH_BOOL, defaultConfig) 61 /** Flow tracking the [KEY_INFLATE_SIGNAL_STRENGTH_BOOL] carrier config */ 62 val shouldInflateSignalStrength: StateFlow<Boolean> = inflateSignalStrength.config 63 64 private val showOperatorName = 65 BooleanCarrierConfig(KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL, defaultConfig) 66 /** Flow tracking the [KEY_SHOW_OPERATOR_NAME_IN_STATUSBAR_BOOL] config */ 67 val showOperatorNameInStatusBar: StateFlow<Boolean> = showOperatorName.config 68 69 private val trackedConfigs = 70 listOf( 71 inflateSignalStrength, 72 showOperatorName, 73 ) 74 75 /** Ingest a new carrier config, and switch all of the tracked keys over to the new values */ 76 fun processNewCarrierConfig(config: PersistableBundle) { 77 isUsingDefault = false 78 trackedConfigs.forEach { it.update(config) } 79 } 80 81 /** For dumpsys, shortcut if we haven't overridden any keys */ 82 fun toStringConsideringDefaults(): String { 83 return if (isUsingDefault) { 84 "using defaults" 85 } else { 86 trackedConfigs.joinToString { it.toString() } 87 } 88 } 89 90 override fun toString(): String = trackedConfigs.joinToString { it.toString() } 91 } 92 93 /** Extracts [key] from the carrier config, and stores it in a flow */ 94 private class BooleanCarrierConfig( 95 val key: String, 96 defaultConfig: PersistableBundle, 97 ) { 98 private val _configValue = MutableStateFlow(defaultConfig.getBoolean(key)) 99 val config = _configValue.asStateFlow() 100 101 fun update(config: PersistableBundle) { 102 _configValue.value = config.getBoolean(key) 103 } 104 105 override fun toString(): String { 106 return "$key=${config.value}" 107 } 108 } 109