2 * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
6 * Privacy Cell is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Cell is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Cell. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacycell.activities
22 import android.Manifest
23 import android.content.Context
24 import android.content.Intent
25 import android.content.pm.PackageManager
26 import android.net.Uri
27 import android.os.Bundle
28 import android.telephony.PhoneStateListener
29 import android.telephony.ServiceState
30 import android.telephony.TelephonyDisplayInfo
31 import android.telephony.TelephonyManager
32 import android.view.MenuItem
33 import android.view.View
34 import android.widget.ImageView
35 import android.widget.LinearLayout
36 import android.widget.TextView
38 import androidx.appcompat.app.ActionBar
39 import androidx.appcompat.app.ActionBarDrawerToggle
40 import androidx.appcompat.app.AppCompatActivity
41 import androidx.appcompat.content.res.AppCompatResources
42 import androidx.appcompat.widget.Toolbar
43 import androidx.core.app.ActivityCompat
44 import androidx.core.view.GravityCompat
45 import androidx.drawerlayout.widget.DrawerLayout
47 import com.google.android.material.navigation.NavigationView
49 import com.stoutner.privacycell.R
50 import com.stoutner.privacycell.dialogs.PhonePermissionDialog
51 import com.stoutner.privacycell.dialogs.WebViewDialog
53 class PrivacyCell : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
54 // Declare the class variables.
55 private lateinit var context: Context
56 private lateinit var telephonyManager: TelephonyManager
57 private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
60 private lateinit var drawerLayout: DrawerLayout
61 private lateinit var stingrayLinearLayout: LinearLayout
62 private lateinit var stingrayImageView: ImageView
63 private lateinit var stingrayTextView: TextView
64 private lateinit var voiceNetworkLinearLayout: LinearLayout
65 private lateinit var voiceNetworkTextView: TextView
66 private lateinit var voiceNetworkDetailsTextView: TextView
67 private lateinit var dataNetworkLinearLayout: LinearLayout
68 private lateinit var dataNetworkTextView: TextView
69 private lateinit var dataNetworkDetailsTextView: TextView
70 private lateinit var additionalNetworkInfoLinearLayout: LinearLayout
71 private lateinit var additionalNetworkInfoTextView: TextView
72 private lateinit var additionalNetworkInfoDetailsTextView: TextView
74 override fun onCreate(savedInstanceState: Bundle?) {
75 // Run the default commands.
76 super.onCreate(savedInstanceState)
78 // Set the content view.
79 setContentView(R.layout.privacy_cell_drawerlayout)
81 // Get handles for the views.
82 drawerLayout = findViewById(R.id.drawerlayout)
83 val toolbar = findViewById<Toolbar>(R.id.toolbar)
84 stingrayLinearLayout = findViewById(R.id.stingray_linearlayout)
85 stingrayImageView = findViewById(R.id.stingray_imageview)
86 stingrayTextView = findViewById(R.id.stingray_textview)
87 voiceNetworkLinearLayout = findViewById(R.id.voice_network_linearlayout)
88 voiceNetworkTextView = findViewById(R.id.voice_network)
89 voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details)
90 dataNetworkLinearLayout = findViewById(R.id.data_network_linearlayout)
91 dataNetworkTextView = findViewById(R.id.data_network)
92 dataNetworkDetailsTextView = findViewById(R.id.data_network_details)
93 additionalNetworkInfoLinearLayout = findViewById(R.id.additional_network_info_linearlayout)
94 additionalNetworkInfoTextView = findViewById(R.id.additional_network_info)
95 additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details)
96 val navigationView = findViewById<NavigationView>(R.id.navigationview)
98 // Get handles for the context and the telephony manager.
100 telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
102 // Set the support action bar.
103 setSupportActionBar(toolbar)
105 // Get a handle for the action bar.
106 val actionBar = supportActionBar!!
108 // Set a custom view on the action bar.
109 actionBar.setCustomView(R.layout.app_bar_textview)
111 // Display the custom view.
112 actionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
114 // Define a hamburger icon at the start of the app bar. It will be populated in `onPostCreate()`.
115 actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer)
117 // Listen for touches on the navigation menu.
118 navigationView.setNavigationItemSelectedListener(this)
120 // Add a drawer listener.
121 drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
122 override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
126 override fun onDrawerOpened(drawerView: View) {
130 override fun onDrawerClosed(drawerView: View) {
131 // Reset the drawer icon when the drawer is closed. Otherwise, it is an arrow if the drawer is open when the app is restarted.
132 actionBarDrawerToggle.syncState()
135 override fun onDrawerStateChanged(newState: Int) {
141 override fun onPostCreate(savedInstanceState: Bundle?) {
142 // Run the default commands.
143 super.onPostCreate(savedInstanceState)
145 // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished. This creates the navigation drawer icon.
146 actionBarDrawerToggle.syncState()
149 override fun onResume() {
150 // Run the default commands.
153 // Check to see if the read phone state permission has been granted. These commands need to be run on every resume so that the listener gets reassigned as it is automatically paused.
154 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted.
155 // Populate Privacy Cell.
156 populatePrivacyCell()
157 } else { // The phone permission has not been granted.
158 // Check if the user has previously denied the storage permission.
159 if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) { // Show a dialog explaining the request first.
160 // Check to see if a phone permission dialog is already displayed. This happens if the app is restarted when the dialog is shown.
161 if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) { // No dialog is currently shown.
162 // Instantiate the phone permission dialog fragment.
163 val phonePermissionDialogFragment = PhonePermissionDialog()
165 // Show the phone permission alert dialog. The permission will be requested when the dialog is closed.
166 phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission))
168 } else { // Show the permission request directly.
169 // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
170 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
175 override fun onNavigationItemSelected(menuItem: MenuItem) : Boolean {
176 // Run the commands that correspond to the selected menu item.
177 when (menuItem.itemId) {
178 R.id.permissions -> { // Permissions.
179 // Instantiate the permissions dialog fragment.
180 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
182 // Show the alert dialog.
183 permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions))
186 R.id.privacy_policy -> { // Privacy Policy.
187 // Instantiate the privacy policy dialog fragment.
188 val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY)
190 // Show the alert dialog.
191 privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy))
194 R.id.changelog -> { // Changelog.
195 // Instantiate the changelog dialog fragment.
196 val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG)
198 // Show the alert dialog.
199 changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog))
202 R.id.licenses -> { // Licenses.
203 // Instantiate the licenses dialog fragment.
204 val licensesDialogFragment = WebViewDialog().type(WebViewDialog.LICENSES)
206 // Show the alert dialog.
207 licensesDialogFragment.show(supportFragmentManager, getString(R.string.licenses))
210 R.id.contributors -> { // Contributors.
211 // Instantiate the contributors dialog fragment.
212 val contributorsDialogFragment = WebViewDialog().type(WebViewDialog.CONTRIBUTORS)
214 // Show the alert dialog.
215 contributorsDialogFragment.show(supportFragmentManager, getString(R.string.contributors))
218 R.id.news -> { // News.
219 // Create a news URL intent.
220 val newsUrlIntent = Intent(Intent.ACTION_VIEW)
222 // Add the URL to the intent.
223 newsUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell/")
226 startActivity(newsUrlIntent)
229 R.id.roadmap -> { // Roadmap.
230 // Create a roadmap URL intent.
231 val roadmapUrlIntent = Intent(Intent.ACTION_VIEW)
233 // Add the URL to the intent.
234 roadmapUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell-roadmap/")
237 startActivity(roadmapUrlIntent)
240 R.id.bug_tracker -> { // Bug tracker.
241 // Create a bug tracker URL intent.
242 val bugTrackerUrlIntent = Intent(Intent.ACTION_VIEW)
244 // Add the URL to the intent.
245 bugTrackerUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/issues")
248 startActivity(bugTrackerUrlIntent)
251 R.id.forum -> { // Forum.
252 // Create a forum URL intent.
253 val forumUrlIntent = Intent(Intent.ACTION_VIEW)
255 // Add the URL to the intent.
256 forumUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/boards")
259 startActivity(forumUrlIntent)
262 R.id.donations -> { // Donations.
263 // Create a donations URL intent.
264 val donationsUrlIntent = Intent(Intent.ACTION_VIEW)
266 // Add the URL to the intent.
267 donationsUrlIntent.data = Uri.parse("https://www.stoutner.com/donations/")
270 startActivity(donationsUrlIntent)
274 // Close the navigation drawer.
275 drawerLayout.closeDrawer(GravityCompat.START)
277 // Consume the click.
281 override fun onCloseStoragePermissionDialog() {
282 // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0.
283 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
286 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
287 // Run the default commands.
288 super.onRequestPermissionsResult(requestCode, permissions, grantResults)
290 //Only process the results if they exist (this method is triggered when a dialog is presented the first time for an app, but no grant results are included).
291 if (grantResults.isNotEmpty()) {
292 // Check to see if the read phone state permission was granted. If the dialog was canceled the grant results will be empty.
293 if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // The read phone state permission was granted.
294 // Populate Privacy Cell.
295 populatePrivacyCell()
296 } else { // The read phone state permission was denied.
297 // Display the phone permission text on the main activity.
298 stingrayTextView.text = getString(R.string.phone_permission_text)
303 private fun populatePrivacyCell() {
304 // Listen to changes in the cell network state.
305 telephonyManager.listen(object : PhoneStateListener() {
306 override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
307 // Populate the stingray security information. <https://source.android.com/devices/tech/connect/acts-5g-testing>
308 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) { // This is a secure 5G NR SA network.
309 // Populate the image view.
310 stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
313 stingrayTextView.text = getString(R.string.secure_from_stingray)
315 // Set the text color.
316 stingrayTextView.setTextColor(getColor(R.color.blue_text))
317 } else { // This is not a secure 5G NR SA network.
318 // Populate the image view.
319 stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
322 stingrayTextView.text = getString(R.string.not_secure_from_stingray)
324 // Set the text color.
325 stingrayTextView.setTextColor(getColor(R.color.red_text))
328 // Get the strings that correspond to the network information.
329 val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
330 val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
332 // Populate the data network text views.
333 dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
334 dataNetworkDetailsTextView.text = dataNetworkType[1]
335 additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
336 additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
338 // Set the stingray click listener.
339 stingrayLinearLayout.setOnClickListener {
340 // Instantiate the stingray dialog fragment.
341 val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
343 // Show the alert dialog.
344 stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
347 // Set the data network click listener.
348 dataNetworkLinearLayout.setOnClickListener {
349 // Instantiate the data network dialog fragment according to the network type.
350 val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
351 TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
352 TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
353 TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
354 TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
355 TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
356 TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
357 TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
358 TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
359 TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
360 TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
361 TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
362 TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
363 TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
364 TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
365 TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
366 TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
367 TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
368 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
369 TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
370 TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
371 else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
374 // Show the alert dialog.
375 dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
378 // Set the additional network info click listener.
379 additionalNetworkInfoLinearLayout.setOnClickListener {
380 // Instantiate the initial network info dialog fragment according to the network type.
381 val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
382 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
383 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
384 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
385 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
386 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
387 else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
390 // Show the alert dialog.
391 additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
395 override fun onServiceStateChanged(serviceState: ServiceState) {
396 // Get the network registration info for the voice network, which is the second of the three entries (the first appears to be Wi-Fi and the third appears to be the cell data network).
397 val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
399 // Get the voice network type.
400 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
402 // Populate the voice network text views.
403 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
404 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
406 // Set the voice network click listener.
407 voiceNetworkLinearLayout.setOnClickListener {
408 // Instantiate the voice network dialog fragment according to the network type.
409 val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
410 TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
411 TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
412 TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
413 TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
414 TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
415 TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
416 TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
417 TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
418 TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
419 TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
420 TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
421 TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
422 TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
423 TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
424 TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
425 TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
426 TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
427 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
428 TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
429 TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
430 else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
433 // Show the alert dialog.
434 voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
437 }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
440 private fun getNetworkType(networkType: Int) : Array<String> {
441 // Return the string that corresponds to the network type.
442 return when(networkType) {
443 TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
444 TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail))
445 TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
446 TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
447 TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
448 TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
449 TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
450 TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
451 TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
452 TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
453 TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
454 TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
455 TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
456 TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
457 TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
458 TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
459 TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
460 TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
461 TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
462 TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
463 else -> arrayOf(getString(R.string.error), "")
467 private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
468 // Return the string that corresponds to the override network type.
469 return when(overrideNetworkType) {
470 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
471 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
472 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
473 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail))
474 TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail))
475 else -> arrayOf(getString(R.string.error), "")