Merge changes I4977aa47,I87686213,If4bd3e31,I727ad3ca,Ib02a1eb6 into tm-qpr-dev am: 18917a1820 am: e6a924a66d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20665129 Change-Id: Ia34e7515b0274e7fabb5168ce14aa4b44642ea91 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -40,6 +40,8 @@ import com.android.systemui.statusbar.StatusIconDisplayable;
|
||||
import com.android.systemui.statusbar.connectivity.ui.MobileContextProvider;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState;
|
||||
import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState;
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -50,20 +52,25 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
|
||||
private final LinearLayout mStatusIcons;
|
||||
private final ArrayList<StatusBarMobileView> mMobileViews = new ArrayList<>();
|
||||
private final ArrayList<ModernStatusBarMobileView> mModernMobileViews = new ArrayList<>();
|
||||
private final int mIconSize;
|
||||
|
||||
private StatusBarWifiView mWifiView;
|
||||
private boolean mDemoMode;
|
||||
private int mColor;
|
||||
|
||||
private final MobileIconsViewModel mMobileIconsViewModel;
|
||||
|
||||
public DemoStatusIcons(
|
||||
LinearLayout statusIcons,
|
||||
MobileIconsViewModel mobileIconsViewModel,
|
||||
int iconSize
|
||||
) {
|
||||
super(statusIcons.getContext());
|
||||
mStatusIcons = statusIcons;
|
||||
mIconSize = iconSize;
|
||||
mColor = DarkIconDispatcher.DEFAULT_ICON_TINT;
|
||||
mMobileIconsViewModel = mobileIconsViewModel;
|
||||
|
||||
if (statusIcons instanceof StatusIconContainer) {
|
||||
setShouldRestrictIcons(((StatusIconContainer) statusIcons).isRestrictingIcons());
|
||||
@@ -71,7 +78,7 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
setShouldRestrictIcons(false);
|
||||
}
|
||||
setLayoutParams(mStatusIcons.getLayoutParams());
|
||||
setPadding(mStatusIcons.getPaddingLeft(),mStatusIcons.getPaddingTop(),
|
||||
setPadding(mStatusIcons.getPaddingLeft(), mStatusIcons.getPaddingTop(),
|
||||
mStatusIcons.getPaddingRight(), mStatusIcons.getPaddingBottom());
|
||||
setOrientation(mStatusIcons.getOrientation());
|
||||
setGravity(Gravity.CENTER_VERTICAL); // no LL.getGravity()
|
||||
@@ -115,6 +122,8 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
public void onDemoModeFinished() {
|
||||
mDemoMode = false;
|
||||
mStatusIcons.setVisibility(View.VISIBLE);
|
||||
mModernMobileViews.clear();
|
||||
mMobileViews.clear();
|
||||
setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -268,6 +277,24 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
addView(view, getChildCount(), createLayoutParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a {@link ModernStatusBarMobileView}
|
||||
* @param mobileContext possibly mcc/mnc overridden mobile context
|
||||
* @param subId the subscriptionId for this mobile view
|
||||
*/
|
||||
public void addModernMobileView(Context mobileContext, int subId) {
|
||||
Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
|
||||
ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
|
||||
mobileContext,
|
||||
"mobile",
|
||||
mMobileIconsViewModel.viewModelForSub(subId)
|
||||
);
|
||||
|
||||
// mobile always goes at the end
|
||||
mModernMobileViews.add(view);
|
||||
addView(view, getChildCount(), createLayoutParams());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply an update to a mobile icon view for the given {@link MobileIconState}. For
|
||||
* compatibility with {@link MobileContextProvider}, we have to recreate the view every time we
|
||||
@@ -292,12 +319,19 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
if (view.getSlot().equals("wifi")) {
|
||||
removeView(mWifiView);
|
||||
mWifiView = null;
|
||||
} else {
|
||||
} else if (view instanceof StatusBarMobileView) {
|
||||
StatusBarMobileView mobileView = matchingMobileView(view);
|
||||
if (mobileView != null) {
|
||||
removeView(mobileView);
|
||||
mMobileViews.remove(mobileView);
|
||||
}
|
||||
} else if (view instanceof ModernStatusBarMobileView) {
|
||||
ModernStatusBarMobileView mobileView = matchingModernMobileView(
|
||||
(ModernStatusBarMobileView) view);
|
||||
if (mobileView != null) {
|
||||
removeView(mobileView);
|
||||
mModernMobileViews.remove(mobileView);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,6 +350,16 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
|
||||
return null;
|
||||
}
|
||||
|
||||
private ModernStatusBarMobileView matchingModernMobileView(ModernStatusBarMobileView other) {
|
||||
for (ModernStatusBarMobileView v : mModernMobileViews) {
|
||||
if (v.getSubId() == other.getSubId()) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private LayoutParams createLayoutParams() {
|
||||
return new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, mIconSize);
|
||||
}
|
||||
|
||||
@@ -536,8 +536,7 @@ public interface StatusBarIconController {
|
||||
mGroup.addView(view, index, onCreateLayoutParams());
|
||||
|
||||
if (mIsInDemoMode) {
|
||||
// TODO (b/249790009): demo mode should be handled at the data layer in the
|
||||
// new pipeline
|
||||
mDemoStatusIcons.addModernMobileView(mContext, subId);
|
||||
}
|
||||
|
||||
return view;
|
||||
@@ -565,11 +564,13 @@ public interface StatusBarIconController {
|
||||
|
||||
private ModernStatusBarMobileView onCreateModernStatusBarMobileView(
|
||||
String slot, int subId) {
|
||||
Context mobileContext = mMobileContextProvider.getMobileContextForSub(subId, mContext);
|
||||
return ModernStatusBarMobileView
|
||||
.constructAndBind(
|
||||
mContext,
|
||||
mobileContext,
|
||||
slot,
|
||||
mMobileIconsViewModel.viewModelForSub(subId));
|
||||
mMobileIconsViewModel.viewModelForSub(subId)
|
||||
);
|
||||
}
|
||||
|
||||
protected LinearLayout.LayoutParams onCreateLayoutParams() {
|
||||
@@ -704,7 +705,7 @@ public interface StatusBarIconController {
|
||||
}
|
||||
|
||||
protected DemoStatusIcons createDemoStatusIcons() {
|
||||
return new DemoStatusIcons((LinearLayout) mGroup, mIconSize);
|
||||
return new DemoStatusIcons((LinearLayout) mGroup, mMobileIconsViewModel, mIconSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,6 +276,11 @@ public class StatusBarIconControllerImpl implements Tunable,
|
||||
String slotName = mContext.getString(com.android.internal.R.string.status_bar_mobile);
|
||||
Slot mobileSlot = mStatusBarIconList.getSlot(slotName);
|
||||
|
||||
// Because of the way we cache the icon holders, we need to remove everything any time
|
||||
// we get a new set of subscriptions. This might change in the future, but is required
|
||||
// to support demo mode for now
|
||||
removeAllIconsForSlot(slotName);
|
||||
|
||||
Collections.reverse(subIds);
|
||||
|
||||
for (Integer subId : subIds) {
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.telephony.TelephonyCallback.ServiceStateListener
|
||||
import android.telephony.TelephonyCallback.SignalStrengthsListener
|
||||
import android.telephony.TelephonyDisplayInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Disconnected
|
||||
|
||||
/**
|
||||
@@ -39,7 +38,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionS
|
||||
* any new field that needs to be tracked should be copied into this data class rather than
|
||||
* threading complex system objects through the pipeline.
|
||||
*/
|
||||
data class MobileSubscriptionModel(
|
||||
data class MobileConnectionModel(
|
||||
/** From [ServiceStateListener.onServiceStateChanged] */
|
||||
val isEmergencyOnly: Boolean = false,
|
||||
|
||||
@@ -65,5 +64,5 @@ data class MobileSubscriptionModel(
|
||||
* [resolvedNetworkType] is the [TelephonyDisplayInfo.getOverrideNetworkType] if it exists or
|
||||
* [TelephonyDisplayInfo.getNetworkType]. This is used to look up the proper network type icon
|
||||
*/
|
||||
val resolvedNetworkType: ResolvedNetworkType = DefaultNetworkType(NETWORK_TYPE_UNKNOWN),
|
||||
val resolvedNetworkType: ResolvedNetworkType = ResolvedNetworkType.UnknownNetworkType,
|
||||
)
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.model
|
||||
|
||||
import android.telephony.Annotation.NetworkType
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
|
||||
/**
|
||||
@@ -26,8 +27,20 @@ import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
*/
|
||||
sealed interface ResolvedNetworkType {
|
||||
@NetworkType val type: Int
|
||||
val lookupKey: String
|
||||
|
||||
object UnknownNetworkType : ResolvedNetworkType {
|
||||
override val type: Int = NETWORK_TYPE_UNKNOWN
|
||||
override val lookupKey: String = "unknown"
|
||||
}
|
||||
|
||||
data class DefaultNetworkType(
|
||||
@NetworkType override val type: Int,
|
||||
override val lookupKey: String,
|
||||
) : ResolvedNetworkType
|
||||
|
||||
data class OverrideNetworkType(
|
||||
@NetworkType override val type: Int,
|
||||
override val lookupKey: String,
|
||||
) : ResolvedNetworkType
|
||||
}
|
||||
|
||||
data class DefaultNetworkType(@NetworkType override val type: Int) : ResolvedNetworkType
|
||||
|
||||
data class OverrideNetworkType(@NetworkType override val type: Int) : ResolvedNetworkType
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SystemUI representation of [SubscriptionInfo]. Currently we only use two fields on the
|
||||
* subscriptions themselves: subscriptionId and isOpportunistic. Any new fields that we need can be
|
||||
* added below and provided in the repository classes
|
||||
*/
|
||||
data class SubscriptionModel(
|
||||
val subscriptionId: Int,
|
||||
/**
|
||||
* True if the subscription that this model represents has [SubscriptionInfo.isOpportunistic].
|
||||
* Opportunistic networks are networks with limited coverage, and we use this bit to determine
|
||||
* filtering in certain cases. See [MobileIconsInteractor] for the filtering logic
|
||||
*/
|
||||
val isOpportunistic: Boolean = false,
|
||||
)
|
||||
@@ -20,7 +20,7 @@ import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.telephony.TelephonyCallback
|
||||
import android.telephony.TelephonyManager
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
@@ -36,11 +36,13 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
* eventually becomes a single icon in the status bar.
|
||||
*/
|
||||
interface MobileConnectionRepository {
|
||||
/** The subscriptionId that this connection represents */
|
||||
val subId: Int
|
||||
/**
|
||||
* A flow that aggregates all necessary callbacks from [TelephonyCallback] into a single
|
||||
* listener + model.
|
||||
*/
|
||||
val subscriptionModelFlow: Flow<MobileSubscriptionModel>
|
||||
val connectionInfo: Flow<MobileConnectionModel>
|
||||
/** Observable tracking [TelephonyManager.isDataConnectionAllowed] */
|
||||
val dataEnabled: StateFlow<Boolean>
|
||||
/**
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||
|
||||
import android.provider.Settings
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import com.android.settingslib.mobile.MobileMappings
|
||||
import com.android.settingslib.mobile.MobileMappings.Config
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
@@ -31,14 +30,11 @@ import kotlinx.coroutines.flow.StateFlow
|
||||
*/
|
||||
interface MobileConnectionsRepository {
|
||||
/** Observable list of current mobile subscriptions */
|
||||
val subscriptionsFlow: Flow<List<SubscriptionInfo>>
|
||||
val subscriptions: StateFlow<List<SubscriptionModel>>
|
||||
|
||||
/** Observable for the subscriptionId of the current mobile data connection */
|
||||
val activeMobileDataSubscriptionId: StateFlow<Int>
|
||||
|
||||
/** Observable for [MobileMappings.Config] tracking the defaults */
|
||||
val defaultDataSubRatConfig: StateFlow<Config>
|
||||
|
||||
/** Tracks [SubscriptionManager.getDefaultDataSubscriptionId] */
|
||||
val defaultDataSubId: StateFlow<Int>
|
||||
|
||||
@@ -50,4 +46,10 @@ interface MobileConnectionsRepository {
|
||||
|
||||
/** Observe changes to the [Settings.Global.MOBILE_DATA] setting */
|
||||
val globalMobileDataSettingChangedEvent: Flow<Unit>
|
||||
|
||||
/** The icon mapping from network type to [MobileIconGroup] for the default subscription */
|
||||
val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>>
|
||||
|
||||
/** Fallback [MobileIconGroup] in the case where there is no icon in the mapping */
|
||||
val defaultMobileIconGroup: Flow<MobileIconGroup>
|
||||
}
|
||||
|
||||
@@ -17,14 +17,14 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||
|
||||
import android.os.Bundle
|
||||
import android.telephony.SubscriptionInfo
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.settingslib.mobile.MobileMappings
|
||||
import com.android.settingslib.SignalIcon
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.demomode.DemoMode
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
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.repository.demo.DemoMobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
|
||||
import javax.inject.Inject
|
||||
@@ -109,14 +109,10 @@ constructor(
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realRepository)
|
||||
|
||||
override val subscriptionsFlow: StateFlow<List<SubscriptionInfo>> =
|
||||
override val subscriptions: StateFlow<List<SubscriptionModel>> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.subscriptionsFlow }
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
realRepository.subscriptionsFlow.value
|
||||
)
|
||||
.flatMapLatest { it.subscriptions }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), realRepository.subscriptions.value)
|
||||
|
||||
override val activeMobileDataSubscriptionId: StateFlow<Int> =
|
||||
activeRepo
|
||||
@@ -127,14 +123,11 @@ constructor(
|
||||
realRepository.activeMobileDataSubscriptionId.value
|
||||
)
|
||||
|
||||
override val defaultDataSubRatConfig: StateFlow<MobileMappings.Config> =
|
||||
activeRepo
|
||||
.flatMapLatest { it.defaultDataSubRatConfig }
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
realRepository.defaultDataSubRatConfig.value
|
||||
)
|
||||
override val defaultMobileIconMapping: Flow<Map<String, SignalIcon.MobileIconGroup>> =
|
||||
activeRepo.flatMapLatest { it.defaultMobileIconMapping }
|
||||
|
||||
override val defaultMobileIconGroup: Flow<SignalIcon.MobileIconGroup> =
|
||||
activeRepo.flatMapLatest { it.defaultMobileIconGroup }
|
||||
|
||||
override val defaultDataSubId: StateFlow<Int> =
|
||||
activeRepo
|
||||
|
||||
@@ -17,26 +17,18 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
|
||||
|
||||
import android.content.Context
|
||||
import android.telephony.Annotation
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_GSM
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_NR
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UMTS
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import android.util.Log
|
||||
import com.android.settingslib.SignalIcon
|
||||
import com.android.settingslib.mobile.MobileMappings
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
|
||||
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.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
|
||||
@@ -49,7 +41,9 @@ import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
@@ -67,61 +61,40 @@ constructor(
|
||||
|
||||
private var demoCommandJob: Job? = null
|
||||
|
||||
private val connectionRepoCache = mutableMapOf<Int, DemoMobileConnectionRepository>()
|
||||
private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionInfo>()
|
||||
private var connectionRepoCache = mutableMapOf<Int, DemoMobileConnectionRepository>()
|
||||
private val subscriptionInfoCache = mutableMapOf<Int, SubscriptionModel>()
|
||||
val demoModeFinishedEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||
|
||||
private val _subscriptions = MutableStateFlow<List<SubscriptionInfo>>(listOf())
|
||||
override val subscriptionsFlow =
|
||||
private val _subscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
||||
override val subscriptions =
|
||||
_subscriptions
|
||||
.onEach { infos -> dropUnusedReposFromCache(infos) }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), _subscriptions.value)
|
||||
|
||||
private fun dropUnusedReposFromCache(newInfos: List<SubscriptionInfo>) {
|
||||
private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
|
||||
// Remove any connection repository from the cache that isn't in the new set of IDs. They
|
||||
// will get garbage collected once their subscribers go away
|
||||
val currentValidSubscriptionIds = newInfos.map { it.subscriptionId }
|
||||
|
||||
connectionRepoCache.keys.forEach {
|
||||
if (!currentValidSubscriptionIds.contains(it)) {
|
||||
connectionRepoCache.remove(it)
|
||||
}
|
||||
}
|
||||
connectionRepoCache =
|
||||
connectionRepoCache
|
||||
.filter { currentValidSubscriptionIds.contains(it.key) }
|
||||
.toMutableMap()
|
||||
}
|
||||
|
||||
private fun maybeCreateSubscription(subId: Int) {
|
||||
if (!subscriptionInfoCache.containsKey(subId)) {
|
||||
createSubscriptionForSubId(subId, subId).also { subscriptionInfoCache[subId] = it }
|
||||
SubscriptionModel(subscriptionId = subId, isOpportunistic = false).also {
|
||||
subscriptionInfoCache[subId] = it
|
||||
}
|
||||
|
||||
_subscriptions.value = subscriptionInfoCache.values.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/** Mimics the old NetworkControllerImpl for now */
|
||||
private fun createSubscriptionForSubId(subId: Int, slotIndex: Int): SubscriptionInfo {
|
||||
return SubscriptionInfo(
|
||||
subId,
|
||||
"",
|
||||
slotIndex,
|
||||
"",
|
||||
"",
|
||||
0,
|
||||
0,
|
||||
"",
|
||||
0,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
"",
|
||||
false,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO(b/261029387): add a command for this value
|
||||
override val activeMobileDataSubscriptionId =
|
||||
subscriptionsFlow
|
||||
subscriptions
|
||||
.mapLatest { infos ->
|
||||
// For now, active is just the first in the list
|
||||
infos.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
|
||||
@@ -129,12 +102,35 @@ constructor(
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
subscriptionsFlow.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
|
||||
subscriptions.value.firstOrNull()?.subscriptionId ?: INVALID_SUBSCRIPTION_ID
|
||||
)
|
||||
|
||||
/** Demo mode doesn't currently support modifications to the mobile mappings */
|
||||
override val defaultDataSubRatConfig =
|
||||
MutableStateFlow(MobileMappings.Config.readConfig(context))
|
||||
val defaultDataSubRatConfig = MutableStateFlow(MobileMappings.Config.readConfig(context))
|
||||
|
||||
override val defaultMobileIconGroup = flowOf(TelephonyIcons.THREE_G)
|
||||
|
||||
override val defaultMobileIconMapping = MutableStateFlow(TelephonyIcons.ICON_NAME_TO_ICON)
|
||||
|
||||
/**
|
||||
* In order to maintain compatibility with the old demo mode shell command API, reverse the
|
||||
* [MobileMappings] lookup from (NetworkType: String -> Icon: MobileIconGroup), so that we can
|
||||
* parse the string from the command line into a preferred icon group, and send _a_ valid
|
||||
* network type for that icon through the pipeline.
|
||||
*
|
||||
* Note: collisions don't matter here, because the data source (the command line) only cares
|
||||
* about the resulting icon, not the underlying network type.
|
||||
*/
|
||||
private val mobileMappingsReverseLookup: StateFlow<Map<SignalIcon.MobileIconGroup, String>> =
|
||||
defaultMobileIconMapping
|
||||
.mapLatest { networkToIconMap -> networkToIconMap.reverse() }
|
||||
.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
defaultMobileIconMapping.value.reverse()
|
||||
)
|
||||
|
||||
private fun <K, V> Map<K, V>.reverse() = entries.associateBy({ it.value }) { it.key }
|
||||
|
||||
// TODO(b/261029387): add a command for this value
|
||||
override val defaultDataSubId =
|
||||
@@ -189,7 +185,7 @@ constructor(
|
||||
connection.dataEnabled.value = true
|
||||
connection.isDefaultDataSubscription.value = state.dataType != null
|
||||
|
||||
connection.subscriptionModelFlow.value = state.toMobileSubscriptionModel()
|
||||
connection.connectionInfo.value = state.toMobileConnectionModel()
|
||||
}
|
||||
|
||||
private fun processDisabledMobileState(state: MobileDisabled) {
|
||||
@@ -229,47 +225,36 @@ constructor(
|
||||
private fun subIdsString(): String =
|
||||
_subscriptions.value.joinToString(",") { it.subscriptionId.toString() }
|
||||
|
||||
private fun Mobile.toMobileConnectionModel(): MobileConnectionModel {
|
||||
return MobileConnectionModel(
|
||||
isEmergencyOnly = false, // TODO(b/261029387): not yet supported
|
||||
isGsm = false, // TODO(b/261029387): not yet supported
|
||||
cdmaLevel = level ?: 0,
|
||||
primaryLevel = level ?: 0,
|
||||
dataConnectionState =
|
||||
DataConnectionState.Connected, // TODO(b/261029387): not yet supported
|
||||
dataActivityDirection = activity,
|
||||
carrierNetworkChangeActive = carrierNetworkChange,
|
||||
resolvedNetworkType = dataType.toResolvedNetworkType()
|
||||
)
|
||||
}
|
||||
|
||||
private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType {
|
||||
val key = mobileMappingsReverseLookup.value[this] ?: "dis"
|
||||
return DefaultNetworkType(DEMO_NET_TYPE, key)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "DemoMobileConnectionsRepo"
|
||||
|
||||
private const val DEFAULT_SUB_ID = 1
|
||||
|
||||
private const val DEMO_NET_TYPE = 1234
|
||||
}
|
||||
}
|
||||
|
||||
private fun Mobile.toMobileSubscriptionModel(): MobileSubscriptionModel {
|
||||
return MobileSubscriptionModel(
|
||||
isEmergencyOnly = false, // TODO(b/261029387): not yet supported
|
||||
isGsm = false, // TODO(b/261029387): not yet supported
|
||||
cdmaLevel = level ?: 0,
|
||||
primaryLevel = level ?: 0,
|
||||
dataConnectionState = DataConnectionState.Connected, // TODO(b/261029387): not yet supported
|
||||
dataActivityDirection = activity,
|
||||
carrierNetworkChangeActive = carrierNetworkChange,
|
||||
// TODO(b/261185097): once mobile mappings can be mocked at this layer, we can build our
|
||||
// own demo map
|
||||
resolvedNetworkType = dataType.toResolvedNetworkType()
|
||||
)
|
||||
}
|
||||
|
||||
@Annotation.NetworkType
|
||||
private fun SignalIcon.MobileIconGroup?.toNetworkType(): Int =
|
||||
when (this) {
|
||||
TelephonyIcons.THREE_G -> NETWORK_TYPE_GSM
|
||||
TelephonyIcons.LTE -> NETWORK_TYPE_LTE
|
||||
TelephonyIcons.FOUR_G -> NETWORK_TYPE_UMTS
|
||||
TelephonyIcons.NR_5G -> NETWORK_TYPE_NR
|
||||
TelephonyIcons.NR_5G_PLUS -> OVERRIDE_NETWORK_TYPE_NR_ADVANCED
|
||||
else -> NETWORK_TYPE_UNKNOWN
|
||||
}
|
||||
|
||||
private fun SignalIcon.MobileIconGroup?.toResolvedNetworkType(): ResolvedNetworkType =
|
||||
when (this) {
|
||||
TelephonyIcons.NR_5G_PLUS -> OverrideNetworkType(toNetworkType())
|
||||
else -> DefaultNetworkType(toNetworkType())
|
||||
}
|
||||
|
||||
class DemoMobileConnectionRepository(val subId: Int) : MobileConnectionRepository {
|
||||
override val subscriptionModelFlow = MutableStateFlow(MobileSubscriptionModel())
|
||||
class DemoMobileConnectionRepository(override val subId: Int) : MobileConnectionRepository {
|
||||
override val connectionInfo = MutableStateFlow(MobileConnectionModel())
|
||||
|
||||
override val dataEnabled = MutableStateFlow(true)
|
||||
|
||||
|
||||
@@ -27,18 +27,20 @@ import android.telephony.TelephonyCallback
|
||||
import android.telephony.TelephonyDisplayInfo
|
||||
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
|
||||
import android.telephony.TelephonyManager
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.toDataConnectionType
|
||||
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.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logOutputChange
|
||||
import com.android.systemui.util.settings.GlobalSettings
|
||||
import java.lang.IllegalStateException
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -58,11 +60,12 @@ import kotlinx.coroutines.flow.stateIn
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class MobileConnectionRepositoryImpl(
|
||||
private val context: Context,
|
||||
private val subId: Int,
|
||||
override val subId: Int,
|
||||
private val telephonyManager: TelephonyManager,
|
||||
private val globalSettings: GlobalSettings,
|
||||
defaultDataSubId: StateFlow<Int>,
|
||||
globalMobileDataSettingChangedEvent: Flow<Unit>,
|
||||
mobileMappingsProxy: MobileMappingsProxy,
|
||||
bgDispatcher: CoroutineDispatcher,
|
||||
logger: ConnectivityPipelineLogger,
|
||||
scope: CoroutineScope,
|
||||
@@ -78,8 +81,8 @@ class MobileConnectionRepositoryImpl(
|
||||
|
||||
private val telephonyCallbackEvent = MutableSharedFlow<Unit>(extraBufferCapacity = 1)
|
||||
|
||||
override val subscriptionModelFlow: StateFlow<MobileSubscriptionModel> = run {
|
||||
var state = MobileSubscriptionModel()
|
||||
override val connectionInfo: StateFlow<MobileConnectionModel> = run {
|
||||
var state = MobileConnectionModel()
|
||||
conflatedCallbackFlow {
|
||||
// TODO (b/240569788): log all of these into the connectivity logger
|
||||
val callback =
|
||||
@@ -141,14 +144,27 @@ class MobileConnectionRepositoryImpl(
|
||||
override fun onDisplayInfoChanged(
|
||||
telephonyDisplayInfo: TelephonyDisplayInfo
|
||||
) {
|
||||
|
||||
val networkType =
|
||||
if (
|
||||
if (telephonyDisplayInfo.networkType == NETWORK_TYPE_UNKNOWN) {
|
||||
UnknownNetworkType
|
||||
} else if (
|
||||
telephonyDisplayInfo.overrideNetworkType ==
|
||||
OVERRIDE_NETWORK_TYPE_NONE
|
||||
) {
|
||||
DefaultNetworkType(telephonyDisplayInfo.networkType)
|
||||
DefaultNetworkType(
|
||||
telephonyDisplayInfo.networkType,
|
||||
mobileMappingsProxy.toIconKey(
|
||||
telephonyDisplayInfo.networkType
|
||||
)
|
||||
)
|
||||
} else {
|
||||
OverrideNetworkType(telephonyDisplayInfo.overrideNetworkType)
|
||||
OverrideNetworkType(
|
||||
telephonyDisplayInfo.overrideNetworkType,
|
||||
mobileMappingsProxy.toIconKeyOverride(
|
||||
telephonyDisplayInfo.overrideNetworkType
|
||||
)
|
||||
)
|
||||
}
|
||||
state = state.copy(resolvedNetworkType = networkType)
|
||||
trySend(state)
|
||||
@@ -211,6 +227,7 @@ class MobileConnectionRepositoryImpl(
|
||||
private val telephonyManager: TelephonyManager,
|
||||
private val logger: ConnectivityPipelineLogger,
|
||||
private val globalSettings: GlobalSettings,
|
||||
private val mobileMappingsProxy: MobileMappingsProxy,
|
||||
@Background private val bgDispatcher: CoroutineDispatcher,
|
||||
@Application private val scope: CoroutineScope,
|
||||
) {
|
||||
@@ -226,6 +243,7 @@ class MobileConnectionRepositoryImpl(
|
||||
globalSettings,
|
||||
defaultDataSubId,
|
||||
globalMobileDataSettingChangedEvent,
|
||||
mobileMappingsProxy,
|
||||
bgDispatcher,
|
||||
logger,
|
||||
scope,
|
||||
|
||||
@@ -36,6 +36,7 @@ import android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener
|
||||
import android.telephony.TelephonyManager
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.internal.telephony.PhoneConstants
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.settingslib.mobile.MobileMappings
|
||||
import com.android.settingslib.mobile.MobileMappings.Config
|
||||
import com.android.systemui.broadcast.BroadcastDispatcher
|
||||
@@ -44,8 +45,10 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.dagger.qualifiers.Background
|
||||
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.repository.MobileConnectionRepository
|
||||
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.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.util.settings.GlobalSettings
|
||||
import javax.inject.Inject
|
||||
@@ -59,6 +62,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@@ -75,6 +79,7 @@ constructor(
|
||||
private val subscriptionManager: SubscriptionManager,
|
||||
private val telephonyManager: TelephonyManager,
|
||||
private val logger: ConnectivityPipelineLogger,
|
||||
mobileMappingsProxy: MobileMappingsProxy,
|
||||
broadcastDispatcher: BroadcastDispatcher,
|
||||
private val globalSettings: GlobalSettings,
|
||||
private val context: Context,
|
||||
@@ -82,14 +87,14 @@ constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val mobileConnectionRepositoryFactory: MobileConnectionRepositoryImpl.Factory
|
||||
) : MobileConnectionsRepository {
|
||||
private val subIdRepositoryCache: MutableMap<Int, MobileConnectionRepository> = mutableMapOf()
|
||||
private var subIdRepositoryCache: MutableMap<Int, MobileConnectionRepository> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* State flow that emits the set of mobile data subscriptions, each represented by its own
|
||||
* [SubscriptionInfo]. We probably only need the [SubscriptionInfo.getSubscriptionId] of each
|
||||
* info object, but for now we keep track of the infos themselves.
|
||||
*/
|
||||
override val subscriptionsFlow: StateFlow<List<SubscriptionInfo>> =
|
||||
override val subscriptions: StateFlow<List<SubscriptionModel>> =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
object : SubscriptionManager.OnSubscriptionsChangedListener() {
|
||||
@@ -105,7 +110,7 @@ constructor(
|
||||
|
||||
awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(callback) }
|
||||
}
|
||||
.mapLatest { fetchSubscriptionsList() }
|
||||
.mapLatest { fetchSubscriptionsList().map { it.toSubscriptionModel() } }
|
||||
.onEach { infos -> dropUnusedReposFromCache(infos) }
|
||||
.stateIn(scope, started = SharingStarted.WhileSubscribed(), listOf())
|
||||
|
||||
@@ -157,7 +162,7 @@ constructor(
|
||||
*
|
||||
* This flow will produce whenever the default data subscription or the carrier config changes.
|
||||
*/
|
||||
override val defaultDataSubRatConfig: StateFlow<Config> =
|
||||
private val defaultDataSubRatConfig: StateFlow<Config> =
|
||||
merge(defaultDataSubIdChangeEvent, carrierConfigChangedEvent)
|
||||
.mapLatest { Config.readConfig(context) }
|
||||
.stateIn(
|
||||
@@ -166,6 +171,12 @@ constructor(
|
||||
initialValue = Config.readConfig(context)
|
||||
)
|
||||
|
||||
override val defaultMobileIconMapping: Flow<Map<String, MobileIconGroup>> =
|
||||
defaultDataSubRatConfig.map { mobileMappingsProxy.mapIconSets(it) }
|
||||
|
||||
override val defaultMobileIconGroup: Flow<MobileIconGroup> =
|
||||
defaultDataSubRatConfig.map { mobileMappingsProxy.getDefaultIcons(it) }
|
||||
|
||||
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
||||
if (!isValidSubId(subId)) {
|
||||
throw IllegalArgumentException(
|
||||
@@ -229,7 +240,7 @@ constructor(
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), MobileConnectivityModel())
|
||||
|
||||
private fun isValidSubId(subId: Int): Boolean {
|
||||
subscriptionsFlow.value.forEach {
|
||||
subscriptions.value.forEach {
|
||||
if (it.subscriptionId == subId) {
|
||||
return true
|
||||
}
|
||||
@@ -248,18 +259,23 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun dropUnusedReposFromCache(newInfos: List<SubscriptionInfo>) {
|
||||
private fun dropUnusedReposFromCache(newInfos: List<SubscriptionModel>) {
|
||||
// Remove any connection repository from the cache that isn't in the new set of IDs. They
|
||||
// will get garbage collected once their subscribers go away
|
||||
val currentValidSubscriptionIds = newInfos.map { it.subscriptionId }
|
||||
|
||||
subIdRepositoryCache.keys.forEach {
|
||||
if (!currentValidSubscriptionIds.contains(it)) {
|
||||
subIdRepositoryCache.remove(it)
|
||||
}
|
||||
}
|
||||
subIdRepositoryCache =
|
||||
subIdRepositoryCache
|
||||
.filter { currentValidSubscriptionIds.contains(it.key) }
|
||||
.toMutableMap()
|
||||
}
|
||||
|
||||
private suspend fun fetchSubscriptionsList(): List<SubscriptionInfo> =
|
||||
withContext(bgDispatcher) { subscriptionManager.completeActiveSubscriptionInfoList }
|
||||
|
||||
private fun SubscriptionInfo.toSubscriptionModel(): SubscriptionModel =
|
||||
SubscriptionModel(
|
||||
subscriptionId = subscriptionId,
|
||||
isOpportunistic = isOpportunistic,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,10 +20,7 @@ import android.telephony.CarrierConfigManager
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState.Connected
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import com.android.systemui.util.CarrierConfigTracker
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -70,10 +67,9 @@ class MobileIconInteractorImpl(
|
||||
defaultMobileIconMapping: StateFlow<Map<String, MobileIconGroup>>,
|
||||
defaultMobileIconGroup: StateFlow<MobileIconGroup>,
|
||||
override val isDefaultConnectionFailed: StateFlow<Boolean>,
|
||||
mobileMappingsProxy: MobileMappingsProxy,
|
||||
connectionRepository: MobileConnectionRepository,
|
||||
) : MobileIconInteractor {
|
||||
private val mobileStatusInfo = connectionRepository.subscriptionModelFlow
|
||||
private val connectionInfo = connectionRepository.connectionInfo
|
||||
|
||||
override val isDataEnabled: StateFlow<Boolean> = connectionRepository.dataEnabled
|
||||
|
||||
@@ -82,33 +78,27 @@ class MobileIconInteractorImpl(
|
||||
/** Observable for the current RAT indicator icon ([MobileIconGroup]) */
|
||||
override val networkTypeIconGroup: StateFlow<MobileIconGroup> =
|
||||
combine(
|
||||
mobileStatusInfo,
|
||||
connectionInfo,
|
||||
defaultMobileIconMapping,
|
||||
defaultMobileIconGroup,
|
||||
) { info, mapping, defaultGroup ->
|
||||
val lookupKey =
|
||||
when (val resolved = info.resolvedNetworkType) {
|
||||
is DefaultNetworkType -> mobileMappingsProxy.toIconKey(resolved.type)
|
||||
is OverrideNetworkType ->
|
||||
mobileMappingsProxy.toIconKeyOverride(resolved.type)
|
||||
}
|
||||
mapping[lookupKey] ?: defaultGroup
|
||||
mapping[info.resolvedNetworkType.lookupKey] ?: defaultGroup
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), defaultMobileIconGroup.value)
|
||||
|
||||
override val isEmergencyOnly: StateFlow<Boolean> =
|
||||
mobileStatusInfo
|
||||
connectionInfo
|
||||
.mapLatest { it.isEmergencyOnly }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
override val level: StateFlow<Int> =
|
||||
mobileStatusInfo
|
||||
.mapLatest { mobileModel ->
|
||||
connectionInfo
|
||||
.mapLatest { connection ->
|
||||
// TODO: incorporate [MobileMappings.Config.alwaysShowCdmaRssi]
|
||||
if (mobileModel.isGsm) {
|
||||
mobileModel.primaryLevel
|
||||
if (connection.isGsm) {
|
||||
connection.primaryLevel
|
||||
} else {
|
||||
mobileModel.cdmaLevel
|
||||
connection.cdmaLevel
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), 0)
|
||||
@@ -120,7 +110,7 @@ class MobileIconInteractorImpl(
|
||||
override val numberOfLevels: StateFlow<Int> = MutableStateFlow(4)
|
||||
|
||||
override val isDataConnected: StateFlow<Boolean> =
|
||||
mobileStatusInfo
|
||||
.mapLatest { subscriptionModel -> subscriptionModel.dataConnectionState == Connected }
|
||||
connectionInfo
|
||||
.mapLatest { connection -> connection.dataConnectionState == Connected }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
}
|
||||
|
||||
@@ -17,17 +17,16 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
||||
|
||||
import android.telephony.CarrierConfigManager
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Application
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import com.android.systemui.util.CarrierConfigTracker
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -53,7 +52,7 @@ import kotlinx.coroutines.flow.stateIn
|
||||
*/
|
||||
interface MobileIconsInteractor {
|
||||
/** List of subscriptions, potentially filtered for CBRS */
|
||||
val filteredSubscriptions: Flow<List<SubscriptionInfo>>
|
||||
val filteredSubscriptions: Flow<List<SubscriptionModel>>
|
||||
/** True if the active mobile data subscription has data enabled */
|
||||
val activeDataConnectionHasDataEnabled: StateFlow<Boolean>
|
||||
/** The icon mapping from network type to [MobileIconGroup] for the default subscription */
|
||||
@@ -79,7 +78,6 @@ class MobileIconsInteractorImpl
|
||||
constructor(
|
||||
private val mobileConnectionsRepo: MobileConnectionsRepository,
|
||||
private val carrierConfigTracker: CarrierConfigTracker,
|
||||
private val mobileMappingsProxy: MobileMappingsProxy,
|
||||
userSetupRepo: UserSetupRepository,
|
||||
@Application private val scope: CoroutineScope,
|
||||
) : MobileIconsInteractor {
|
||||
@@ -102,8 +100,8 @@ constructor(
|
||||
.flatMapLatest { it?.dataEnabled ?: flowOf(false) }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
private val unfilteredSubscriptions: Flow<List<SubscriptionInfo>> =
|
||||
mobileConnectionsRepo.subscriptionsFlow
|
||||
private val unfilteredSubscriptions: Flow<List<SubscriptionModel>> =
|
||||
mobileConnectionsRepo.subscriptions
|
||||
|
||||
/**
|
||||
* Generally, SystemUI wants to show iconography for each subscription that is listed by
|
||||
@@ -118,7 +116,7 @@ constructor(
|
||||
* [CarrierConfigManager.KEY_ALWAYS_SHOW_PRIMARY_SIGNAL_BAR_IN_OPPORTUNISTIC_NETWORK_BOOLEAN],
|
||||
* and by checking which subscription is opportunistic, or which one is active.
|
||||
*/
|
||||
override val filteredSubscriptions: Flow<List<SubscriptionInfo>> =
|
||||
override val filteredSubscriptions: Flow<List<SubscriptionModel>> =
|
||||
combine(unfilteredSubscriptions, activeMobileDataSubscriptionId) { unfilteredSubs, activeId
|
||||
->
|
||||
// Based on the old logic,
|
||||
@@ -154,15 +152,19 @@ constructor(
|
||||
* subscription Id. This mapping is the same for every subscription.
|
||||
*/
|
||||
override val defaultMobileIconMapping: StateFlow<Map<String, MobileIconGroup>> =
|
||||
mobileConnectionsRepo.defaultDataSubRatConfig
|
||||
.mapLatest { mobileMappingsProxy.mapIconSets(it) }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), initialValue = mapOf())
|
||||
mobileConnectionsRepo.defaultMobileIconMapping.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
initialValue = mapOf()
|
||||
)
|
||||
|
||||
/** If there is no mapping in [defaultMobileIconMapping], then use this default icon group */
|
||||
override val defaultMobileIconGroup: StateFlow<MobileIconGroup> =
|
||||
mobileConnectionsRepo.defaultDataSubRatConfig
|
||||
.mapLatest { mobileMappingsProxy.getDefaultIcons(it) }
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), initialValue = TelephonyIcons.G)
|
||||
mobileConnectionsRepo.defaultMobileIconGroup.stateIn(
|
||||
scope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
initialValue = TelephonyIcons.G
|
||||
)
|
||||
|
||||
/**
|
||||
* We want to show an error state when cellular has actually failed to validate, but not if some
|
||||
@@ -189,7 +191,6 @@ constructor(
|
||||
defaultMobileIconMapping,
|
||||
defaultMobileIconGroup,
|
||||
isDefaultConnectionFailed,
|
||||
mobileMappingsProxy,
|
||||
mobileConnectionsRepo.getRepoForSubId(subId),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ constructor(
|
||||
private val statusBarPipelineFlags: StatusBarPipelineFlags,
|
||||
) : CoreStartable {
|
||||
private val mobileSubIds: Flow<List<Int>> =
|
||||
interactor.filteredSubscriptions.mapLatest { infos ->
|
||||
infos.map { subscriptionInfo -> subscriptionInfo.subscriptionId }
|
||||
interactor.filteredSubscriptions.mapLatest { subscriptions ->
|
||||
subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,8 @@ class ModernStatusBarMobileView(
|
||||
attrs: AttributeSet?,
|
||||
) : BaseStatusBarFrameLayout(context, attrs) {
|
||||
|
||||
var subId: Int = -1
|
||||
|
||||
private lateinit var slot: String
|
||||
override fun getSlot() = slot
|
||||
|
||||
@@ -76,6 +78,7 @@ class ModernStatusBarMobileView(
|
||||
as ModernStatusBarMobileView)
|
||||
.also {
|
||||
it.slot = slot
|
||||
it.subId = viewModel.subscriptionId
|
||||
MobileIconBinder.bind(it, viewModel)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMob
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* View model for describing the system's current mobile cellular connections. The result is a list
|
||||
@@ -33,7 +33,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
class MobileIconsViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
val subscriptionIdsFlow: Flow<List<Int>>,
|
||||
val subscriptionIdsFlow: StateFlow<List<Int>>,
|
||||
private val interactor: MobileIconsInteractor,
|
||||
private val logger: ConnectivityPipelineLogger,
|
||||
) {
|
||||
@@ -51,7 +51,7 @@ constructor(
|
||||
private val interactor: MobileIconsInteractor,
|
||||
private val logger: ConnectivityPipelineLogger,
|
||||
) {
|
||||
fun create(subscriptionIdsFlow: Flow<List<Int>>): MobileIconsViewModel {
|
||||
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
|
||||
return MobileIconsViewModel(
|
||||
subscriptionIdsFlow,
|
||||
interactor,
|
||||
|
||||
@@ -16,12 +16,13 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeMobileConnectionRepository : MobileConnectionRepository {
|
||||
private val _subscriptionsModelFlow = MutableStateFlow(MobileSubscriptionModel())
|
||||
override val subscriptionModelFlow = _subscriptionsModelFlow
|
||||
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionRepository
|
||||
class FakeMobileConnectionRepository(override val subId: Int) : MobileConnectionRepository {
|
||||
private val _connectionInfo = MutableStateFlow(MobileConnectionModel())
|
||||
override val connectionInfo = _connectionInfo
|
||||
|
||||
private val _dataEnabled = MutableStateFlow(true)
|
||||
override val dataEnabled = _dataEnabled
|
||||
@@ -29,8 +30,8 @@ class FakeMobileConnectionRepository : MobileConnectionRepository {
|
||||
private val _isDefaultDataSubscription = MutableStateFlow(true)
|
||||
override val isDefaultDataSubscription = _isDefaultDataSubscription
|
||||
|
||||
fun setMobileSubscriptionModel(model: MobileSubscriptionModel) {
|
||||
_subscriptionsModelFlow.value = model
|
||||
fun setConnectionInfo(model: MobileConnectionModel) {
|
||||
_connectionInfo.value = model
|
||||
}
|
||||
|
||||
fun setDataEnabled(enabled: Boolean) {
|
||||
|
||||
@@ -16,23 +16,43 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository
|
||||
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
import com.android.settingslib.mobile.MobileMappings.Config
|
||||
import android.telephony.TelephonyDisplayInfo
|
||||
import android.telephony.TelephonyManager
|
||||
import com.android.settingslib.SignalIcon
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeMobileConnectionsRepository : MobileConnectionsRepository {
|
||||
private val _subscriptionsFlow = MutableStateFlow<List<SubscriptionInfo>>(listOf())
|
||||
override val subscriptionsFlow: Flow<List<SubscriptionInfo>> = _subscriptionsFlow
|
||||
// TODO(b/261632894): remove this in favor of the real impl or DemoMobileConnectionsRepository
|
||||
class FakeMobileConnectionsRepository(mobileMappings: MobileMappingsProxy) :
|
||||
MobileConnectionsRepository {
|
||||
val GSM_KEY = mobileMappings.toIconKey(GSM)
|
||||
val LTE_KEY = mobileMappings.toIconKey(LTE)
|
||||
val UMTS_KEY = mobileMappings.toIconKey(UMTS)
|
||||
val LTE_ADVANCED_KEY = mobileMappings.toIconKeyOverride(LTE_ADVANCED_PRO)
|
||||
|
||||
/**
|
||||
* To avoid a reliance on [MobileMappings], we'll build a simpler map from network type to
|
||||
* mobile icon. See TelephonyManager.NETWORK_TYPES for a list of types and [TelephonyIcons] for
|
||||
* the exhaustive set of icons
|
||||
*/
|
||||
val TEST_MAPPING: Map<String, SignalIcon.MobileIconGroup> =
|
||||
mapOf(
|
||||
GSM_KEY to TelephonyIcons.THREE_G,
|
||||
LTE_KEY to TelephonyIcons.LTE,
|
||||
UMTS_KEY to TelephonyIcons.FOUR_G,
|
||||
LTE_ADVANCED_KEY to TelephonyIcons.NR_5G,
|
||||
)
|
||||
|
||||
private val _subscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
||||
override val subscriptions = _subscriptions
|
||||
|
||||
private val _activeMobileDataSubscriptionId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
|
||||
override val activeMobileDataSubscriptionId = _activeMobileDataSubscriptionId
|
||||
|
||||
private val _defaultDataSubRatConfig = MutableStateFlow(Config())
|
||||
override val defaultDataSubRatConfig = _defaultDataSubRatConfig
|
||||
|
||||
private val _defaultDataSubId = MutableStateFlow(INVALID_SUBSCRIPTION_ID)
|
||||
override val defaultDataSubId = _defaultDataSubId
|
||||
|
||||
@@ -41,18 +61,21 @@ class FakeMobileConnectionsRepository : MobileConnectionsRepository {
|
||||
|
||||
private val subIdRepos = mutableMapOf<Int, MobileConnectionRepository>()
|
||||
override fun getRepoForSubId(subId: Int): MobileConnectionRepository {
|
||||
return subIdRepos[subId] ?: FakeMobileConnectionRepository().also { subIdRepos[subId] = it }
|
||||
return subIdRepos[subId]
|
||||
?: FakeMobileConnectionRepository(subId).also { subIdRepos[subId] = it }
|
||||
}
|
||||
|
||||
private val _globalMobileDataSettingChangedEvent = MutableStateFlow(Unit)
|
||||
override val globalMobileDataSettingChangedEvent = _globalMobileDataSettingChangedEvent
|
||||
|
||||
fun setSubscriptions(subs: List<SubscriptionInfo>) {
|
||||
_subscriptionsFlow.value = subs
|
||||
}
|
||||
private val _defaultMobileIconMapping = MutableStateFlow(TEST_MAPPING)
|
||||
override val defaultMobileIconMapping = _defaultMobileIconMapping
|
||||
|
||||
fun setDefaultDataSubRatConfig(config: Config) {
|
||||
_defaultDataSubRatConfig.value = config
|
||||
private val _defaultMobileIconGroup = MutableStateFlow(DEFAULT_ICON)
|
||||
override val defaultMobileIconGroup = _defaultMobileIconGroup
|
||||
|
||||
fun setSubscriptions(subs: List<SubscriptionModel>) {
|
||||
_subscriptions.value = subs
|
||||
}
|
||||
|
||||
fun setDefaultDataSubId(id: Int) {
|
||||
@@ -74,4 +97,14 @@ class FakeMobileConnectionsRepository : MobileConnectionsRepository {
|
||||
fun setMobileConnectionRepositoryMap(connections: Map<Int, MobileConnectionRepository>) {
|
||||
connections.forEach { entry -> subIdRepos[entry.key] = entry.value }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val DEFAULT_ICON = TelephonyIcons.G
|
||||
|
||||
// Use [MobileMappings] to define some simple definitions
|
||||
const val GSM = TelephonyManager.NETWORK_TYPE_GSM
|
||||
const val LTE = TelephonyManager.NETWORK_TYPE_LTE
|
||||
const val UMTS = TelephonyManager.NETWORK_TYPE_UMTS
|
||||
const val LTE_ADVANCED_PRO = TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,13 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.demomode.DemoMode
|
||||
import com.android.systemui.demomode.DemoModeController
|
||||
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.DemoModeMobileConnectionDataSource
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.validMobileEvent
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.MobileConnectionsRepositoryImpl
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.kotlinArgumentCaptor
|
||||
@@ -76,6 +78,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
|
||||
private val globalSettings = FakeSettings()
|
||||
private val fakeNetworkEventsFlow = MutableStateFlow<FakeNetworkEventModel?>(null)
|
||||
private val mobileMappings = FakeMobileMappingsProxy()
|
||||
|
||||
private val scope = CoroutineScope(IMMEDIATE)
|
||||
|
||||
@@ -97,6 +100,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
subscriptionManager,
|
||||
telephonyManager,
|
||||
logger,
|
||||
mobileMappings,
|
||||
fakeBroadcastDispatcher,
|
||||
globalSettings,
|
||||
context,
|
||||
@@ -155,15 +159,15 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1, SUB_2))
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// The real subscriptions has 2 subs
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1, SUB_2))
|
||||
getSubscriptionCallback().onSubscriptionsChanged()
|
||||
|
||||
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_2))
|
||||
assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2))
|
||||
|
||||
// Demo mode turns on, and we should see only the demo subscriptions
|
||||
startDemoMode()
|
||||
@@ -176,7 +180,7 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
|
||||
finishDemoMode()
|
||||
|
||||
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_2))
|
||||
assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2))
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -211,9 +215,11 @@ class MobileRepositorySwitcherTest : SysuiTestCase() {
|
||||
private const val SUB_1_ID = 1
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
|
||||
private val MODEL_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
|
||||
|
||||
private const val SUB_2_ID = 2
|
||||
private val SUB_2 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) }
|
||||
private val MODEL_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import com.android.settingslib.SignalIcon
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
@@ -109,18 +109,18 @@ internal class DemoMobileConnectionParameterizedTest(private val testCase: TestC
|
||||
) {
|
||||
when (model) {
|
||||
is FakeNetworkEventModel.Mobile -> {
|
||||
val subscriptionModel: MobileSubscriptionModel = conn.subscriptionModelFlow.value
|
||||
val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
|
||||
assertThat(conn.subId).isEqualTo(model.subId)
|
||||
assertThat(subscriptionModel.cdmaLevel).isEqualTo(model.level)
|
||||
assertThat(subscriptionModel.primaryLevel).isEqualTo(model.level)
|
||||
assertThat(subscriptionModel.dataActivityDirection).isEqualTo(model.activity)
|
||||
assertThat(subscriptionModel.carrierNetworkChangeActive)
|
||||
assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.dataActivityDirection).isEqualTo(model.activity)
|
||||
assertThat(connectionInfo.carrierNetworkChangeActive)
|
||||
.isEqualTo(model.carrierNetworkChange)
|
||||
|
||||
// TODO(b/261029387): check these once we start handling them
|
||||
assertThat(subscriptionModel.isEmergencyOnly).isFalse()
|
||||
assertThat(subscriptionModel.isGsm).isFalse()
|
||||
assertThat(subscriptionModel.dataConnectionState)
|
||||
assertThat(connectionInfo.isEmergencyOnly).isFalse()
|
||||
assertThat(connectionInfo.isGsm).isFalse()
|
||||
assertThat(connectionInfo.dataConnectionState)
|
||||
.isEqualTo(DataConnectionState.Connected)
|
||||
}
|
||||
// MobileDisabled isn't combinatorial in nature, and is tested in
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.data.repository.demo
|
||||
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.TelephonyManager.DATA_ACTIVITY_INOUT
|
||||
import android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID
|
||||
import androidx.test.filters.SmallTest
|
||||
@@ -24,7 +23,8 @@ import com.android.settingslib.SignalIcon
|
||||
import com.android.settingslib.mobile.TelephonyIcons.THREE_G
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.demo.model.FakeNetworkEventModel.MobileDisabled
|
||||
import com.android.systemui.util.mockito.mock
|
||||
@@ -73,8 +73,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `network event - create new subscription`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
@@ -89,8 +89,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `network event - reuses subscription when same Id`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
@@ -111,8 +111,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `multiple subscriptions`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1)
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 2)
|
||||
@@ -125,8 +125,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `mobile disabled event - disables connection - subId specified - single conn`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
|
||||
|
||||
@@ -140,8 +140,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `mobile disabled event - disables connection - subId not specified - single conn`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
|
||||
|
||||
@@ -155,8 +155,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `mobile disabled event - disables connection - subId specified - multiple conn`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
|
||||
@@ -171,8 +171,8 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `mobile disabled event - subId not specified - multiple conn - ignores command`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
|
||||
@@ -184,13 +184,32 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
/** Regression test for b/261706421 */
|
||||
@Test
|
||||
fun `multiple connections - remove all - does not throw`() =
|
||||
testScope.runTest {
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// Two subscriptions are added
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 1, level = 1)
|
||||
fakeNetworkEventFlow.value = validMobileEvent(subId = 2, level = 1)
|
||||
|
||||
// Then both are removed by turning off demo mode
|
||||
underTest.stopProcessingCommands()
|
||||
|
||||
assertThat(latest).isEmpty()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `demo connection - single subscription`() =
|
||||
testScope.runTest {
|
||||
var currentEvent: FakeNetworkEventModel = validMobileEvent(subId = 1)
|
||||
var connections: List<DemoMobileConnectionRepository>? = null
|
||||
val job =
|
||||
underTest.subscriptionsFlow
|
||||
underTest.subscriptions
|
||||
.onEach { infos ->
|
||||
connections =
|
||||
infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
|
||||
@@ -222,7 +241,7 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
var connection2: DemoMobileConnectionRepository? = null
|
||||
var connections: List<DemoMobileConnectionRepository>? = null
|
||||
val job =
|
||||
underTest.subscriptionsFlow
|
||||
underTest.subscriptions
|
||||
.onEach { infos ->
|
||||
connections =
|
||||
infos.map { info -> underTest.getRepoForSubId(info.subscriptionId) }
|
||||
@@ -266,18 +285,18 @@ class DemoMobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
) {
|
||||
when (model) {
|
||||
is FakeNetworkEventModel.Mobile -> {
|
||||
val subscriptionModel: MobileSubscriptionModel = conn.subscriptionModelFlow.value
|
||||
val connectionInfo: MobileConnectionModel = conn.connectionInfo.value
|
||||
assertThat(conn.subId).isEqualTo(model.subId)
|
||||
assertThat(subscriptionModel.cdmaLevel).isEqualTo(model.level)
|
||||
assertThat(subscriptionModel.primaryLevel).isEqualTo(model.level)
|
||||
assertThat(subscriptionModel.dataActivityDirection).isEqualTo(model.activity)
|
||||
assertThat(subscriptionModel.carrierNetworkChangeActive)
|
||||
assertThat(connectionInfo.cdmaLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.primaryLevel).isEqualTo(model.level)
|
||||
assertThat(connectionInfo.dataActivityDirection).isEqualTo(model.activity)
|
||||
assertThat(connectionInfo.carrierNetworkChangeActive)
|
||||
.isEqualTo(model.carrierNetworkChange)
|
||||
|
||||
// TODO(b/261029387) check these once we start handling them
|
||||
assertThat(subscriptionModel.isEmergencyOnly).isFalse()
|
||||
assertThat(subscriptionModel.isGsm).isFalse()
|
||||
assertThat(subscriptionModel.dataConnectionState)
|
||||
assertThat(connectionInfo.isEmergencyOnly).isFalse()
|
||||
assertThat(connectionInfo.isGsm).isFalse()
|
||||
assertThat(connectionInfo.dataConnectionState)
|
||||
.isEqualTo(DataConnectionState.Connected)
|
||||
}
|
||||
else -> {}
|
||||
|
||||
@@ -37,10 +37,12 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.UnknownNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
@@ -72,8 +74,9 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||
|
||||
private val scope = CoroutineScope(IMMEDIATE)
|
||||
private val mobileMappings = FakeMobileMappingsProxy()
|
||||
private val globalSettings = FakeSettings()
|
||||
private val connectionsRepo = FakeMobileConnectionsRepository()
|
||||
private val connectionsRepo = FakeMobileConnectionsRepository(mobileMappings)
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
@@ -89,6 +92,7 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
globalSettings,
|
||||
connectionsRepo.defaultDataSubId,
|
||||
connectionsRepo.globalMobileDataSettingChangedEvent,
|
||||
mobileMappings,
|
||||
IMMEDIATE,
|
||||
logger,
|
||||
scope,
|
||||
@@ -103,10 +107,10 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_default() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEqualTo(MobileSubscriptionModel())
|
||||
assertThat(latest).isEqualTo(MobileConnectionModel())
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -114,8 +118,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_emergencyOnly() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val serviceState = ServiceState()
|
||||
serviceState.isEmergencyOnly = true
|
||||
@@ -130,8 +134,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_emergencyOnly_toggles() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<ServiceStateListener>()
|
||||
val serviceState = ServiceState()
|
||||
@@ -148,8 +152,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_signalStrengths_levelsUpdate() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<TelephonyCallback.SignalStrengthsListener>()
|
||||
val strength = signalStrength(gsmLevel = 1, cdmaLevel = 2, isGsm = true)
|
||||
@@ -165,8 +169,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataConnectionState_connected() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback =
|
||||
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
|
||||
@@ -180,8 +184,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataConnectionState_connecting() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback =
|
||||
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
|
||||
@@ -195,8 +199,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataConnectionState_disconnected() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback =
|
||||
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
|
||||
@@ -210,8 +214,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataConnectionState_disconnecting() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback =
|
||||
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
|
||||
@@ -225,8 +229,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataConnectionState_unknown() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback =
|
||||
getTelephonyCallbackForType<TelephonyCallback.DataConnectionStateListener>()
|
||||
@@ -240,8 +244,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_dataActivity() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<TelephonyCallback.DataActivityListener>()
|
||||
callback.onDataActivity(3)
|
||||
@@ -254,8 +258,8 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testFlowForSubId_carrierNetworkChange() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<TelephonyCallback.CarrierNetworkListener>()
|
||||
callback.onCarrierNetworkChange(true)
|
||||
@@ -268,11 +272,11 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun subscriptionFlow_networkType_default() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val type = NETWORK_TYPE_UNKNOWN
|
||||
val expected = DefaultNetworkType(type)
|
||||
val expected = UnknownNetworkType
|
||||
|
||||
assertThat(latest?.resolvedNetworkType).isEqualTo(expected)
|
||||
|
||||
@@ -282,12 +286,12 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun subscriptionFlow_networkType_updatesUsingDefault() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
|
||||
val type = NETWORK_TYPE_LTE
|
||||
val expected = DefaultNetworkType(type)
|
||||
val expected = DefaultNetworkType(type, mobileMappings.toIconKey(type))
|
||||
val ti = mock<TelephonyDisplayInfo>().also { whenever(it.networkType).thenReturn(type) }
|
||||
callback.onDisplayInfoChanged(ti)
|
||||
|
||||
@@ -299,14 +303,15 @@ class MobileConnectionRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun subscriptionFlow_networkType_updatesUsingOverride() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: MobileSubscriptionModel? = null
|
||||
val job = underTest.subscriptionModelFlow.onEach { latest = it }.launchIn(this)
|
||||
var latest: MobileConnectionModel? = null
|
||||
val job = underTest.connectionInfo.onEach { latest = it }.launchIn(this)
|
||||
|
||||
val callback = getTelephonyCallbackForType<TelephonyCallback.DisplayInfoListener>()
|
||||
val type = OVERRIDE_NETWORK_TYPE_LTE_CA
|
||||
val expected = OverrideNetworkType(type)
|
||||
val expected = OverrideNetworkType(type, mobileMappings.toIconKeyOverride(type))
|
||||
val ti =
|
||||
mock<TelephonyDisplayInfo>().also {
|
||||
whenever(it.networkType).thenReturn(type)
|
||||
whenever(it.overrideNetworkType).thenReturn(type)
|
||||
}
|
||||
callback.onDisplayInfoChanged(ti)
|
||||
|
||||
@@ -32,6 +32,8 @@ import androidx.test.filters.SmallTest
|
||||
import com.android.internal.telephony.PhoneConstants
|
||||
import com.android.systemui.SysuiTestCase
|
||||
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.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.util.mockito.any
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
@@ -50,6 +52,7 @@ import org.junit.After
|
||||
import org.junit.Assert.assertThrows
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.mockito.ArgumentMatchers.anyInt
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.MockitoAnnotations
|
||||
@@ -65,6 +68,8 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Mock private lateinit var telephonyManager: TelephonyManager
|
||||
@Mock private lateinit var logger: ConnectivityPipelineLogger
|
||||
|
||||
private val mobileMappings = FakeMobileMappingsProxy()
|
||||
|
||||
private val scope = CoroutineScope(IMMEDIATE)
|
||||
private val globalSettings = FakeSettings()
|
||||
|
||||
@@ -72,18 +77,37 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
|
||||
// Set up so the individual connection repositories
|
||||
whenever(telephonyManager.createForSubscriptionId(anyInt())).thenAnswer { invocation ->
|
||||
telephonyManager.also {
|
||||
whenever(telephonyManager.subscriptionId).thenReturn(invocation.getArgument(0))
|
||||
}
|
||||
}
|
||||
|
||||
val connectionFactory: MobileConnectionRepositoryImpl.Factory =
|
||||
MobileConnectionRepositoryImpl.Factory(
|
||||
context = context,
|
||||
telephonyManager = telephonyManager,
|
||||
bgDispatcher = IMMEDIATE,
|
||||
globalSettings = globalSettings,
|
||||
logger = logger,
|
||||
mobileMappingsProxy = mobileMappings,
|
||||
scope = scope,
|
||||
)
|
||||
|
||||
underTest =
|
||||
MobileConnectionsRepositoryImpl(
|
||||
connectivityManager,
|
||||
subscriptionManager,
|
||||
telephonyManager,
|
||||
logger,
|
||||
mobileMappings,
|
||||
fakeBroadcastDispatcher,
|
||||
globalSettings,
|
||||
context,
|
||||
IMMEDIATE,
|
||||
scope,
|
||||
mock(),
|
||||
connectionFactory,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -95,21 +119,21 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testSubscriptions_initiallyEmpty() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
assertThat(underTest.subscriptionsFlow.value).isEqualTo(listOf<SubscriptionInfo>())
|
||||
assertThat(underTest.subscriptions.value).isEqualTo(listOf<SubscriptionModel>())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSubscriptions_listUpdates() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1, SUB_2))
|
||||
getSubscriptionCallback().onSubscriptionsChanged()
|
||||
|
||||
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_2))
|
||||
assertThat(latest).isEqualTo(listOf(MODEL_1, MODEL_2))
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -117,9 +141,9 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testSubscriptions_removingSub_updatesList() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
|
||||
val job = underTest.subscriptionsFlow.onEach { latest = it }.launchIn(this)
|
||||
val job = underTest.subscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// WHEN 2 networks show up
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
@@ -132,7 +156,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
getSubscriptionCallback().onSubscriptionsChanged()
|
||||
|
||||
// THEN the subscriptions list represents the newest change
|
||||
assertThat(latest).isEqualTo(listOf(SUB_2))
|
||||
assertThat(latest).isEqualTo(listOf(MODEL_2))
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -162,7 +186,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testConnectionRepository_validSubId_isCached() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val job = underTest.subscriptionsFlow.launchIn(this)
|
||||
val job = underTest.subscriptions.launchIn(this)
|
||||
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1))
|
||||
@@ -179,7 +203,7 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun testConnectionCache_clearsInvalidSubscriptions() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val job = underTest.subscriptionsFlow.launchIn(this)
|
||||
val job = underTest.subscriptions.launchIn(this)
|
||||
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1, SUB_2))
|
||||
@@ -202,10 +226,36 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
/** Regression test for b/261706421 */
|
||||
@Test
|
||||
fun testConnectionsCache_clearMultipleSubscriptionsAtOnce_doesNotThrow() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val job = underTest.subscriptions.launchIn(this)
|
||||
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList)
|
||||
.thenReturn(listOf(SUB_1, SUB_2))
|
||||
getSubscriptionCallback().onSubscriptionsChanged()
|
||||
|
||||
// Get repos to trigger caching
|
||||
val repo1 = underTest.getRepoForSubId(SUB_1_ID)
|
||||
val repo2 = underTest.getRepoForSubId(SUB_2_ID)
|
||||
|
||||
assertThat(underTest.getSubIdRepoCache())
|
||||
.containsExactly(SUB_1_ID, repo1, SUB_2_ID, repo2)
|
||||
|
||||
// All subscriptions disappear
|
||||
whenever(subscriptionManager.completeActiveSubscriptionInfoList).thenReturn(listOf())
|
||||
getSubscriptionCallback().onSubscriptionsChanged()
|
||||
|
||||
assertThat(underTest.getSubIdRepoCache()).isEmpty()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testConnectionRepository_invalidSubId_throws() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
val job = underTest.subscriptionsFlow.launchIn(this)
|
||||
val job = underTest.subscriptions.launchIn(this)
|
||||
|
||||
assertThrows(IllegalArgumentException::class.java) {
|
||||
underTest.getRepoForSubId(SUB_1_ID)
|
||||
@@ -371,10 +421,12 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
|
||||
private const val SUB_1_ID = 1
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
|
||||
private val MODEL_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
|
||||
|
||||
private const val SUB_2_ID = 2
|
||||
private val SUB_2 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) }
|
||||
private val MODEL_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
|
||||
|
||||
private const val NET_ID = 123
|
||||
private val NETWORK = mock<Network>().apply { whenever(getNetId()).thenReturn(NET_ID) }
|
||||
|
||||
@@ -16,14 +16,15 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
||||
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_GSM
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
|
||||
import android.telephony.TelephonyManager.NETWORK_TYPE_UMTS
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
class FakeMobileIconsInteractor(mobileMappings: MobileMappingsProxy) : MobileIconsInteractor {
|
||||
@@ -47,8 +48,8 @@ class FakeMobileIconsInteractor(mobileMappings: MobileMappingsProxy) : MobileIco
|
||||
|
||||
override val isDefaultConnectionFailed = MutableStateFlow(false)
|
||||
|
||||
private val _filteredSubscriptions = MutableStateFlow<List<SubscriptionInfo>>(listOf())
|
||||
override val filteredSubscriptions = _filteredSubscriptions
|
||||
private val _filteredSubscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
||||
override val filteredSubscriptions: Flow<List<SubscriptionModel>> = _filteredSubscriptions
|
||||
|
||||
private val _activeDataConnectionHasDataEnabled = MutableStateFlow(false)
|
||||
override val activeDataConnectionHasDataEnabled = _activeDataConnectionHasDataEnabled
|
||||
|
||||
@@ -24,9 +24,9 @@ import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileSubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.OverrideNetworkType
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FIVE_G_OVERRIDE
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor.Companion.FOUR_G
|
||||
@@ -49,7 +49,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
private lateinit var underTest: MobileIconInteractor
|
||||
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
||||
private val mobileIconsInteractor = FakeMobileIconsInteractor(mobileMappingsProxy)
|
||||
private val connectionRepository = FakeMobileConnectionRepository()
|
||||
private val connectionRepository = FakeMobileConnectionRepository(SUB_1_ID)
|
||||
|
||||
private val scope = CoroutineScope(IMMEDIATE)
|
||||
|
||||
@@ -62,7 +62,6 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
mobileIconsInteractor.defaultMobileIconMapping,
|
||||
mobileIconsInteractor.defaultMobileIconGroup,
|
||||
mobileIconsInteractor.isDefaultConnectionFailed,
|
||||
mobileMappingsProxy,
|
||||
connectionRepository,
|
||||
)
|
||||
}
|
||||
@@ -70,8 +69,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun gsm_level_default_unknown() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(isGsm = true),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(isGsm = true),
|
||||
)
|
||||
|
||||
var latest: Int? = null
|
||||
@@ -85,8 +84,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun gsm_usesGsmLevel() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
isGsm = true,
|
||||
primaryLevel = GSM_LEVEL,
|
||||
cdmaLevel = CDMA_LEVEL
|
||||
@@ -104,8 +103,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun cdma_level_default_unknown() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(isGsm = false),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(isGsm = false),
|
||||
)
|
||||
|
||||
var latest: Int? = null
|
||||
@@ -118,8 +117,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun cdma_usesCdmaLevel() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
isGsm = false,
|
||||
primaryLevel = GSM_LEVEL,
|
||||
cdmaLevel = CDMA_LEVEL
|
||||
@@ -137,8 +136,11 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun iconGroup_three_g() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(resolvedNetworkType = DefaultNetworkType(THREE_G)),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
resolvedNetworkType =
|
||||
DefaultNetworkType(THREE_G, mobileMappingsProxy.toIconKey(THREE_G))
|
||||
),
|
||||
)
|
||||
|
||||
var latest: MobileIconGroup? = null
|
||||
@@ -152,16 +154,23 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun iconGroup_updates_on_change() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(resolvedNetworkType = DefaultNetworkType(THREE_G)),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
resolvedNetworkType =
|
||||
DefaultNetworkType(THREE_G, mobileMappingsProxy.toIconKey(THREE_G))
|
||||
),
|
||||
)
|
||||
|
||||
var latest: MobileIconGroup? = null
|
||||
val job = underTest.networkTypeIconGroup.onEach { latest = it }.launchIn(this)
|
||||
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(
|
||||
resolvedNetworkType = DefaultNetworkType(FOUR_G),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
resolvedNetworkType =
|
||||
DefaultNetworkType(
|
||||
FOUR_G,
|
||||
mobileMappingsProxy.toIconKey(FOUR_G),
|
||||
),
|
||||
),
|
||||
)
|
||||
yield()
|
||||
@@ -174,8 +183,14 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun iconGroup_5g_override_type() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(resolvedNetworkType = OverrideNetworkType(FIVE_G_OVERRIDE)),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
resolvedNetworkType =
|
||||
OverrideNetworkType(
|
||||
FIVE_G_OVERRIDE,
|
||||
mobileMappingsProxy.toIconKeyOverride(FIVE_G_OVERRIDE)
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
var latest: MobileIconGroup? = null
|
||||
@@ -189,9 +204,13 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun iconGroup_default_if_no_lookup() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(
|
||||
resolvedNetworkType = DefaultNetworkType(NETWORK_TYPE_UNKNOWN),
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(
|
||||
resolvedNetworkType =
|
||||
DefaultNetworkType(
|
||||
NETWORK_TYPE_UNKNOWN,
|
||||
mobileMappingsProxy.toIconKey(NETWORK_TYPE_UNKNOWN)
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -238,8 +257,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
|
||||
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(dataConnectionState = DataConnectionState.Connected)
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(dataConnectionState = DataConnectionState.Connected)
|
||||
)
|
||||
yield()
|
||||
|
||||
@@ -254,8 +273,8 @@ class MobileIconInteractorTest : SysuiTestCase() {
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isDataConnected.onEach { latest = it }.launchIn(this)
|
||||
|
||||
connectionRepository.setMobileSubscriptionModel(
|
||||
MobileSubscriptionModel(dataConnectionState = DataConnectionState.Disconnected)
|
||||
connectionRepository.setConnectionInfo(
|
||||
MobileConnectionModel(dataConnectionState = DataConnectionState.Disconnected)
|
||||
)
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.mobile.domain.interactor
|
||||
|
||||
import android.telephony.SubscriptionInfo
|
||||
import android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
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.repository.FakeMobileConnectionRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
import com.android.systemui.util.CarrierConfigTracker
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -45,8 +44,8 @@ import org.mockito.MockitoAnnotations
|
||||
class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
private lateinit var underTest: MobileIconsInteractor
|
||||
private val userSetupRepository = FakeUserSetupRepository()
|
||||
private val connectionsRepository = FakeMobileConnectionsRepository()
|
||||
private val mobileMappingsProxy = FakeMobileMappingsProxy()
|
||||
private val connectionsRepository = FakeMobileConnectionsRepository(mobileMappingsProxy)
|
||||
private val scope = CoroutineScope(IMMEDIATE)
|
||||
|
||||
@Mock private lateinit var carrierConfigTracker: CarrierConfigTracker
|
||||
@@ -69,7 +68,6 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
MobileIconsInteractorImpl(
|
||||
connectionsRepository,
|
||||
carrierConfigTracker,
|
||||
mobileMappingsProxy,
|
||||
userSetupRepository,
|
||||
scope
|
||||
)
|
||||
@@ -80,10 +78,10 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun filteredSubscriptions_default() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEqualTo(listOf<SubscriptionInfo>())
|
||||
assertThat(latest).isEqualTo(listOf<SubscriptionModel>())
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
@@ -93,7 +91,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
runBlocking(IMMEDIATE) {
|
||||
connectionsRepository.setSubscriptions(listOf(SUB_1, SUB_2))
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
assertThat(latest).isEqualTo(listOf(SUB_1, SUB_2))
|
||||
@@ -109,7 +107,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
|
||||
.thenReturn(false)
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// Filtered subscriptions should show the active one when the config is false
|
||||
@@ -126,7 +124,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
|
||||
.thenReturn(false)
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// Filtered subscriptions should show the active one when the config is false
|
||||
@@ -143,7 +141,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
|
||||
.thenReturn(true)
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// Filtered subscriptions should show the primary (non-opportunistic) if the config is
|
||||
@@ -161,7 +159,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
whenever(carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault)
|
||||
.thenReturn(true)
|
||||
|
||||
var latest: List<SubscriptionInfo>? = null
|
||||
var latest: List<SubscriptionModel>? = null
|
||||
val job = underTest.filteredSubscriptions.onEach { latest = it }.launchIn(this)
|
||||
|
||||
// Filtered subscriptions should show the primary (non-opportunistic) if the config is
|
||||
@@ -261,29 +259,19 @@ class MobileIconsInteractorTest : SysuiTestCase() {
|
||||
private val IMMEDIATE = Dispatchers.Main.immediate
|
||||
|
||||
private const val SUB_1_ID = 1
|
||||
private val SUB_1 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_1_ID) }
|
||||
private val CONNECTION_1 = FakeMobileConnectionRepository()
|
||||
private val SUB_1 = SubscriptionModel(subscriptionId = SUB_1_ID)
|
||||
private val CONNECTION_1 = FakeMobileConnectionRepository(SUB_1_ID)
|
||||
|
||||
private const val SUB_2_ID = 2
|
||||
private val SUB_2 =
|
||||
mock<SubscriptionInfo>().also { whenever(it.subscriptionId).thenReturn(SUB_2_ID) }
|
||||
private val CONNECTION_2 = FakeMobileConnectionRepository()
|
||||
private val SUB_2 = SubscriptionModel(subscriptionId = SUB_2_ID)
|
||||
private val CONNECTION_2 = FakeMobileConnectionRepository(SUB_2_ID)
|
||||
|
||||
private const val SUB_3_ID = 3
|
||||
private val SUB_3_OPP =
|
||||
mock<SubscriptionInfo>().also {
|
||||
whenever(it.subscriptionId).thenReturn(SUB_3_ID)
|
||||
whenever(it.isOpportunistic).thenReturn(true)
|
||||
}
|
||||
private val CONNECTION_3 = FakeMobileConnectionRepository()
|
||||
private val SUB_3_OPP = SubscriptionModel(subscriptionId = SUB_3_ID, isOpportunistic = true)
|
||||
private val CONNECTION_3 = FakeMobileConnectionRepository(SUB_3_ID)
|
||||
|
||||
private const val SUB_4_ID = 4
|
||||
private val SUB_4_OPP =
|
||||
mock<SubscriptionInfo>().also {
|
||||
whenever(it.subscriptionId).thenReturn(SUB_4_ID)
|
||||
whenever(it.isOpportunistic).thenReturn(true)
|
||||
}
|
||||
private val CONNECTION_4 = FakeMobileConnectionRepository()
|
||||
private val SUB_4_OPP = SubscriptionModel(subscriptionId = SUB_4_ID, isOpportunistic = true)
|
||||
private val CONNECTION_4 = FakeMobileConnectionRepository(SUB_4_ID)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user