Merge changes from topic "wifi-constants" into tm-qpr-dev
* changes: [Sb refactor] Mobile icon view model logging [Sb refactor] Add logging to mobile connections pipeline [Sb refactor] Move shouldShowActivityConfig to ConnectivityConstants [Sb refactor] Add location to mobile view models
This commit is contained in:
committed by
Android (Google) Code Review
commit
5bba501a33
@@ -60,10 +60,12 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
|||||||
private int mColor;
|
private int mColor;
|
||||||
|
|
||||||
private final MobileIconsViewModel mMobileIconsViewModel;
|
private final MobileIconsViewModel mMobileIconsViewModel;
|
||||||
|
private final StatusBarLocation mLocation;
|
||||||
|
|
||||||
public DemoStatusIcons(
|
public DemoStatusIcons(
|
||||||
LinearLayout statusIcons,
|
LinearLayout statusIcons,
|
||||||
MobileIconsViewModel mobileIconsViewModel,
|
MobileIconsViewModel mobileIconsViewModel,
|
||||||
|
StatusBarLocation location,
|
||||||
int iconSize
|
int iconSize
|
||||||
) {
|
) {
|
||||||
super(statusIcons.getContext());
|
super(statusIcons.getContext());
|
||||||
@@ -71,6 +73,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
|||||||
mIconSize = iconSize;
|
mIconSize = iconSize;
|
||||||
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
||||||
mMobileIconsViewModel = mobileIconsViewModel;
|
mMobileIconsViewModel = mobileIconsViewModel;
|
||||||
|
mLocation = location;
|
||||||
|
|
||||||
if (statusIcons instanceof StatusIconContainer) {
|
if (statusIcons instanceof StatusIconContainer) {
|
||||||
setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
|
setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
|
||||||
@@ -287,7 +290,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
|||||||
ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
|
ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
|
||||||
mobileContext,
|
mobileContext,
|
||||||
"mobile",
|
"mobile",
|
||||||
mMobileIconsViewModel.viewModelForSub(subId)
|
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
|
||||||
);
|
);
|
||||||
|
|
||||||
// mobile always goes at the end
|
// mobile always goes at the end
|
||||||
|
|||||||
@@ -359,6 +359,7 @@ public interface StatusBarIconController {
|
|||||||
// Whether or not these icons show up in dumpsys
|
// Whether or not these icons show up in dumpsys
|
||||||
protected boolean mShouldLog = false;
|
protected boolean mShouldLog = false;
|
||||||
private StatusBarIconController mController;
|
private StatusBarIconController mController;
|
||||||
|
private final StatusBarLocation mLocation;
|
||||||
|
|
||||||
// Enables SystemUI demo mode to take effect in this group
|
// Enables SystemUI demo mode to take effect in this group
|
||||||
protected boolean mDemoable = true;
|
protected boolean mDemoable = true;
|
||||||
@@ -381,11 +382,12 @@ public interface StatusBarIconController {
|
|||||||
mContext = group.getContext();
|
mContext = group.getContext();
|
||||||
mIconSize = mContext.getResources().getDimensionPixelSize(
|
mIconSize = mContext.getResources().getDimensionPixelSize(
|
||||||
com.android.internal.R.dimen.status_bar_icon_size);
|
com.android.internal.R.dimen.status_bar_icon_size);
|
||||||
|
mLocation = location;
|
||||||
|
|
||||||
if (statusBarPipelineFlags.runNewMobileIconsBackend()) {
|
if (statusBarPipelineFlags.runNewMobileIconsBackend()) {
|
||||||
// This starts the flow for the new pipeline, and will notify us of changes if
|
// This starts the flow for the new pipeline, and will notify us of changes if
|
||||||
// {@link StatusBarPipelineFlags#useNewMobileIcons} is also true.
|
// {@link StatusBarPipelineFlags#useNewMobileIcons} is also true.
|
||||||
mMobileIconsViewModel = mobileUiAdapter.createMobileIconsViewModel();
|
mMobileIconsViewModel = mobileUiAdapter.getMobileIconsViewModel();
|
||||||
MobileIconsBinder.bind(mGroup, mMobileIconsViewModel);
|
MobileIconsBinder.bind(mGroup, mMobileIconsViewModel);
|
||||||
} else {
|
} else {
|
||||||
mMobileIconsViewModel = null;
|
mMobileIconsViewModel = null;
|
||||||
@@ -394,7 +396,7 @@ public interface StatusBarIconController {
|
|||||||
if (statusBarPipelineFlags.runNewWifiIconBackend()) {
|
if (statusBarPipelineFlags.runNewWifiIconBackend()) {
|
||||||
// This starts the flow for the new pipeline, and will notify us of changes if
|
// This starts the flow for the new pipeline, and will notify us of changes if
|
||||||
// {@link StatusBarPipelineFlags#useNewWifiIcon} is also true.
|
// {@link StatusBarPipelineFlags#useNewWifiIcon} is also true.
|
||||||
mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, location);
|
mWifiViewModel = wifiUiAdapter.bindGroup(mGroup, mLocation);
|
||||||
} else {
|
} else {
|
||||||
mWifiViewModel = null;
|
mWifiViewModel = null;
|
||||||
}
|
}
|
||||||
@@ -569,7 +571,7 @@ public interface StatusBarIconController {
|
|||||||
.constructAndBind(
|
.constructAndBind(
|
||||||
mobileContext,
|
mobileContext,
|
||||||
slot,
|
slot,
|
||||||
mMobileIconsViewModel.viewModelForSub(subId)
|
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +707,12 @@ public interface StatusBarIconController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected DemoStatusIcons createDemoStatusIcons() {
|
protected DemoStatusIcons createDemoStatusIcons() {
|
||||||
return new DemoStatusIcons((LinearLayout) mGroup, mMobileIconsViewModel, mIconSize);
|
return new DemoStatusIcons(
|
||||||
|
(LinearLayout) mGroup,
|
||||||
|
mMobileIconsViewModel,
|
||||||
|
mLocation,
|
||||||
|
mIconSize
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ import android.telephony.TelephonyCallback.ServiceStateListener
|
|||||||
import android.telephony.TelephonyCallback.SignalStrengthsListener
|
import android.telephony.TelephonyCallback.SignalStrengthsListener
|
||||||
import android.telephony.TelephonyDisplayInfo
|
import android.telephony.TelephonyDisplayInfo
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
|
import com.android.systemui.log.table.Diffable
|
||||||
|
import com.android.systemui.log.table.TableRowLogger
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||||
|
|
||||||
@@ -79,4 +81,72 @@ data class MobileConnectionModel(
|
|||||||
* [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
|
* [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
|
||||||
*/
|
*/
|
||||||
val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
|
val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
|
||||||
)
|
) : Diffable<MobileConnectionModel> {
|
||||||
|
override fun logDiffs(prevVal: MobileConnectionModel, row: TableRowLogger) {
|
||||||
|
if (prevVal.dataConnectionState != dataConnectionState) {
|
||||||
|
row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.isEmergencyOnly != isEmergencyOnly) {
|
||||||
|
row.logChange(COL_EMERGENCY, isEmergencyOnly)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.isRoaming != isRoaming) {
|
||||||
|
row.logChange(COL_ROAMING, isRoaming)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.operatorAlphaShort != operatorAlphaShort) {
|
||||||
|
row.logChange(COL_OPERATOR, operatorAlphaShort)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.isGsm != isGsm) {
|
||||||
|
row.logChange(COL_IS_GSM, isGsm)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.cdmaLevel != cdmaLevel) {
|
||||||
|
row.logChange(COL_CDMA_LEVEL, cdmaLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.primaryLevel != primaryLevel) {
|
||||||
|
row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.dataActivityDirection != dataActivityDirection) {
|
||||||
|
row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.carrierNetworkChangeActive != carrierNetworkChangeActive) {
|
||||||
|
row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevVal.resolvedNetworkType != resolvedNetworkType) {
|
||||||
|
row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logFull(row: TableRowLogger) {
|
||||||
|
row.logChange(COL_CONNECTION_STATE, dataConnectionState.toString())
|
||||||
|
row.logChange(COL_EMERGENCY, isEmergencyOnly)
|
||||||
|
row.logChange(COL_ROAMING, isRoaming)
|
||||||
|
row.logChange(COL_OPERATOR, operatorAlphaShort)
|
||||||
|
row.logChange(COL_IS_GSM, isGsm)
|
||||||
|
row.logChange(COL_CDMA_LEVEL, cdmaLevel)
|
||||||
|
row.logChange(COL_PRIMARY_LEVEL, primaryLevel)
|
||||||
|
row.logChange(COL_ACTIVITY_DIRECTION, dataActivityDirection.toString())
|
||||||
|
row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChangeActive)
|
||||||
|
row.logChange(COL_RESOLVED_NETWORK_TYPE, resolvedNetworkType.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val COL_EMERGENCY = "EmergencyOnly"
|
||||||
|
const val COL_ROAMING = "Roaming"
|
||||||
|
const val COL_OPERATOR = "OperatorName"
|
||||||
|
const val COL_IS_GSM = "IsGsm"
|
||||||
|
const val COL_CDMA_LEVEL = "CdmaLevel"
|
||||||
|
const val COL_PRIMARY_LEVEL = "PrimaryLevel"
|
||||||
|
const val COL_CONNECTION_STATE = "ConnectionState"
|
||||||
|
const val COL_ACTIVITY_DIRECTION = "DataActivity"
|
||||||
|
const val COL_CARRIER_NETWORK_CHANGE = "CarrierNetworkChangeActive"
|
||||||
|
const val COL_RESOLVED_NETWORK_TYPE = "NetworkType"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,22 +21,48 @@ import android.telephony.TelephonyManager.EXTRA_DATA_SPN
|
|||||||
import android.telephony.TelephonyManager.EXTRA_PLMN
|
import android.telephony.TelephonyManager.EXTRA_PLMN
|
||||||
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
|
import android.telephony.TelephonyManager.EXTRA_SHOW_PLMN
|
||||||
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
|
import android.telephony.TelephonyManager.EXTRA_SHOW_SPN
|
||||||
|
import com.android.systemui.log.table.Diffable
|
||||||
|
import com.android.systemui.log.table.TableRowLogger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulates the data needed to show a network name for a mobile network. The data is parsed from
|
* Encapsulates the data needed to show a network name for a mobile network. The data is parsed from
|
||||||
* the intent sent by [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED].
|
* the intent sent by [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED].
|
||||||
*/
|
*/
|
||||||
sealed interface NetworkNameModel {
|
sealed interface NetworkNameModel : Diffable<NetworkNameModel> {
|
||||||
val name: String
|
val name: String
|
||||||
|
|
||||||
/** The default name is read from [com.android.internal.R.string.lockscreen_carrier_default] */
|
/** The default name is read from [com.android.internal.R.string.lockscreen_carrier_default] */
|
||||||
data class Default(override val name: String) : NetworkNameModel
|
data class Default(override val name: String) : NetworkNameModel {
|
||||||
|
override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) {
|
||||||
|
if (prevVal !is Default || prevVal.name != name) {
|
||||||
|
row.logChange(COL_NETWORK_NAME, "Default($name)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logFull(row: TableRowLogger) {
|
||||||
|
row.logChange(COL_NETWORK_NAME, "Default($name)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This name has been derived from telephony intents. see
|
* This name has been derived from telephony intents. see
|
||||||
* [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED]
|
* [android.telephony.TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED]
|
||||||
*/
|
*/
|
||||||
data class Derived(override val name: String) : NetworkNameModel
|
data class Derived(override val name: String) : NetworkNameModel {
|
||||||
|
override fun logDiffs(prevVal: NetworkNameModel, row: TableRowLogger) {
|
||||||
|
if (prevVal !is Derived || prevVal.name != name) {
|
||||||
|
row.logChange(COL_NETWORK_NAME, "Derived($name)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logFull(row: TableRowLogger) {
|
||||||
|
row.logChange(COL_NETWORK_NAME, "Derived($name)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val COL_NETWORK_NAME = "networkName"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
|
fun Intent.toNetworkNameModel(separator: String): NetworkNameModel? {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.telephony.SubscriptionInfo
|
|||||||
import android.telephony.SubscriptionManager
|
import android.telephony.SubscriptionManager
|
||||||
import android.telephony.TelephonyCallback
|
import android.telephony.TelephonyCallback
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -39,6 +40,13 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
interface MobileConnectionRepository {
|
interface MobileConnectionRepository {
|
||||||
/** The subscriptionId that this connection represents */
|
/** The subscriptionId that this connection represents */
|
||||||
val subId: Int
|
val subId: Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The table log buffer created for this connection. Will have the name "MobileConnectionLog
|
||||||
|
* [subId]"
|
||||||
|
*/
|
||||||
|
val tableLogBuffer: TableLogBuffer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
|
* A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
|
||||||
* listener + model.
|
* listener + model.
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import com.android.settingslib.SignalIcon
|
|||||||
import com.android.settingslib.mobile.MobileMappings
|
import com.android.settingslib.mobile.MobileMappings
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||||
@@ -60,6 +62,7 @@ constructor(
|
|||||||
private val dataSource: DemoModeMobileConnectionDataSource,
|
private val dataSource: DemoModeMobileConnectionDataSource,
|
||||||
@Application private val scope: CoroutineScope,
|
@Application private val scope: CoroutineScope,
|
||||||
context: Context,
|
context: Context,
|
||||||
|
private val logFactory: TableLogBufferFactory,
|
||||||
) : MobileConnectionsRepository {
|
) : MobileConnectionsRepository {
|
||||||
|
|
||||||
private var demoCommandJob: Job? = null
|
private var demoCommandJob: Job? = null
|
||||||
@@ -149,7 +152,16 @@ constructor(
|
|||||||
|
|
||||||
override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
|
override fun getRepoForSubId(subId: Int): DemoMobileConnectionRepository {
|
||||||
return connectionRepoCache[subId]
|
return connectionRepoCache[subId]
|
||||||
?: DemoMobileConnectionRepository(subId).also { connectionRepoCache[subId] = it }
|
?: createDemoMobileConnectionRepo(subId).also { connectionRepoCache[subId] = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createDemoMobileConnectionRepo(subId: Int): DemoMobileConnectionRepository {
|
||||||
|
val tableLogBuffer = logFactory.create("DemoMobileConnectionLog [$subId]", 100)
|
||||||
|
|
||||||
|
return DemoMobileConnectionRepository(
|
||||||
|
subId,
|
||||||
|
tableLogBuffer,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
override val globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
||||||
@@ -260,7 +272,10 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DemoMobileConnectionRepository(override val subId: Int) : MobileConnectionRepository {
|
class DemoMobileConnectionRepository(
|
||||||
|
override val subId: Int,
|
||||||
|
override val tableLogBuffer: TableLogBuffer,
|
||||||
|
) : MobileConnectionRepository {
|
||||||
override val connectionInfo = MutableStateFlow(MobileConnectionModel())
|
override val connectionInfo = MutableStateFlow(MobileConnectionModel())
|
||||||
|
|
||||||
override val dataEnabled = MutableStateFlow(true)
|
override val dataEnabled = MutableStateFlow(true)
|
||||||
|
|||||||
@@ -36,6 +36,9 @@ import com.android.systemui.broadcast.BroadcastDispatcher
|
|||||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.dagger.qualifiers.Background
|
import com.android.systemui.dagger.qualifiers.Background
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
|
import com.android.systemui.log.table.logDiffsForTable
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
||||||
@@ -46,7 +49,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameMo
|
|||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
||||||
import com.android.systemui.util.settings.GlobalSettings
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@@ -59,6 +61,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
@@ -79,6 +82,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
mobileMappingsProxy: MobileMappingsProxy,
|
mobileMappingsProxy: MobileMappingsProxy,
|
||||||
bgDispatcher: CoroutineDispatcher,
|
bgDispatcher: CoroutineDispatcher,
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
|
mobileLogger: TableLogBuffer,
|
||||||
scope: CoroutineScope,
|
scope: CoroutineScope,
|
||||||
) : MobileConnectionRepository {
|
) : MobileConnectionRepository {
|
||||||
init {
|
init {
|
||||||
@@ -92,10 +96,11 @@ class MobileConnectionRepositoryImpl(
|
|||||||
|
|
||||||
private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||||
|
|
||||||
|
override val tableLogBuffer: TableLogBuffer = mobileLogger
|
||||||
|
|
||||||
override val connectionInfo: StateFlow<MobileConnectionModel> = run {
|
override val connectionInfo: StateFlow<MobileConnectionModel> = run {
|
||||||
var state = MobileConnectionModel()
|
var state = MobileConnectionModel()
|
||||||
conflatedCallbackFlow {
|
conflatedCallbackFlow {
|
||||||
// TODO (b/240569788): log all of these into the connectivity logger
|
|
||||||
val callback =
|
val callback =
|
||||||
object :
|
object :
|
||||||
TelephonyCallback(),
|
TelephonyCallback(),
|
||||||
@@ -106,6 +111,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
TelephonyCallback.CarrierNetworkListener,
|
TelephonyCallback.CarrierNetworkListener,
|
||||||
TelephonyCallback.DisplayInfoListener {
|
TelephonyCallback.DisplayInfoListener {
|
||||||
override fun onServiceStateChanged(serviceState: ServiceState) {
|
override fun onServiceStateChanged(serviceState: ServiceState) {
|
||||||
|
logger.logOnServiceStateChanged(serviceState, subId)
|
||||||
state =
|
state =
|
||||||
state.copy(
|
state.copy(
|
||||||
isEmergencyOnly = serviceState.isEmergencyOnly,
|
isEmergencyOnly = serviceState.isEmergencyOnly,
|
||||||
@@ -116,6 +122,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
|
override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
|
||||||
|
logger.logOnSignalStrengthsChanged(signalStrength, subId)
|
||||||
val cdmaLevel =
|
val cdmaLevel =
|
||||||
signalStrength
|
signalStrength
|
||||||
.getCellSignalStrengths(CellSignalStrengthCdma::class.java)
|
.getCellSignalStrengths(CellSignalStrengthCdma::class.java)
|
||||||
@@ -142,12 +149,14 @@ class MobileConnectionRepositoryImpl(
|
|||||||
dataState: Int,
|
dataState: Int,
|
||||||
networkType: Int
|
networkType: Int
|
||||||
) {
|
) {
|
||||||
|
logger.logOnDataConnectionStateChanged(dataState, networkType, subId)
|
||||||
state =
|
state =
|
||||||
state.copy(dataConnectionState = dataState.toDataConnectionType())
|
state.copy(dataConnectionState = dataState.toDataConnectionType())
|
||||||
trySend(state)
|
trySend(state)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDataActivity(direction: Int) {
|
override fun onDataActivity(direction: Int) {
|
||||||
|
logger.logOnDataActivity(direction, subId)
|
||||||
state =
|
state =
|
||||||
state.copy(
|
state.copy(
|
||||||
dataActivityDirection = direction.toMobileDataActivityModel()
|
dataActivityDirection = direction.toMobileDataActivityModel()
|
||||||
@@ -156,6 +165,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCarrierNetworkChange(active: Boolean) {
|
override fun onCarrierNetworkChange(active: Boolean) {
|
||||||
|
logger.logOnCarrierNetworkChange(active, subId)
|
||||||
state = state.copy(carrierNetworkChangeActive = active)
|
state = state.copy(carrierNetworkChangeActive = active)
|
||||||
trySend(state)
|
trySend(state)
|
||||||
}
|
}
|
||||||
@@ -163,6 +173,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
override fun onDisplayInfoChanged(
|
override fun onDisplayInfoChanged(
|
||||||
telephonyDisplayInfo: TelephonyDisplayInfo
|
telephonyDisplayInfo: TelephonyDisplayInfo
|
||||||
) {
|
) {
|
||||||
|
logger.logOnDisplayInfoChanged(telephonyDisplayInfo, subId)
|
||||||
|
|
||||||
val networkType =
|
val networkType =
|
||||||
if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
|
if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
|
||||||
@@ -193,7 +204,11 @@ class MobileConnectionRepositoryImpl(
|
|||||||
awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
|
awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
|
||||||
}
|
}
|
||||||
.onEach { telephonyCallbackEvent.tryEmit(Unit) }
|
.onEach { telephonyCallbackEvent.tryEmit(Unit) }
|
||||||
.logOutputChange(logger, "MobileSubscriptionModel")
|
.logDiffsForTable(
|
||||||
|
mobileLogger,
|
||||||
|
columnPrefix = "MobileConnection ($subId)",
|
||||||
|
initialValue = state,
|
||||||
|
)
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), state)
|
.stateIn(scope, SharingStarted.WhileSubscribed(), state)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,19 +258,43 @@ class MobileConnectionRepositoryImpl(
|
|||||||
intent.toNetworkNameModel(networkNameSeparator) ?: defaultNetworkName
|
intent.toNetworkNameModel(networkNameSeparator) ?: defaultNetworkName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
mobileLogger,
|
||||||
|
columnPrefix = "",
|
||||||
|
initialValue = defaultNetworkName,
|
||||||
|
)
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
|
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultNetworkName)
|
||||||
|
|
||||||
override val dataEnabled: StateFlow<Boolean> =
|
override val dataEnabled: StateFlow<Boolean> = run {
|
||||||
|
val initial = dataConnectionAllowed()
|
||||||
telephonyPollingEvent
|
telephonyPollingEvent
|
||||||
.mapLatest { dataConnectionAllowed() }
|
.mapLatest { dataConnectionAllowed() }
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), dataConnectionAllowed())
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
mobileLogger,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "dataEnabled",
|
||||||
|
initialValue = initial,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), initial)
|
||||||
|
}
|
||||||
|
|
||||||
private fun dataConnectionAllowed(): Boolean = telephonyManager.isDataConnectionAllowed
|
private fun dataConnectionAllowed(): Boolean = telephonyManager.isDataConnectionAllowed
|
||||||
|
|
||||||
override val isDefaultDataSubscription: StateFlow<Boolean> =
|
override val isDefaultDataSubscription: StateFlow<Boolean> = run {
|
||||||
|
val initialValue = defaultDataSubId.value == subId
|
||||||
defaultDataSubId
|
defaultDataSubId
|
||||||
.mapLatest { it == subId }
|
.mapLatest { it == subId }
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultDataSubId.value == subId)
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
mobileLogger,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "isDefaultDataSub",
|
||||||
|
initialValue = initialValue,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), initialValue)
|
||||||
|
}
|
||||||
|
|
||||||
class Factory
|
class Factory
|
||||||
@Inject
|
@Inject
|
||||||
@@ -266,6 +305,7 @@ class MobileConnectionRepositoryImpl(
|
|||||||
private val logger: ConnectivityPipelineLogger,
|
private val logger: ConnectivityPipelineLogger,
|
||||||
private val globalSettings: GlobalSettings,
|
private val globalSettings: GlobalSettings,
|
||||||
private val mobileMappingsProxy: MobileMappingsProxy,
|
private val mobileMappingsProxy: MobileMappingsProxy,
|
||||||
|
private val logFactory: TableLogBufferFactory,
|
||||||
@Background private val bgDispatcher: CoroutineDispatcher,
|
@Background private val bgDispatcher: CoroutineDispatcher,
|
||||||
@Application private val scope: CoroutineScope,
|
@Application private val scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
@@ -276,6 +316,8 @@ class MobileConnectionRepositoryImpl(
|
|||||||
defaultDataSubId: StateFlow<Int>,
|
defaultDataSubId: StateFlow<Int>,
|
||||||
globalMobileDataSettingChangedEvent: Flow<Unit>,
|
globalMobileDataSettingChangedEvent: Flow<Unit>,
|
||||||
): MobileConnectionRepository {
|
): MobileConnectionRepository {
|
||||||
|
val mobileLogger = logFactory.create(tableBufferLogName(subId), 100)
|
||||||
|
|
||||||
return MobileConnectionRepositoryImpl(
|
return MobileConnectionRepositoryImpl(
|
||||||
context,
|
context,
|
||||||
subId,
|
subId,
|
||||||
@@ -289,8 +331,13 @@ class MobileConnectionRepositoryImpl(
|
|||||||
mobileMappingsProxy,
|
mobileMappingsProxy,
|
||||||
bgDispatcher,
|
bgDispatcher,
|
||||||
logger,
|
logger,
|
||||||
|
mobileLogger,
|
||||||
scope,
|
scope,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun tableBufferLogName(subId: Int): String = "MobileConnectionLog [$subId]"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
|
|||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange
|
||||||
import com.android.systemui.util.settings.GlobalSettings
|
import com.android.systemui.util.settings.GlobalSettings
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
@@ -120,6 +121,7 @@ constructor(
|
|||||||
awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
|
awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
|
||||||
}
|
}
|
||||||
.mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
|
.mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
|
||||||
|
.logInputChange(logger, "onSubscriptionsChanged")
|
||||||
.onEach { infos -> dropUnusedReposFromCache(infos) }
|
.onEach { infos -> dropUnusedReposFromCache(infos) }
|
||||||
.stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())
|
.stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())
|
||||||
|
|
||||||
@@ -136,6 +138,8 @@ constructor(
|
|||||||
telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
|
telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
|
||||||
awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
|
awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
|
||||||
}
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "onActiveDataSubscriptionIdChanged")
|
||||||
.stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)
|
.stateIn(scope, started = SharingStarted.WhileSubscribed(), INVALID_SUBSCRIPTION_ID)
|
||||||
|
|
||||||
private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
|
private val defaultDataSubIdChangeEvent: MutableSharedFlow<Unit> =
|
||||||
@@ -149,6 +153,7 @@ constructor(
|
|||||||
intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
|
intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, INVALID_SUBSCRIPTION_ID)
|
||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED")
|
||||||
.onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
|
.onEach { defaultDataSubIdChangeEvent.tryEmit(Unit) }
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope,
|
scope,
|
||||||
@@ -157,13 +162,15 @@ constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
private val carrierConfigChangedEvent =
|
private val carrierConfigChangedEvent =
|
||||||
broadcastDispatcher.broadcastFlow(
|
broadcastDispatcher
|
||||||
IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)
|
.broadcastFlow(IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED))
|
||||||
)
|
.logInputChange(logger, "ACTION_CARRIER_CONFIG_CHANGED")
|
||||||
|
|
||||||
override val defaultDataSubRatConfig: StateFlow<Config> =
|
override val defaultDataSubRatConfig: StateFlow<Config> =
|
||||||
merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
|
merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
|
||||||
.mapLatest { Config.readConfig(context) }
|
.mapLatest { Config.readConfig(context) }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "defaultDataSubRatConfig")
|
||||||
.stateIn(
|
.stateIn(
|
||||||
scope,
|
scope,
|
||||||
SharingStarted.WhileSubscribed(),
|
SharingStarted.WhileSubscribed(),
|
||||||
@@ -171,10 +178,16 @@ constructor(
|
|||||||
)
|
)
|
||||||
|
|
||||||
override val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>> =
|
override val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>> =
|
||||||
defaultDataSubRatConfig.map { mobileMappingsProxy.mapIconSets(it) }
|
defaultDataSubRatConfig
|
||||||
|
.map { mobileMappingsProxy.mapIconSets(it) }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "defaultMobileIconMapping")
|
||||||
|
|
||||||
override val defaultMobileIconGroup: Flow<MobileIconGroup> =
|
override val defaultMobileIconGroup: Flow<MobileIconGroup> =
|
||||||
defaultDataSubRatConfig.map { mobileMappingsProxy.getDefaultIcons(it) }
|
defaultDataSubRatConfig
|
||||||
|
.map { mobileMappingsProxy.getDefaultIcons(it) }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "defaultMobileIconGroup")
|
||||||
|
|
||||||
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
||||||
if (!isValidSubId(subId)) {
|
if (!isValidSubId(subId)) {
|
||||||
@@ -191,22 +204,24 @@ constructor(
|
|||||||
* In single-SIM devices, the [MOBILE_DATA] setting is phone-wide. For multi-SIM, the individual
|
* In single-SIM devices, the [MOBILE_DATA] setting is phone-wide. For multi-SIM, the individual
|
||||||
* connection repositories also observe the URI for [MOBILE_DATA] + subId.
|
* connection repositories also observe the URI for [MOBILE_DATA] + subId.
|
||||||
*/
|
*/
|
||||||
override val globalMobileDataSettingChangedEvent: Flow<Unit> = conflatedCallbackFlow {
|
override val globalMobileDataSettingChangedEvent: Flow<Unit> =
|
||||||
val observer =
|
conflatedCallbackFlow {
|
||||||
object : ContentObserver(null) {
|
val observer =
|
||||||
override fun onChange(selfChange: Boolean) {
|
object : ContentObserver(null) {
|
||||||
trySend(Unit)
|
override fun onChange(selfChange: Boolean) {
|
||||||
}
|
trySend(Unit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
globalSettings.registerContentObserver(
|
||||||
|
globalSettings.getUriFor(MOBILE_DATA),
|
||||||
|
true,
|
||||||
|
observer
|
||||||
|
)
|
||||||
|
|
||||||
|
awaitClose { context.contentResolver.unregisterContentObserver(observer) }
|
||||||
}
|
}
|
||||||
|
.logInputChange(logger, "globalMobileDataSettingChangedEvent")
|
||||||
globalSettings.registerContentObserver(
|
|
||||||
globalSettings.getUriFor(MOBILE_DATA),
|
|
||||||
true,
|
|
||||||
observer
|
|
||||||
)
|
|
||||||
|
|
||||||
awaitClose { context.contentResolver.unregisterContentObserver(observer) }
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("MissingPermission")
|
@SuppressLint("MissingPermission")
|
||||||
override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
|
override val defaultMobileNetworkConnectivity: StateFlow<MobileConnectivityModel> =
|
||||||
@@ -236,6 +251,8 @@ constructor(
|
|||||||
|
|
||||||
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
|
awaitClose { connectivityManager.unregisterNetworkCallback(callback) }
|
||||||
}
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logInputChange(logger, "defaultMobileNetworkConnectivity")
|
||||||
.stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())
|
.stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())
|
||||||
|
|
||||||
private fun isValidSubId(subId: Int): Boolean {
|
private fun isValidSubId(subId: Int): Boolean {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
|||||||
import android.telephony.CarrierConfigManager
|
import android.telephony.CarrierConfigManager
|
||||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||||
@@ -35,6 +36,9 @@ import kotlinx.coroutines.flow.mapLatest
|
|||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
interface MobileIconInteractor {
|
interface MobileIconInteractor {
|
||||||
|
/** The table log created for this connection */
|
||||||
|
val tableLogBuffer: TableLogBuffer
|
||||||
|
|
||||||
/** The current mobile data activity */
|
/** The current mobile data activity */
|
||||||
val activity: Flow<DataActivityModel>
|
val activity: Flow<DataActivityModel>
|
||||||
|
|
||||||
@@ -97,6 +101,8 @@ class MobileIconInteractorImpl(
|
|||||||
) : MobileIconInteractor {
|
) : MobileIconInteractor {
|
||||||
private val connectionInfo = connectionRepository.connectionInfo
|
private val connectionInfo = connectionRepository.connectionInfo
|
||||||
|
|
||||||
|
override val tableLogBuffer: TableLogBuffer = connectionRepository.tableLogBuffer
|
||||||
|
|
||||||
override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
|
override val activity = connectionInfo.mapLatest { it.dataActivityDirection }
|
||||||
|
|
||||||
override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled
|
override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import com.android.systemui.CoreStartable
|
|||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
import com.android.systemui.dagger.qualifiers.Application
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconController
|
import com.android.systemui.statusbar.phone.StatusBarIconController
|
||||||
import com.android.systemui.statusbar.phone.StatusBarIconController.IconManager
|
|
||||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
|
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
|
||||||
@@ -70,6 +69,9 @@ constructor(
|
|||||||
private val mobileSubIdsState: StateFlow<List<Int>> =
|
private val mobileSubIdsState: StateFlow<List<Int>> =
|
||||||
mobileSubIds.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
|
mobileSubIds.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
|
||||||
|
|
||||||
|
/** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */
|
||||||
|
val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState)
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
// Only notify the icon controller if we want to *render* the new icons.
|
// Only notify the icon controller if we want to *render* the new icons.
|
||||||
// Note that this flow may still run if
|
// Note that this flow may still run if
|
||||||
@@ -81,12 +83,4 @@ constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a MobileIconsViewModel for a given [IconManager], and bind it to to the manager's
|
|
||||||
* lifecycle. This will start collecting on [mobileSubIdsState] and link our new pipeline with
|
|
||||||
* the old view system.
|
|
||||||
*/
|
|
||||||
fun createMobileIconsViewModel(): MobileIconsViewModel =
|
|
||||||
iconsViewModelFactory.create(mobileSubIdsState)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import com.android.settingslib.graph.SignalDrawable
|
|||||||
import com.android.systemui.R
|
import com.android.systemui.R
|
||||||
import com.android.systemui.common.ui.binder.IconViewBinder
|
import com.android.systemui.common.ui.binder.IconViewBinder
|
||||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
|
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -39,7 +39,7 @@ object MobileIconBinder {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun bind(
|
fun bind(
|
||||||
view: ViewGroup,
|
view: ViewGroup,
|
||||||
viewModel: MobileIconViewModel,
|
viewModel: LocationBasedMobileViewModel,
|
||||||
) {
|
) {
|
||||||
val activityContainer = view.requireViewById<View>(R.id.inout_container)
|
val activityContainer = view.requireViewById<View>(R.id.inout_container)
|
||||||
val activityIn = view.requireViewById<ImageView>(R.id.mobile_in)
|
val activityIn = view.requireViewById<ImageView>(R.id.mobile_in)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import com.android.systemui.R
|
|||||||
import com.android.systemui.statusbar.BaseStatusBarFrameLayout
|
import com.android.systemui.statusbar.BaseStatusBarFrameLayout
|
||||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
|
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
|
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class ModernStatusBarMobileView(
|
class ModernStatusBarMobileView(
|
||||||
@@ -71,7 +71,7 @@ class ModernStatusBarMobileView(
|
|||||||
fun constructAndBind(
|
fun constructAndBind(
|
||||||
context: Context,
|
context: Context,
|
||||||
slot: String,
|
slot: String,
|
||||||
viewModel: MobileIconViewModel,
|
viewModel: LocationBasedMobileViewModel,
|
||||||
): ModernStatusBarMobileView {
|
): ModernStatusBarMobileView {
|
||||||
return (LayoutInflater.from(context)
|
return (LayoutInflater.from(context)
|
||||||
.inflate(R.layout.status_bar_mobile_signal_group_new, null)
|
.inflate(R.layout.status_bar_mobile_signal_group_new, null)
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||||
|
|
||||||
|
import android.graphics.Color
|
||||||
|
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A view model for an individual mobile icon that embeds the notion of a [StatusBarLocation]. This
|
||||||
|
* allows the mobile icon to change some view parameters at different locations
|
||||||
|
*
|
||||||
|
* @param commonImpl for convenience, this class wraps a base interface that can provides all of the
|
||||||
|
* common implementations between locations. See [MobileIconViewModel]
|
||||||
|
*/
|
||||||
|
abstract class LocationBasedMobileViewModel(
|
||||||
|
val commonImpl: MobileIconViewModelCommon,
|
||||||
|
val logger: ConnectivityPipelineLogger,
|
||||||
|
) : MobileIconViewModelCommon by commonImpl {
|
||||||
|
abstract val tint: Flow<Int>
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun viewModelForLocation(
|
||||||
|
commonImpl: MobileIconViewModelCommon,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
loc: StatusBarLocation,
|
||||||
|
): LocationBasedMobileViewModel =
|
||||||
|
when (loc) {
|
||||||
|
StatusBarLocation.HOME -> HomeMobileIconViewModel(commonImpl, logger)
|
||||||
|
StatusBarLocation.KEYGUARD -> KeyguardMobileIconViewModel(commonImpl, logger)
|
||||||
|
StatusBarLocation.QS -> QsMobileIconViewModel(commonImpl, logger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class HomeMobileIconViewModel(
|
||||||
|
commonImpl: MobileIconViewModelCommon,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
) : MobileIconViewModelCommon, LocationBasedMobileViewModel(commonImpl, logger) {
|
||||||
|
override val tint: Flow<Int> =
|
||||||
|
flowOf(Color.CYAN)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logOutputChange(logger, "HOME tint(${commonImpl.subscriptionId})")
|
||||||
|
}
|
||||||
|
|
||||||
|
class QsMobileIconViewModel(
|
||||||
|
commonImpl: MobileIconViewModelCommon,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
) : MobileIconViewModelCommon, LocationBasedMobileViewModel(commonImpl, logger) {
|
||||||
|
override val tint: Flow<Int> =
|
||||||
|
flowOf(Color.GREEN)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logOutputChange(logger, "QS tint(${commonImpl.subscriptionId})")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KeyguardMobileIconViewModel(
|
||||||
|
commonImpl: MobileIconViewModelCommon,
|
||||||
|
logger: ConnectivityPipelineLogger,
|
||||||
|
) : MobileIconViewModelCommon, LocationBasedMobileViewModel(commonImpl, logger) {
|
||||||
|
override val tint: Flow<Int> =
|
||||||
|
flowOf(Color.MAGENTA)
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logOutputChange(logger, "KEYGUARD tint(${commonImpl.subscriptionId})")
|
||||||
|
}
|
||||||
@@ -16,23 +16,40 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import com.android.settingslib.graph.SignalDrawable
|
import com.android.settingslib.graph.SignalDrawable
|
||||||
import com.android.systemui.common.shared.model.ContentDescription
|
import com.android.systemui.common.shared.model.ContentDescription
|
||||||
import com.android.systemui.common.shared.model.Icon
|
import com.android.systemui.common.shared.model.Icon
|
||||||
|
import com.android.systemui.log.table.logDiffsForTable
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
|
/** Common interface for all of the location-based mobile icon view models. */
|
||||||
|
interface MobileIconViewModelCommon {
|
||||||
|
val subscriptionId: Int
|
||||||
|
/** An int consumable by [SignalDrawable] for display */
|
||||||
|
val iconId: Flow<Int>
|
||||||
|
val roaming: Flow<Boolean>
|
||||||
|
/** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
|
||||||
|
val networkTypeIcon: Flow<Icon?>
|
||||||
|
val activityInVisible: Flow<Boolean>
|
||||||
|
val activityOutVisible: Flow<Boolean>
|
||||||
|
val activityContainerVisible: Flow<Boolean>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View model for the state of a single mobile icon. Each [MobileIconViewModel] will keep watch over
|
* View model for the state of a single mobile icon. Each [MobileIconViewModel] will keep watch over
|
||||||
@@ -40,25 +57,29 @@ import kotlinx.coroutines.flow.mapLatest
|
|||||||
* subscription's information.
|
* subscription's information.
|
||||||
*
|
*
|
||||||
* There will be exactly one [MobileIconViewModel] per filtered subscription offered from
|
* There will be exactly one [MobileIconViewModel] per filtered subscription offered from
|
||||||
* [MobileIconsInteractor.filteredSubscriptions]
|
* [MobileIconsInteractor.filteredSubscriptions].
|
||||||
*
|
*
|
||||||
* TODO: figure out where carrier merged and VCN models go (probably here?)
|
* For the sake of keeping log spam in check, every flow funding the [MobileIconViewModelCommon]
|
||||||
|
* interface is implemented as a [StateFlow]. This ensures that each location-based mobile icon view
|
||||||
|
* model gets the exact same information, as well as allows us to log that unified state only once
|
||||||
|
* per icon.
|
||||||
*/
|
*/
|
||||||
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class MobileIconViewModel
|
class MobileIconViewModel
|
||||||
constructor(
|
constructor(
|
||||||
val subscriptionId: Int,
|
override val subscriptionId: Int,
|
||||||
iconInteractor: MobileIconInteractor,
|
iconInteractor: MobileIconInteractor,
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
constants: ConnectivityConstants,
|
constants: ConnectivityConstants,
|
||||||
) {
|
scope: CoroutineScope,
|
||||||
|
) : MobileIconViewModelCommon {
|
||||||
/** Whether or not to show the error state of [SignalDrawable] */
|
/** Whether or not to show the error state of [SignalDrawable] */
|
||||||
private val showExclamationMark: Flow<Boolean> =
|
private val showExclamationMark: Flow<Boolean> =
|
||||||
iconInteractor.isDefaultDataEnabled.mapLatest { !it }
|
iconInteractor.isDefaultDataEnabled.mapLatest { !it }
|
||||||
|
|
||||||
/** An int consumable by [SignalDrawable] for display */
|
override val iconId: Flow<Int> = run {
|
||||||
val iconId: Flow<Int> =
|
val initial = SignalDrawable.getEmptyState(iconInteractor.numberOfLevels.value)
|
||||||
combine(iconInteractor.level, iconInteractor.numberOfLevels, showExclamationMark) {
|
combine(iconInteractor.level, iconInteractor.numberOfLevels, showExclamationMark) {
|
||||||
level,
|
level,
|
||||||
numberOfLevels,
|
numberOfLevels,
|
||||||
@@ -66,32 +87,56 @@ constructor(
|
|||||||
SignalDrawable.getState(level, numberOfLevels, showExclamationMark)
|
SignalDrawable.getState(level, numberOfLevels, showExclamationMark)
|
||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.logOutputChange(logger, "iconId($subscriptionId)")
|
.logDiffsForTable(
|
||||||
|
iconInteractor.tableLogBuffer,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "iconId",
|
||||||
|
initialValue = initial,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), initial)
|
||||||
|
}
|
||||||
|
|
||||||
/** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
|
override val networkTypeIcon: Flow<Icon?> =
|
||||||
val networkTypeIcon: Flow<Icon?> =
|
|
||||||
combine(
|
combine(
|
||||||
iconInteractor.networkTypeIconGroup,
|
iconInteractor.networkTypeIconGroup,
|
||||||
iconInteractor.isDataConnected,
|
iconInteractor.isDataConnected,
|
||||||
iconInteractor.isDataEnabled,
|
iconInteractor.isDataEnabled,
|
||||||
iconInteractor.isDefaultConnectionFailed,
|
iconInteractor.isDefaultConnectionFailed,
|
||||||
iconInteractor.alwaysShowDataRatIcon,
|
iconInteractor.alwaysShowDataRatIcon,
|
||||||
) { networkTypeIconGroup, dataConnected, dataEnabled, failedConnection, alwaysShow ->
|
) { networkTypeIconGroup, dataConnected, dataEnabled, failedConnection, alwaysShow ->
|
||||||
val desc =
|
val desc =
|
||||||
if (networkTypeIconGroup.dataContentDescription != 0)
|
if (networkTypeIconGroup.dataContentDescription != 0)
|
||||||
ContentDescription.Resource(networkTypeIconGroup.dataContentDescription)
|
ContentDescription.Resource(networkTypeIconGroup.dataContentDescription)
|
||||||
else null
|
else null
|
||||||
val icon = Icon.Resource(networkTypeIconGroup.dataType, desc)
|
val icon = Icon.Resource(networkTypeIconGroup.dataType, desc)
|
||||||
return@combine when {
|
return@combine when {
|
||||||
alwaysShow -> icon
|
alwaysShow -> icon
|
||||||
!dataConnected -> null
|
!dataConnected -> null
|
||||||
!dataEnabled -> null
|
!dataEnabled -> null
|
||||||
failedConnection -> null
|
failedConnection -> null
|
||||||
else -> icon
|
else -> icon
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.distinctUntilChanged()
|
||||||
|
.onEach {
|
||||||
|
// This is done as an onEach side effect since Icon is not Diffable (yet)
|
||||||
|
iconInteractor.tableLogBuffer.logChange(
|
||||||
|
prefix = "",
|
||||||
|
columnName = "networkTypeIcon",
|
||||||
|
value = it.toString(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), null)
|
||||||
|
|
||||||
val roaming: Flow<Boolean> = iconInteractor.isRoaming
|
override val roaming: StateFlow<Boolean> =
|
||||||
|
iconInteractor.isRoaming
|
||||||
|
.logDiffsForTable(
|
||||||
|
iconInteractor.tableLogBuffer,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "roaming",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
private val activity: Flow<DataActivityModel?> =
|
private val activity: Flow<DataActivityModel?> =
|
||||||
if (!constants.shouldShowActivityConfig) {
|
if (!constants.shouldShowActivityConfig) {
|
||||||
@@ -100,10 +145,39 @@ constructor(
|
|||||||
iconInteractor.activity
|
iconInteractor.activity
|
||||||
}
|
}
|
||||||
|
|
||||||
val activityInVisible: Flow<Boolean> = activity.map { it?.hasActivityIn ?: false }
|
override val activityInVisible: Flow<Boolean> =
|
||||||
val activityOutVisible: Flow<Boolean> = activity.map { it?.hasActivityOut ?: false }
|
activity
|
||||||
val activityContainerVisible: Flow<Boolean> =
|
.map { it?.hasActivityIn ?: false }
|
||||||
activity.map { it != null && (it.hasActivityIn || it.hasActivityOut) }
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
iconInteractor.tableLogBuffer,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "activityInVisible",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
val tint: Flow<Int> = flowOf(Color.CYAN)
|
override val activityOutVisible: Flow<Boolean> =
|
||||||
|
activity
|
||||||
|
.map { it?.hasActivityOut ?: false }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
iconInteractor.tableLogBuffer,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "activityOutVisible",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
|
|
||||||
|
override val activityContainerVisible: Flow<Boolean> =
|
||||||
|
activity
|
||||||
|
.map { it != null && (it.hasActivityIn || it.hasActivityOut) }
|
||||||
|
.distinctUntilChanged()
|
||||||
|
.logDiffsForTable(
|
||||||
|
iconInteractor.tableLogBuffer,
|
||||||
|
columnPrefix = "",
|
||||||
|
columnName = "activityContainerVisible",
|
||||||
|
initialValue = false,
|
||||||
|
)
|
||||||
|
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,19 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:OptIn(InternalCoroutinesApi::class)
|
|
||||||
|
|
||||||
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import com.android.systemui.dagger.qualifiers.Application
|
||||||
|
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
|
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.InternalCoroutinesApi
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* View model for describing the system's current mobile cellular connections. The result is a list
|
* View model for describing the system's current mobile cellular connections. The result is a list
|
||||||
@@ -38,15 +40,33 @@ constructor(
|
|||||||
private val interactor: MobileIconsInteractor,
|
private val interactor: MobileIconsInteractor,
|
||||||
private val logger: ConnectivityPipelineLogger,
|
private val logger: ConnectivityPipelineLogger,
|
||||||
private val constants: ConnectivityConstants,
|
private val constants: ConnectivityConstants,
|
||||||
|
@Application private val scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
/** TODO: do we need to cache these? */
|
@VisibleForTesting val mobileIconSubIdCache = mutableMapOf<Int, MobileIconViewModel>()
|
||||||
fun viewModelForSub(subId: Int): MobileIconViewModel =
|
|
||||||
MobileIconViewModel(
|
init {
|
||||||
subId,
|
scope.launch { subscriptionIdsFlow.collect { removeInvalidModelsFromCache(it) } }
|
||||||
interactor.createMobileConnectionInteractorForSubId(subId),
|
}
|
||||||
logger,
|
|
||||||
constants,
|
fun viewModelForSub(subId: Int, location: StatusBarLocation): LocationBasedMobileViewModel {
|
||||||
)
|
val common =
|
||||||
|
mobileIconSubIdCache[subId]
|
||||||
|
?: MobileIconViewModel(
|
||||||
|
subId,
|
||||||
|
interactor.createMobileConnectionInteractorForSubId(subId),
|
||||||
|
logger,
|
||||||
|
constants,
|
||||||
|
scope,
|
||||||
|
)
|
||||||
|
.also { mobileIconSubIdCache[subId] = it }
|
||||||
|
|
||||||
|
return LocationBasedMobileViewModel.viewModelForLocation(common, logger, location)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeInvalidModelsFromCache(subIds: List<Int>) {
|
||||||
|
val subIdsToRemove = mobileIconSubIdCache.keys.filter { !subIds.contains(it) }
|
||||||
|
subIdsToRemove.forEach { mobileIconSubIdCache.remove(it) }
|
||||||
|
}
|
||||||
|
|
||||||
class Factory
|
class Factory
|
||||||
@Inject
|
@Inject
|
||||||
@@ -54,6 +74,7 @@ constructor(
|
|||||||
private val interactor: MobileIconsInteractor,
|
private val interactor: MobileIconsInteractor,
|
||||||
private val logger: ConnectivityPipelineLogger,
|
private val logger: ConnectivityPipelineLogger,
|
||||||
private val constants: ConnectivityConstants,
|
private val constants: ConnectivityConstants,
|
||||||
|
@Application private val scope: CoroutineScope,
|
||||||
) {
|
) {
|
||||||
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
|
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
|
||||||
return MobileIconsViewModel(
|
return MobileIconsViewModel(
|
||||||
@@ -61,6 +82,7 @@ constructor(
|
|||||||
interactor,
|
interactor,
|
||||||
logger,
|
logger,
|
||||||
constants,
|
constants,
|
||||||
|
scope,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,11 @@ package com.android.systemui.statusbar.pipeline.shared
|
|||||||
|
|
||||||
import android.net.Network
|
import android.net.Network
|
||||||
import android.net.NetworkCapabilities
|
import android.net.NetworkCapabilities
|
||||||
import com.android.systemui.log.dagger.StatusBarConnectivityLog
|
import android.telephony.ServiceState
|
||||||
|
import android.telephony.SignalStrength
|
||||||
|
import android.telephony.TelephonyDisplayInfo
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.log.dagger.StatusBarConnectivityLog
|
||||||
import com.android.systemui.plugins.log.LogBuffer
|
import com.android.systemui.plugins.log.LogBuffer
|
||||||
import com.android.systemui.plugins.log.LogLevel
|
import com.android.systemui.plugins.log.LogLevel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.toString
|
||||||
@@ -28,7 +31,9 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class ConnectivityPipelineLogger @Inject constructor(
|
class ConnectivityPipelineLogger
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
@StatusBarConnectivityLog private val buffer: LogBuffer,
|
@StatusBarConnectivityLog private val buffer: LogBuffer,
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
@@ -37,34 +42,23 @@ class ConnectivityPipelineLogger @Inject constructor(
|
|||||||
* Use this method for inputs that don't have any extra information besides their callback name.
|
* Use this method for inputs that don't have any extra information besides their callback name.
|
||||||
*/
|
*/
|
||||||
fun logInputChange(callbackName: String) {
|
fun logInputChange(callbackName: String) {
|
||||||
|
buffer.log(SB_LOGGING_TAG, LogLevel.INFO, { str1 = callbackName }, { "Input: $str1" })
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Logs a change in one of the **raw inputs** to the connectivity pipeline. */
|
||||||
|
fun logInputChange(callbackName: String, changeInfo: String?) {
|
||||||
buffer.log(
|
buffer.log(
|
||||||
SB_LOGGING_TAG,
|
SB_LOGGING_TAG,
|
||||||
LogLevel.INFO,
|
LogLevel.INFO,
|
||||||
{ str1 = callbackName },
|
{
|
||||||
{ "Input: $str1" }
|
str1 = callbackName
|
||||||
|
str2 = changeInfo
|
||||||
|
},
|
||||||
|
{ "Input: $str1: $str2" }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Logs a **data transformation** that we performed within the connectivity pipeline. */
|
||||||
* Logs a change in one of the **raw inputs** to the connectivity pipeline.
|
|
||||||
*/
|
|
||||||
fun logInputChange(callbackName: String, changeInfo: String?) {
|
|
||||||
buffer.log(
|
|
||||||
SB_LOGGING_TAG,
|
|
||||||
LogLevel.INFO,
|
|
||||||
{
|
|
||||||
str1 = callbackName
|
|
||||||
str2 = changeInfo
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Input: $str1: $str2"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Logs a **data transformation** that we performed within the connectivity pipeline.
|
|
||||||
*/
|
|
||||||
fun logTransformation(transformationName: String, oldValue: Any?, newValue: Any?) {
|
fun logTransformation(transformationName: String, oldValue: Any?, newValue: Any?) {
|
||||||
if (oldValue == newValue) {
|
if (oldValue == newValue) {
|
||||||
buffer.log(
|
buffer.log(
|
||||||
@@ -74,9 +68,7 @@ class ConnectivityPipelineLogger @Inject constructor(
|
|||||||
str1 = transformationName
|
str1 = transformationName
|
||||||
str2 = oldValue.toString()
|
str2 = oldValue.toString()
|
||||||
},
|
},
|
||||||
{
|
{ "Transform: $str1: $str2 (transformation didn't change it)" }
|
||||||
"Transform: $str1: $str2 (transformation didn't change it)"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
buffer.log(
|
buffer.log(
|
||||||
@@ -87,27 +79,21 @@ class ConnectivityPipelineLogger @Inject constructor(
|
|||||||
str2 = oldValue.toString()
|
str2 = oldValue.toString()
|
||||||
str3 = newValue.toString()
|
str3 = newValue.toString()
|
||||||
},
|
},
|
||||||
{
|
{ "Transform: $str1: $str2 -> $str3" }
|
||||||
"Transform: $str1: $str2 -> $str3"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Logs a change in one of the **outputs** to the connectivity pipeline. */
|
||||||
* Logs a change in one of the **outputs** to the connectivity pipeline.
|
|
||||||
*/
|
|
||||||
fun logOutputChange(outputParamName: String, changeInfo: String) {
|
fun logOutputChange(outputParamName: String, changeInfo: String) {
|
||||||
buffer.log(
|
buffer.log(
|
||||||
SB_LOGGING_TAG,
|
SB_LOGGING_TAG,
|
||||||
LogLevel.INFO,
|
LogLevel.INFO,
|
||||||
{
|
{
|
||||||
str1 = outputParamName
|
str1 = outputParamName
|
||||||
str2 = changeInfo
|
str2 = changeInfo
|
||||||
},
|
},
|
||||||
{
|
{ "Output: $str1: $str2" }
|
||||||
"Output: $str1: $str2"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,31 +105,101 @@ class ConnectivityPipelineLogger @Inject constructor(
|
|||||||
int1 = network.getNetId()
|
int1 = network.getNetId()
|
||||||
str1 = networkCapabilities.toString()
|
str1 = networkCapabilities.toString()
|
||||||
},
|
},
|
||||||
{
|
{ "onCapabilitiesChanged: net=$int1 capabilities=$str1" }
|
||||||
"onCapabilitiesChanged: net=$int1 capabilities=$str1"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun logOnLost(network: Network) {
|
fun logOnLost(network: Network) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{ int1 = network.getNetId() },
|
||||||
|
{ "onLost: net=$int1" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logOnServiceStateChanged(serviceState: ServiceState, subId: Int) {
|
||||||
buffer.log(
|
buffer.log(
|
||||||
SB_LOGGING_TAG,
|
SB_LOGGING_TAG,
|
||||||
LogLevel.INFO,
|
LogLevel.INFO,
|
||||||
{
|
{
|
||||||
int1 = network.getNetId()
|
int1 = subId
|
||||||
|
bool1 = serviceState.isEmergencyOnly
|
||||||
|
bool2 = serviceState.roaming
|
||||||
|
str1 = serviceState.operatorAlphaShort
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"onLost: net=$int1"
|
"onServiceStateChanged: subId=$int1 emergencyOnly=$bool1 roaming=$bool2" +
|
||||||
|
" operator=$str1"
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun logOnSignalStrengthsChanged(signalStrength: SignalStrength, subId: Int) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{
|
||||||
|
int1 = subId
|
||||||
|
str1 = signalStrength.toString()
|
||||||
|
},
|
||||||
|
{ "onSignalStrengthsChanged: subId=$int1 strengths=$str1" }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logOnDataConnectionStateChanged(dataState: Int, networkType: Int, subId: Int) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{
|
||||||
|
int1 = subId
|
||||||
|
int2 = dataState
|
||||||
|
str1 = networkType.toString()
|
||||||
|
},
|
||||||
|
{ "onDataConnectionStateChanged: subId=$int1 dataState=$int2 networkType=$str1" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logOnDataActivity(direction: Int, subId: Int) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{
|
||||||
|
int1 = subId
|
||||||
|
int2 = direction
|
||||||
|
},
|
||||||
|
{ "onDataActivity: subId=$int1 direction=$int2" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logOnCarrierNetworkChange(active: Boolean, subId: Int) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{
|
||||||
|
int1 = subId
|
||||||
|
bool1 = active
|
||||||
|
},
|
||||||
|
{ "onCarrierNetworkChange: subId=$int1 active=$bool1" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logOnDisplayInfoChanged(displayInfo: TelephonyDisplayInfo, subId: Int) {
|
||||||
|
buffer.log(
|
||||||
|
SB_LOGGING_TAG,
|
||||||
|
LogLevel.INFO,
|
||||||
|
{
|
||||||
|
int1 = subId
|
||||||
|
str1 = displayInfo.toString()
|
||||||
|
},
|
||||||
|
{ "onDisplayInfoChanged: subId=$int1 displayInfo=$str1" },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val SB_LOGGING_TAG = "SbConnectivity"
|
const val SB_LOGGING_TAG = "SbConnectivity"
|
||||||
|
|
||||||
/**
|
/** Log a change in one of the **inputs** to the connectivity pipeline. */
|
||||||
* Log a change in one of the **inputs** to the connectivity pipeline.
|
|
||||||
*/
|
|
||||||
fun Flow<Unit>.logInputChange(
|
fun Flow<Unit>.logInputChange(
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
inputParamName: String,
|
inputParamName: String,
|
||||||
@@ -155,26 +211,26 @@ class ConnectivityPipelineLogger @Inject constructor(
|
|||||||
* Log a change in one of the **inputs** to the connectivity pipeline.
|
* Log a change in one of the **inputs** to the connectivity pipeline.
|
||||||
*
|
*
|
||||||
* @param prettyPrint an optional function to transform the value into a readable string.
|
* @param prettyPrint an optional function to transform the value into a readable string.
|
||||||
* [toString] is used if no custom function is provided.
|
* [toString] is used if no custom function is provided.
|
||||||
*/
|
*/
|
||||||
fun <T> Flow<T>.logInputChange(
|
fun <T> Flow<T>.logInputChange(
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
inputParamName: String,
|
inputParamName: String,
|
||||||
prettyPrint: (T) -> String = { it.toString() }
|
prettyPrint: (T) -> String = { it.toString() }
|
||||||
): Flow<T> {
|
): Flow<T> {
|
||||||
return this.onEach {logger.logInputChange(inputParamName, prettyPrint(it)) }
|
return this.onEach { logger.logInputChange(inputParamName, prettyPrint(it)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log a change in one of the **outputs** to the connectivity pipeline.
|
* Log a change in one of the **outputs** to the connectivity pipeline.
|
||||||
*
|
*
|
||||||
* @param prettyPrint an optional function to transform the value into a readable string.
|
* @param prettyPrint an optional function to transform the value into a readable string.
|
||||||
* [toString] is used if no custom function is provided.
|
* [toString] is used if no custom function is provided.
|
||||||
*/
|
*/
|
||||||
fun <T> Flow<T>.logOutputChange(
|
fun <T> Flow<T>.logOutputChange(
|
||||||
logger: ConnectivityPipelineLogger,
|
logger: ConnectivityPipelineLogger,
|
||||||
outputParamName: String,
|
outputParamName: String,
|
||||||
prettyPrint: (T) -> String = { it.toString() }
|
prettyPrint: (T) -> String = { it.toString() }
|
||||||
): Flow<T> {
|
): Flow<T> {
|
||||||
return this.onEach { logger.logOutputChange(outputParamName, prettyPrint(it)) }
|
return this.onEach { logger.logOutputChange(outputParamName, prettyPrint(it)) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,16 +38,12 @@ class WifiConstants @Inject constructor(
|
|||||||
dumpManager.registerDumpable("${SB_LOGGING_TAG}WifiConstants", this)
|
dumpManager.registerDumpable("${SB_LOGGING_TAG}WifiConstants", this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True if we should show the activityIn/activityOut icons and false otherwise. */
|
|
||||||
val shouldShowActivityConfig = context.resources.getBoolean(R.bool.config_showActivity)
|
|
||||||
|
|
||||||
/** True if we should always show the wifi icon when wifi is enabled and false otherwise. */
|
/** True if we should always show the wifi icon when wifi is enabled and false otherwise. */
|
||||||
val alwaysShowIconIfEnabled =
|
val alwaysShowIconIfEnabled =
|
||||||
context.resources.getBoolean(R.bool.config_showWifiIndicatorWhenEnabled)
|
context.resources.getBoolean(R.bool.config_showWifiIndicatorWhenEnabled)
|
||||||
|
|
||||||
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
||||||
pw.apply {
|
pw.apply {
|
||||||
println("shouldShowActivityConfig=$shouldShowActivityConfig")
|
|
||||||
println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled")
|
println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ constructor(
|
|||||||
|
|
||||||
/** The wifi activity status. Null if we shouldn't display the activity status. */
|
/** The wifi activity status. Null if we shouldn't display the activity status. */
|
||||||
private val activity: Flow<DataActivityModel?> =
|
private val activity: Flow<DataActivityModel?> =
|
||||||
if (!wifiConstants.shouldShowActivityConfig) {
|
if (!connectivityConstants.shouldShowActivityConfig) {
|
||||||
flowOf(null)
|
flowOf(null)
|
||||||
} else {
|
} else {
|
||||||
combine(interactor.activity, interactor.ssid) { activity, ssid ->
|
combine(interactor.activity, interactor.ssid) { activity, ssid ->
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.pipeline.mobile.data.model
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableRowLogger
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ACTIVITY_DIRECTION
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CARRIER_NETWORK_CHANGE
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CDMA_LEVEL
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_CONNECTION_STATE
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_EMERGENCY
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_IS_GSM
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_OPERATOR
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_PRIMARY_LEVEL
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_RESOLVED_NETWORK_TYPE
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel.Companion.COL_ROAMING
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
class MobileConnectionModelTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `log diff - initial log contains all columns`() {
|
||||||
|
val logger = TestLogger()
|
||||||
|
val connection = MobileConnectionModel()
|
||||||
|
|
||||||
|
connection.logFull(logger)
|
||||||
|
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_EMERGENCY, connection.isEmergencyOnly.toString()))
|
||||||
|
assertThat(logger.changes).contains(Pair(COL_ROAMING, connection.isRoaming.toString()))
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_OPERATOR, connection.operatorAlphaShort.toString()))
|
||||||
|
assertThat(logger.changes).contains(Pair(COL_IS_GSM, connection.isGsm.toString()))
|
||||||
|
assertThat(logger.changes).contains(Pair(COL_CDMA_LEVEL, connection.cdmaLevel.toString()))
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_PRIMARY_LEVEL, connection.primaryLevel.toString()))
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_CONNECTION_STATE, connection.dataConnectionState.toString()))
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_ACTIVITY_DIRECTION, connection.dataActivityDirection.toString()))
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(
|
||||||
|
Pair(COL_CARRIER_NETWORK_CHANGE, connection.carrierNetworkChangeActive.toString())
|
||||||
|
)
|
||||||
|
assertThat(logger.changes)
|
||||||
|
.contains(Pair(COL_RESOLVED_NETWORK_TYPE, connection.resolvedNetworkType.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `log diff - primary level changes - only level is logged`() {
|
||||||
|
val logger = TestLogger()
|
||||||
|
val connectionOld = MobileConnectionModel(primaryLevel = 1)
|
||||||
|
|
||||||
|
val connectionNew = MobileConnectionModel(primaryLevel = 2)
|
||||||
|
|
||||||
|
connectionNew.logDiffs(connectionOld, logger)
|
||||||
|
|
||||||
|
assertThat(logger.changes).isEqualTo(listOf(Pair(COL_PRIMARY_LEVEL, "2")))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestLogger : TableRowLogger {
|
||||||
|
val changes = mutableListOf<Pair<String, String>>()
|
||||||
|
|
||||||
|
override fun logChange(columnName: String, value: String?) {
|
||||||
|
changes.add(Pair(columnName, value.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logChange(columnName: String, value: Int) {
|
||||||
|
changes.add(Pair(columnName, value.toString()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun logChange(columnName: String, value: Boolean) {
|
||||||
|
changes.add(Pair(columnName, value.toString()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,12 +16,16 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||||
|
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
|
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
|
||||||
class FakeMobileConnectionRepository(override val subId: Int) : MobileConnectionRepository {
|
class FakeMobileConnectionRepository(
|
||||||
|
override val subId: Int,
|
||||||
|
override val tableLogBuffer: TableLogBuffer,
|
||||||
|
) : MobileConnectionRepository {
|
||||||
private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
|
private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
|
||||||
override val connectionInfo = _connectionInfo
|
override val connectionInfo = _connectionInfo
|
||||||
|
|
||||||
|
|||||||
@@ -22,14 +22,17 @@ import android.telephony.TelephonyManager
|
|||||||
import com.android.settingslib.SignalIcon
|
import com.android.settingslib.SignalIcon
|
||||||
import com.android.settingslib.mobile.MobileMappings
|
import com.android.settingslib.mobile.MobileMappings
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
|
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
|
||||||
class FakeMobileConnectionsRepository(mobileMappings: MobileMappingsProxy) :
|
class FakeMobileConnectionsRepository(
|
||||||
MobileConnectionsRepository {
|
mobileMappings: MobileMappingsProxy,
|
||||||
|
val tableLogBuffer: TableLogBuffer,
|
||||||
|
) : MobileConnectionsRepository {
|
||||||
val GSM_KEY = mobileMappings.toIconKey(GSM)
|
val GSM_KEY = mobileMappings.toIconKey(GSM)
|
||||||
val LTE_KEY = mobileMappings.toIconKey(LTE)
|
val LTE_KEY = mobileMappings.toIconKey(LTE)
|
||||||
val UMTS_KEY = mobileMappings.toIconKey(UMTS)
|
val UMTS_KEY = mobileMappings.toIconKey(UMTS)
|
||||||
@@ -63,7 +66,7 @@ class FakeMobileConnectionsRepository(mobileMappings: MobileMappingsProxy) :
|
|||||||
private val subIdRepos = mutableMapOf<Int, MobileConnectionRepository>()
|
private val subIdRepos = mutableMapOf<Int, MobileConnectionRepository>()
|
||||||
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
||||||
return subIdRepos[subId]
|
return subIdRepos[subId]
|
||||||
?: FakeMobileConnectionRepository(subId).also { subIdRepos[subId] = it }
|
?: FakeMobileConnectionRepository(subId, tableLogBuffer).also { subIdRepos[subId] = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val _globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
private val _globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import androidx.test.filters.SmallTest
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.demomode.DemoMode
|
import com.android.systemui.demomode.DemoMode
|
||||||
import com.android.systemui.demomode.DemoModeController
|
import com.android.systemui.demomode.DemoModeController
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoMobileConnectionsRepository
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoModeMobileConnectionDataSource
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.DemoModeMobileConnectionDataSource
|
||||||
@@ -37,6 +39,7 @@ import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
|||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
import com.android.systemui.util.settings.FakeSettings
|
import com.android.systemui.util.settings.FakeSettings
|
||||||
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -69,12 +72,14 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
|||||||
private lateinit var realRepo: MobileConnectionsRepositoryImpl
|
private lateinit var realRepo: MobileConnectionsRepositoryImpl
|
||||||
private lateinit var demoRepo: DemoMobileConnectionsRepository
|
private lateinit var demoRepo: DemoMobileConnectionsRepository
|
||||||
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
|
private lateinit var mockDataSource: DemoModeMobileConnectionDataSource
|
||||||
|
private lateinit var logFactory: TableLogBufferFactory
|
||||||
|
|
||||||
@Mock private lateinit var connectivityManager: ConnectivityManager
|
@Mock private lateinit var connectivityManager: ConnectivityManager
|
||||||
@Mock private lateinit var subscriptionManager: SubscriptionManager
|
@Mock private lateinit var subscriptionManager: SubscriptionManager
|
||||||
@Mock private lateinit var telephonyManager: TelephonyManager
|
@Mock private lateinit var telephonyManager: TelephonyManager
|
||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
@Mock private lateinit var demoModeController: DemoModeController
|
@Mock private lateinit var demoModeController: DemoModeController
|
||||||
|
@Mock private lateinit var dumpManager: DumpManager
|
||||||
|
|
||||||
private val globalSettings = FakeSettings()
|
private val globalSettings = FakeSettings()
|
||||||
private val fakeNetworkEventsFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
|
private val fakeNetworkEventsFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
|
||||||
@@ -86,6 +91,8 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
|
||||||
|
|
||||||
// Never start in demo mode
|
// Never start in demo mode
|
||||||
whenever(demoModeController.isInDemoMode).thenReturn(false)
|
whenever(demoModeController.isInDemoMode).thenReturn(false)
|
||||||
|
|
||||||
@@ -114,6 +121,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
|||||||
dataSource = mockDataSource,
|
dataSource = mockDataSource,
|
||||||
scope = scope,
|
scope = scope,
|
||||||
context = context,
|
context = context,
|
||||||
|
logFactory = logFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
underTest =
|
underTest =
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import androidx.test.filters.SmallTest
|
|||||||
import com.android.settingslib.SignalIcon
|
import com.android.settingslib.SignalIcon
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
@@ -30,6 +31,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model
|
|||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.cancel
|
import kotlinx.coroutines.cancel
|
||||||
@@ -54,6 +56,9 @@ import org.junit.runners.Parameterized.Parameters
|
|||||||
@RunWith(Parameterized::class)
|
@RunWith(Parameterized::class)
|
||||||
internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
|
internal class DemoMobileConnectionParameterizedTest(private val testCase: TestCase) :
|
||||||
SysuiTestCase() {
|
SysuiTestCase() {
|
||||||
|
|
||||||
|
private val logFactory = TableLogBufferFactory(mock(), FakeSystemClock())
|
||||||
|
|
||||||
private val testDispatcher = UnconfinedTestDispatcher()
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
private val testScope = TestScope(testDispatcher)
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
@@ -76,6 +81,7 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
|||||||
dataSource = mockDataSource,
|
dataSource = mockDataSource,
|
||||||
scope = testScope.backgroundScope,
|
scope = testScope.backgroundScope,
|
||||||
context = context,
|
context = context,
|
||||||
|
logFactory = logFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
connectionsRepo.startProcessingCommands()
|
connectionsRepo.startProcessingCommands()
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ import androidx.test.filters.SmallTest
|
|||||||
import com.android.settingslib.SignalIcon
|
import com.android.settingslib.SignalIcon
|
||||||
import com.android.settingslib.mobile.TelephonyIcons.THREE_G
|
import com.android.settingslib.mobile.TelephonyIcons.THREE_G
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
@@ -32,6 +34,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model
|
|||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import junit.framework.Assert
|
import junit.framework.Assert
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
@@ -47,6 +50,9 @@ import org.junit.Test
|
|||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||||
|
private val dumpManager: DumpManager = mock()
|
||||||
|
private val logFactory = TableLogBufferFactory(dumpManager, FakeSystemClock())
|
||||||
|
|
||||||
private val testDispatcher = UnconfinedTestDispatcher()
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
private val testScope = TestScope(testDispatcher)
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
@@ -68,6 +74,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
dataSource = mockDataSource,
|
dataSource = mockDataSource,
|
||||||
scope = testScope.backgroundScope,
|
scope = testScope.backgroundScope,
|
||||||
context = context,
|
context = context,
|
||||||
|
logFactory = logFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
underTest.startProcessingCommands()
|
underTest.startProcessingCommands()
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
|
|||||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
@@ -87,14 +88,15 @@ import org.mockito.MockitoAnnotations
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
class MobileConnectionRepositoryTest : SysuiTestCase() {
|
class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||||
private lateinit var underTest: MobileConnectionRepositoryImpl
|
private lateinit var underTest: MobileConnectionRepositoryImpl
|
||||||
|
private lateinit var connectionsRepo: FakeMobileConnectionsRepository
|
||||||
|
|
||||||
@Mock private lateinit var telephonyManager: TelephonyManager
|
@Mock private lateinit var telephonyManager: TelephonyManager
|
||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
@Mock private lateinit var tableLogger: TableLogBuffer
|
||||||
|
|
||||||
private val scope = CoroutineScope(IMMEDIATE)
|
private val scope = CoroutineScope(IMMEDIATE)
|
||||||
private val mobileMappings = FakeMobileMappingsProxy()
|
private val mobileMappings = FakeMobileMappingsProxy()
|
||||||
private val globalSettings = FakeSettings()
|
private val globalSettings = FakeSettings()
|
||||||
private val connectionsRepo = FakeMobileConnectionsRepository(mobileMappings)
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
@@ -102,6 +104,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
|||||||
globalSettings.userId = UserHandle.USER_ALL
|
globalSettings.userId = UserHandle.USER_ALL
|
||||||
whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
|
whenever(telephonyManager.subscriptionId).thenReturn(SUB_1_ID)
|
||||||
|
|
||||||
|
connectionsRepo = FakeMobileConnectionsRepository(mobileMappings, tableLogger)
|
||||||
|
|
||||||
underTest =
|
underTest =
|
||||||
MobileConnectionRepositoryImpl(
|
MobileConnectionRepositoryImpl(
|
||||||
context,
|
context,
|
||||||
@@ -116,6 +120,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
|||||||
mobileMappings,
|
mobileMappings,
|
||||||
IMMEDIATE,
|
IMMEDIATE,
|
||||||
logger,
|
logger,
|
||||||
|
tableLogger,
|
||||||
scope,
|
scope,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,12 +34,15 @@ import com.android.internal.telephony.PhoneConstants
|
|||||||
import com.android.settingslib.R
|
import com.android.settingslib.R
|
||||||
import com.android.settingslib.mobile.MobileMappings
|
import com.android.settingslib.mobile.MobileMappings
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import com.android.systemui.log.table.TableLogBufferFactory
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.util.mockito.any
|
import com.android.systemui.util.mockito.any
|
||||||
import com.android.systemui.util.mockito.argumentCaptor
|
import com.android.systemui.util.mockito.argumentCaptor
|
||||||
|
import com.android.systemui.util.mockito.eq
|
||||||
import com.android.systemui.util.mockito.mock
|
import com.android.systemui.util.mockito.mock
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
import com.android.systemui.util.settings.FakeSettings
|
import com.android.systemui.util.settings.FakeSettings
|
||||||
@@ -57,6 +60,7 @@ import org.junit.Assert.assertTrue
|
|||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.ArgumentMatchers.anyInt
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
|
import org.mockito.ArgumentMatchers.anyString
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
@@ -72,6 +76,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
@Mock private lateinit var subscriptionManager: SubscriptionManager
|
@Mock private lateinit var subscriptionManager: SubscriptionManager
|
||||||
@Mock private lateinit var telephonyManager: TelephonyManager
|
@Mock private lateinit var telephonyManager: TelephonyManager
|
||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
@Mock private lateinit var logBufferFactory: TableLogBufferFactory
|
||||||
|
|
||||||
private val mobileMappings = FakeMobileMappingsProxy()
|
private val mobileMappings = FakeMobileMappingsProxy()
|
||||||
|
|
||||||
@@ -89,6 +94,10 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
whenever(logBufferFactory.create(anyString(), anyInt())).thenAnswer { _ ->
|
||||||
|
mock<TableLogBuffer>()
|
||||||
|
}
|
||||||
|
|
||||||
connectionFactory =
|
connectionFactory =
|
||||||
MobileConnectionRepositoryImpl.Factory(
|
MobileConnectionRepositoryImpl.Factory(
|
||||||
fakeBroadcastDispatcher,
|
fakeBroadcastDispatcher,
|
||||||
@@ -99,6 +108,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
logger = logger,
|
logger = logger,
|
||||||
mobileMappingsProxy = mobileMappings,
|
mobileMappingsProxy = mobileMappings,
|
||||||
scope = scope,
|
scope = scope,
|
||||||
|
logFactory = logBufferFactory,
|
||||||
)
|
)
|
||||||
|
|
||||||
underTest =
|
underTest =
|
||||||
@@ -270,6 +280,32 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `connection repository - log buffer contains sub id in its name`() =
|
||||||
|
runBlocking(IMMEDIATE) {
|
||||||
|
val job = underTest.subscriptions.launchIn(this)
|
||||||
|
|
||||||
|
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||||
|
.thenReturn(listOf(SUB_1, SUB_2))
|
||||||
|
getSubscriptionCallback().onSubscriptionsChanged()
|
||||||
|
|
||||||
|
// Get repos to trigger creation
|
||||||
|
underTest.getRepoForSubId(SUB_1_ID)
|
||||||
|
verify(logBufferFactory)
|
||||||
|
.create(
|
||||||
|
eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_1_ID)),
|
||||||
|
anyInt(),
|
||||||
|
)
|
||||||
|
underTest.getRepoForSubId(SUB_2_ID)
|
||||||
|
verify(logBufferFactory)
|
||||||
|
.create(
|
||||||
|
eq(MobileConnectionRepositoryImpl.tableBufferLogName(SUB_2_ID)),
|
||||||
|
anyInt(),
|
||||||
|
)
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDefaultDataSubId_updatesOnBroadcast() =
|
fun testDefaultDataSubId_updatesOnBroadcast() =
|
||||||
runBlocking(IMMEDIATE) {
|
runBlocking(IMMEDIATE) {
|
||||||
|
|||||||
@@ -19,11 +19,14 @@ package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
|||||||
import android.telephony.CellSignalStrength
|
import android.telephony.CellSignalStrength
|
||||||
import com.android.settingslib.SignalIcon
|
import com.android.settingslib.SignalIcon
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
class FakeMobileIconInteractor : MobileIconInteractor {
|
class FakeMobileIconInteractor(
|
||||||
|
override val tableLogBuffer: TableLogBuffer,
|
||||||
|
) : MobileIconInteractor {
|
||||||
override val alwaysShowDataRatIcon = MutableStateFlow(false)
|
override val alwaysShowDataRatIcon = MutableStateFlow(false)
|
||||||
|
|
||||||
override val activity =
|
override val activity =
|
||||||
|
|||||||
@@ -22,12 +22,15 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
|
|||||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UMTS
|
import android.telephony.TelephonyManager.NETWORK_TYPE_UMTS
|
||||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
|
||||||
class FakeMobileIconsInteractor(mobileMappings: MobileMappingsProxy) : MobileIconsInteractor {
|
class FakeMobileIconsInteractor(
|
||||||
|
mobileMappings: MobileMappingsProxy,
|
||||||
|
val tableLogBuffer: TableLogBuffer,
|
||||||
|
) : MobileIconsInteractor {
|
||||||
val THREE_G_KEY = mobileMappings.toIconKey(THREE_G)
|
val THREE_G_KEY = mobileMappings.toIconKey(THREE_G)
|
||||||
val LTE_KEY = mobileMappings.toIconKey(LTE)
|
val LTE_KEY = mobileMappings.toIconKey(LTE)
|
||||||
val FOUR_G_KEY = mobileMappings.toIconKey(FOUR_G)
|
val FOUR_G_KEY = mobileMappings.toIconKey(FOUR_G)
|
||||||
@@ -48,8 +51,7 @@ class FakeMobileIconsInteractor(mobileMappings: MobileMappingsProxy) : MobileIco
|
|||||||
|
|
||||||
override val isDefaultConnectionFailed = MutableStateFlow(false)
|
override val isDefaultConnectionFailed = MutableStateFlow(false)
|
||||||
|
|
||||||
private val _filteredSubscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
override val filteredSubscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
||||||
override val filteredSubscriptions: Flow<List<SubscriptionModel>> = _filteredSubscriptions
|
|
||||||
|
|
||||||
private val _activeDataConnectionHasDataEnabled = MutableStateFlow(false)
|
private val _activeDataConnectionHasDataEnabled = MutableStateFlow(false)
|
||||||
override val activeDataConnectionHasDataEnabled = _activeDataConnectionHasDataEnabled
|
override val activeDataConnectionHasDataEnabled = _activeDataConnectionHasDataEnabled
|
||||||
@@ -67,7 +69,7 @@ class FakeMobileIconsInteractor(mobileMappings: MobileMappingsProxy) : MobileIco
|
|||||||
|
|
||||||
/** Always returns a new fake interactor */
|
/** Always returns a new fake interactor */
|
||||||
override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor {
|
override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor {
|
||||||
return FakeMobileIconInteractor()
|
return FakeMobileIconInteractor(tableLogBuffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -49,8 +49,8 @@ import org.junit.Test
|
|||||||
class MobileIconInteractorTest : SysuiTestCase() {
|
class MobileIconInteractorTest : SysuiTestCase() {
|
||||||
private lateinit var underTest: MobileIconInteractor
|
private lateinit var underTest: MobileIconInteractor
|
||||||
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
||||||
private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy)
|
private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy, mock())
|
||||||
private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID)
|
private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID, mock())
|
||||||
|
|
||||||
private val scope = CoroutineScope(IMMEDIATE)
|
private val scope = CoroutineScope(IMMEDIATE)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
|||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
import com.android.settingslib.mobile.MobileMappings
|
import com.android.settingslib.mobile.MobileMappings
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
|
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
|
||||||
@@ -28,6 +29,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSe
|
|||||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||||
import com.android.systemui.util.CarrierConfigTracker
|
import com.android.systemui.util.CarrierConfigTracker
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
|
import com.android.systemui.util.time.FakeSystemClock
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -44,9 +46,9 @@ import org.mockito.MockitoAnnotations
|
|||||||
@SmallTest
|
@SmallTest
|
||||||
class MobileIconsInteractorTest : SysuiTestCase() {
|
class MobileIconsInteractorTest : SysuiTestCase() {
|
||||||
private lateinit var underTest: MobileIconsInteractor
|
private lateinit var underTest: MobileIconsInteractor
|
||||||
|
private lateinit var connectionsRepository: FakeMobileConnectionsRepository
|
||||||
private val userSetupRepository = FakeUserSetupRepository()
|
private val userSetupRepository = FakeUserSetupRepository()
|
||||||
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
||||||
private val connectionsRepository = FakeMobileConnectionsRepository(mobileMappingsProxy)
|
|
||||||
private val scope = CoroutineScope(IMMEDIATE)
|
private val scope = CoroutineScope(IMMEDIATE)
|
||||||
|
|
||||||
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
|
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
|
||||||
@@ -55,6 +57,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
|||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
connectionsRepository = FakeMobileConnectionsRepository(mobileMappingsProxy, tableLogBuffer)
|
||||||
connectionsRepository.setMobileConnectionRepositoryMap(
|
connectionsRepository.setMobileConnectionRepositoryMap(
|
||||||
mapOf(
|
mapOf(
|
||||||
SUB_1_ID to CONNECTION_1,
|
SUB_1_ID to CONNECTION_1,
|
||||||
@@ -290,21 +293,23 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||||
|
private val tableLogBuffer =
|
||||||
|
TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())
|
||||||
|
|
||||||
private const val SUB_1_ID = 1
|
private const val SUB_1_ID = 1
|
||||||
private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
|
private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
|
||||||
private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID)
|
private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer)
|
||||||
|
|
||||||
private const val SUB_2_ID = 2
|
private const val SUB_2_ID = 2
|
||||||
private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
|
private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
|
||||||
private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID)
|
private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID, tableLogBuffer)
|
||||||
|
|
||||||
private const val SUB_3_ID = 3
|
private const val SUB_3_ID = 3
|
||||||
private val SUB_3_OPP = SubscriptionModel(subscriptionId = SUB_3_ID, isOpportunistic = true)
|
private val SUB_3_OPP = SubscriptionModel(subscriptionId = SUB_3_ID, isOpportunistic = true)
|
||||||
private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID)
|
private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID, tableLogBuffer)
|
||||||
|
|
||||||
private const val SUB_4_ID = 4
|
private const val SUB_4_ID = 4
|
||||||
private val SUB_4_OPP = SubscriptionModel(subscriptionId = SUB_4_ID, isOpportunistic = true)
|
private val SUB_4_OPP = SubscriptionModel(subscriptionId = SUB_4_ID, isOpportunistic = true)
|
||||||
private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID)
|
private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID, tableLogBuffer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@SmallTest
|
||||||
|
class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
|
||||||
|
private lateinit var commonImpl: MobileIconViewModelCommon
|
||||||
|
private lateinit var homeIcon: HomeMobileIconViewModel
|
||||||
|
private lateinit var qsIcon: QsMobileIconViewModel
|
||||||
|
private lateinit var keyguardIcon: KeyguardMobileIconViewModel
|
||||||
|
private lateinit var interactor: FakeMobileIconInteractor
|
||||||
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
@Mock private lateinit var constants: ConnectivityConstants
|
||||||
|
@Mock private lateinit var tableLogBuffer: TableLogBuffer
|
||||||
|
|
||||||
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
interactor = FakeMobileIconInteractor(tableLogBuffer)
|
||||||
|
interactor.apply {
|
||||||
|
setLevel(1)
|
||||||
|
setIsDefaultDataEnabled(true)
|
||||||
|
setIsFailedConnection(false)
|
||||||
|
setIconGroup(TelephonyIcons.THREE_G)
|
||||||
|
setIsEmergencyOnly(false)
|
||||||
|
setNumberOfLevels(4)
|
||||||
|
isDataConnected.value = true
|
||||||
|
}
|
||||||
|
commonImpl =
|
||||||
|
MobileIconViewModel(SUB_1_ID, interactor, logger, constants, testScope.backgroundScope)
|
||||||
|
|
||||||
|
homeIcon = HomeMobileIconViewModel(commonImpl, logger)
|
||||||
|
qsIcon = QsMobileIconViewModel(commonImpl, logger)
|
||||||
|
keyguardIcon = KeyguardMobileIconViewModel(commonImpl, logger)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `location based view models receive same icon id when common impl updates`() =
|
||||||
|
testScope.runTest {
|
||||||
|
var latestHome: Int? = null
|
||||||
|
val homeJob = homeIcon.iconId.onEach { latestHome = it }.launchIn(this)
|
||||||
|
|
||||||
|
var latestQs: Int? = null
|
||||||
|
val qsJob = qsIcon.iconId.onEach { latestQs = it }.launchIn(this)
|
||||||
|
|
||||||
|
var latestKeyguard: Int? = null
|
||||||
|
val keyguardJob = keyguardIcon.iconId.onEach { latestKeyguard = it }.launchIn(this)
|
||||||
|
|
||||||
|
var expected = defaultSignal(level = 1)
|
||||||
|
|
||||||
|
assertThat(latestHome).isEqualTo(expected)
|
||||||
|
assertThat(latestQs).isEqualTo(expected)
|
||||||
|
assertThat(latestKeyguard).isEqualTo(expected)
|
||||||
|
|
||||||
|
interactor.setLevel(2)
|
||||||
|
expected = defaultSignal(level = 2)
|
||||||
|
|
||||||
|
assertThat(latestHome).isEqualTo(expected)
|
||||||
|
assertThat(latestQs).isEqualTo(expected)
|
||||||
|
assertThat(latestKeyguard).isEqualTo(expected)
|
||||||
|
|
||||||
|
homeJob.cancel()
|
||||||
|
qsJob.cancel()
|
||||||
|
keyguardJob.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val SUB_1_ID = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,32 +22,42 @@ import com.android.settingslib.mobile.TelephonyIcons.THREE_G
|
|||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.common.shared.model.ContentDescription
|
import com.android.systemui.common.shared.model.ContentDescription
|
||||||
import com.android.systemui.common.shared.model.Icon
|
import com.android.systemui.common.shared.model.Icon
|
||||||
|
import com.android.systemui.log.table.TableLogBuffer
|
||||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||||
import com.android.systemui.util.mockito.whenever
|
import com.android.systemui.util.mockito.whenever
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.coroutines.yield
|
import kotlinx.coroutines.yield
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
class MobileIconViewModelTest : SysuiTestCase() {
|
class MobileIconViewModelTest : SysuiTestCase() {
|
||||||
private lateinit var underTest: MobileIconViewModel
|
private lateinit var underTest: MobileIconViewModel
|
||||||
private val interactor = FakeMobileIconInteractor()
|
private lateinit var interactor: FakeMobileIconInteractor
|
||||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
@Mock private lateinit var constants: ConnectivityConstants
|
@Mock private lateinit var constants: ConnectivityConstants
|
||||||
|
@Mock private lateinit var tableLogBuffer: TableLogBuffer
|
||||||
|
|
||||||
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
|
interactor = FakeMobileIconInteractor(tableLogBuffer)
|
||||||
interactor.apply {
|
interactor.apply {
|
||||||
setLevel(1)
|
setLevel(1)
|
||||||
setIsDefaultDataEnabled(true)
|
setIsDefaultDataEnabled(true)
|
||||||
@@ -57,12 +67,13 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
setNumberOfLevels(4)
|
setNumberOfLevels(4)
|
||||||
isDataConnected.value = true
|
isDataConnected.value = true
|
||||||
}
|
}
|
||||||
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
|
underTest =
|
||||||
|
MobileIconViewModel(SUB_1_ID, interactor, logger, constants, testScope.backgroundScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun iconId_correctLevel_notCutout() =
|
fun iconId_correctLevel_notCutout() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
var latest: Int? = null
|
var latest: Int? = null
|
||||||
val job = underTest.iconId.onEach { latest = it }.launchIn(this)
|
val job = underTest.iconId.onEach { latest = it }.launchIn(this)
|
||||||
val expected = defaultSignal()
|
val expected = defaultSignal()
|
||||||
@@ -74,7 +85,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun iconId_cutout_whenDefaultDataDisabled() =
|
fun iconId_cutout_whenDefaultDataDisabled() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIsDefaultDataEnabled(false)
|
interactor.setIsDefaultDataEnabled(false)
|
||||||
|
|
||||||
var latest: Int? = null
|
var latest: Int? = null
|
||||||
@@ -88,7 +99,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_dataEnabled_groupIsRepresented() =
|
fun networkType_dataEnabled_groupIsRepresented() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
val expected =
|
val expected =
|
||||||
Icon.Resource(
|
Icon.Resource(
|
||||||
THREE_G.dataType,
|
THREE_G.dataType,
|
||||||
@@ -106,7 +117,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_nullWhenDisabled() =
|
fun networkType_nullWhenDisabled() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIconGroup(THREE_G)
|
interactor.setIconGroup(THREE_G)
|
||||||
interactor.setIsDataEnabled(false)
|
interactor.setIsDataEnabled(false)
|
||||||
var latest: Icon? = null
|
var latest: Icon? = null
|
||||||
@@ -119,7 +130,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_nullWhenFailedConnection() =
|
fun networkType_nullWhenFailedConnection() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIconGroup(THREE_G)
|
interactor.setIconGroup(THREE_G)
|
||||||
interactor.setIsDataEnabled(true)
|
interactor.setIsDataEnabled(true)
|
||||||
interactor.setIsFailedConnection(true)
|
interactor.setIsFailedConnection(true)
|
||||||
@@ -133,7 +144,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_nullWhenDataDisconnects() =
|
fun networkType_nullWhenDataDisconnects() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
val initial =
|
val initial =
|
||||||
Icon.Resource(
|
Icon.Resource(
|
||||||
THREE_G.dataType,
|
THREE_G.dataType,
|
||||||
@@ -157,7 +168,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_null_changeToDisabled() =
|
fun networkType_null_changeToDisabled() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
val expected =
|
val expected =
|
||||||
Icon.Resource(
|
Icon.Resource(
|
||||||
THREE_G.dataType,
|
THREE_G.dataType,
|
||||||
@@ -180,7 +191,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_alwaysShow_shownEvenWhenDisabled() =
|
fun networkType_alwaysShow_shownEvenWhenDisabled() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIconGroup(THREE_G)
|
interactor.setIconGroup(THREE_G)
|
||||||
interactor.setIsDataEnabled(true)
|
interactor.setIsDataEnabled(true)
|
||||||
interactor.alwaysShowDataRatIcon.value = true
|
interactor.alwaysShowDataRatIcon.value = true
|
||||||
@@ -200,7 +211,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_alwaysShow_shownEvenWhenDisconnected() =
|
fun networkType_alwaysShow_shownEvenWhenDisconnected() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIconGroup(THREE_G)
|
interactor.setIconGroup(THREE_G)
|
||||||
interactor.isDataConnected.value = false
|
interactor.isDataConnected.value = false
|
||||||
interactor.alwaysShowDataRatIcon.value = true
|
interactor.alwaysShowDataRatIcon.value = true
|
||||||
@@ -220,7 +231,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun networkType_alwaysShow_shownEvenWhenFailedConnection() =
|
fun networkType_alwaysShow_shownEvenWhenFailedConnection() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.setIconGroup(THREE_G)
|
interactor.setIconGroup(THREE_G)
|
||||||
interactor.setIsFailedConnection(true)
|
interactor.setIsFailedConnection(true)
|
||||||
interactor.alwaysShowDataRatIcon.value = true
|
interactor.alwaysShowDataRatIcon.value = true
|
||||||
@@ -240,7 +251,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun roaming() =
|
fun roaming() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
interactor.isRoaming.value = true
|
interactor.isRoaming.value = true
|
||||||
var latest: Boolean? = null
|
var latest: Boolean? = null
|
||||||
val job = underTest.roaming.onEach { latest = it }.launchIn(this)
|
val job = underTest.roaming.onEach { latest = it }.launchIn(this)
|
||||||
@@ -256,10 +267,17 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `data activity - null when config is off`() =
|
fun `data activity - null when config is off`() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
// Create a new view model here so the constants are properly read
|
// Create a new view model here so the constants are properly read
|
||||||
whenever(constants.shouldShowActivityConfig).thenReturn(false)
|
whenever(constants.shouldShowActivityConfig).thenReturn(false)
|
||||||
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
|
underTest =
|
||||||
|
MobileIconViewModel(
|
||||||
|
SUB_1_ID,
|
||||||
|
interactor,
|
||||||
|
logger,
|
||||||
|
constants,
|
||||||
|
testScope.backgroundScope,
|
||||||
|
)
|
||||||
|
|
||||||
var inVisible: Boolean? = null
|
var inVisible: Boolean? = null
|
||||||
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
|
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
|
||||||
@@ -288,10 +306,17 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `data activity - config on - test indicators`() =
|
fun `data activity - config on - test indicators`() =
|
||||||
runBlocking(IMMEDIATE) {
|
testScope.runTest {
|
||||||
// Create a new view model here so the constants are properly read
|
// Create a new view model here so the constants are properly read
|
||||||
whenever(constants.shouldShowActivityConfig).thenReturn(true)
|
whenever(constants.shouldShowActivityConfig).thenReturn(true)
|
||||||
underTest = MobileIconViewModel(SUB_1_ID, interactor, logger, constants)
|
underTest =
|
||||||
|
MobileIconViewModel(
|
||||||
|
SUB_1_ID,
|
||||||
|
interactor,
|
||||||
|
logger,
|
||||||
|
constants,
|
||||||
|
testScope.backgroundScope,
|
||||||
|
)
|
||||||
|
|
||||||
var inVisible: Boolean? = null
|
var inVisible: Boolean? = null
|
||||||
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
|
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
|
||||||
@@ -340,16 +365,15 @@ class MobileIconViewModelTest : SysuiTestCase() {
|
|||||||
containerJob.cancel()
|
containerJob.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Convenience constructor for these tests */
|
|
||||||
private fun defaultSignal(
|
|
||||||
level: Int = 1,
|
|
||||||
connected: Boolean = true,
|
|
||||||
): Int {
|
|
||||||
return SignalDrawable.getState(level, /* numLevels */ 4, !connected)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
|
||||||
private const val SUB_1_ID = 1
|
private const val SUB_1_ID = 1
|
||||||
|
|
||||||
|
/** Convenience constructor for these tests */
|
||||||
|
fun defaultSignal(
|
||||||
|
level: Int = 1,
|
||||||
|
connected: Boolean = true,
|
||||||
|
): Int {
|
||||||
|
return SignalDrawable.getState(level, /* numLevels */ 4, !connected)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2022 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||||
|
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||||
|
import com.android.systemui.util.mockito.mock
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@SmallTest
|
||||||
|
class MobileIconsViewModelTest : SysuiTestCase() {
|
||||||
|
private lateinit var underTest: MobileIconsViewModel
|
||||||
|
private val interactor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
|
||||||
|
|
||||||
|
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||||
|
@Mock private lateinit var constants: ConnectivityConstants
|
||||||
|
|
||||||
|
private val testDispatcher = UnconfinedTestDispatcher()
|
||||||
|
private val testScope = TestScope(testDispatcher)
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
|
||||||
|
val subscriptionIdsFlow =
|
||||||
|
interactor.filteredSubscriptions
|
||||||
|
.map { subs -> subs.map { it.subscriptionId } }
|
||||||
|
.stateIn(testScope.backgroundScope, SharingStarted.WhileSubscribed(), listOf())
|
||||||
|
|
||||||
|
underTest =
|
||||||
|
MobileIconsViewModel(
|
||||||
|
subscriptionIdsFlow,
|
||||||
|
interactor,
|
||||||
|
logger,
|
||||||
|
constants,
|
||||||
|
testScope.backgroundScope,
|
||||||
|
)
|
||||||
|
|
||||||
|
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `caching - mobile icon view model is reused for same sub id`() =
|
||||||
|
testScope.runTest {
|
||||||
|
val model1 = underTest.viewModelForSub(1, StatusBarLocation.HOME)
|
||||||
|
val model2 = underTest.viewModelForSub(1, StatusBarLocation.QS)
|
||||||
|
|
||||||
|
assertThat(model1.commonImpl).isSameInstanceAs(model2.commonImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `caching - invalid view models are removed from cache when sub disappears`() =
|
||||||
|
testScope.runTest {
|
||||||
|
// Retrieve models to trigger caching
|
||||||
|
val model1 = underTest.viewModelForSub(1, StatusBarLocation.HOME)
|
||||||
|
val model2 = underTest.viewModelForSub(2, StatusBarLocation.QS)
|
||||||
|
|
||||||
|
// Both impls are cached
|
||||||
|
assertThat(underTest.mobileIconSubIdCache)
|
||||||
|
.containsExactly(1, model1.commonImpl, 2, model2.commonImpl)
|
||||||
|
|
||||||
|
// SUB_1 is removed from the list...
|
||||||
|
interactor.filteredSubscriptions.value = listOf(SUB_2)
|
||||||
|
|
||||||
|
// ... and dropped from the cache
|
||||||
|
assertThat(underTest.mobileIconSubIdCache).containsExactly(2, model2.commonImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val SUB_1 = SubscriptionModel(subscriptionId = 1, isOpportunistic = false)
|
||||||
|
private val SUB_2 = SubscriptionModel(subscriptionId = 2, isOpportunistic = false)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -146,7 +146,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activity_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
fun activity_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(false)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activity_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) {
|
fun activity_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(false)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(false)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activity_nullSsid_outputsFalse() = runBlocking(IMMEDIATE) {
|
fun activity_nullSsid_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
|
|
||||||
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null))
|
wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, ssid = null))
|
||||||
@@ -268,7 +268,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activity_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) {
|
fun activity_allLocationViewModelsReceiveSameData() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -308,7 +308,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityIn_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
fun activityIn_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityIn_hasActivityInFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
fun activityIn_hasActivityInFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityOut_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
fun activityOut_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityOut_hasActivityOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
fun activityOut_hasActivityOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -396,7 +396,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityContainer_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
fun activityContainer_hasActivityInTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -418,7 +418,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityContainer_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
fun activityContainer_hasActivityOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityContainer_inAndOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
fun activityContainer_inAndOutTrue_outputsTrue() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
@@ -462,7 +462,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun activityContainer_inAndOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
fun activityContainer_inAndOutFalse_outputsFalse() = runBlocking(IMMEDIATE) {
|
||||||
whenever(wifiConstants.shouldShowActivityConfig).thenReturn(true)
|
whenever(connectivityConstants.shouldShowActivityConfig).thenReturn(true)
|
||||||
createAndSetViewModel()
|
createAndSetViewModel()
|
||||||
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user