Add a logcat activity. https://redmine.stoutner.com/issues/768
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / activities / PrivacyCellActivity.kt
1 /*
2  * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 package com.stoutner.privacycell.activities
21
22 import android.Manifest
23 import android.app.ActivityManager
24 import android.content.Context
25 import android.content.Intent
26 import android.content.pm.PackageManager
27 import android.net.Uri
28 import android.os.Bundle
29 import android.telephony.PhoneStateListener
30 import android.telephony.ServiceState
31 import android.telephony.TelephonyDisplayInfo
32 import android.telephony.TelephonyManager
33 import android.view.MenuItem
34 import android.view.View
35 import android.widget.ImageView
36 import android.widget.LinearLayout
37 import android.widget.TextView
38
39 import androidx.appcompat.app.ActionBar
40 import androidx.appcompat.app.ActionBarDrawerToggle
41 import androidx.appcompat.app.AppCompatActivity
42 import androidx.appcompat.content.res.AppCompatResources
43 import androidx.appcompat.widget.Toolbar
44 import androidx.core.app.ActivityCompat
45 import androidx.core.view.GravityCompat
46 import androidx.drawerlayout.widget.DrawerLayout
47 import androidx.preference.PreferenceManager
48
49 import com.google.android.material.navigation.NavigationView
50
51 import com.stoutner.privacycell.R
52 import com.stoutner.privacycell.dialogs.PhonePermissionDialog
53 import com.stoutner.privacycell.dialogs.WebViewDialog
54 import com.stoutner.privacycell.services.RealtimeMonitoringService
55
56 class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
57     // Declare the class variables.
58     private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
59
60     // Declare the views.
61     private lateinit var drawerLayout: DrawerLayout
62     private lateinit var stingrayLinearLayout: LinearLayout
63     private lateinit var stingrayImageView: ImageView
64     private lateinit var stingrayTextView: TextView
65     private lateinit var voiceNetworkLinearLayout: LinearLayout
66     private lateinit var voiceNetworkTextView: TextView
67     private lateinit var voiceNetworkDetailsTextView: TextView
68     private lateinit var dataNetworkLinearLayout: LinearLayout
69     private lateinit var dataNetworkTextView: TextView
70     private lateinit var dataNetworkDetailsTextView: TextView
71     private lateinit var additionalNetworkInfoLinearLayout: LinearLayout
72     private lateinit var additionalNetworkInfoTextView: TextView
73     private lateinit var additionalNetworkInfoDetailsTextView: TextView
74
75     override fun onCreate(savedInstanceState: Bundle?) {
76         // Run the default commands.
77         super.onCreate(savedInstanceState)
78
79         // Get a handle for the shared preferences.
80         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
81
82         // Get the preferences.
83         val realtimeMonitoring = sharedPreferences.getBoolean(getString(R.string.realtime_monitoring_key), false)
84         val bottomAppBar = sharedPreferences.getBoolean(getString(R.string.bottom_app_bar_key), false)
85
86         // Set the content view.
87         if (bottomAppBar) {
88             setContentView(R.layout.privacy_cell_bottom_appbar)
89         } else {
90             setContentView(R.layout.privacy_cell_top_appbar)
91         }
92
93         // Get handles for the views.
94         drawerLayout = findViewById(R.id.drawerlayout)
95         val toolbar = findViewById<Toolbar>(R.id.toolbar)
96         stingrayLinearLayout = findViewById(R.id.stingray_linearlayout)
97         stingrayImageView = findViewById(R.id.stingray_imageview)
98         stingrayTextView = findViewById(R.id.stingray_textview)
99         voiceNetworkLinearLayout = findViewById(R.id.voice_network_linearlayout)
100         voiceNetworkTextView = findViewById(R.id.voice_network)
101         voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details)
102         dataNetworkLinearLayout = findViewById(R.id.data_network_linearlayout)
103         dataNetworkTextView = findViewById(R.id.data_network)
104         dataNetworkDetailsTextView = findViewById(R.id.data_network_details)
105         additionalNetworkInfoLinearLayout = findViewById(R.id.additional_network_info_linearlayout)
106         additionalNetworkInfoTextView = findViewById(R.id.additional_network_info)
107         additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details)
108         val navigationView = findViewById<NavigationView>(R.id.navigationview)
109
110         // Set the support action bar.
111         setSupportActionBar(toolbar)
112
113         // Get a handle for the action bar.
114         val actionBar = supportActionBar!!
115
116         // Set a custom view on the action bar.
117         actionBar.setCustomView(R.layout.app_bar_textview)
118
119         // Display the custom view.
120         actionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
121
122         // Define a hamburger icon at the start of the app bar.  It will be populated in `onPostCreate()`.
123         actionBarDrawerToggle = ActionBarDrawerToggle(this, drawerLayout, toolbar, R.string.open_navigation_drawer, R.string.close_navigation_drawer)
124
125         // Listen for touches on the navigation menu.
126         navigationView.setNavigationItemSelectedListener(this)
127
128         // Add a drawer listener.
129         drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
130             override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
131                 // Do nothing.
132             }
133
134             override fun onDrawerOpened(drawerView: View) {
135                 // Do nothing.
136             }
137
138             override fun onDrawerClosed(drawerView: View) {
139                 // Reset the drawer icon when the drawer is closed.  Otherwise, it is an arrow if the drawer is open when the app is restarted.
140                 actionBarDrawerToggle.syncState()
141             }
142
143             override fun onDrawerStateChanged(newState: Int) {
144                 // Do nothing.
145             }
146         })
147
148         // Start the realtime monitoring service if it is enabled.
149         if (realtimeMonitoring) {
150             // Get a handle for the activity manager.
151             val activityManager: ActivityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
152
153             // Get a list of the running service info.  The deprecated `getRunningServices()` now only returns services stared by Privacy Cell, but that is all we want to know anyway.
154             val runningServiceInfoList: List<ActivityManager.RunningServiceInfo> = activityManager.getRunningServices(1)
155
156             // Start the service if it is not already running.
157             if (runningServiceInfoList.isEmpty()) {
158                 startService(Intent(this, RealtimeMonitoringService::class.java))
159             }
160         }
161     }
162
163     override fun onPostCreate(savedInstanceState: Bundle?) {
164         // Run the default commands.
165         super.onPostCreate(savedInstanceState)
166
167         // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished.  This creates the navigation drawer icon.
168         actionBarDrawerToggle.syncState()
169     }
170
171     override fun onResume() {
172         // Run the default commands.
173         super.onResume()
174
175         // 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.
176         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
177             // Populate Privacy Cell.
178             populatePrivacyCell(this)
179         } else {  // The phone permission has not been granted.
180             // Check if the user has previously denied the storage permission.
181             if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {  // Show a dialog explaining the request first.
182                 // Check to see if a phone permission dialog is already displayed.  This happens if the app is restarted when the dialog is shown.
183                 if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) {  // No dialog is currently shown.
184                     // Instantiate the phone permission dialog fragment.
185                     val phonePermissionDialogFragment = PhonePermissionDialog()
186
187                     // Show the phone permission alert dialog.  The permission will be requested when the dialog is closed.
188                     phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission))
189                 }
190             } else {  // Show the permission request directly.
191                 // Request the read phone state permission.  There is only one permission request in the app, so it has a request code of 0.
192                 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
193             }
194         }
195     }
196
197     override fun onNavigationItemSelected(menuItem: MenuItem) : Boolean {
198         // Run the commands that correspond to the selected menu item.
199         when (menuItem.itemId) {
200             R.id.settings -> {  // Settings.
201                 // Create an intent to load the Settings activity.
202                 val settingsIntent = Intent(this, SettingsActivity::class.java)
203
204                 // Make it so.
205                 startActivity(settingsIntent)
206             }
207
208             R.id.logcat -> {  // Logcat.
209                 // Create an intent to load the Logcat activity.
210                 val logcatIntent = Intent(this, LogcatActivity::class.java)
211
212                 // Make it so.
213                 startActivity(logcatIntent)
214             }
215
216             R.id.permissions -> {  // Permissions.
217                 // Instantiate the permissions dialog fragment.
218                 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
219
220                 // Show the alert dialog.
221                 permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions))
222             }
223
224             R.id.privacy_policy -> {  // Privacy Policy.
225                 // Instantiate the privacy policy dialog fragment.
226                 val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY)
227
228                 // Show the alert dialog.
229                 privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy))
230             }
231
232             R.id.changelog -> {  // Changelog.
233                 // Instantiate the changelog dialog fragment.
234                 val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG)
235
236                 // Show the alert dialog.
237                 changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog))
238             }
239
240             R.id.licenses -> {  // Licenses.
241                 // Instantiate the licenses dialog fragment.
242                 val licensesDialogFragment = WebViewDialog().type(WebViewDialog.LICENSES)
243
244                 // Show the alert dialog.
245                 licensesDialogFragment.show(supportFragmentManager, getString(R.string.licenses))
246             }
247
248             R.id.contributors -> {  // Contributors.
249                 // Instantiate the contributors dialog fragment.
250                 val contributorsDialogFragment = WebViewDialog().type(WebViewDialog.CONTRIBUTORS)
251
252                 // Show the alert dialog.
253                 contributorsDialogFragment.show(supportFragmentManager, getString(R.string.contributors))
254             }
255
256             R.id.news -> {  // News.
257                 // Create a news URL intent.
258                 val newsUrlIntent = Intent(Intent.ACTION_VIEW)
259
260                 // Add the URL to the intent.
261                 newsUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell/")
262
263                 // Make it so.
264                 startActivity(newsUrlIntent)
265             }
266
267             R.id.roadmap -> {  // Roadmap.
268                 // Create a roadmap URL intent.
269                 val roadmapUrlIntent = Intent(Intent.ACTION_VIEW)
270
271                 // Add the URL to the intent.
272                 roadmapUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell-roadmap/")
273
274                 // Make it so.
275                 startActivity(roadmapUrlIntent)
276             }
277
278             R.id.bug_tracker -> {  // Bug tracker.
279                 // Create a bug tracker URL intent.
280                 val bugTrackerUrlIntent = Intent(Intent.ACTION_VIEW)
281
282                 // Add the URL to the intent.
283                 bugTrackerUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/issues")
284
285                 // Make it so.
286                 startActivity(bugTrackerUrlIntent)
287             }
288
289             R.id.forum -> {  // Forum.
290                 // Create a forum URL intent.
291                 val forumUrlIntent = Intent(Intent.ACTION_VIEW)
292
293                 // Add the URL to the intent.
294                 forumUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/boards")
295
296                 // Make it so.
297                 startActivity(forumUrlIntent)
298             }
299
300             R.id.donations -> {  // Donations.
301                 // Create a donations URL intent.
302                 val donationsUrlIntent = Intent(Intent.ACTION_VIEW)
303
304                 // Add the URL to the intent.
305                 donationsUrlIntent.data = Uri.parse("https://www.stoutner.com/donations/")
306
307                 // Make it so.
308                 startActivity(donationsUrlIntent)
309             }
310         }
311
312         // Close the navigation drawer.
313         drawerLayout.closeDrawer(GravityCompat.START)
314
315         // Consume the click.
316         return true
317     }
318
319     override fun onCloseStoragePermissionDialog() {
320         // Request the read phone state permission.  There is only one permission request in the app, so it has a request code of 0.
321         ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
322     }
323
324     override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
325         // Run the default commands.
326         super.onRequestPermissionsResult(requestCode, permissions, grantResults)
327
328         //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).
329         if (grantResults.isNotEmpty()) {
330             // Check to see if the read phone state permission was granted.  If the dialog was canceled the grant results will be empty.
331             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {  // The read phone state permission was granted.
332                 // Populate Privacy Cell.
333                 populatePrivacyCell(this)
334             } else {  // The read phone state permission was denied.
335                 // Display the phone permission text on the main activity.
336                 stingrayTextView.text = getString(R.string.phone_permission_text)
337             }
338         }
339     }
340
341     private fun populatePrivacyCell(context: Context) {
342         // Get a handle for the telephony manager.
343         val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
344
345         // Listen to changes in the cell network state.
346         telephonyManager.listen(object : PhoneStateListener() {
347             override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
348                 // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
349                 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
350                     // Populate the image view.
351                     stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
352
353                     // Set the text.
354                     stingrayTextView.text = getString(R.string.secure_from_stingray)
355
356                     // Set the text color.
357                     stingrayTextView.setTextColor(getColor(R.color.blue_text))
358                 } else {  // This is not a secure 5G NR SA network.
359                     // Populate the image view.
360                     stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
361
362                     // Set the text.
363                     stingrayTextView.text = getString(R.string.not_secure_from_stingray)
364
365                     // Set the text color.
366                     stingrayTextView.setTextColor(getColor(R.color.red_text))
367                 }
368
369                 // Get the strings that correspond to the network information.
370                 val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
371                 val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
372
373                 // Populate the data network text views.
374                 dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
375                 dataNetworkDetailsTextView.text = dataNetworkType[1]
376                 additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
377                 additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
378
379                 // Set the stingray click listener.
380                 stingrayLinearLayout.setOnClickListener {
381                     // Instantiate the stingray dialog fragment.
382                     val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
383
384                     // Show the alert dialog.
385                     stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
386                 }
387
388                 // Set the data network click listener.
389                 dataNetworkLinearLayout.setOnClickListener {
390                     // Instantiate the data network dialog fragment according to the network type.
391                     val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
392                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
393                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
394                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
395                         TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
396                         TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
397                         TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
398                         TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
399                         TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
400                         TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
401                         TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
402                         TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
403                         TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
404                         TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
405                         TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
406                         TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
407                         TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
408                         TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
409                         TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
410                         TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
411                         TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
412                         else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
413                     }
414
415                     // Show the alert dialog.
416                     dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
417                 }
418
419                 // Set the additional network info click listener.
420                 additionalNetworkInfoLinearLayout.setOnClickListener {
421                     // Instantiate the initial network info dialog fragment according to the network type.
422                     val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
423                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
424                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
425                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
426                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
427                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
428                         else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
429                     }
430
431                     // Show the alert dialog.
432                     additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
433                 }
434             }
435
436             override fun onServiceStateChanged(serviceState: ServiceState) {
437                 // 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).
438                 val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
439
440                 // Get the voice network type.
441                 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
442
443                 // Populate the voice network text views.
444                 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
445                 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
446
447                 // Set the voice network click listener.
448                 voiceNetworkLinearLayout.setOnClickListener {
449                     // Instantiate the voice network dialog fragment according to the network type.
450                     val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
451                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
452                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
453                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
454                         TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
455                         TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
456                         TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
457                         TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
458                         TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
459                         TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
460                         TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
461                         TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
462                         TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
463                         TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
464                         TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
465                         TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
466                         TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
467                         TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
468                         TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
469                         TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
470                         TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
471                         else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
472                     }
473
474                     // Show the alert dialog.
475                     voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
476                 }
477             }
478         }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
479     }
480
481     private fun getNetworkType(networkType: Int) : Array<String> {
482         // Return the string that corresponds to the network type.
483         return when(networkType) {
484             TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
485             TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail))
486             TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
487             TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
488             TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
489             TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
490             TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
491             TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
492             TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
493             TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
494             TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
495             TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
496             TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
497             TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
498             TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
499             TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
500             TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
501             TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
502             TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
503             TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
504             else -> arrayOf(getString(R.string.error), "")
505         }
506     }
507
508     private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
509         // Return the string that corresponds to the override network type.
510         return when(overrideNetworkType) {
511             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
512             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
513             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
514             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail))
515             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail))
516             else -> arrayOf(getString(R.string.error), "")
517         }
518     }
519 }