Android U pipeline-statusbar

news2024/11/20 9:37:13

Android U - statusbar pipeline

写在前面

Android原生从T开始对SystemUI进行MVVM改造,U上状态栏部分进行了修改;第一次出现修改不会删除原有逻辑,而是两版并行,留给其他开发者适配的时间;在下一个大版本可能会删除原有逻辑,只留下MVVM。
新版MVVM放在pipeline目录下,本篇文章对状态栏部分进行分析,以及整理与原有逻辑的对应关系。


SystemUI/packages/SystemUI/src/com/android/systemui/statusbar/pipeline

目前可以切换pipeline的控件为数据信号和wifi,开启位置:

# StatusBarPipelineFlags

/** True if we should display the mobile icons using the new status bar data pipeline. */
fun useNewMobileIcons(): Boolean =  featureFlags.isEnabled(Flags.NEW_STATUS_BAR_MOBILE_ICONS)

/** True if we should display the wifi icon using the new status bar data pipeline. */
fun useNewWifiIcon(): Boolean =  featureFlags.isEnabled(Flags.NEW_STATUS_BAR_WIFI_ICON)

Mobile

pipeline-mobile

1 data

1.1 model

DataConnectionState.kt 枚举;数据连接状态

1 Connected,
2 Connecting,
3 Disconnected,
4 Disconnecting,
5 Suspended,
6 HandoverInProgress,
7 Unknown,
8 Invalid;

NetworkNameModel.kt ⽹络名称,通过密封接⼝的⽅式声明了三个
密封接⼝:https://www.jianshu.com/p/6d70e3b5d380
通过TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED更新

1 Default 默认,读取[com.android.internal.R.string.lockscreen_carrier_default]
2 IntentDerived intent传过来
3 SimDerived sim卡传过来

ResolvedNetworkType.kt ⽹络类型,从TelephonyDisplayInfo中获取的

1 UnknownNetworkType
2 DefaultNetworkType
3 OverrideNetworkType
4 CarrierMergedNetworkType

SubscriptionModel.kt
[SubscriptionInfo]的SystemUI表⽰。⽬前,我们仅在订阅本⾝上使⽤两个字段:subscriptionId和isOpportunistic。我们需要的任何新字段都可以添加到下⾯并在存储库类中提供

1 subscriptionId  : subId
2 isOpportunistic : https://learn.microsoft.com/zh-cn/dotnet/api/android.telephon
3 groupUuid       : 合并相同的uuid下的⽹络;
					NetworkControllerImpl.filterMobileSubscriptionInSameGroup,
					MobileIconsInteractor.filteredSubscriptions

SystemUiCarrierConfig.kt 给定subId,获取systemUI需要的读取的数据的key

1 inflateSignalStrength
2 showOperatorName
1.2 repository
1.2.1 demo

demo模式下的显⽰,对照下⽅1.2.2 prod去看

1.2.2 prod

MobileConnectionRepositoryImpl和MobileConnectionsRepositoryImpl是下⽅两个接⼝的实现类,具体接收底层数据回调⻅MobileConnectionRepositoryImpl.callbackEvents,对标MobileStatusTracker中注册的回调:

private val callbackEvents: StateFlow<TelephonyCallbackState> = run {
        val initial = TelephonyCallbackState()
        callbackFlow {
                val callback =
                    object :
                        TelephonyCallback(),
                        TelephonyCallback.ServiceStateListener,
                        TelephonyCallback.SignalStrengthsListener,
                        TelephonyCallback.DataConnectionStateListener,
                        TelephonyCallback.DataActivityListener,
                        TelephonyCallback.CarrierNetworkListener,
                        TelephonyCallback.DisplayInfoListener,
                        TelephonyCallback.DataEnabledListener {
                        override fun onServiceStateChanged(serviceState: ServiceState) {
                            logger.logOnServiceStateChanged(serviceState, subId)
                            trySend(CallbackEvent.OnServiceStateChanged(serviceState))
                        }

                        override fun onSignalStrengthsChanged(signalStrength: SignalStrength) {
                            logger.logOnSignalStrengthsChanged(signalStrength, subId)
                            trySend(CallbackEvent.OnSignalStrengthChanged(signalStrength))
                        }

                        override fun onDataConnectionStateChanged(
                            dataState: Int,
                            networkType: Int
                        ) {
                            logger.logOnDataConnectionStateChanged(dataState, networkType, subId)
                            trySend(CallbackEvent.OnDataConnectionStateChanged(dataState))
                        }

                        override fun onDataActivity(direction: Int) {
                            logger.logOnDataActivity(direction, subId)
                            trySend(CallbackEvent.OnDataActivity(direction))
                        }

                        override fun onCarrierNetworkChange(active: Boolean) {
                            logger.logOnCarrierNetworkChange(active, subId)
                            trySend(CallbackEvent.OnCarrierNetworkChange(active))
                        }

                        override fun onDisplayInfoChanged(
                            telephonyDisplayInfo: TelephonyDisplayInfo
                        ) {
                            logger.logOnDisplayInfoChanged(telephonyDisplayInfo, subId)
                            trySend(CallbackEvent.OnDisplayInfoChanged(telephonyDisplayInfo))
                        }

                        override fun onDataEnabledChanged(enabled: Boolean, reason: Int) {
                            logger.logOnDataEnabledChanged(enabled, subId)
                            trySend(CallbackEvent.OnDataEnabledChanged(enabled))
                        }
                    }
                telephonyManager.registerTelephonyCallback(bgDispatcher.asExecutor(), callback)
                awaitClose { telephonyManager.unregisterTelephonyCallback(callback) }
            }
            .scan(initial = initial) { state, event -> state.applyEvent(event) }
            .stateIn(scope = scope, started = SharingStarted.WhileSubscribed(), initial)
    }

接收到数据后通知view更新显⽰,⻅下⽅3.4 viewmodel
MobileConnectionRepository

1 subId                       :subId
2 carrier 		              :See [TelephonyManager.getSimCarrierId]
3 isEmergencyOnly             :紧急呼叫,⻅MobileSignalController
4 isRoaming                   :漫游,⻅MobileSignalController
5 operatorAlphaShort          :运营商名字⼩写
6 isInService.                :in service,⻅MobileSignalController
7 isGsm.                      :MobileSignalController中只有在判断是否为cdma时⽤到了,
8 cdmaLevel
9 primaryLevel                :两个level放⼀起看⼀下
10						       根据aospLevel和qcomLevel去计算,⻅MobileSignalController
11 dataConnectionState.       :⻅MobileSignalController.dataConnected,区分了各种状态
12 dataActivityDirection      :上下⾏,⻅MobileSignalController
13 carrierNetworkChangeActive :carrierNetworkChangeMode
14 resolvedNetworkType.       :override network type
15 numberOfLevels             :信号个数
16 dataEnabled                :是否开了数据;⻅StatusBarSignalPolicy
17 cdmaRoaming.               :cdma是否漫游,TODO 没⻅过
18 networkName                :⻅1.1 networknamemodel

MobileConnectionsRepository (TODO 后面再填)

1 subscriptions :
2 activeMobileDataSubscriptionId:
3 activeMobileDataRepository :
4 activeSubChangedInGroupEvent :
5 defaultDataSubId :
6 mobileIsDefault :
7 hasCarrierMergedConnection :
8 defaultConnectionIsValidated :
9 defaultDataSubRatConfig :
10 defaultMobileIconMapping :
11 defaultMobileIconGroup :

FullMobileConnectionRepository.kt 整体的移动通信repo,包含了移动数据的repo(MobileConnectionRepositoryImpl)和运营商合并⽹络的repo(CarrierMergedConnectionRepository);
数据获取从Full repo中读取,Full repo选择mobile或carrierMerged中的⼀个做为activeRepo读取数据

CarrierMergedConnectionRepository.kt 运营商合并⽹络的repo

/**
 * A repository implementation for a carrier merged (aka VCN) network. A carrier merged network is
 * delivered to SysUI as a wifi network (see [WifiNetworkModel.CarrierMerged], but is visually
 * displayed as a mobile network triangle.
 *
 * See [android.net.wifi.WifiInfo.isCarrierMerged] for more information.
 *
 * See [MobileConnectionRepositoryImpl] for a repository implementation of a typical mobile
 * connection.
 */
 运营商合并(⼜名 VCN)⽹络的存储库实现。运营商合并⽹络作为 wifi ⽹络传递到 SysUI
 有关更多信息,请参阅 [android.net.wifi.WifiInfo.isCarrierMerged]。
 有关典型移动连接的存储库实现,请参阅 [MobileConnectionRepositoryImpl]。

CarrierConfigCoreStartable.kt.
⽤于启动CarrierConfigRepository
CarrierConfigRepository.kt.
给定subId,获取缓存的设置;数据key⻅SystemUiCarrierConfig.
MobileRepositorySwitcher.kt 切换demo模式和真实数据的显⽰.

1 RealRepository
2                │
3                ├──►RepositorySwitcher──►RealInteractor──►RealViewModel
4                │
5 DemoRepository

UserSetupRepositoryImpl.kt user,使⽤在MobileIconsInteractor中isUserSetup,⽬前没有使⽤到的地⽅

1.3 others

MobileInputLogger.kt logBuffer

2 domin

2.1 interactor

MobileIconInteractor.kt

1 tableLogBuffer            :log
2 activity                  :上下⾏
3 mobileIsDefault           :See [MobileConnectionsRepository.mobileIsDefault]
4 
5 isDataConnected           :数据是否连接(判断条件去MobileSignalController中看下)
6 isDefaultConnectionFailed :是否连接失败;⽤于判断是否显⽰错误状态下的SignalDrawable
7 isInService               :是否有服务
8 isDefaultDataEnabled      :dataEnabled default设置,MobileIconsInterator.active
9 isDataEnabled             :dataEnabled
10 alwaysShowDataRatIcon.   :是否要⼀直显⽰数据图标;
11                           U之前没这个功能,数据图表常驻的;根据需求决定这东西还要不要
12                           个⼈理解可直接改成false,具体情况适配时注意下
13 alwaysUseCdmaLevel       :cdma是单独判断的,⻅MobileSignalController.isCdma;
14                           该变量影响level值的选择
15                           个⼈理解可直接改成false,具体情况适配时注意下
16 networkTypeIconGroup     :⽹络类型的iconGroup,⻅2.2中NetworkTypeIconGroup
17 networkName              :⽹络名称,⻅1.1中NetworkNameModel
18 isEmergencyOnly          :仅可紧急通话
19 isRoaming                :是否是漫游
20 level                    :信号强度格数
21 numberOfLevels           :最⼤信号格数,4还是5;海外(日本)有此类定制
22                           后续可以⽤此处来拓展
23 isForceHidden            :强制隐藏信号图标;寻找是不是在icon_blacklist中
24 carrierNetworkChangeActive:对应MobileSignalController.isCarrierNetworkChangeActive

MobileIconsInteractor.kt

1 mobileIsDefault           :同上MobileIconInteractor中
2 filteredSubscriptions     :
3 activeDataConnectionHasDataEnabled :
4 alwaysShowDataRatIcon     :同上MobileIconInteractor中
5 alwaysUseCdmaLevel.       :同上MobileIconInteractor中
6 defaultMobileIconMapping  :
7 defaultMobileIconGroup    :
8 isDefaultConnectionFailed :同上MobileIconInteractor中
9 isUserSetup               :
10 isForceHidden            :同上MobileIconInteractor中
11
12 fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor
13 ⽤于创建MobileIconInteractor实例
2.2 model

NetworkTypeIconModel.kt 密封类 ⽹络类型图标,根据是否是override type,对应下⽅两种类型

1 val contentDescription: Int
2 val iconId: Int
3 val name: String
4
5 data class DefaultIcon
6 data class OverriddenIcon

3 ui

3.1 binder

MobileIconBinder:更新ModernStatusBarMobileView的显⽰,对标StatusBarMobileView.
区别:StatusBarMobileView中,通过bean类传递最新的信息,每次整体更新view的显⽰,根据计算后是否有变化来决定是否刷新;
MobileIconBinder中,每个不同的变量都通过各⾃注册的监听来回调,只触发各⾃的部分;
此处适配时,对于新增的ui和变量,很多都是多种条件组合判断的;需要将多种条件都放⼊监听中,根据计算后的结果来判断,例如:

1 // Set the activity indicators
2 launch {
3   combine(viewModel.activityInVisible, viewModel.activityOutVi
4     activityIn, activityOut, dataConnected ->
5   if (dataConnected) {
6     if (activityIn && activityOut) {
7       viewModel.leftInOutResId = R.drawable.xxx;
8       viewModel.rightInOutResId = R.drawable.xxx;
9     } else if (activityIn) {
10      viewModel.leftInOutResId = R.drawable.xxx;
11      viewModel.rightInOutResId = R.drawable.xxx;
12    } else if (activityOut) {
13      viewModel.leftInOutResId = R.drawable.xxx;
14      viewModel.rightInOutResId = R.drawable.xxx;
15    } else {
16      viewModel.leftInOutResId = R.drawable.xxx;
17      viewModel.rightInOutResId = R.drawable.xxx;
18    }
19   }
20   leftInOut.setImageResource(transformResId(viewModel.left));
21   rightInOut.setImageResource(transformResId(viewModel.right));
22  }
23 }

MobileIconsBinder:提供对外的static⽅法,bind后在每次声明周期为STARTED时更新;
⽬前collect中为空,因为和旧版逻辑适配的原因,此处逻辑在MobileUiAdapter中;后续⼤版本如果移除了旧版逻辑,会迁移⾄此处.

3.2 model

SignalIconModel.kt 打信号格相关的log;选择信号格的图⽚.
⻅2.1中numberOfLevels

	/** Convert this model to an [Int] consumable by [SignalDrawable]. */
    fun toSignalDrawableState(): Int =
        if (carrierNetworkChange) {
            SignalDrawable.getCarrierChangeState(numberOfLevels)
        } else {
            SignalDrawable.getState(level, numberOfLevels, showExclamationMark)
        }
3.3 view

ModernStatusBarMobileView.kt pipeline的信号view;内部逻辑都放到了MobileIconBinder中,剩下布局的加载和⼀些变量获取

	companion object {
        /**
         * Inflates a new instance of [ModernStatusBarMobileView], binds it to [viewModel], and
         * returns it.
         */
        @JvmStatic
        fun constructAndBind(
            context: Context,
            logger: MobileViewLogger,
            slot: String,
            viewModel: LocationBasedMobileViewModel,
        ): ModernStatusBarMobileView {
            return (LayoutInflater.from(context)
                    .inflate(R.layout.status_bar_mobile_signal_group_new, null)
                    as ModernStatusBarMobileView)
                .also {
                    it.subId = viewModel.subscriptionId
                    it.initView(slot) { MobileIconBinder.bind(it, viewModel, logger) }
                    logger.logNewViewBinding(it, viewModel)
                }
        }
    }
3.4 viewmodel

LocationBasedMobileViewModel.kt 根据location创建三个不同的viewmodel

1 HomeMobileIconViewModel
2 QsMobileIconViewModel
3 KeyguardMobileIconViewModel

MobileIconsViewModel.kt.
MobileIconViewModel.kt
为MobileIconBinder提供数据;binder中监听的变量是从viewmodel中获取的,viewmodel中的变量
通过2.1中interactor获取;
即当信号的数据发⽣变化时,底层数据发⽣变化->通知interactor中变化->通知viewmodel中变化->通知binder去更新显⽰;例如:

# MobileIconBinder.kt

// 信号格图标,监听的viewmodel中icon的变化
// Set the icon for the triangle
launch {
     viewModel.icon.distinctUntilChanged().collect { icon ->
       viewModel.verboseLogger?.logBinderReceivedSignalIcon(
             view,
             viewModel.subscriptionId,
             icon,
        )
     mobileDrawable.level = icon.toSignalDrawableState()
   }
}

# MobileIconViewModel.kt

val icon: Flow<SignalIconModel>

override val icon: Flow<SignalIconModel> = run {
        val initial =
            SignalIconModel(
                level = shownLevel.value,
                numberOfLevels = iconInteractor.numberOfLevels.value,
                showExclamationMark = showExclamationMark.value,
                carrierNetworkChange = iconInteractor.carrierNetworkChangeActive.value,
            )
        combine(
                shownLevel,
                iconInteractor.numberOfLevels,
                showExclamationMark,
                iconInteractor.carrierNetworkChangeActive,
            ) { shownLevel, numberOfLevels, showExclamationMark, carrierNetworkChange ->
                SignalIconModel(
                    shownLevel,
                    numberOfLevels,
                    showExclamationMark,
                    carrierNetworkChange,
                )
            }
            .distinctUntilChanged()
            .logDiffsForTable(
                iconInteractor.tableLogBuffer,
                columnPrefix = "icon",
                initialValue = initial,
            )
            .stateIn(scope, SharingStarted.WhileSubscribed(), initial)
    }

# MobileIconInteractor.kt

val numberOfLevels: StateFlow<Int>

override val numberOfLevels: StateFlow<Int> =
        connectionRepository.numberOfLevels.stateIn(
            scope,
            SharingStarted.WhileSubscribed(),
            connectionRepository.numberOfLevels.value,
        )

# MobileConnectionRepository.kt

val numberOfLevels: StateFlow<Int>

# 最后数据落到底层回调,⻅上⽂中1.2.2
3.5 others

MobileUiAdapter.kt pipeline和旧版的连接,将UI刷新转回到StatusBarIconControllerImpl中;后续如果移除旧版逻辑,可能会移⾛,⻅MobileIconsBinder.

	override fun start() {
        // Only notify the icon controller if we want to *render* the new icons.
        // Note that this flow may still run if
        // [statusBarPipelineFlags.runNewMobileIconsBackend] is true because we may want to
        // get the logging data without rendering.
        if (statusBarPipelineFlags.useNewMobileIcons()) {
            scope.launch {
                isCollecting = true
                mobileIconsViewModel.subscriptionIdsFlow.collectLatest {
                    logger.logUiAdapterSubIdsSentToIconController(it)
                    lastValue = it
                    iconController.setNewMobileIconSubIds(it)
                }
            }
        }
    }

MobileViewLogger.kt log.
VerboseMobileViewLogger.kt log.

4 util

MobileMappings.kt ⾥⾯是proxy,提供对外⽅法

1 MobileMappingsProxyImpl
2 # fun mapIconSets(config: Config): Map<String, MobileIconGroup>
3 # fun getDefaultIcons(config: Config): MobileIconGroup
4 # fun getIconKey(displayInfo: TelephonyDisplayInfo): String
5 # fun toIconKey(@NetworkType networkType: Int): String
6 # fun toIconKeyOverride(@NetworkType networkType: Int): String

SubscriptionManagerProxy.kt

1 SubscriptionManagerProxyImpl
2 # fun getDefaultDataSubscriptionId(): Int

Wifi

pipeline-wifi

1 data

1.1 repository

repository层是MVVM框架中⽤于解耦业务逻辑和数据的独⽴的⼀层:

https://www.jianshu.com/p/4679c384acae

1 # WifiRepository.kt
2
3 // 声明变量;具体实现在prod下的两个类中;Disabled开头是禁⽤下的
4 // 对应WifiStatusTracker
5 // wifi是否开启,对应enabled
6 val isWifiEnabled: StateFlow<Boolean>
7 // 对应isWifi
8 val isWifiDefault: StateFlow<Boolean>
9 // 连接变化和中断的回调,对应mNetworkCallback
10 val wifiNetwork: StateFlow<WifiNetworkModel>
11 // 上下⾏
12 val wifiActivity: StateFlow<DataActivityModel>
# WifiRepositorySwitcher.kt

// 根据demo mode开启状态,切换数据源是真实数据还是demo数据;该类上⽅的注释详细的描述了

/**
 * Provides the [WifiRepository] interface either through the [DemoWifiRepository] implementation,
 * or the [WifiRepositoryImpl]'s prod implementation, based on the current demo mode value. In this
 * way, downstream clients can all consist of real implementations and not care about which
 * repository is responsible for the data. Graphically:
 * ```
 * RealRepository
 *                 │
 *                 ├──►RepositorySwitcher──►RealInteractor──►RealViewModel
 *                 │
 * DemoRepository
 * ```
 *
 * When demo mode turns on, every flow will [flatMapLatest] to the current provider's version of
 * that flow.
 */

2 domain

2.1 interactor

WifiInteractor.kt.
业务逻辑层,对应MiuiWifiSignalController.java中copyWifiStates(),将wifi变化后的数据传给实际应⽤的bean类中

3 shared

3.1 model

WifiNetworkModel.kt.
sealed class:https://blog.csdn.net/qq_33552379/article/details/125996716,类似枚举,但只能在当前类中去声明

1 Unavailable:wifi不可⽤,WifiManager为null
2 Invalid:wifi信息⽆效
3 Inactive:⽆有效的wifi⽹络
4 CarrierMerged:该模型表⽰我们的 WiFi ⽹络实际上是运营商合并⽹络,这意味着它更像是移动⽹络
5 Active:有效的wifi⽹络

WifiConstants.kt.
alwaysShowIconIfEnabled:是否⼀直显⽰wifi icon;miui⽬前逻辑不需要这个,适配的时候改成false

WifiInputLogger.kt.
为repository提供log⽅法

4 ui

4.1 binder

WifiViewBinder.kt.
根据数据为wifi icon更新UI显⽰,对应StatusBarWifiView.java;
pipeline中UI类替换成了ModernStatusBarWifiView.kt,具体UI显⽰逻辑移到了binder类中return值:改类返回⼀个ModernStatusBarViewBinding对象,实现需要对外提供信息的接⼝;对外提供其他数据可在该接⼝中增加⽅法并实现.

4.2 model

WifiIcon.kt.
sealed class;内部⼦类有两个 Visible和Hidden,在WifiViewBinder和WifiViewModel中使⽤.

4.3 view

ModernStatusBarWifiView.kt.
包含inflate时的布局,其他逻辑都交由binder中处理

4.4 viewmodel

WifiViewModelCommon.kt.

1 // 接⼝,声明变量
2 // wifi icon是否可⻅
3 val wifiIcon: StateFlow<WifiIcon>
4 // 上下⾏是否可⻅
5 val isActivityInViewVisible: Flow<Boolean>
6 val isActivityOutViewVisible: Flow<Boolean>
7 val isActivityContainerVisible: Flow<Boolean>
8 // ⻜⾏模式图标是否可⻅
9 val isAirplaneSpacerVisible: Flow<Boolean>
10 //
11 val isSignalSpacerVisible: Flow<Boolean>

WifiViewModel.kt.

  1. 实现了WifiViewModelCommon接⼝;WifiViewModel是单例,不能直接它来控制view;⽽是使⽤LocationBasedWifiViewModel,它其中声明了多个不同情况下的viewmodel
  2. 如上⽅2.1所述,wifi状态变化的数据被存放在WifiInteractor中;WifiViewModel中使⽤WifiInteractor的数据,计算出控件是否需要显⽰.
// 此处对应wifi icon图⽚的获取;
// miui⽬前新增逻辑,在MiuiStatusBarSignalPolicy和MiuiWifiSignalController有定制;
// 可通过WifiIcons的引⽤进⾏查找;适配wifi 7、热点等图⽚需要在这⾥
private fun WifiNetworkModel.icon(): WifiIcon {
        return when (this) {
            // 不可⽤、⾮wifi情况下隐藏
            is WifiNetworkModel.Unavailable -> WifiIcon.Hidden
            is WifiNetworkModel.Invalid -> WifiIcon.Hidden
            is WifiNetworkModel.CarrierMerged -> WifiIcon.Hidden
            is WifiNetworkModel.Inactive ->
                WifiIcon.Visible(
                    res = WIFI_NO_NETWORK,
                    ContentDescription.Loaded(
                        "${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}"
                    )
                )
            // 可⽤情况下,需要额外增加miui图⽚选择的逻辑
            is WifiNetworkModel.Active -> {
                val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level])
                when {
                    this.isValidated ->
                        WifiIcon.Visible(
                            WIFI_FULL_ICONS[this.level],
                            ContentDescription.Loaded(levelDesc),
                        )
                    else ->
                        WifiIcon.Visible(
                            WIFI_NO_INTERNET_ICONS[this.level],
                            ContentDescription.Loaded(
                                "$levelDesc,${context.getString(NO_INTERNET)}"
                            ),
                        )
                }
            }
        }
    }

LocationBasedWifiViewModel.kt
WifiViewModel是单例,不能直接使⽤来操作view显⽰,需通过LocationBasedWifiViewModel中的三个⼦类,来操作不同情况下的view:

HomeWifiViewModel
KeyguardWifiViewModel
QsWifiViewModel

⽬前看到的区别是打出的log、debug下的tint不同

5 WifiUiAdapter.kt

单例;连接旧版UI和新pipeline数据的adapter类;
⽬前使⽤pipeline时,也需要通过iconManager将icon加⼊iconGroup;
注释标明随着后续pipeline逐渐完善,会优化这⾥

	fun bindGroup(
        statusBarIconGroup: ViewGroup,
        location: StatusBarLocation,
    ): LocationBasedWifiViewModel {
        val locationViewModel =
            viewModelForLocation(wifiViewModel, statusBarPipelineFlags, location)

        statusBarIconGroup.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    locationViewModel.wifiIcon.collect { wifiIcon ->
                        // Only notify the icon controller if we want to *render* the new icon.
                        // Note that this flow may still run if
                        // [statusBarPipelineFlags.runNewWifiIconBackend] is true because we may
                        // want to get the logging data without rendering.
                        if (
                            wifiIcon is WifiIcon.Visible && statusBarPipelineFlags.useNewWifiIcon()
                        ) {
                            iconController.setNewWifiIcon()
                        }
                    }
                }
            }
        }

        return locationViewModel
    }

Shared

提供Mobile和Wifi使⽤的公共部分;提供CollapsedStatusBarFragment相关的控制类

pipeline-shared

1 data

1.1 model

ConnectivitySlots.kt.

1 airplaneSlot
2 mobileSlot
3 wifiSlot
4 ethernetSlot

DataActivityModel.kt 存放上下⾏数据
DefaultConnectionModel.kt

1.2 repository

ConnectivityRepository.kt

forceHiddenSlots :是否强制隐藏slots;当前pipeline中的icon,都有isForceHidden这个变量,信号、Wifi、⻜⾏模式
defaultConnections:default连接对应WifiStatusTracker中的mDefaultNetworkCallback
vcnSubId :TODO 没找到好的解释。。使⽤上在MobileIconsInteractor.filteredSubscriptions
			carrierConfigTracker.alwaysShowPrimarySignalBarInOpportunisticNetworkDefault

2 ui

2.1 binder

CollapsedStatusBarViewBinder.kt

# CollapsedStatusBarFragment.onViewCreated

// 此处进⾏bind
mCollapsedStatusBarViewBinder.bind(
                mStatusBar, mCollapsedStatusBarViewModel, mStatusBarVisibilityChangeListener);

# CollapsedStatusBarViewBinderImpl

// 为viewmodel中的两个变量增加回调
override fun bind(
        view: View,
        viewModel: CollapsedStatusBarViewModel,
        listener: StatusBarVisibilityChangeListener,
    ) {
        view.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                launch {
                    viewModel.isTransitioningFromLockscreenToOccluded.collect {
                        listener.onStatusBarVisibilityMaybeChanged()
                    }
                }

                launch {
                    viewModel.transitionFromLockscreenToDreamStartedEvent.collect {
                        listener.onTransitionFromLockscreenToDreamStarted()
                    }
                }
            }
        }
    }

# CollapsedStatusBarFragment

// listener具体实现的位置
private StatusBarVisibilityChangeListener mStatusBarVisibilityChangeListener =
            new StatusBarVisibilityChangeListener() {
                @Override
                public void onStatusBarVisibilityMaybeChanged() {
                	// 触发状态栏visibility的计算
                    updateStatusBarVisibilities(/* animate= */ true);
                }

                @Override
                public void onTransitionFromLockscreenToDreamStarted() {
                	// 该变量⽤于shouldHideStatusBar()中的判断
                    mTransitionFromLockscreenToDreamStarted = true;
                }
            };

ModernStatusBarViewBinding.kt 为2.2 ModernStatusBarView声明必须实现的接⼝

2.2 view

ModernStatusBarView.kt 新版的mobile和wifi icon的⽗类,提供⼀些公共⽅法

2.3 viewmodel

CollapsedStatusBarViewModel.kt 根据设备状态,控制CollapsedStatusBarFragment的visibility
但是⽬前逻辑没有完全迁过来,当前类中只有两个变量:

1 isTransitioningFromLockscreenToOccluded :如果设备当前正在从锁定屏幕转换为遮挡屏幕
2 transitionFromLockscreenToDreamStartedEvent:每当从锁屏到屏保的转换开始时发出

PS:DreamManager:https://blog.51cto.com/u_16213432/9289886
这两个变量控制的是:

# CollapsedStatusBarFragment.shouldHideStatusBar()

// While the status bar is transitioning from lockscreen to an occluded, we don't yet know
// if the occluding activity is fullscreen or not. If it *is* fullscreen, we don't want to
// briefly show the status bar just to immediately hide it again. So, we wait for the
// transition to occluding to finish before allowing us to potentially show the status bar
// again. (This status bar is always hidden on keyguard, so it's safe to continue hiding it
 // during this transition.) See b/273314977.
if (mCollapsedStatusBarViewModel.isTransitioningFromLockscreenToOccluded().getValue()) {
    return true;
}

# transitionFromLockscreenToDreamStartedEvent⻅2.1 CollapsedStatusBarViewBinder

3 others

ConnectivityConstants.kt

1 hasDataCapabilities      :telephonyManager.isDataCapable
2 shouldShowActivityConfig :R.bool.config_showActivity

ConnectivityInputLogger.kt log
LoggerHelper.kt log


写在后面

如果文章中有错误的地方,希望各位大佬们批评指正~

If you like this article, it is written by Johnny Deng.
If not, I don’t know who wrote it.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1520960.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flask库

文章目录 flask库1. 基本使用2. 路由路径和路由参数3. 请求跳转和请求参数4. 模板渲染1. 模板变量2. 过滤器3. 测试器 5. 钩子函数与响应对象 flask库 flask是python编写的轻量级框架&#xff0c;提供Werkzeug&#xff08;WSGI工具集&#xff09;和jinjia2&#xff08;渲染模板…

SpringBoot+Vue.js协同过滤算法美食推荐小程序

摘 要 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对各种需求进行规范而严格是十分有必要的&#xff0c;所以许许多多的微信小程序应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套协同过滤算法美食推荐小程序&#xff0c;帮助…

【SQL Server】实验四 数据更新

1 实验目的 掌握SQL数据更新语句的基本使用方法&#xff0c;如UPDATE、DELETE、INSERT。掌握更新语句条件中的嵌套查询使用方法。 2 实验内容 2.1 掌握SQL更新语句的基本使用方法 INSERT基本语句。UPDATE基本语句。DELETE基本语句。 2.2 掌握SQL更新语句的高级使用方法 …

SimpleDateFormat类 --java学习笔记

SimpleDateFormat 代表简单日期格式化&#xff0c;可以用来把日期对象、时间毫秒值格式化成我们想要的形式 常见构造器和方法&#xff1a; pattern 代表需要应用的时间格式—— 时间格式的常见符号&#xff1a; 时间格式的应用举例&#xff1a; import java.text.SimpleDate…

(二)丶RabbitMQ的六大核心

一丶什么是MQ Message Queue(消息队列&#xff09;简称MQ&#xff0c;是一种应用程序对应用程序的消息通信机制。在MQ中&#xff0c;消息以队列形式存储&#xff0c;以便于异步传输&#xff0c;在MQ中&#xff0c;发布者&#xff08;生产者&#xff09;将消息放入队列&#xff…

基于信号分解的几种一维时间序列降噪方法(MATLAB R2021B)

自适应信号分解算法是一种适合对非平稳信号分析的方法&#xff0c;它将一个信号分解为多个模态叠加的形式&#xff0c;进而可以准确反应信号中所包含的频率分量以及瞬时频率随时间变化的规律。自适应信号分解算法与众多“刚性”方法(如傅里叶变换&#xff0c;小波变换)不同&…

最后十几天!未备案小程序将会被清退

微信官方通知 2023年8月9日&#xff0c;微信公众平台发布了“关于开展微信小程序备案的通知”&#xff1a; 去年就已经在逐步推进备案了&#xff0c;新注册小程序必须备案才可以上架。若微信小程序已上架&#xff0c;须于2024年3月31日前完成备案&#xff0c;逾期未完成备案&a…

苹果大模型MM1强势来袭!300亿参数所向披靡

功能展示 左图问&#xff1a;图片中有多少个苹果&#xff1f; 苹果大模型答&#xff1a;7个 左图问&#xff1a;这些州中哪一个是最北的&#xff1f; 回答&#xff1a;Delaware 追问&#xff1a;其他的州是什么&#xff1f; 回答&#xff1a;Arizona, Oklahoma, North Caro…

Ant Design Pro complete版本的下载及运行

前言 complete 版本提供了很多基础、美观的页面和组件&#xff0c;对于前端不太熟练的小白十分友好&#xff0c;可以直接套用或者修改提供的代码完成自己的页面开发&#xff0c;简直不要太爽。故记录一些下载的步骤。 环境 E:\code>npm -v 9.8.1E:\code>node -v v18.1…

[HTML]Web前端开发技术24(HTML5、CSS3、JavaScript )JavaScript基础JavaScript,Netscape,事件处理代码,外部JS——喵喵画网页

希望你开心&#xff0c;希望你健康&#xff0c;希望你幸福&#xff0c;希望你点赞&#xff01; 最后的最后&#xff0c;关注喵&#xff0c;关注喵&#xff0c;关注喵&#xff0c;佬佬会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我真的…

Java学习笔记(12)

包 导包 Final 不能被改变的&#xff0c;修饰方法 类 变量 方法不能被重写 类不能被继承 变量&#xff0c;赋值一次&#xff0c;变成常量&#xff0c;不能再被赋值 final修饰引用数据类型&#xff0c;地址值不能变&#xff0c;里面的内容可以变 字符串是不可变的 源码中使…

ubuntu(20.04)-安装JAVA环境-IDEA

1.下载IDEA 2.解压文件 sudo tar -zxvf idealC-2022.2.3.tar.gz -C /opt 3.添加环境变量&#xff1a; .vim ~/.bashrc export IDEA_HOME/opt/ideaIC-2022.2.3/ export PATH${IDEA_HOME}/bin:$PATH source ~/.bashrc 4.启动&#xff1a; cd /opt/ideaIC-2…

安装jupyter报错:404 GET /static/notebook/4131.bundle.js

1、报错安装过程 我直接是pip install jupyter 进行的安装&#xff0c;如下&#xff0c;安装的版本是7.1.2 2、报错结果 运行jupyternotebook后报错&#xff1a;404 GET /static/notebook/4131.bundle.js (3bea7012d1534d70a935c3c193d9308d127.0.0.1) 5.70ms refererht…

cf(163)

D. Tandem Repeats? 找最长串联字串的长度 #include<iostream> #include<algorithm> #include<cstring> #include<queue> #include<vector> #include<map> using namespace std; typedef pair<int,int>PII; typedef long long ll…

ThingsBoard Edge 安装部署

文章目录 一、概述1.官方文档2.部署说明3.安装准备3.1. 克隆服务器3.2.安装 Docker3.3.安装 Java 113.4.安装 PostgreSQL3.5.下载安装包 二、安装部署1.创建 Edge 实例2.创建数据库3.Edge 服务安装3.1.安装服务3.2.配置 Edge3.3.运行安装脚本3.4.重新启动服务 4.访问 Edge5.故障…

基于ssm+layui的图书管理系统

基于ssmlayui的图书管理系统 账户类型分为&#xff1a;管理员&#xff0c;用户管理员私有功能用户私有功能公共功能技术栈功能实现图 视频演示 账户类型分为&#xff1a;管理员&#xff0c;用户 图书管理系统主要登录账户类型为管理员账户与用户账户 管理员私有功能 账户管理…

算法的渐进时间复杂度

T(n) = O(F(n)) T(n):Time 渐进时间复杂度 O:正比例关系 F(n):代码执行次数 只要代码执行的次数越来越多 所耗费的时间也就越来越高 常见的5种: O(n^2) O(n logn) O(n) O(logn) O(1):不管重复多少次1次也是这个时间,10次也是这个时间。 时间复杂度排序:由小到…

关于如何在BIOS中设置引导顺序,看这篇文章就差不多了

前言 更改计算机上“可引导”设备(如USB端口、软盘驱动器或光盘驱动器中的硬盘驱动器或可引导介质)的引导顺序非常容易。 为什么要更改引导顺序 有几个场景需要更改引导顺序,例如启动一些数据销毁工具和可引导防病毒程序,以及安装操作系统。 BIOS设置实用程序用于更改引…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:ScrollBar)

滚动条组件ScrollBar&#xff0c;用于配合可滚动组件使用&#xff0c;如List、Grid、Scroll。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 可以包含单个子组件。 接口 ScrollBar(val…

C++ 入门篇

目录 1、了解C 2、C关键字 2、命名空间 2.1 命名空间的定义 2.2 命名空间的使用 3. C输入与输出 4.缺省参数 4.1 缺省参数的概念 4.2 缺省参数的分类 5. 函数重载 5.1 函数重载的概念 5.2 C中支持函数重载的原理--名字修饰 6. 引用 6.1 引用概念 6.2 引用…