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