Merge changes I88baa0eb,Ic63ada05,I5e7eb52c,Ifd28e920 into tm-qpr-dev

* changes:
  [SB Refactor] Add verbose logging about values received by the binder.
  [SB Refactor] Add logs for view creation and collection.
  [SB Refactor] Define a MobileViewLogger and move the UI logs there.
  [SB Refactor] Minor logging changes to StatusBarIconController etc.
This commit is contained in:
Caitlin Shkuratov
2023-03-06 19:02:41 +00:00
committed by Android (Google) Code Review
34 changed files with 621 additions and 71 deletions

View File

@@ -93,6 +93,16 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
@IntDef({STATE_ICON, STATE_DOT, STATE_HIDDEN})
public @interface VisibleState { }
/** Returns a human-readable string of {@link VisibleState}. */
public static String getVisibleStateString(@VisibleState int state) {
switch(state) {
case STATE_ICON: return "ICON";
case STATE_DOT: return "DOT";
case STATE_HIDDEN: return "HIDDEN";
default: return "UNKNOWN";
}
}
private static final String TAG = "StatusBarIconView";
private static final Property<StatusBarIconView, Float> ICON_APPEAR_AMOUNT
= new FloatProperty<StatusBarIconView>("iconAppearAmount") {
@@ -561,7 +571,8 @@ public class StatusBarIconView extends AnimatedImageView implements StatusIconDi
@Override
public String toString() {
return "StatusBarIconView("
+ "slot='" + mSlot + " alpha=" + getAlpha() + " icon=" + mIcon
+ "slot='" + mSlot + "' alpha=" + getAlpha() + " icon=" + mIcon
+ " visibleState=" + getVisibleStateString(getVisibleState())
+ " iconColor=#" + Integer.toHexString(mIconColor)
+ " notification=" + mNotification + ')';
}

View File

@@ -40,6 +40,7 @@ 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.MobileViewLogger;
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView;
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel;
import com.android.systemui.statusbar.pipeline.wifi.ui.view.ModernStatusBarWifiView;
@@ -288,10 +289,14 @@ public class DemoStatusIcons extends StatusIconContainer implements DemoMode, Da
* @param mobileContext possibly mcc/mnc overridden mobile context
* @param subId the subscriptionId for this mobile view
*/
public void addModernMobileView(Context mobileContext, int subId) {
public void addModernMobileView(
Context mobileContext,
MobileViewLogger mobileViewLogger,
int subId) {
Log.d(TAG, "addModernMobileView (subId=" + subId + ")");
ModernStatusBarMobileView view = ModernStatusBarMobileView.constructAndBind(
mobileContext,
mobileViewLogger,
"mobile",
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
);

View File

@@ -569,7 +569,10 @@ public interface StatusBarIconController {
mGroup.addView(view, index, onCreateLayoutParams());
if (mIsInDemoMode) {
mDemoStatusIcons.addModernMobileView(mContext, subId);
mDemoStatusIcons.addModernMobileView(
mContext,
mMobileIconsViewModel.getLogger(),
subId);
}
return view;
@@ -601,6 +604,7 @@ public interface StatusBarIconController {
return ModernStatusBarMobileView
.constructAndBind(
mobileContext,
mMobileIconsViewModel.getLogger(),
slot,
mMobileIconsViewModel.viewModelForSub(subId, mLocation)
);

View File

@@ -79,6 +79,18 @@ public class StatusBarIconHolder {
private @IconType int mType = TYPE_ICON;
private int mTag = 0;
/** Returns a human-readable string representing the given type. */
public static String getTypeString(@IconType int type) {
switch(type) {
case TYPE_ICON: return "ICON";
case TYPE_WIFI: return "WIFI_OLD";
case TYPE_MOBILE: return "MOBILE_OLD";
case TYPE_MOBILE_NEW: return "MOBILE_NEW";
case TYPE_WIFI_NEW: return "WIFI_NEW";
default: return "UNKNOWN";
}
}
private StatusBarIconHolder() {
}
@@ -230,4 +242,11 @@ public class StatusBarIconHolder {
public int getTag() {
return mTag;
}
@Override
public String toString() {
return "StatusBarIconHolder(type=" + getTypeString(mType)
+ " tag=" + getTag()
+ " visible=" + isVisible() + ")";
}
}

View File

@@ -27,6 +27,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/** A class holding the list of all the system icons that could be shown in the status bar. */
public class StatusBarIconList {
@@ -302,7 +303,7 @@ public class StatusBarIconList {
@Override
public String toString() {
return String.format("(%s) %s", mName, subSlotsString());
return String.format("(%s) holder=%s %s", mName, mHolder, subSlotsString());
}
private String subSlotsString() {
@@ -310,7 +311,10 @@ public class StatusBarIconList {
return "";
}
return "" + mSubSlots.size() + " subSlots";
return "| " + mSubSlots.size() + " subSlots: "
+ mSubSlots.stream()
.map(StatusBarIconHolder::toString)
.collect(Collectors.joining("|"));
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 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.dagger
import javax.inject.Qualifier
/** Logs for changes with the new mobile views. */
@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class MobileViewLog

View File

@@ -148,5 +148,19 @@ abstract class StatusBarPipelineModule {
fun provideMobileInputLogBuffer(factory: LogBufferFactory): LogBuffer {
return factory.create("MobileInputLog", 100)
}
@Provides
@SysUISingleton
@MobileViewLog
fun provideMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
return factory.create("MobileViewLog", 100)
}
@Provides
@SysUISingleton
@VerboseMobileViewLog
fun provideVerboseMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
return factory.create("VerboseMobileViewLog", 100)
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2023 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.dagger
import javax.inject.Qualifier
/** Logs for **verbose** changes with the new mobile views. */
@Qualifier
@MustBeDocumented
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class VerboseMobileViewLog

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.mobile.shared
package com.android.systemui.statusbar.pipeline.mobile.data
import android.net.Network
import android.net.NetworkCapabilities
@@ -133,24 +133,6 @@ constructor(
)
}
fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
buffer.log(
TAG,
LogLevel.INFO,
{ str1 = subs.toString() },
{ "Sub IDs in MobileUiAdapter updated internally: $str1" },
)
}
fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
buffer.log(
TAG,
LogLevel.INFO,
{ str1 = subs.toString() },
{ "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
)
}
fun logCarrierConfigChanged(subId: Int) {
buffer.log(
TAG,

View File

@@ -30,8 +30,8 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfig
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope

View File

@@ -36,6 +36,7 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.ResolvedNetworkType.DefaultNetworkType
@@ -47,7 +48,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameMo
import com.android.systemui.statusbar.pipeline.mobile.data.repository.CarrierConfigRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel
import javax.inject.Inject

View File

@@ -45,11 +45,11 @@ import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.dagger.MobileSummaryLog
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectivityModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel

View File

@@ -22,7 +22,6 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
import java.io.PrintWriter
import javax.inject.Inject
@@ -55,17 +54,14 @@ constructor(
interactor: MobileIconsInteractor,
private val iconController: StatusBarIconController,
private val iconsViewModelFactory: MobileIconsViewModel.Factory,
private val logger: MobileInputLogger,
private val logger: MobileViewLogger,
@Application private val scope: CoroutineScope,
private val statusBarPipelineFlags: StatusBarPipelineFlags,
) : CoreStartable {
private val mobileSubIds: Flow<List<Int>> =
interactor.filteredSubscriptions
.mapLatest { subscriptions ->
subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
}
.distinctUntilChanged()
.onEach { logger.logUiAdapterSubIdsUpdated(it) }
interactor.filteredSubscriptions.mapLatest { subscriptions ->
subscriptions.map { subscriptionModel -> subscriptionModel.subscriptionId }
}
/**
* We expose the list of tracked subscriptions as a flow of a list of ints, where each int is
@@ -75,7 +71,10 @@ constructor(
* NOTE: this should go away as the view presenter learns more about this data pipeline
*/
private val mobileSubIdsState: StateFlow<List<Int>> =
mobileSubIds.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
mobileSubIds
.distinctUntilChanged()
.onEach { logger.logUiAdapterSubIdsUpdated(it) }
.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
/** In order to keep the logs tame, we will reuse the same top-level mobile icons view model */
val mobileIconsViewModel = iconsViewModelFactory.create(mobileSubIdsState)

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.mobile.ui
import android.view.View
import com.android.systemui.Dumpable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.MobileViewLog
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import java.io.PrintWriter
import javax.inject.Inject
/** Logs for changes with the new mobile views. */
@SysUISingleton
class MobileViewLogger
@Inject
constructor(
@MobileViewLog private val buffer: LogBuffer,
dumpManager: DumpManager,
) : Dumpable {
init {
dumpManager.registerNormalDumpable(this)
}
private val collectionStatuses = mutableMapOf<String, Boolean>()
fun logUiAdapterSubIdsUpdated(subs: List<Int>) {
buffer.log(
TAG,
LogLevel.INFO,
{ str1 = subs.toString() },
{ "Sub IDs in MobileUiAdapter updated internally: $str1" },
)
}
fun logUiAdapterSubIdsSentToIconController(subs: List<Int>) {
buffer.log(
TAG,
LogLevel.INFO,
{ str1 = subs.toString() },
{ "Sub IDs in MobileUiAdapter being sent to icon controller: $str1" },
)
}
fun logNewViewBinding(view: View, viewModel: LocationBasedMobileViewModel) {
buffer.log(
TAG,
LogLevel.INFO,
{
str1 = view.getIdForLogging()
str2 = viewModel.getIdForLogging()
str3 = viewModel.locationName
},
{ "New view binding. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
)
}
fun logCollectionStarted(view: View, viewModel: LocationBasedMobileViewModel) {
collectionStatuses[view.getIdForLogging()] = true
buffer.log(
TAG,
LogLevel.INFO,
{
str1 = view.getIdForLogging()
str2 = viewModel.getIdForLogging()
str3 = viewModel.locationName
},
{ "Collection started. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
)
}
fun logCollectionStopped(view: View, viewModel: LocationBasedMobileViewModel) {
collectionStatuses[view.getIdForLogging()] = false
buffer.log(
TAG,
LogLevel.INFO,
{
str1 = view.getIdForLogging()
str2 = viewModel.getIdForLogging()
str3 = viewModel.locationName
},
{ "Collection stopped. viewId=$str1, viewModelId=$str2, viewModelLocation=$str3" },
)
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.println("Collection statuses per view:---")
collectionStatuses.forEach { viewId, isCollecting ->
pw.println("viewId=$viewId, isCollecting=$isCollecting")
}
}
companion object {
fun Any.getIdForLogging(): String {
// The identityHashCode is guaranteed to be constant for the lifetime of the object.
return Integer.toHexString(System.identityHashCode(this))
}
}
}
private const val TAG = "MobileViewLogger"

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.mobile.ui
import android.view.View
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.statusbar.pipeline.dagger.VerboseMobileViewLog
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
import javax.inject.Inject
/**
* Logs for **verbose** changes with the new mobile views.
*
* This is a hopefully temporary log until we resolve some open bugs (b/267236367, b/269565345,
* b/270300839).
*/
@SysUISingleton
class VerboseMobileViewLogger
@Inject
constructor(
@VerboseMobileViewLog private val buffer: LogBuffer,
) {
fun logBinderReceivedSignalIcon(parentView: View, subId: Int, icon: SignalIconModel) {
buffer.log(
TAG,
LogLevel.VERBOSE,
{
str1 = parentView.getIdForLogging()
int1 = subId
int2 = icon.level
bool1 = icon.showExclamationMark
},
{
"Binder[subId=$int1, viewId=$str1] received new signal icon: " +
"level=$int2 showExclamation=$bool1"
},
)
}
fun logBinderReceivedNetworkTypeIcon(parentView: View, subId: Int, icon: Icon.Resource?) {
buffer.log(
TAG,
LogLevel.VERBOSE,
{
str1 = parentView.getIdForLogging()
int1 = subId
bool1 = icon != null
int2 = icon?.res ?: -1
},
{
"Binder[subId=$int1, viewId=$str1] received new network type icon: " +
if (bool1) "resId=$int2" else "null"
},
)
}
}
private const val TAG = "VerboseMobileViewLogger"

View File

@@ -36,8 +36,10 @@ import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch
@@ -48,6 +50,7 @@ object MobileIconBinder {
fun bind(
view: ViewGroup,
viewModel: LocationBasedMobileViewModel,
logger: MobileViewLogger,
): ModernStatusBarViewBinding {
val mobileGroupView = view.requireViewById<ViewGroup>(R.id.mobile_group)
val activityContainer = view.requireViewById<View>(R.id.inout_container)
@@ -70,8 +73,13 @@ object MobileIconBinder {
val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
var isCollecting: Boolean = false
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
logger.logCollectionStarted(view, viewModel)
isCollecting = true
launch {
visibilityState.collect { state ->
when (state) {
@@ -96,6 +104,11 @@ object MobileIconBinder {
// Set the icon for the triangle
launch {
viewModel.icon.distinctUntilChanged().collect { icon ->
viewModel.verboseLogger?.logBinderReceivedSignalIcon(
view,
viewModel.subscriptionId,
icon,
)
mobileDrawable.level =
SignalDrawable.getState(
icon.level,
@@ -114,6 +127,11 @@ object MobileIconBinder {
// Set the network type icon
launch {
viewModel.networkTypeIcon.distinctUntilChanged().collect { dataTypeId ->
viewModel.verboseLogger?.logBinderReceivedNetworkTypeIcon(
view,
viewModel.subscriptionId,
dataTypeId,
)
dataTypeId?.let { IconViewBinder.bind(dataTypeId, networkTypeView) }
networkTypeView.visibility = if (dataTypeId != null) VISIBLE else GONE
}
@@ -150,6 +168,13 @@ object MobileIconBinder {
}
launch { decorTint.collect { tint -> dotView.setDecorColor(tint) } }
try {
awaitCancellation()
} finally {
isCollecting = false
logger.logCollectionStopped(view, viewModel)
}
}
}
@@ -175,6 +200,10 @@ object MobileIconBinder {
}
decorTint.value = newTint
}
override fun isCollecting(): Boolean {
return isCollecting
}
}
}
}

View File

@@ -20,6 +20,8 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import com.android.systemui.R
import com.android.systemui.statusbar.StatusBarIconView.getVisibleStateString
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.binder.MobileIconBinder
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
@@ -31,6 +33,15 @@ class ModernStatusBarMobileView(
var subId: Int = -1
override fun toString(): String {
return "ModernStatusBarMobileView(" +
"slot='$slot', " +
"subId=$subId, " +
"isCollecting=${binding.isCollecting()}, " +
"visibleState=${getVisibleStateString(visibleState)}); " +
"viewString=${super.toString()}"
}
companion object {
/**
@@ -40,6 +51,7 @@ class ModernStatusBarMobileView(
@JvmStatic
fun constructAndBind(
context: Context,
logger: MobileViewLogger,
slot: String,
viewModel: LocationBasedMobileViewModel,
): ModernStatusBarMobileView {
@@ -48,7 +60,8 @@ class ModernStatusBarMobileView(
as ModernStatusBarMobileView)
.also {
it.subId = viewModel.subscriptionId
it.initView(slot) { MobileIconBinder.bind(it, viewModel) }
it.initView(slot) { MobileIconBinder.bind(it, viewModel, logger) }
logger.logNewViewBinding(it, viewModel)
}
}
}

View File

@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
import android.graphics.Color
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
/**
* A view model for an individual mobile icon that embeds the notion of a [StatusBarLocation]. This
@@ -26,11 +27,15 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
*
* @param commonImpl for convenience, this class wraps a base interface that can provides all of the
* common implementations between locations. See [MobileIconViewModel]
* @property locationName the name of the location of this VM, used for logging.
* @property verboseLogger an optional logger to log extremely verbose view updates.
*/
abstract class LocationBasedMobileViewModel(
val commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
debugTint: Int,
val locationName: String,
val verboseLogger: VerboseMobileViewLogger?,
) : MobileIconViewModelCommon by commonImpl {
val useDebugColoring: Boolean = statusBarPipelineFlags.useDebugColoring()
@@ -45,11 +50,16 @@ abstract class LocationBasedMobileViewModel(
fun viewModelForLocation(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
verboseMobileViewLogger: VerboseMobileViewLogger,
loc: StatusBarLocation,
): LocationBasedMobileViewModel =
when (loc) {
StatusBarLocation.HOME ->
HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
HomeMobileIconViewModel(
commonImpl,
statusBarPipelineFlags,
verboseMobileViewLogger,
)
StatusBarLocation.KEYGUARD ->
KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
StatusBarLocation.QS -> QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
@@ -60,20 +70,41 @@ abstract class LocationBasedMobileViewModel(
class HomeMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
verboseMobileViewLogger: VerboseMobileViewLogger,
) :
MobileIconViewModelCommon,
LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.CYAN)
LocationBasedMobileViewModel(
commonImpl,
statusBarPipelineFlags,
debugTint = Color.CYAN,
locationName = "Home",
verboseMobileViewLogger,
)
class QsMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
) :
MobileIconViewModelCommon,
LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.GREEN)
LocationBasedMobileViewModel(
commonImpl,
statusBarPipelineFlags,
debugTint = Color.GREEN,
locationName = "QS",
// Only do verbose logging for the Home location.
verboseLogger = null,
)
class KeyguardMobileIconViewModel(
commonImpl: MobileIconViewModelCommon,
statusBarPipelineFlags: StatusBarPipelineFlags,
) :
MobileIconViewModelCommon,
LocationBasedMobileViewModel(commonImpl, statusBarPipelineFlags, debugTint = Color.MAGENTA)
LocationBasedMobileViewModel(
commonImpl,
statusBarPipelineFlags,
debugTint = Color.MAGENTA,
locationName = "Keyguard",
// Only do verbose logging for the Home location.
verboseLogger = null,
)

View File

@@ -49,7 +49,7 @@ interface MobileIconViewModelCommon {
val contentDescription: Flow<ContentDescription>
val roaming: Flow<Boolean>
/** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */
val networkTypeIcon: Flow<Icon?>
val networkTypeIcon: Flow<Icon.Resource?>
val activityInVisible: Flow<Boolean>
val activityOutVisible: Flow<Boolean>
val activityContainerVisible: Flow<Boolean>
@@ -161,7 +161,7 @@ constructor(
)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val networkTypeIcon: Flow<Icon?> =
override val networkTypeIcon: Flow<Icon.Resource?> =
combine(
iconInteractor.networkTypeIconGroup,
showNetworkTypeIcon,

View File

@@ -23,6 +23,8 @@ import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import javax.inject.Inject
@@ -39,6 +41,8 @@ class MobileIconsViewModel
@Inject
constructor(
val subscriptionIdsFlow: StateFlow<List<Int>>,
val logger: MobileViewLogger,
private val verboseLogger: VerboseMobileViewLogger,
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val constants: ConnectivityConstants,
@@ -66,6 +70,7 @@ constructor(
return LocationBasedMobileViewModel.viewModelForLocation(
common,
statusBarPipelineFlags,
verboseLogger,
location,
)
}
@@ -79,6 +84,8 @@ constructor(
class Factory
@Inject
constructor(
private val logger: MobileViewLogger,
private val verboseLogger: VerboseMobileViewLogger,
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val constants: ConnectivityConstants,
@@ -88,6 +95,8 @@ constructor(
fun create(subscriptionIdsFlow: StateFlow<List<Int>>): MobileIconsViewModel {
return MobileIconsViewModel(
subscriptionIdsFlow,
logger,
verboseLogger,
interactor,
airplaneModeInteractor,
constants,

View File

@@ -37,4 +37,7 @@ interface ModernStatusBarViewBinding {
/** Notifies that the decor tint has been updated (used only for the dot). */
fun onDecorTintChanged(newTint: Int)
/** Returns true if the binding between the view and view-model is currently collecting. */
fun isCollecting(): Boolean
}

View File

@@ -36,7 +36,7 @@ open class ModernStatusBarView(context: Context, attrs: AttributeSet?) :
BaseStatusBarFrameLayout(context, attrs) {
private lateinit var slot: String
private lateinit var binding: ModernStatusBarViewBinding
internal lateinit var binding: ModernStatusBarViewBinding
@StatusBarIconView.VisibleState
private var iconVisibleState: Int = STATE_HIDDEN

View File

@@ -34,6 +34,7 @@ import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarV
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -74,8 +75,12 @@ object WifiViewBinder {
val iconTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
val decorTint: MutableStateFlow<Int> = MutableStateFlow(viewModel.defaultColor)
var isCollecting: Boolean = false
view.repeatWhenAttached {
repeatOnLifecycle(Lifecycle.State.STARTED) {
isCollecting = true
launch {
visibilityState.collect { visibilityState ->
groupView.isVisible = visibilityState == STATE_ICON
@@ -127,6 +132,12 @@ object WifiViewBinder {
airplaneSpacer.isVisible = visible
}
}
try {
awaitCancellation()
} finally {
isCollecting = false
}
}
}
@@ -152,6 +163,10 @@ object WifiViewBinder {
}
decorTint.value = newTint
}
override fun isCollecting(): Boolean {
return isCollecting
}
}
}
}

View File

@@ -21,6 +21,7 @@ import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import com.android.systemui.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.pipeline.shared.ui.view.ModernStatusBarView
import com.android.systemui.statusbar.pipeline.wifi.ui.binder.WifiViewBinder
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
@@ -33,6 +34,15 @@ class ModernStatusBarWifiView(
context: Context,
attrs: AttributeSet?,
) : ModernStatusBarView(context, attrs) {
override fun toString(): String {
return "ModernStatusBarWifiView(" +
"slot='$slot', " +
"isCollecting=${binding.isCollecting()}, " +
"visibleState=${StatusBarIconView.getVisibleStateString(visibleState)}); " +
"viewString=${super.toString()}"
}
companion object {
/**
* Inflates a new instance of [ModernStatusBarWifiView], binds it to a view model, and
@@ -45,12 +55,9 @@ class ModernStatusBarWifiView(
slot: String,
wifiViewModel: LocationBasedWifiViewModel,
): ModernStatusBarWifiView {
return (
LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
as ModernStatusBarWifiView
).also {
it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) }
}
return (LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
as ModernStatusBarWifiView)
.also { it.initView(slot) { WifiViewBinder.bind(it, wifiViewModel) } }
}
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.mobile.shared
package com.android.systemui.statusbar.pipeline.mobile.data
import android.net.Network
import android.net.NetworkCapabilities

View File

@@ -24,8 +24,8 @@ import androidx.test.filters.SmallTest
import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrierConfigTest.Companion.createTestConfig
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi

View File

@@ -27,13 +27,13 @@ import com.android.systemui.demomode.DemoModeController
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
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.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.demo.DemoModeWifiDataSource

View File

@@ -53,6 +53,7 @@ import android.telephony.TelephonyManager.NETWORK_TYPE_LTE
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.data.model.DataConnectionState
import com.android.systemui.statusbar.pipeline.mobile.data.model.MobileConnectionModel
import com.android.systemui.statusbar.pipeline.mobile.data.model.NetworkNameModel
@@ -65,7 +66,6 @@ import com.android.systemui.statusbar.pipeline.mobile.data.model.SystemUiCarrier
import com.android.systemui.statusbar.pipeline.mobile.data.model.toNetworkNameModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository.Companion.DEFAULT_NUM_LEVELS
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.model.toMobileDataActivityModel

View File

@@ -37,12 +37,12 @@ import com.android.settingslib.mobile.MobileMappings
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.statusbar.pipeline.mobile.data.MobileInputLogger
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.CarrierConfigRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.prod.FullMobileConnectionRepository.Factory.Companion.tableBufferLogName
import com.android.systemui.statusbar.pipeline.mobile.shared.MobileInputLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.statusbar.pipeline.mobile.ui
import android.widget.TextView
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger.Companion.getIdForLogging
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.KeyguardMobileIconViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import java.io.PrintWriter
import java.io.StringWriter
import org.junit.Before
import org.junit.Test
import org.mockito.Mock
import org.mockito.MockitoAnnotations
@SmallTest
class MobileViewLoggerTest : SysuiTestCase() {
private val buffer = LogBufferFactory(DumpManager(), mock()).create("buffer", 10)
private val stringWriter = StringWriter()
private val printWriter = PrintWriter(stringWriter)
private val underTest = MobileViewLogger(buffer, mock())
@Mock private lateinit var flags: StatusBarPipelineFlags
@Mock private lateinit var commonViewModel: MobileIconViewModel
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
}
@Test
fun collectionStarted_dumpHasInfo() {
val view = TextView(context)
val viewModel = QsMobileIconViewModel(commonViewModel, flags)
underTest.logCollectionStarted(view, viewModel)
val dumpString = getDumpString()
assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
}
@Test
fun collectionStarted_multipleViews_dumpHasInfo() {
val view = TextView(context)
val view2 = TextView(context)
val viewModel = QsMobileIconViewModel(commonViewModel, flags)
val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
underTest.logCollectionStarted(view, viewModel)
underTest.logCollectionStarted(view2, viewModel2)
val dumpString = getDumpString()
assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=true")
assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
}
@Test
fun collectionStopped_dumpHasInfo() {
val view = TextView(context)
val view2 = TextView(context)
val viewModel = QsMobileIconViewModel(commonViewModel, flags)
val viewModel2 = KeyguardMobileIconViewModel(commonViewModel, flags)
underTest.logCollectionStarted(view, viewModel)
underTest.logCollectionStarted(view2, viewModel2)
underTest.logCollectionStopped(view, viewModel)
val dumpString = getDumpString()
assertThat(dumpString).contains("${view.getIdForLogging()}, isCollecting=false")
assertThat(dumpString).contains("${view2.getIdForLogging()}, isCollecting=true")
}
private fun getDumpString(): String {
underTest.dump(printWriter, args = arrayOf())
return stringWriter.toString()
}
}

View File

@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
@@ -60,6 +61,7 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var tableLogBuffer: TableLogBuffer
@Mock private lateinit var viewLogger: MobileViewLogger
@Mock private lateinit var constants: ConnectivityConstants
private lateinit var interactor: FakeMobileIconInteractor
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
@@ -94,7 +96,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_icon_iconShownDotHidden() {
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
view.setVisibleState(StatusBarIconView.STATE_ICON, /* animate= */ false)
@@ -109,8 +117,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_dot_iconHiddenDotShown() {
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
view.setVisibleState(StatusBarIconView.STATE_DOT, /* animate= */ false)
ViewUtils.attachView(view)
@@ -124,8 +137,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setVisibleState_hidden_iconAndDotHidden() {
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
view.setVisibleState(StatusBarIconView.STATE_HIDDEN, /* animate= */ false)
ViewUtils.attachView(view)
@@ -142,8 +160,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
whenever(constants.hasDataCapabilities).thenReturn(false)
createViewModel()
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -157,8 +180,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
whenever(constants.hasDataCapabilities).thenReturn(true)
createViewModel()
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -171,8 +199,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
fun isIconVisible_notAirplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(false)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -185,8 +218,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
fun isIconVisible_airplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(true)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -198,7 +236,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun onDarkChanged_iconHasNewColor() {
whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
@@ -214,7 +258,13 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Test
fun setStaticDrawableColor_iconHasNewColor() {
whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
val view =
ModernStatusBarMobileView.constructAndBind(
context,
viewLogger,
SLOT_NAME,
viewModel,
)
ViewUtils.attachView(view)
testableLooper.processAllMessages()

View File

@@ -28,6 +28,7 @@ import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -84,7 +85,7 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
testScope.backgroundScope,
)
homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags, mock())
qsIcon = QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)
keyguardIcon = KeyguardMobileIconViewModel(commonImpl, statusBarPipelineFlags)
}

View File

@@ -24,6 +24,8 @@ import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirp
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
@@ -51,6 +53,8 @@ class MobileIconsViewModelTest : SysuiTestCase() {
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var constants: ConnectivityConstants
@Mock private lateinit var logger: MobileViewLogger
@Mock private lateinit var verboseLogger: VerboseMobileViewLogger
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -73,6 +77,8 @@ class MobileIconsViewModelTest : SysuiTestCase() {
underTest =
MobileIconsViewModel(
subscriptionIdsFlow,
logger,
verboseLogger,
interactor,
airplaneModeInteractor,
constants,

View File

@@ -164,6 +164,10 @@ class ModernStatusBarViewTest : SysuiTestCase() {
override fun getShouldIconBeVisible(): Boolean {
return shouldIconBeVisibleInternal
}
override fun isCollecting(): Boolean {
return true
}
}
}