c8c77120a244e072a0fa8535c280ba29cc6a3d11
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / activities / PrivacyCell.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 Browser.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package com.stoutner.privacycell.activities
21
22 import android.Manifest
23 import android.content.Context
24 import android.content.pm.PackageManager
25 import android.os.Bundle
26 import android.telephony.PhoneStateListener
27 import android.telephony.ServiceState
28 import android.telephony.TelephonyDisplayInfo
29 import android.telephony.TelephonyManager
30 import android.widget.ImageView
31 import android.widget.TextView
32
33 import androidx.appcompat.app.AppCompatActivity
34 import androidx.appcompat.content.res.AppCompatResources
35 import androidx.core.app.ActivityCompat
36 import androidx.fragment.app.DialogFragment
37
38 import com.stoutner.privacycell.R
39 import com.stoutner.privacycell.dialogs.PhonePermissionDialog
40
41 class PrivacyCell : AppCompatActivity(), PhonePermissionDialog.StoragePermissionDialogListener {
42     // Declare the class variables.
43     private lateinit var context: Context
44     private lateinit var telephonyManager: TelephonyManager
45
46     // Declare the views.
47     lateinit var secureFromStingrayImageView: ImageView
48     lateinit var secureFromStingrayTextView: TextView
49     lateinit var voiceNetworkTextView: TextView
50     lateinit var voiceNetworkDetailsTextView: TextView
51     lateinit var dataNetworkTextView: TextView
52     lateinit var dataNetworkDetailsTextView: TextView
53     lateinit var additionalNetworkInfoTextView: TextView
54     lateinit var additionalNetworkInfoDetailsTextView: TextView
55
56     override fun onCreate(savedInstanceState: Bundle?) {
57         // Run the default commands.
58         super.onCreate(savedInstanceState)
59
60         // Set the content view.
61         setContentView(R.layout.privacy_cell_scrollview)
62
63         // Get handles for the views.
64         secureFromStingrayImageView = findViewById(R.id.secure_from_stingray_imageview)
65         secureFromStingrayTextView = findViewById(R.id.secure_from_stingray_textview)
66         voiceNetworkTextView = findViewById(R.id.voice_network)
67         voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details)
68         dataNetworkTextView = findViewById(R.id.data_network)
69         dataNetworkDetailsTextView = findViewById(R.id.data_network_details)
70         additionalNetworkInfoTextView = findViewById(R.id.additional_network_info)
71         additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details)
72
73         // Get handles for the context and the telephony manager.
74         context = this
75         telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
76
77         // Check to see if the read phone state permission has been granted.
78         if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {  // The storage permission has been granted.
79             // Populate Privacy Cell.
80             populatePrivacyCell()
81         } else {  // The phone permission has not been granted.
82             // Check if the user has previously denied the storage permission.
83             if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) {  // Show a dialog explaining the request first.
84                 // Check to see if a phone permission dialog is already displayed.  This happens if the app is restarted when the dialog is shown.
85                 if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) {  // No dialog is currently shown.
86                     // Instantiate the phone permission dialog fragment.
87                     val phonePermissionDialogFragment: DialogFragment = PhonePermissionDialog()
88
89                     // Show the phone permission alert dialog.  The permission will be requested when the dialog is closed.
90                     phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission))
91                 }
92             } else {  // Show the permission request directly.
93                 // Request the read phone state permission.  There is only one permission request in the app, so it has a request code of 0.
94                 ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
95             }
96         }
97     }
98
99     override fun onCloseStoragePermissionDialog() {
100         // Request the read phone state permission.  There is only one permission request in the app, so it has a request code of 0.
101         ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0)
102     }
103
104     override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
105         // Run the default commands.
106         super.onRequestPermissionsResult(requestCode, permissions, grantResults)
107
108         //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).
109         if (grantResults.isNotEmpty()) {
110             // Check to see if the read phone state permission was granted.  If the dialog was canceled the grant results will be empty.
111             if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {  // The read phone state permission was granted.
112                 // Populate Privacy Cell.
113                 populatePrivacyCell()
114             } else {  // The read phone state permission was denied.
115                 // Display the phone permission text on the main activity.
116                 secureFromStingrayTextView.text = getString(R.string.phone_permission_text)
117             }
118         }
119     }
120
121     private fun populatePrivacyCell() {
122         // Listen to changes in the cell network state.
123         telephonyManager.listen(object : PhoneStateListener() {
124             override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
125                 // Populate the stingray security information.  <https://source.android.com/devices/tech/connect/acts-5g-testing>
126                 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
127                     // Populate the image view.
128                     secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa))
129
130                     // Set the text.
131                     secureFromStingrayTextView.text = getString(R.string.secure_from_stingray)
132
133                     // Set the text color.
134                     secureFromStingrayTextView.setTextColor(getColor(R.color.blue_text))
135                 } else {  // This is not a secure 5G NR SA network.
136                     // Populate the image view.
137                     secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure))
138
139                     // Set the text.
140                     secureFromStingrayTextView.text = getString(R.string.not_secure_from_stingray)
141
142                     // Set the text color.
143                     secureFromStingrayTextView.setTextColor(getColor(R.color.red_text))
144
145                     // Get the strings that correspond to the network information.
146                     val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType)
147                     val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType)
148
149                     // Populate the data network text views.
150                     dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0])
151                     dataNetworkDetailsTextView.text = dataNetworkType[1]
152                     additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0])
153                     additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1]
154                 }
155             }
156
157             override fun onServiceStateChanged(serviceState: ServiceState) {
158                 // 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).
159                 val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1]
160
161                 // Get the voice network type.
162                 val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology)
163
164                 // Populate the voice network text views.
165                 voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0])
166                 voiceNetworkDetailsTextView.text = voiceNetworkType[1]
167             }
168         }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE)
169     }
170
171     private fun getNetworkType(networkType: Int) : Array<String> {
172         // Return the string that corresponds to the network type.
173         return when(networkType) {
174             TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "")
175             TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detal))
176             TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail))
177             TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail))
178             TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail))
179             TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail))
180             TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail))
181             TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail))
182             TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail))
183             TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail))
184             TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail))
185             TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail))
186             TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail))
187             TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail))
188             TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail))
189             TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail))
190             TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail))
191             TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail))
192             TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail))
193             TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail))
194             else -> arrayOf(getString(R.string.error), "")
195         }
196     }
197
198     private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array<String> {
199         // Return the string that corresponds to the override network type.
200         return when(overrideNetworkType) {
201             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "")
202             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail))
203             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail))
204             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.lte_nr_nsa), getString(R.string.lte_nr_nsa_detail))
205             TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.lte_nr_nsa_mmwave), getString(R.string.lte_nr_nsa_mmwave_detail))
206             else -> arrayOf(getString(R.string.error), "")
207         }
208     }
209 }