2d3b184abb3f56bad08b6fb3b65091b245ca285f
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / services / RealtimeMonitoringService.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.services
21
22 import android.app.Notification
23 import android.app.NotificationChannel
24 import android.app.NotificationChannelGroup
25 import android.app.NotificationManager
26 import android.app.PendingIntent
27 import android.app.Service
28 import android.content.Context
29 import android.content.Intent
30 import android.os.Binder
31 import android.os.IBinder
32 import android.telephony.PhoneStateListener
33 import android.telephony.TelephonyDisplayInfo
34 import android.telephony.TelephonyManager
35
36 import androidx.work.ExistingPeriodicWorkPolicy
37 import androidx.work.PeriodicWorkRequestBuilder
38 import androidx.work.WorkManager
39
40 import com.stoutner.privacycell.R
41 import com.stoutner.privacycell.activities.PrivacyCellActivity
42 import com.stoutner.privacycell.workers.RegisterRealtimeListener
43
44 import java.util.concurrent.TimeUnit
45
46 // Define the class constants.
47 const val REALTIME_MONITORING = "realtime_monitoring"
48 const val NOTIFICATION_ID = 1
49 const val UNKNOWN_NETWORK = "unknown_network"
50
51 class RealtimeMonitoringService : Service() {
52     companion object {
53         // Define the public constants.  These are used in the settings fragment to launch intents to edit the sound that plays for each channel.
54         const val SECURE_NETWORK = "secure_network"
55         const val INSECURE_NETWORK = "insecure_network"
56     }
57
58     // Define the class variables.
59     private var currentStatus = ""
60
61     inner class ServiceBinder : Binder() {
62         // Get a copy of this service as a binder.
63         fun getService(): RealtimeMonitoringService = this@RealtimeMonitoringService
64     }
65
66     override fun onBind(intent: Intent): IBinder {
67         // Return a copy of the service binder.
68         return ServiceBinder()
69     }
70
71     override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
72         // Get a handle for the notification manager.
73         val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
74
75         // Create a notification channel group.
76         notificationManager.createNotificationChannelGroup(NotificationChannelGroup(REALTIME_MONITORING, getString(R.string.realtime_monitoring)))
77
78         // Prepare the notification channels.
79         val secureNetworkChannel = NotificationChannel(SECURE_NETWORK, getString(R.string.secure_network_channel), NotificationManager.IMPORTANCE_HIGH)
80         val insecureNetworkChannel = NotificationChannel(INSECURE_NETWORK, getString(R.string.insecure_network_channel), NotificationManager.IMPORTANCE_HIGH)
81         val unknownNetworkChannel = NotificationChannel(UNKNOWN_NETWORK, getString(R.string.unknown_network_channel), NotificationManager.IMPORTANCE_LOW)
82
83         // Set the notification channel group.
84         secureNetworkChannel.group = REALTIME_MONITORING
85         insecureNetworkChannel.group = REALTIME_MONITORING
86         unknownNetworkChannel.group = REALTIME_MONITORING
87
88         // Disable the notification dots.
89         secureNetworkChannel.setShowBadge(false)
90         insecureNetworkChannel.setShowBadge(false)
91         unknownNetworkChannel.setShowBadge(false)
92
93         // Set the notifications to be public for the secure and insecure networks.
94         secureNetworkChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
95         insecureNetworkChannel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
96
97         // Create the notification channels.
98         notificationManager.createNotificationChannel(secureNetworkChannel)
99         notificationManager.createNotificationChannel(insecureNetworkChannel)
100         notificationManager.createNotificationChannel(unknownNetworkChannel)
101
102         // Create a notification builder.
103         val notificationBuilder = Notification.Builder(this, UNKNOWN_NETWORK)
104
105         // Create an intent to open Privacy Cell.
106         val privacyCellIntent = Intent(this, PrivacyCellActivity::class.java)
107
108         // Create a pending intent from the Privacy Cell intent.
109         val privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE)
110
111         // Set the notification to open Privacy Cell.
112         notificationBuilder.setContentIntent(privacyCellPendingIntent)
113
114         // Set the notification text.
115         notificationBuilder.setContentText(getString(R.string.unknown_network))
116
117         // Set the notification icon.
118         notificationBuilder.setSmallIcon(R.drawable.insecure_notification)
119
120         // Set the color.
121         notificationBuilder.setColor(getColor(R.color.red_text))
122
123         // Start the foreground notification.
124         startForeground(NOTIFICATION_ID, notificationBuilder.build())
125
126         // Register the telephony manager listener.
127         registerTelephonyManagerListener()
128
129         // Create a register realtime listener work request that fires every 15 minutes with a 1 minute initial delay.
130         val registerRealtimeListenerWorkRequest = PeriodicWorkRequestBuilder<RegisterRealtimeListener>(15, TimeUnit.MINUTES).setInitialDelay(1, TimeUnit.MINUTES).build()
131
132         // Register the realtime listener work request.
133         WorkManager.getInstance(this).enqueueUniquePeriodicWork(getString(R.string.register_listener_work_request), ExistingPeriodicWorkPolicy.REPLACE, registerRealtimeListenerWorkRequest)
134
135         // Return a sticky service.
136         return START_STICKY
137     }
138
139     fun registerTelephonyManagerListener() {
140         // Get a handle for the telephony manager.
141         val telephonyManager = getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager
142
143         // Get a handle for the notification manager.
144         val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
145
146         // Create an intent to open Privacy Cell.
147         val privacyCellIntent = Intent(this, PrivacyCellActivity::class.java)
148
149         // Create a pending intent from the Privacy Cell intent.
150         val privacyCellPendingIntent = PendingIntent.getActivity(this, 0, privacyCellIntent, PendingIntent.FLAG_IMMUTABLE)
151
152         // Listen for changes to the phone state.
153         telephonyManager.listen(object : PhoneStateListener() {
154             override fun onDisplayInfoChanged(telephonyDisplayInfo: TelephonyDisplayInfo) {
155                 // Populate the notification according to the network type.
156                 if (telephonyDisplayInfo.networkType == TelephonyManager.NETWORK_TYPE_NR) {  // This is a secure 5G NR SA network.
157                     // Only update the notification if the network status has changed.
158                     if (currentStatus != SECURE_NETWORK) {
159                         // Create a secure network notification builder.
160                         val secureNetworkNotificationBuilder = Notification.Builder(applicationContext, SECURE_NETWORK)
161
162                         // Set the notification to open Privacy Cell.
163                         secureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
164
165                         // Set the notification text.
166                         secureNetworkNotificationBuilder.setContentText(getString(R.string.secure_network))
167
168                         // Set the notification icon.
169                         secureNetworkNotificationBuilder.setSmallIcon(R.drawable.secure_notification)
170
171                         // Set the color.
172                         secureNetworkNotificationBuilder.setColor(getColor(R.color.blue_text))
173
174                         // Update the notification.
175                         notificationManager.notify(NOTIFICATION_ID, secureNetworkNotificationBuilder.build())
176
177                         // Store the new network status.
178                         currentStatus = SECURE_NETWORK
179                     }
180                 } else {  // This is not a secure 5G NR SA network.
181                     // Only update the notification if the network status has changed.
182                     if (currentStatus !=INSECURE_NETWORK) {
183                         // Create an insecure network notification builder.
184                         val insecureNetworkNotificationBuilder = Notification.Builder(applicationContext, INSECURE_NETWORK)
185
186                         // Set the notification to open Privacy Cell.
187                         insecureNetworkNotificationBuilder.setContentIntent(privacyCellPendingIntent)
188
189                         // Set the notification text.
190                         insecureNetworkNotificationBuilder.setContentText(getString(R.string.insecure_network))
191
192                         // Set the notification icon.
193                         insecureNetworkNotificationBuilder.setSmallIcon(R.drawable.insecure_notification)
194
195                         // Set the color.
196                         insecureNetworkNotificationBuilder.setColor(getColor(R.color.red_text))
197
198                         // Update the notification.
199                         notificationManager.notify(NOTIFICATION_ID, insecureNetworkNotificationBuilder.build())
200
201                         // Store the new network status.
202                         currentStatus = INSECURE_NETWORK
203                     }
204                 }
205             }
206         }, PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED)
207     }
208 }