1 /*
2  * Copyright (C) 2024 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.settings.network.telephony
18 
19 import android.content.Context
20 import android.telephony.AccessNetworkConstants.AccessNetworkType
21 import android.telephony.CellIdentity
22 import android.telephony.CellIdentityCdma
23 import android.telephony.CellIdentityGsm
24 import android.telephony.CellIdentityLte
25 import android.telephony.CellIdentityNr
26 import android.telephony.CellIdentityTdscdma
27 import android.telephony.CellIdentityWcdma
28 import android.telephony.CellInfo
29 import android.telephony.CellInfoCdma
30 import android.telephony.CellInfoGsm
31 import android.telephony.CellInfoLte
32 import android.telephony.CellInfoNr
33 import android.telephony.CellInfoTdscdma
34 import android.telephony.CellInfoWcdma
35 import android.telephony.SignalStrength
36 import android.util.Log
37 import androidx.annotation.OpenForTesting
38 import androidx.preference.Preference
39 import com.android.internal.telephony.OperatorInfo
40 import com.android.settings.R
41 import com.android.settings.network.telephony.CellInfoUtil.getNetworkTitle
42 import com.android.settings.network.telephony.CellInfoUtil.getOperatorNumeric
43 import java.util.Objects
44 
45 /**
46  * A Preference represents a network operator in the NetworkSelectSetting fragment.
47  */
48 @OpenForTesting
49 open class NetworkOperatorPreference(
50     context: Context,
51     private val forbiddenPlmns: List<String>,
52     private val show4GForLTE: Boolean,
53 ) : Preference(context) {
54     private var cellInfo: CellInfo? = null
55     private var cellId: CellIdentity? = null
56     private val useNewApi = context.resources.getBoolean(
57         com.android.internal.R.bool.config_enableNewAutoSelectNetworkUI
58     )
59 
60     /**
61      * Change cell information
62      */
63     @JvmOverloads
updateCellnull64     fun updateCell(cellInfo: CellInfo?, cellId: CellIdentity? = cellInfo?.cellIdentity) {
65         this.cellInfo = cellInfo
66         this.cellId = cellId
67         refresh()
68     }
69 
70     /**
71      * Compare cell within preference
72      */
isSameCellnull73     fun isSameCell(cellInfo: CellInfo): Boolean = cellInfo.cellIdentity == cellId
74 
75     /**
76      * Return true when this preference is for forbidden network
77      */
78     fun isForbiddenNetwork(): Boolean = cellId?.getOperatorNumeric() in forbiddenPlmns
79 
80     /**
81      * Refresh the NetworkOperatorPreference by updating the title and the icon.
82      */
83     fun refresh() {
84         var networkTitle = cellId?.getNetworkTitle() ?: return
85         if (isForbiddenNetwork()) {
86             if (DBG) Log.d(TAG, "refresh forbidden network: $networkTitle")
87             networkTitle += " ${context.getString(R.string.forbidden_network)}"
88         } else {
89             if (DBG) Log.d(TAG, "refresh the network: $networkTitle")
90         }
91         title = networkTitle
92         val level = (cellInfo ?: return).cellSignalStrength.level
93         if (DBG) Log.d(TAG, "refresh level: $level")
94         setIcon(level)
95     }
96 
97     /**
98      * Update the icon according to the input signal strength level.
99      */
setIconnull100     override fun setIcon(level: Int) {
101         if (!useNewApi || level < 0 || level >= SignalStrength.NUM_SIGNAL_STRENGTH_BINS) {
102             return
103         }
104         icon = MobileNetworkUtils.getSignalStrengthIcon(
105             context,
106             level,
107             SignalStrength.NUM_SIGNAL_STRENGTH_BINS,
108             getIconIdForCell(),
109             false,
110             false,
111         )
112     }
113 
114     /**
115      * Operator name of this cell
116      */
getOperatorNamenull117     fun getOperatorName(): String? = cellId?.getNetworkTitle()
118 
119     /**
120      * Operator info of this cell
121      */
122     fun getOperatorInfo() = OperatorInfo(
123         Objects.toString(cellId?.operatorAlphaLong, ""),
124         Objects.toString(cellId?.operatorAlphaShort, ""),
125         cellId?.getOperatorNumeric(),
126         getAccessNetworkTypeFromCellInfo(),
127     )
128 
129     private fun getIconIdForCell(): Int = when (cellId) {
130         is CellIdentityGsm -> R.drawable.signal_strength_g
131         is CellIdentityCdma -> R.drawable.signal_strength_1x
132         is CellIdentityWcdma, is CellIdentityTdscdma -> R.drawable.signal_strength_3g
133 
134         is CellIdentityLte -> {
135             if (show4GForLTE) R.drawable.ic_signal_strength_4g
136             else R.drawable.signal_strength_lte
137         }
138 
139         is CellIdentityNr -> R.drawable.signal_strength_5g
140         else -> MobileNetworkUtils.NO_CELL_DATA_TYPE_ICON
141     }
142 
getAccessNetworkTypeFromCellInfonull143     private fun getAccessNetworkTypeFromCellInfo(): Int = when (cellInfo) {
144         is CellInfoGsm -> AccessNetworkType.GERAN
145         is CellInfoCdma -> AccessNetworkType.CDMA2000
146         is CellInfoWcdma, is CellInfoTdscdma -> AccessNetworkType.UTRAN
147         is CellInfoLte -> AccessNetworkType.EUTRAN
148         is CellInfoNr -> AccessNetworkType.NGRAN
149         else -> AccessNetworkType.UNKNOWN
150     }
151 
152     companion object {
153         private const val TAG = "NetworkOperatorPref"
154         private const val DBG = false
155     }
156 }
157