1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.pipeline.wifi.ui.model 18 19 import android.annotation.DrawableRes 20 import android.content.Context 21 import androidx.annotation.StringRes 22 import androidx.annotation.VisibleForTesting 23 import com.android.settingslib.AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH 24 import com.android.settingslib.AccessibilityContentDescriptions.WIFI_NO_CONNECTION 25 import com.android.settingslib.AccessibilityContentDescriptions.WIFI_OTHER_DEVICE_CONNECTION 26 import com.android.systemui.common.shared.model.ContentDescription 27 import com.android.systemui.common.shared.model.Icon 28 import com.android.systemui.log.table.Diffable 29 import com.android.systemui.log.table.TableRowLogger 30 import com.android.systemui.res.R 31 import com.android.systemui.statusbar.connectivity.WifiIcons 32 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel 33 34 /** Represents the various states of the wifi icon. */ 35 sealed interface WifiIcon : Diffable<WifiIcon> { 36 /** Represents a wifi icon that should be hidden (not visible). */ 37 object Hidden : WifiIcon { toStringnull38 override fun toString() = "hidden" 39 } 40 41 /** 42 * Represents a visible wifi icon that uses [res] as its image and [contentDescription] as its 43 * description. 44 */ 45 class Visible( 46 @DrawableRes val res: Int, 47 val contentDescription: ContentDescription.Loaded, 48 ) : WifiIcon { 49 val icon = Icon.Resource(res, contentDescription) 50 51 override fun toString() = contentDescription.description.toString() 52 } 53 logDiffsnull54 override fun logDiffs(prevVal: WifiIcon, row: TableRowLogger) { 55 if (prevVal.toString() != toString()) { 56 row.logChange(COL_ICON, toString()) 57 } 58 } 59 logFullnull60 override fun logFull(row: TableRowLogger) { 61 row.logChange(COL_ICON, toString()) 62 } 63 64 companion object { 65 @StringRes 66 @VisibleForTesting 67 internal val NO_INTERNET = R.string.data_connection_no_internet 68 69 /** 70 * Mapping from a [WifiNetworkModel] to the appropriate [WifiIcon]. 71 * 72 * @param showHotspotInfo true if the wifi icon should represent the hotspot device (if it 73 * exists) and false if the wifi icon should only ever show the wifi level and *not* the 74 * hotspot device. 75 */ fromModelnull76 fun fromModel( 77 model: WifiNetworkModel, 78 context: Context, 79 showHotspotInfo: Boolean, 80 ): WifiIcon = 81 when (model) { 82 is WifiNetworkModel.Unavailable -> Hidden 83 is WifiNetworkModel.Invalid -> Hidden 84 is WifiNetworkModel.CarrierMerged -> Hidden 85 is WifiNetworkModel.Inactive -> 86 Visible( 87 res = WifiIcons.WIFI_NO_NETWORK, 88 ContentDescription.Loaded( 89 "${context.getString(WIFI_NO_CONNECTION)},${context.getString( 90 NO_INTERNET 91 )}" 92 ) 93 ) 94 is WifiNetworkModel.Active -> model.toIcon(showHotspotInfo, context) 95 } 96 toIconnull97 private fun WifiNetworkModel.Active.toIcon( 98 showHotspotInfo: Boolean, 99 context: Context, 100 ): Visible { 101 return if ( 102 !showHotspotInfo || 103 this.hotspotDeviceType == WifiNetworkModel.HotspotDeviceType.NONE 104 ) { 105 this.toBasicIcon(context) 106 } else { 107 val icon = 108 when (this.hotspotDeviceType) { 109 WifiNetworkModel.HotspotDeviceType.TABLET -> 110 com.android.settingslib.R.drawable.ic_hotspot_tablet 111 WifiNetworkModel.HotspotDeviceType.LAPTOP -> 112 com.android.settingslib.R.drawable.ic_hotspot_laptop 113 WifiNetworkModel.HotspotDeviceType.WATCH -> 114 com.android.settingslib.R.drawable.ic_hotspot_watch 115 WifiNetworkModel.HotspotDeviceType.AUTO -> 116 com.android.settingslib.R.drawable.ic_hotspot_auto 117 // Use phone as the default drawable 118 WifiNetworkModel.HotspotDeviceType.PHONE, 119 WifiNetworkModel.HotspotDeviceType.UNKNOWN, 120 WifiNetworkModel.HotspotDeviceType.INVALID -> 121 com.android.settingslib.R.drawable.ic_hotspot_phone 122 WifiNetworkModel.HotspotDeviceType.NONE -> 123 throw IllegalStateException("NONE checked earlier") 124 } 125 Visible( 126 icon, 127 ContentDescription.Loaded(context.getString(WIFI_OTHER_DEVICE_CONNECTION)), 128 ) 129 } 130 } 131 toBasicIconnull132 private fun WifiNetworkModel.Active.toBasicIcon(context: Context): Visible { 133 val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level]) 134 return if (this.isValidated) { 135 Visible( 136 WifiIcons.WIFI_FULL_ICONS[this.level], 137 ContentDescription.Loaded(levelDesc), 138 ) 139 } else { 140 Visible( 141 WifiIcons.WIFI_NO_INTERNET_ICONS[this.level], 142 ContentDescription.Loaded("$levelDesc,${context.getString(NO_INTERNET)}"), 143 ) 144 } 145 } 146 } 147 } 148 149 private const val COL_ICON = "icon" 150