1 /* <lambda>null2 * 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.repository 18 19 import android.content.Intent 20 import android.os.PersistableBundle 21 import android.telephony.CarrierConfigManager 22 import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID 23 import androidx.test.ext.junit.runners.AndroidJUnit4 24 import androidx.test.filters.SmallTest 25 import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.dump.DumpManager 28 import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger 29 import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig 30 import com.android.systemui.util.mockito.whenever 31 import com.google.common.truth.Truth.assertThat 32 import kotlinx.coroutines.ExperimentalCoroutinesApi 33 import kotlinx.coroutines.flow.launchIn 34 import kotlinx.coroutines.flow.onEach 35 import kotlinx.coroutines.test.TestScope 36 import kotlinx.coroutines.test.UnconfinedTestDispatcher 37 import kotlinx.coroutines.test.runTest 38 import org.junit.After 39 import org.junit.Before 40 import org.junit.Test 41 import org.junit.runner.RunWith 42 import org.mockito.ArgumentMatchers.anyInt 43 import org.mockito.Mock 44 import org.mockito.MockitoAnnotations 45 import org.mockito.MockitoSession 46 import org.mockito.quality.Strictness 47 48 @OptIn(ExperimentalCoroutinesApi::class) 49 @SmallTest 50 @RunWith(AndroidJUnit4::class) 51 class CarrierConfigRepositoryTest : SysuiTestCase() { 52 private val testDispatcher = UnconfinedTestDispatcher() 53 private val testScope = TestScope(testDispatcher) 54 55 private lateinit var underTest: CarrierConfigRepository 56 private lateinit var mockitoSession: MockitoSession 57 private lateinit var carrierConfigCoreStartable: CarrierConfigCoreStartable 58 59 @Mock private lateinit var logger: MobileInputLogger 60 @Mock private lateinit var carrierConfigManager: CarrierConfigManager 61 @Mock private lateinit var dumpManager: DumpManager 62 63 @Before 64 fun setUp() { 65 MockitoAnnotations.initMocks(this) 66 mockitoSession = 67 mockitoSession() 68 .initMocks(this) 69 .mockStatic(CarrierConfigManager::class.java) 70 .strictness(Strictness.LENIENT) 71 .startMocking() 72 73 whenever(CarrierConfigManager.getDefaultConfig()).thenReturn(DEFAULT_CONFIG) 74 75 whenever(carrierConfigManager.getConfigForSubId(anyInt())).thenAnswer { invocation -> 76 when (invocation.getArgument(0) as Int) { 77 1 -> CONFIG_1 78 2 -> CONFIG_2 79 else -> null 80 } 81 } 82 83 underTest = 84 CarrierConfigRepository( 85 fakeBroadcastDispatcher, 86 carrierConfigManager, 87 dumpManager, 88 logger, 89 testScope.backgroundScope, 90 ) 91 92 carrierConfigCoreStartable = 93 CarrierConfigCoreStartable(underTest, testScope.backgroundScope) 94 } 95 96 @After 97 fun tearDown() { 98 mockitoSession.finishMocking() 99 } 100 101 @Test 102 fun carrierConfigStreamProducesIntBundlePairs() = 103 testScope.runTest { 104 var latest: Pair<Int, PersistableBundle>? = null 105 val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this) 106 107 sendConfig(SUB_ID_1) 108 assertThat(latest).isEqualTo(Pair(SUB_ID_1, CONFIG_1)) 109 110 sendConfig(SUB_ID_2) 111 assertThat(latest).isEqualTo(Pair(SUB_ID_2, CONFIG_2)) 112 113 job.cancel() 114 } 115 116 @Test 117 fun carrierConfigStreamIgnoresInvalidSubscriptions() = 118 testScope.runTest { 119 var latest: Pair<Int, PersistableBundle>? = null 120 val job = underTest.carrierConfigStream.onEach { latest = it }.launchIn(this) 121 122 sendConfig(INVALID_SUBSCRIPTION_ID) 123 124 assertThat(latest).isNull() 125 126 job.cancel() 127 } 128 129 @Test 130 fun getOrCreateConfig_usesDefaultConfigIfNoOverride() { 131 val config = underTest.getOrCreateConfigForSubId(123) 132 assertThat(config.isUsingDefault).isTrue() 133 } 134 135 @Test 136 fun getOrCreateConfig_usesOverrideIfExists() { 137 val config = underTest.getOrCreateConfigForSubId(SUB_ID_1) 138 assertThat(config.isUsingDefault).isFalse() 139 } 140 141 @Test 142 fun config_updatesWhileConfigStreamIsCollected() = 143 testScope.runTest { 144 CONFIG_1.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, false) 145 146 carrierConfigCoreStartable.start() 147 148 val config = underTest.getOrCreateConfigForSubId(SUB_ID_1) 149 assertThat(config.shouldInflateSignalStrength.value).isFalse() 150 151 CONFIG_1.putBoolean(CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL, true) 152 sendConfig(SUB_ID_1) 153 154 assertThat(config.shouldInflateSignalStrength.value).isTrue() 155 } 156 157 private fun sendConfig(subId: Int) { 158 fakeBroadcastDispatcher.sendIntentToMatchingReceiversOnly( 159 context, 160 Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED) 161 .putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, subId), 162 ) 163 } 164 165 companion object { 166 private const val SUB_ID_1 = 1 167 private const val SUB_ID_2 = 2 168 169 private val DEFAULT_CONFIG = createTestConfig() 170 private val CONFIG_1 = createTestConfig() 171 private val CONFIG_2 = createTestConfig() 172 } 173 } 174