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