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.systemui.R
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.statusbar.connectivity.WifiIcons
31 import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
32 
33 /** Represents the various states of the wifi icon. */
34 sealed interface WifiIcon : Diffable<WifiIcon> {
35     /** Represents a wifi icon that should be hidden (not visible). */
36     object Hidden : WifiIcon {
37         override fun toString() = "hidden"
38     }
39 
40     /**
41      * Represents a visible wifi icon that uses [res] as its image and [contentDescription] as its
42      * description.
43      */
44     class Visible(
45         @DrawableRes val res: Int,
46         val contentDescription: ContentDescription.Loaded,
47     ) : WifiIcon {
48         val icon = Icon.Resource(res, contentDescription)
49 
50         override fun toString() = contentDescription.description.toString()
51     }
52 
53     override fun logDiffs(prevVal: WifiIcon, row: TableRowLogger) {
54         if (prevVal.toString() != toString()) {
55             row.logChange(COL_ICON, toString())
56         }
57     }
58 
59     override fun logFull(row: TableRowLogger) {
60         row.logChange(COL_ICON, toString())
61     }
62 
63     companion object {
64         @StringRes
65         @VisibleForTesting
66         internal val NO_INTERNET = R.string.data_connection_no_internet
67 
68         /** Mapping from a [WifiNetworkModel] to the appropriate [WifiIcon] */
69         fun fromModel(model: WifiNetworkModel, context: Context): WifiIcon =
70             when (model) {
71                 is WifiNetworkModel.Unavailable -> Hidden
72                 is WifiNetworkModel.Invalid -> Hidden
73                 is WifiNetworkModel.CarrierMerged -> Hidden
74                 is WifiNetworkModel.Inactive ->
75                     Visible(
76                         res = WifiIcons.WIFI_NO_NETWORK,
77                         ContentDescription.Loaded(
78                             "${context.getString(WIFI_NO_CONNECTION)},${context.getString(
79                                 NO_INTERNET
80                             )}"
81                         )
82                     )
83                 is WifiNetworkModel.Active -> {
84                     val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[model.level])
85                     when {
86                         model.isValidated ->
87                             Visible(
88                                 WifiIcons.WIFI_FULL_ICONS[model.level],
89                                 ContentDescription.Loaded(levelDesc),
90                             )
91                         else ->
92                             Visible(
93                                 WifiIcons.WIFI_NO_INTERNET_ICONS[model.level],
94                                 ContentDescription.Loaded(
95                                     "$levelDesc,${context.getString(NO_INTERNET)}"
96                                 ),
97                             )
98                     }
99                 }
100             }
101     }
102 }
103 
104 private const val COL_ICON = "icon"
105