091586fdf9386896a8161013ddd2825551ab1650
[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.permissions -> {  // Permissions.
209                 // Instantiate the permissions dialog fragment.
210                 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
211
212                 // Show the alert dialog.
213                 permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions))
214             }
215
216             R.id.privacy_policy -> {  // Privacy Policy.
217                 // Instantiate the privacy policy dialog fragment.
218                 val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY)
219
220                 // Show the alert dialog.
221                 privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy))
222             }
223
224             R.id.changelog -> {  // Changelog.
225                 // Instantiate the changelog dialog fragment.
226                 val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG)
227
228                 // Show the alert dialog.
229                 changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog))
230             }
231
232             R.id.licenses -> {  // Licenses.
233                 // Instantiate the licenses dialog fragment.
234                 val licensesDialogFragment = WebViewDialog().type(WebViewDialog.LICENSES)
235
236                 // Show the alert dialog.
237                 licensesDialogFragment.show(supportFragmentManager, getString(R.string.licenses))
238             }
239
240             R.id.contributors -> {  // Contributors.
241                 // Instantiate the contributors dialog fragment.
242                 val contributorsDialogFragment = WebViewDialog().type(WebViewDialog.CONTRIBUTORS)
243
244                 // Show the alert dialog.
245                 contributorsDialogFragment.show(supportFragmentManager, getString(R.string.contributors))
246             }
247
248             R.id.news -> {  // News.
249                 // Create a news URL intent.
250                 val newsUrlIntent = Intent(Intent.ACTION_VIEW)
251
252                 // Add the URL to the intent.
253                 newsUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell/")
254
255                 // Make it so.
256                 startActivity(newsUrlIntent)
257             }
258
259             R.id.roadmap -> {  // Roadmap.
260                 // Create a roadmap URL intent.
261                 val roadmapUrlIntent = Intent(Intent.ACTION_VIEW)
262
263                 // Add the URL to the intent.
264                 roadmapUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell-roadmap/")
265
266                 // Make it so.
267                 startActivity(roadmapUrlIntent)
268             }
269
270             R.id.bug_tracker -> {  // Bug tracker.
271                 // Create a bug tracker URL intent.
272                 val bugTrackerUrlIntent = Intent(Intent.ACTION_VIEW)
273
274                 // Add the URL to the intent.
275                 bugTrackerUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/issues")
276
277                 // Make it so.
278                 startActivity(bugTrackerUrlIntent)
279             }
280
281             R.id.forum -> {  // Forum.
282                 // Create a forum URL intent.
283                 val forumUrlIntent = Intent(Intent.ACTION_VIEW)
284
285                 // Add the URL to the intent.
286                 forumUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/boards")
287
288                 // Make it so.
289                 startActivity(forumUrlIntent)
290             }
291
292             R.id.donations -> {  // Donations.
293                 // Create a donations URL intent.
294                 val donationsUrlIntent = Intent(Intent.ACTION_VIEW)
295
296                 // Add the URL to the intent.
297                 donationsUrlIntent.data = Uri.parse("https://www.stoutner.com/donations/")
298
299                 // Make it so.
300                 startActivity(donationsUrlIntent)
301             }
302         }
303
304         // Close the navigation drawer.
305         drawerLayout.closeDrawer(GravityCompat.START)
306
307         // Consume the click.
308         return true
309     }
310
311     override fun onCloseStoragePermissionDialog() {
312         // Request the read phone state permission.  There is only one permission request in the app, so it has a request code of 0.
313         ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
314     }
315
316     override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
317         // Run the default commands.
318         super.onRequestPermissionsResult(requestCode, permissions, grantResults)
319
320         //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).
321         if (grantResults.isNotEmpty()) {
322             // Check to see if the read phone state permission was granted.  If the dialog was canceled the grant results will be empty.
323             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {  // The read phone state permission was granted.
324                 // Populate Privacy Cell.
325                 populatePrivacyCell(this)
326             } else {  // The read phone state permission was denied.
327                 // Display the phone permission text on the main activity.
328                 stingrayTextView.text = getString(R.string.phone_permission_text)
329             }
330         }
331     }
332
333     private fun populatePrivacyCell(context: Context) {
334         // Get a handle for the telephony manager.
335         val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
336
337         // Listen to changes in the cell network state.
338         telephonyManager.listen(object : PhoneStateListener() {
339             override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
340                 // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
341                 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
342                     // Populate the image view.
343                     stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
344
345                     // Set the text.
346                     stingrayTextView.text = getString(R.string.secure_from_stingray)
347
348                     // Set the text color.
349                     stingrayTextView.setTextColor(getColor(R.color.blue_text))
350                 } else {  // This is not a secure 5G NR SA network.
351                     // Populate the image view.
352                     stingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
353
354                     // Set the text.
355                     stingrayTextView.text = getString(R.string.not_secure_from_stingray)
356
357                     // Set the text color.
358                     stingrayTextView.setTextColor(getColor(R.color.red_text))
359                 }
360
361                 // Get the strings that correspond to the network information.
362                 val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
363                 val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
364
365                 // Populate the data network text views.
366                 dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
367                 dataNetworkDetailsTextView.text = dataNetworkType[1]
368                 additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
369                 additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
370
371                 // Set the stingray click listener.
372                 stingrayLinearLayout.setOnClickListener {
373                     // Instantiate the stingray dialog fragment.
374                     val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
375
376                     // Show the alert dialog.
377                     stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
378                 }
379
380                 // Set the data network click listener.
381                 dataNetworkLinearLayout.setOnClickListener {
382                     // Instantiate the data network dialog fragment according to the network type.
383                     val dataNetworkDialogFragment = when (telephonyDisplayInfo.networkType) {
384                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
385                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
386                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
387                         TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
388                         TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
389                         TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
390                         TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
391                         TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
392                         TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
393                         TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
394                         TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
395                         TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
396                         TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
397                         TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
398                         TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
399                         TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
400                         TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
401                         TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
402                         TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
403                         TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
404                         else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
405                     }
406
407                     // Show the alert dialog.
408                     dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
409                 }
410
411                 // Set the additional network info click listener.
412                 additionalNetworkInfoLinearLayout.setOnClickListener {
413                     // Instantiate the initial network info dialog fragment according to the network type.
414                     val additionalNetworkInfoDialogFragment = when (telephonyDisplayInfo.overrideNetworkType) {
415                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NONE)
416                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_CA)
417                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_LTE_ADVANCED_PRO)
418                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA)
419                         TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
420                         else -> WebViewDialog().type(WebViewDialog.OVERRIDE_NETWORK_NR_NSA_MMWAVE)
421                     }
422
423                     // Show the alert dialog.
424                     additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
425                 }
426             }
427
428             override fun onServiceStateChanged(serviceState: ServiceState) {
429                 // 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).
430                 val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
431
432                 // Get the voice network type.
433                 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
434
435                 // Populate the voice network text views.
436                 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
437                 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
438
439                 // Set the voice network click listener.
440                 voiceNetworkLinearLayout.setOnClickListener {
441                     // Instantiate the voice network dialog fragment according to the network type.
442                     val voiceNetworkDialogFragment = when (networkRegistrationInfo.accessNetworkTechnology) {
443                         TelephonyManager.NETWORK_TYPE_UNKNOWN -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
444                         TelephonyManager.NETWORK_TYPE_GPRS -> WebViewDialog().type(WebViewDialog.NETWORK_GPRS)
445                         TelephonyManager.NETWORK_TYPE_EDGE -> WebViewDialog().type(WebViewDialog.NETWORK_EDGE)
446                         TelephonyManager.NETWORK_TYPE_UMTS -> WebViewDialog().type(WebViewDialog.NETWORK_UMTS)
447                         TelephonyManager.NETWORK_TYPE_CDMA -> WebViewDialog().type(WebViewDialog.NETWORK_CDMA)
448                         TelephonyManager.NETWORK_TYPE_EVDO_0 -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_0)
449                         TelephonyManager.NETWORK_TYPE_EVDO_A -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_A)
450                         TelephonyManager.NETWORK_TYPE_1xRTT -> WebViewDialog().type(WebViewDialog.NETWORK_1xRTT)
451                         TelephonyManager.NETWORK_TYPE_HSDPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSDPA)
452                         TelephonyManager.NETWORK_TYPE_HSUPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSUPA)
453                         TelephonyManager.NETWORK_TYPE_HSPA -> WebViewDialog().type(WebViewDialog.NETWORK_HSPA)
454                         TelephonyManager.NETWORK_TYPE_IDEN -> WebViewDialog().type(WebViewDialog.NETWORK_IDEN)
455                         TelephonyManager.NETWORK_TYPE_EVDO_B -> WebViewDialog().type(WebViewDialog.NETWORK_EVDO_B)
456                         TelephonyManager.NETWORK_TYPE_LTE -> WebViewDialog().type(WebViewDialog.NETWORK_LTE)
457                         TelephonyManager.NETWORK_TYPE_EHRPD -> WebViewDialog().type(WebViewDialog.NETWORK_EHRPD)
458                         TelephonyManager.NETWORK_TYPE_HSPAP -> WebViewDialog().type(WebViewDialog.NETWORK_HSPAP)
459                         TelephonyManager.NETWORK_TYPE_GSM -> WebViewDialog().type(WebViewDialog.NETWORK_GSM)
460                         TelephonyManager.NETWORK_TYPE_TD_SCDMA -> WebViewDialog().type(WebViewDialog.NETWORK_TD_SCDMA)
461                         TelephonyManager.NETWORK_TYPE_IWLAN -> WebViewDialog().type(WebViewDialog.NETWORK_IWLAN)
462                         TelephonyManager.NETWORK_TYPE_NR -> WebViewDialog().type(WebViewDialog.NETWORK_NR)
463                         else -> WebViewDialog().type(WebViewDialog.NETWORK_UNKNOWN)
464                     }
465
466                     // Show the alert dialog.
467                     voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
468                 }
469             }
470         }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
471     }
472
473     private fun getNetworkType(networkType: Int) : Array<String> {
474         // Return the string that corresponds to the network type.
475         return when(networkType) {
476             TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
477             TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detail))
478             TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
479             TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
480             TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
481             TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
482             TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
483             TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
484             TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
485             TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
486             TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
487             TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
488             TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
489             TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
490             TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
491             TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
492             TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
493             TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
494             TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
495             TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
496             else -> arrayOf(getString(R.string.error), "")
497         }
498     }
499
500     private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
501         // Return the string that corresponds to the override network type.
502         return when(overrideNetworkType) {
503             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
504             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
505             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
506             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.nr_nsa), getString(R.string.nr_nsa_detail))
507             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.nr_nsa_mmwave), getString(R.string.nr_nsa_mmwave_detail))
508             else -> arrayOf(getString(R.string.error), "")
509         }
510     }
511 }