/* * Copyright © 2021 Soren Stoutner . * * This file is part of Privacy Cell . * * Privacy Cell is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Privacy Cell is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Privacy Browser. If not, see . */ package com.stoutner.privacycell.activities import android.Manifest import android.content.Context import android.content.pm.PackageManager import android.os.Bundle import android.telephony.PhoneStateListener import android.telephony.ServiceState import android.telephony.TelephonyDisplayInfo import android.telephony.TelephonyManager import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.content.res.AppCompatResources import androidx.core.app.ActivityCompat import androidx.fragment.app.DialogFragment import com.stoutner.privacycell.R import com.stoutner.privacycell.dialogs.PhonePermissionDialog class PrivacyCell : AppCompatActivity(), PhonePermissionDialog.StoragePermissionDialogListener { // Declare the class variables. private lateinit var context: Context private lateinit var telephonyManager: TelephonyManager // Declare the views. lateinit var secureFromStingrayImageView: ImageView lateinit var secureFromStingrayTextView: TextView lateinit var voiceNetworkTextView: TextView lateinit var voiceNetworkDetailsTextView: TextView lateinit var dataNetworkTextView: TextView lateinit var dataNetworkDetailsTextView: TextView lateinit var additionalNetworkInfoTextView: TextView lateinit var additionalNetworkInfoDetailsTextView: TextView override fun onCreate(savedInstanceState: Bundle?) { // Run the default commands. super.onCreate(savedInstanceState) // Set the content view. setContentView(R.layout.privacy_cell_scrollview) // Get handles for the views. secureFromStingrayImageView = findViewById(R.id.secure_from_stingray_imageview) secureFromStingrayTextView = findViewById(R.id.secure_from_stingray_textview) voiceNetworkTextView = findViewById(R.id.voice_network) voiceNetworkDetailsTextView = findViewById(R.id.voice_network_details) dataNetworkTextView = findViewById(R.id.data_network) dataNetworkDetailsTextView = findViewById(R.id.data_network_details) additionalNetworkInfoTextView = findViewById(R.id.additional_network_info) additionalNetworkInfoDetailsTextView = findViewById(R.id.additional_network_info_details) // Get handles for the context and the telephony manager. context = this telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager // Check to see if the read phone state permission has been granted. if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) { // The storage permission has been granted. // Populate Privacy Cell. populatePrivacyCell() } else { // The phone permission has not been granted. // Check if the user has previously denied the storage permission. if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.READ_PHONE_STATE)) { // Show a dialog explaining the request first. // Check to see if a phone permission dialog is already displayed. This happens if the app is restarted when the dialog is shown. if (supportFragmentManager.findFragmentByTag(getString(R.string.phone_permission)) == null) { // No dialog is currently shown. // Instantiate the phone permission dialog fragment. val phonePermissionDialogFragment: DialogFragment = PhonePermissionDialog() // Show the phone permission alert dialog. The permission will be requested when the dialog is closed. phonePermissionDialogFragment.show(supportFragmentManager, getString(R.string.phone_permission)) } } else { // Show the permission request directly. // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0. ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0) } } } override fun onCloseStoragePermissionDialog() { // Request the read phone state permission. There is only one permission request in the app, so it has a request code of 0. ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_PHONE_STATE), 0) } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { // Run the default commands. super.onRequestPermissionsResult(requestCode, permissions, grantResults) //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). if (grantResults.isNotEmpty()) { // Check to see if the read phone state permission was granted. If the dialog was canceled the grant results will be empty. if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { // The read phone state permission was granted. // Populate Privacy Cell. populatePrivacyCell() } else { // The read phone state permission was denied. // Display the phone permission text on the main activity. secureFromStingrayTextView.text = getString(R.string.phone_permission_text) } } } private fun populatePrivacyCell() { // Listen to changes in the cell network state. telephonyManager.listen(object : PhoneStateListener() { override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) { // Populate the stingray security information. if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) { // This is a secure 5G NR SA network. // Populate the image view. secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.secure_5g_nr_sa)) // Set the text. secureFromStingrayTextView.text = getString(R.string.secure_from_stingray) // Set the text color. secureFromStingrayTextView.setTextColor(getColor(R.color.blue_text)) } else { // This is not a secure 5G NR SA network. // Populate the image view. secureFromStingrayImageView.setImageDrawable(AppCompatResources.getDrawable(context, R.drawable.not_secure)) // Set the text. secureFromStingrayTextView.text = getString(R.string.not_secure_from_stingray) // Set the text color. secureFromStingrayTextView.setTextColor(getColor(R.color.red_text)) // Get the strings that correspond to the network information. val dataNetworkType = getNetworkType(telephonyDisplayInfo.networkType) val additionalNetworkInfo = getAdditionalNetworkInfo(telephonyDisplayInfo.overrideNetworkType) // Populate the data network text views. dataNetworkTextView.text = getString(R.string.data_network, dataNetworkType[0]) dataNetworkDetailsTextView.text = dataNetworkType[1] additionalNetworkInfoTextView.text = getString(R.string.additional_network_info, additionalNetworkInfo[0]) additionalNetworkInfoDetailsTextView.text = additionalNetworkInfo[1] } } override fun onServiceStateChanged(serviceState: ServiceState) { // 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). val networkRegistrationInfo = serviceState.networkRegistrationInfoList[1] // Get the voice network type. val voiceNetworkType = getNetworkType(networkRegistrationInfo.accessNetworkTechnology) // Populate the voice network text views. voiceNetworkTextView.text = getString(R.string.voice_network, voiceNetworkType[0]) voiceNetworkDetailsTextView.text = voiceNetworkType[1] } }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED or PhoneStateListener.LISTEN_SERVICE_STATE) } private fun getNetworkType(networkType: Int) : Array { // Return the string that corresponds to the network type. return when(networkType) { TelephonyManager.NETWORK_TYPE_UNKNOWN -> arrayOf(getString(R.string.unknown), "") TelephonyManager.NETWORK_TYPE_GPRS -> arrayOf(getString(R.string.gprs), getString(R.string.gprs_detal)) TelephonyManager.NETWORK_TYPE_EDGE -> arrayOf(getString(R.string.edge), getString(R.string.edge_detail)) TelephonyManager.NETWORK_TYPE_UMTS -> arrayOf(getString(R.string.umts), getString(R.string.umts_detail)) TelephonyManager.NETWORK_TYPE_CDMA -> arrayOf(getString(R.string.cdma), getString(R.string.cdma_detail)) TelephonyManager.NETWORK_TYPE_EVDO_0 -> arrayOf(getString(R.string.evdo_0), getString(R.string.evdo_0_detail)) TelephonyManager.NETWORK_TYPE_EVDO_A -> arrayOf(getString(R.string.evdo_a), getString(R.string.evdo_a_detail)) TelephonyManager.NETWORK_TYPE_1xRTT -> arrayOf(getString(R.string.rtt), getString(R.string.rtt_detail)) TelephonyManager.NETWORK_TYPE_HSDPA -> arrayOf(getString(R.string.hsdpa), getString(R.string.hsdpa_detail)) TelephonyManager.NETWORK_TYPE_HSUPA -> arrayOf(getString(R.string.hsupa), getString(R.string.hsupa_detail)) TelephonyManager.NETWORK_TYPE_HSPA -> arrayOf(getString(R.string.hspa), getString(R.string.hspa_detail)) TelephonyManager.NETWORK_TYPE_IDEN -> arrayOf(getString(R.string.iden), getString(R.string.iden_detail)) TelephonyManager.NETWORK_TYPE_EVDO_B -> arrayOf(getString(R.string.evdo_b), getString(R.string.evdo_b_detail)) TelephonyManager.NETWORK_TYPE_LTE -> arrayOf(getString(R.string.lte), getString(R.string.lte_detail)) TelephonyManager.NETWORK_TYPE_EHRPD -> arrayOf(getString(R.string.ehrpd), getString(R.string.ehrpd_detail)) TelephonyManager.NETWORK_TYPE_HSPAP -> arrayOf(getString(R.string.hspap), getString(R.string.hspap_detail)) TelephonyManager.NETWORK_TYPE_GSM -> arrayOf(getString(R.string.gsm), getString(R.string.gsm_detail)) TelephonyManager.NETWORK_TYPE_TD_SCDMA -> arrayOf(getString(R.string.td_scdma), getString(R.string.td_scdma_detail)) TelephonyManager.NETWORK_TYPE_IWLAN -> arrayOf(getString(R.string.iwlan), getString(R.string.iwlan_detail)) TelephonyManager.NETWORK_TYPE_NR -> arrayOf(getString(R.string.nr), getString(R.string.nr_detail)) else -> arrayOf(getString(R.string.error), "") } } private fun getAdditionalNetworkInfo(overrideNetworkType: Int) : Array { // Return the string that corresponds to the override network type. return when(overrideNetworkType) { TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE -> arrayOf(getString(R.string.none), "") TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA -> arrayOf(getString(R.string.lte_ca), getString(R.string.lte_ca_detail)) TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO -> arrayOf(getString(R.string.lte_advanced_pro), getString(R.string.lte_advanced_pro_detail)) TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA -> arrayOf(getString(R.string.lte_nr_nsa), getString(R.string.lte_nr_nsa_detail)) TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE -> arrayOf(getString(R.string.lte_nr_nsa_mmwave), getString(R.string.lte_nr_nsa_mmwave_detail)) else -> arrayOf(getString(R.string.error), "") } } }