Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75fecd34 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Automerger Merge Worker
Browse files

Merge "[SB Refactor] Show space between wifi and RAT icon if needed." into udc-dev am: 46c1fea2

parents 7425be05 46c1fea2
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupR
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxyImpl
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxy
@@ -53,6 +54,9 @@ import dagger.Module
import dagger.Provides
import dagger.multibindings.ClassKey
import dagger.multibindings.IntoMap
import kotlinx.coroutines.flow.Flow
import java.util.function.Supplier
import javax.inject.Named

@Module
abstract class StatusBarPipelineModule {
@@ -113,6 +117,17 @@ abstract class StatusBarPipelineModule {
            }
        }

        @Provides
        @SysUISingleton
        @Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
        fun provideFirstMobileSubShowingNetworkTypeIconProvider(
            mobileIconsViewModel: MobileIconsViewModel,
        ): Supplier<Flow<Boolean>> {
            return Supplier<Flow<Boolean>> {
                mobileIconsViewModel.firstMobileSubShowingNetworkTypeIcon
            }
        }

        @Provides
        @SysUISingleton
        @WifiInputLog
@@ -168,5 +183,8 @@ abstract class StatusBarPipelineModule {
        fun provideVerboseMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
            return factory.create("VerboseMobileViewLog", 100)
        }

        const val FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON =
            "FirstMobileSubShowingNetworkTypeIcon"
    }
}
+40 −11
Original line number Diff line number Diff line
@@ -32,6 +32,9 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@@ -63,13 +66,46 @@ constructor(
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), listOf())

    private val firstMobileSubViewModel: StateFlow<MobileIconViewModelCommon?> =
        subscriptionIdsFlow
            .map {
                if (it.isEmpty()) {
                    null
                } else {
                    // Mobile icons get reversed by [StatusBarIconController], so the last element
                    // in this list will show up visually first.
                    commonViewModelForSub(it.last())
                }
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), null)

    /**
     * A flow that emits `true` if the mobile sub that's displayed first visually is showing its
     * network type icon and `false` otherwise.
     */
    val firstMobileSubShowingNetworkTypeIcon: StateFlow<Boolean> =
        firstMobileSubViewModel
            .flatMapLatest { firstMobileSubViewModel ->
                firstMobileSubViewModel?.networkTypeIcon?.map { it != null } ?: flowOf(false)
            }
            .stateIn(scope, SharingStarted.WhileSubscribed(), false)

    init {
        scope.launch { subscriptionIdsFlow.collect { removeInvalidModelsFromCache(it) } }
    }

    fun viewModelForSub(subId: Int, location: StatusBarLocation): LocationBasedMobileViewModel {
        val common =
            mobileIconSubIdCache[subId]
        val common = commonViewModelForSub(subId)
        return LocationBasedMobileViewModel.viewModelForLocation(
            common,
            statusBarPipelineFlags,
            verboseLogger,
            location,
        )
    }

    private fun commonViewModelForSub(subId: Int): MobileIconViewModelCommon {
        return mobileIconSubIdCache[subId]
            ?: MobileIconViewModel(
                    subId,
                    interactor.createMobileConnectionInteractorForSubId(subId),
@@ -78,13 +114,6 @@ constructor(
                    scope,
                )
                .also { mobileIconSubIdCache[subId] = it }

        return LocationBasedMobileViewModel.viewModelForLocation(
            common,
            statusBarPipelineFlags,
            verboseLogger,
            location,
        )
    }

    private fun removeInvalidModelsFromCache(subIds: List<Int>) {
+7 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWi
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.launch

@@ -64,6 +63,7 @@ object WifiViewBinder {
        val activityOutView = view.requireViewById<ImageView>(R.id.wifi_out)
        val activityContainerView = view.requireViewById<View>(R.id.inout_container)
        val airplaneSpacer = view.requireViewById<View>(R.id.wifi_airplane_spacer)
        val signalSpacer = view.requireViewById<View>(R.id.wifi_signal_spacer)

        view.isVisible = true
        iconView.isVisible = true
@@ -133,6 +133,12 @@ object WifiViewBinder {
                    }
                }

                launch {
                    viewModel.isSignalSpacerVisible.distinctUntilChanged().collect { visible ->
                        signalSpacer.isVisible = visible
                    }
                }

                try {
                    awaitCancellation()
                } finally {
+12 −8
Original line number Diff line number Diff line
@@ -30,8 +30,8 @@ import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule.Companion.FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON
import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
@@ -39,7 +39,9 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiIntera
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
import java.util.function.Supplier
import javax.inject.Inject
import javax.inject.Named
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
@@ -53,24 +55,24 @@ import kotlinx.coroutines.flow.stateIn
/**
 * Models the UI state for the status bar wifi icon.
 *
 * This class exposes three view models, one per status bar location: [home], [keyguard], and [qs].
 * In order to get the UI state for the wifi icon, you must use one of those view models (whichever
 * is correct for your location).
 *
 * Internally, this class maintains the current state of the wifi icon and notifies those three view
 * models of any changes.
 * This is a singleton so that we don't have duplicate logs and should *not* be used directly to
 * control views. Instead, use an instance of [LocationBasedWifiViewModel]. See
 * [LocationBasedWifiViewModel.viewModelForLocation].
 */
@SysUISingleton
class WifiViewModel
@Inject
constructor(
    airplaneModeViewModel: AirplaneModeViewModel,
    // TODO(b/238425913): The wifi icon shouldn't need to consume mobile information. A
    //  container-level view model should do the work instead.
    @Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
    shouldShowSignalSpacerProvider: Supplier<Flow<Boolean>>,
    connectivityConstants: ConnectivityConstants,
    private val context: Context,
    @WifiTableLog wifiTableLogBuffer: TableLogBuffer,
    interactor: WifiInteractor,
    @Application private val scope: CoroutineScope,
    statusBarPipelineFlags: StatusBarPipelineFlags,
    wifiConstants: WifiConstants,
) : WifiViewModelCommon {
    /** Returns the icon to use based on the given network. */
@@ -183,6 +185,8 @@ constructor(
    override val isAirplaneSpacerVisible: Flow<Boolean> =
        airplaneModeViewModel.isAirplaneModeIconVisible

    override val isSignalSpacerVisible: Flow<Boolean> = shouldShowSignalSpacerProvider.get()

    companion object {
        @StringRes
        @VisibleForTesting
+3 −0
Original line number Diff line number Diff line
@@ -39,4 +39,7 @@ interface WifiViewModelCommon {

    /** True if the airplane spacer view should be visible. */
    val isAirplaneSpacerVisible: Flow<Boolean>

    /** True if the spacer between the wifi icon and the RAT icon should be visible. */
    val isSignalSpacerVisible: Flow<Boolean>
}
Loading