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

Commit e04e312e authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[SB Refactor] Implement the TunerService callback for the icon hide...

Merge "[SB Refactor] Implement the TunerService callback for the icon hide list and pipe it through to the wifi icon." into tm-qpr-dev
parents 65278634 62b78f59
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.pipeline.dagger

import com.android.systemui.CoreStartable
import com.android.systemui.statusbar.pipeline.ConnectivityInfoProcessor
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryImpl
import dagger.Binds
@@ -33,6 +35,9 @@ abstract class StatusBarPipelineModule {
    @ClassKey(ConnectivityInfoProcessor::class)
    abstract fun bindConnectivityInfoProcessor(cip: ConnectivityInfoProcessor): CoreStartable

    @Binds
    abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository

    @Binds
    abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository
}
+1 −1
Original line number Diff line number Diff line
@@ -34,7 +34,7 @@ class ConnectivityPipelineLogger @Inject constructor(
    /**
     * Logs a change in one of the **raw inputs** to the connectivity pipeline.
     */
    fun logInputChange(callbackName: String, changeInfo: String) {
    fun logInputChange(callbackName: String, changeInfo: String?) {
        buffer.log(
                SB_LOGGING_TAG,
                LogLevel.INFO,
+56 −0
Original line number Diff line number Diff line
/*
 * 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.shared.data.model

import android.content.Context
import com.android.internal.R
import com.android.systemui.dagger.SysUISingleton
import javax.inject.Inject

/**
 * A container for all the different types of connectivity slots: wifi, mobile, etc.
 */
@SysUISingleton
class ConnectivitySlots @Inject constructor(context: Context) {
    private val airplaneSlot: String = context.getString(R.string.status_bar_airplane)
    private val mobileSlot: String = context.getString(R.string.status_bar_mobile)
    private val wifiSlot: String = context.getString(R.string.status_bar_wifi)
    private val ethernetSlot: String = context.getString(R.string.status_bar_ethernet)

    private val slotByName: Map<String, ConnectivitySlot> = mapOf(
        airplaneSlot to ConnectivitySlot.AIRPLANE,
        mobileSlot to ConnectivitySlot.MOBILE,
        wifiSlot to ConnectivitySlot.WIFI,
        ethernetSlot to ConnectivitySlot.ETHERNET
    )

    /**
     * Given a string name of a slot, returns the instance of [ConnectivitySlot] that it corresponds
     * to, or null if we couldn't find that slot name.
     */
    fun getSlotFromName(slotName: String): ConnectivitySlot? {
        return slotByName[slotName]
    }
}

/** The different types of connectivity slots. */
enum class ConnectivitySlot {
    AIRPLANE,
    ETHERNET,
    MOBILE,
    WIFI,
}
+120 −0
Original line number Diff line number Diff line
/*
 * 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.shared.data.repository

import android.content.Context
import androidx.annotation.ArrayRes
import androidx.annotation.VisibleForTesting
import com.android.systemui.Dumpable
import com.android.systemui.R
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.phone.StatusBarIconController
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots
import com.android.systemui.tuner.TunerService
import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn

/**
 * Provides data related to the connectivity state that needs to be shared across multiple different
 * types of connectivity (wifi, mobile, ethernet, etc.)
 */
interface ConnectivityRepository {
    /**
     * Observable for the current set of connectivity icons that should be force-hidden.
     */
    val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>>
}

@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class ConnectivityRepositoryImpl @Inject constructor(
    private val connectivitySlots: ConnectivitySlots,
    context: Context,
    dumpManager: DumpManager,
    logger: ConnectivityPipelineLogger,
    @Application scope: CoroutineScope,
    tunerService: TunerService,
) : ConnectivityRepository, Dumpable {
    init {
        dumpManager.registerDumpable("$SB_LOGGING_TAG:ConnectivityRepository", this)
    }

    // The default set of hidden icons to use if we don't get any from [TunerService].
    private val defaultHiddenIcons: Set<ConnectivitySlot> =
            context.resources.getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE)
                .asList()
                .toSlotSet(connectivitySlots)

    override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = conflatedCallbackFlow {
        val callback = object : TunerService.Tunable {
            override fun onTuningChanged(key: String, newHideList: String?) {
                if (key != HIDDEN_ICONS_TUNABLE_KEY) {
                    return
                }
                logger.logInputChange("onTuningChanged", newHideList)

                val outputList = newHideList?.split(",")?.toSlotSet(connectivitySlots)
                    ?: defaultHiddenIcons
                trySend(outputList)
            }
        }
        tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY)

        awaitClose { tunerService.removeTunable(callback) }
    }
        .stateIn(
            scope,
            started = SharingStarted.WhileSubscribed(),
            initialValue = defaultHiddenIcons
        )

    override fun dump(pw: PrintWriter, args: Array<out String>) {
        pw.apply {
            println("defaultHiddenIcons=$defaultHiddenIcons")
        }
    }

    companion object {
        @VisibleForTesting
        internal const val HIDDEN_ICONS_TUNABLE_KEY = StatusBarIconController.ICON_HIDE_LIST
        @VisibleForTesting
        @ArrayRes
        internal val DEFAULT_HIDDEN_ICONS_RESOURCE = R.array.config_statusBarIconsToExclude

        /** Converts a list of string slot names to a set of [ConnectivitySlot] instances. */
        private fun List<String>.toSlotSet(
            connectivitySlots: ConnectivitySlots
        ): Set<ConnectivitySlot> {
            return this
                .filter { it.isNotBlank() }
                .mapNotNull { connectivitySlots.getSlotFromName(it) }
                .toSet()
        }
    }
}
+13 −4
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar.pipeline.wifi.domain.interactor

import android.net.wifi.WifiManager
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel
import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository
import javax.inject.Inject
@@ -33,9 +35,10 @@ import kotlinx.coroutines.flow.map
 */
@SysUISingleton
class WifiInteractor @Inject constructor(
    repository: WifiRepository,
    connectivityRepository: ConnectivityRepository,
    wifiRepository: WifiRepository,
) {
    private val ssid: Flow<String?> = repository.wifiNetwork.map { info ->
    private val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info ->
        when (info) {
            is WifiNetworkModel.Inactive -> null
            is WifiNetworkModel.CarrierMerged -> null
@@ -49,10 +52,16 @@ class WifiInteractor @Inject constructor(
    }

    /** Our current wifi network. See [WifiNetworkModel]. */
    val wifiNetwork: Flow<WifiNetworkModel> = repository.wifiNetwork
    val wifiNetwork: Flow<WifiNetworkModel> = wifiRepository.wifiNetwork

    /** True if we're configured to force-hide the wifi icon and false otherwise. */
    val isForceHidden: Flow<Boolean> = connectivityRepository.forceHiddenSlots.map {
        it.contains(ConnectivitySlot.WIFI)
    }

    /** True if our wifi network has activity in (download), and false otherwise. */
    val hasActivityIn: Flow<Boolean> = combine(repository.wifiActivity, ssid) { activity, ssid ->
    val hasActivityIn: Flow<Boolean> =
        combine(wifiRepository.wifiActivity, ssid) { activity, ssid ->
            activity.hasActivityIn && ssid != null
        }
}
Loading