1 /*
2  * Copyright (C) 2023 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.mobile.domain.model
18 
19 import com.android.settingslib.graph.SignalDrawable
20 import com.android.systemui.common.shared.model.Icon
21 import com.android.systemui.log.table.Diffable
22 import com.android.systemui.log.table.TableRowLogger
23 
24 sealed interface SignalIconModel : Diffable<SignalIconModel> {
25     val level: Int
26 
logDiffsnull27     override fun logDiffs(prevVal: SignalIconModel, row: TableRowLogger) {
28         logPartial(prevVal, row)
29     }
30 
logFullnull31     override fun logFull(row: TableRowLogger) = logFully(row)
32 
33     fun logFully(row: TableRowLogger)
34 
35     fun logPartial(prevVal: SignalIconModel, row: TableRowLogger)
36 
37     /** A model that will be consumed by [SignalDrawable] to show the mobile triangle icon. */
38     data class Cellular(
39         override val level: Int,
40         val numberOfLevels: Int,
41         val showExclamationMark: Boolean,
42         val carrierNetworkChange: Boolean,
43     ) : SignalIconModel {
44         override fun logPartial(prevVal: SignalIconModel, row: TableRowLogger) {
45             if (prevVal !is Cellular) {
46                 logFull(row)
47             } else {
48                 if (prevVal.level != level) {
49                     row.logChange(COL_LEVEL, level)
50                 }
51                 if (prevVal.numberOfLevels != numberOfLevels) {
52                     row.logChange(COL_NUM_LEVELS, numberOfLevels)
53                 }
54                 if (prevVal.showExclamationMark != showExclamationMark) {
55                     row.logChange(COL_SHOW_EXCLAMATION, showExclamationMark)
56                 }
57                 if (prevVal.carrierNetworkChange != carrierNetworkChange) {
58                     row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChange)
59                 }
60             }
61         }
62 
63         override fun logFully(row: TableRowLogger) {
64             row.logChange(COL_TYPE, "c")
65             row.logChange(COL_LEVEL, level)
66             row.logChange(COL_NUM_LEVELS, numberOfLevels)
67             row.logChange(COL_SHOW_EXCLAMATION, showExclamationMark)
68             row.logChange(COL_CARRIER_NETWORK_CHANGE, carrierNetworkChange)
69         }
70 
71         /** Convert this model to an [Int] consumable by [SignalDrawable]. */
72         fun toSignalDrawableState(): Int =
73             if (carrierNetworkChange) {
74                 SignalDrawable.getCarrierChangeState(numberOfLevels)
75             } else {
76                 SignalDrawable.getState(level, numberOfLevels, showExclamationMark)
77             }
78     }
79 
80     /**
81      * For non-terrestrial networks, we can use a resource-backed icon instead of the
82      * [SignalDrawable]-backed version above
83      */
84     data class Satellite(
85         override val level: Int,
86         val icon: Icon.Resource,
87     ) : SignalIconModel {
logPartialnull88         override fun logPartial(prevVal: SignalIconModel, row: TableRowLogger) {
89             if (prevVal !is Satellite) {
90                 logFull(row)
91             } else {
92                 if (prevVal.level != level) row.logChange(COL_LEVEL, level)
93             }
94         }
95 
logFullynull96         override fun logFully(row: TableRowLogger) {
97             // Satellite icon has only 3 levels, unchanging
98             row.logChange(COL_NUM_LEVELS, "3")
99             row.logChange(COL_TYPE, "s")
100             row.logChange(COL_LEVEL, level)
101         }
102     }
103 
104     companion object {
105         private const val COL_LEVEL = "level"
106         private const val COL_NUM_LEVELS = "numLevels"
107         private const val COL_SHOW_EXCLAMATION = "showExclamation"
108         private const val COL_CARRIER_NETWORK_CHANGE = "carrierNetworkChange"
109         private const val COL_TYPE = "type"
110     }
111 }
112