2 * Copyright © 2021 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Cell <https://www.stoutner.com/privacy-cell>.
6 * Privacy Cell is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Cell is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Cell. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacycell.activities
22 import android.Manifest
23 import android.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
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
49 import com.google.android.material.navigation.NavigationView
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
56 class PrivacyCellActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener, PhonePermissionDialog.StoragePermissionDialogListener {
57 // Declare the class variables.
58 private lateinit var actionBarDrawerToggle: ActionBarDrawerToggle
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
75 override fun onCreate(savedInstanceState: Bundle?) {
76 // Run the default commands.
77 super.onCreate(savedInstanceState)
79 // Get a handle for the shared preferences.
80 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
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)
86 // Set the content view.
88 setContentView(R.layout.privacy_cell_bottom_appbar)
90 setContentView(R.layout.privacy_cell_top_appbar)
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)
110 // Set the support action bar.
111 setSupportActionBar(toolbar)
113 // Get a handle for the action bar.
114 val actionBar = supportActionBar!!
116 // Set a custom view on the action bar.
117 actionBar.setCustomView(R.layout.app_bar_textview)
119 // Display the custom view.
120 actionBar.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
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)
125 // Listen for touches on the navigation menu.
126 navigationView.setNavigationItemSelectedListener(this)
128 // Add a drawer listener.
129 drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
130 override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
134 override fun onDrawerOpened(drawerView: View) {
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()
143 override fun onDrawerStateChanged(newState: Int) {
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
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)
156 // Start the service if it is not already running.
157 if (runningServiceInfoList.isEmpty()) {
158 startService(Intent(this, RealtimeMonitoringService::class.java))
163 override fun onPostCreate(savedInstanceState: Bundle?) {
164 // Run the default commands.
165 super.onPostCreate(savedInstanceState)
167 // Sync the state of the DrawerToggle after the default `onRestoreInstanceState()` has finished. This creates the navigation drawer icon.
168 actionBarDrawerToggle.syncState()
171 override fun onResume() {
172 // Run the default commands.
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()
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))
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)
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)
205 startActivity(settingsIntent)
208 R.id.permissions -> { // Permissions.
209 // Instantiate the permissions dialog fragment.
210 val permissionsDialogFragment = WebViewDialog().type(WebViewDialog.PERMISSIONS)
212 // Show the alert dialog.
213 permissionsDialogFragment.show(supportFragmentManager, getString(R.string.permissions))
216 R.id.privacy_policy -> { // Privacy Policy.
217 // Instantiate the privacy policy dialog fragment.
218 val privacyPolicyDialogFragment = WebViewDialog().type(WebViewDialog.PRIVACY_POLICY)
220 // Show the alert dialog.
221 privacyPolicyDialogFragment.show(supportFragmentManager, getString(R.string.privacy_policy))
224 R.id.changelog -> { // Changelog.
225 // Instantiate the changelog dialog fragment.
226 val changelogDialogFragment = WebViewDialog().type(WebViewDialog.CHANGELOG)
228 // Show the alert dialog.
229 changelogDialogFragment.show(supportFragmentManager, getString(R.string.changelog))
232 R.id.licenses -> { // Licenses.
233 // Instantiate the licenses dialog fragment.
234 val licensesDialogFragment = WebViewDialog().type(WebViewDialog.LICENSES)
236 // Show the alert dialog.
237 licensesDialogFragment.show(supportFragmentManager, getString(R.string.licenses))
240 R.id.contributors -> { // Contributors.
241 // Instantiate the contributors dialog fragment.
242 val contributorsDialogFragment = WebViewDialog().type(WebViewDialog.CONTRIBUTORS)
244 // Show the alert dialog.
245 contributorsDialogFragment.show(supportFragmentManager, getString(R.string.contributors))
248 R.id.news -> { // News.
249 // Create a news URL intent.
250 val newsUrlIntent = Intent(Intent.ACTION_VIEW)
252 // Add the URL to the intent.
253 newsUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell/")
256 startActivity(newsUrlIntent)
259 R.id.roadmap -> { // Roadmap.
260 // Create a roadmap URL intent.
261 val roadmapUrlIntent = Intent(Intent.ACTION_VIEW)
263 // Add the URL to the intent.
264 roadmapUrlIntent.data = Uri.parse("https://www.stoutner.com/category/privacy-cell-roadmap/")
267 startActivity(roadmapUrlIntent)
270 R.id.bug_tracker -> { // Bug tracker.
271 // Create a bug tracker URL intent.
272 val bugTrackerUrlIntent = Intent(Intent.ACTION_VIEW)
274 // Add the URL to the intent.
275 bugTrackerUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/issues")
278 startActivity(bugTrackerUrlIntent)
281 R.id.forum -> { // Forum.
282 // Create a forum URL intent.
283 val forumUrlIntent = Intent(Intent.ACTION_VIEW)
285 // Add the URL to the intent.
286 forumUrlIntent.data = Uri.parse("https://redmine.stoutner.com/projects/privacy-cell/boards")
289 startActivity(forumUrlIntent)
292 R.id.donations -> { // Donations.
293 // Create a donations URL intent.
294 val donationsUrlIntent = Intent(Intent.ACTION_VIEW)
296 // Add the URL to the intent.
297 donationsUrlIntent.data = Uri.parse("https://www.stoutner.com/donations/")
300 startActivity(donationsUrlIntent)
304 // Close the navigation drawer.
305 drawerLayout.closeDrawer(GravityCompat.START)
307 // Consume the click.
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)
316 override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
317 // Run the default commands.
318 super.onRequestPermissionsResult(requestCode, permissions, grantResults)
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)
333 private fun populatePrivacyCell(context: Context) {
334 // Get a handle for the telephony manager.
335 val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
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))
346 stingrayTextView.text = getString(R.string.secure_from_stingray)
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))
355 stingrayTextView.text = getString(R.string.not_secure_from_stingray)
357 // Set the text color.
358 stingrayTextView.setTextColor(getColor(R.color.red_text))
361 // Get the strings that correspond to the network information.
362 val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
363 val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
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]
371 // Set the stingray click listener.
372 stingrayLinearLayout.setOnClickListener {
373 // Instantiate the stingray dialog fragment.
374 val stingrayDialogFragment = WebViewDialog().type(WebViewDialog.STINGRAY)
376 // Show the alert dialog.
377 stingrayDialogFragment.show(supportFragmentManager, getString(R.string.stingrays))
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)
407 // Show the alert dialog.
408 dataNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
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)
423 // Show the alert dialog.
424 additionalNetworkInfoDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
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]
432 // Get the voice network type.
433 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
435 // Populate the voice network text views.
436 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
437 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
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)
466 // Show the alert dialog.
467 voiceNetworkDialogFragment.show(supportFragmentManager, getString(R.string.voice_network))
470 }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
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), "")
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), "")