Fix Android 12 preventing the restarting of the monitoring service. https://redmine...
[PrivacyCell.git] / app / src / main / java / com / stoutner / privacycell / workers / RegisterRealtimeListenerWorker.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.workers
21
22 import android.app.ActivityManager
23 import android.content.ComponentName
24 import android.content.Context
25 import android.content.Intent
26 import android.content.ServiceConnection
27 import android.os.IBinder
28
29 import androidx.preference.PreferenceManager
30 import androidx.work.OneTimeWorkRequestBuilder
31 import androidx.work.OutOfQuotaPolicy
32 import androidx.work.WorkManager
33 import androidx.work.Worker
34 import androidx.work.WorkerParameters
35
36 import com.stoutner.privacycell.R
37 import com.stoutner.privacycell.services.RealtimeMonitoringService
38
39 class RegisterRealtimeListenerWorker(appContext: Context, workerParameters: WorkerParameters) : Worker(appContext, workerParameters) {
40     override fun doWork(): Result {
41         // Get a handle for the shared preferences.
42         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(applicationContext)
43
44         // Get the realtime monitoring preference.  Sometimes the shared preferences can't return a value in time, because Android sucks.
45         // So, the default value is set to true, which is the safest value if the shared preferences can't be queried.
46         val realtimeMonitoring = sharedPreferences.getBoolean(applicationContext.getString(R.string.realtime_monitoring_key), true)
47
48         // Perform the functions according to the realtime monitoring status.
49         if (realtimeMonitoring) {  // Realtime monitoring is enabled.
50             // Get a handle for the activity manager.
51             val activityManager: ActivityManager = applicationContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
52
53             // 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.
54             val runningServiceInfoList: List<ActivityManager.RunningServiceInfo> = activityManager.getRunningServices(1)
55
56             // Check to see if the service is currently running.
57             if (runningServiceInfoList.isEmpty()) {  // The service is currently stopped.
58                 // Create a restart service work request.  This task can't be run from here because of Android 12's foreground service restrictions on non-expedited workers.
59                 val restartServiceWorkRequest = OneTimeWorkRequestBuilder<RestartServiceWorker>().apply {
60                     // Set the status to be expedited so that it can start a foreground service.
61                     setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
62                 }.build()
63
64                 // Make it so.
65                 WorkManager.getInstance(applicationContext).enqueue(restartServiceWorkRequest)
66             } else {  // The service is currently running.
67                 // Create a service connection.
68                 val serviceConnection = object : ServiceConnection {
69                     override fun onServiceConnected(componentName: ComponentName, serviceIBinder: IBinder) {
70                         // Get a handle for the realtime monitoring service binder.
71                         val realtimeMonitoringServiceBinder = serviceIBinder as RealtimeMonitoringService.ServiceBinder
72
73                         // Get a handle for the realtime monitoring service.
74                         val realtimeMonitoringService = realtimeMonitoringServiceBinder.getService()
75
76                         // Register the telephony manager listener.
77                         realtimeMonitoringService.registerTelephonyManagerListener()
78
79                         // Unbind the service.
80                         applicationContext.unbindService(this)
81                     }
82
83                     override fun onServiceDisconnected(componentName: ComponentName) {
84                         // Do nothing.
85                     }
86                 }
87
88                 // Bind to the realtime monitoring service.
89                 applicationContext.bindService(Intent(applicationContext, RealtimeMonitoringService::class.java), serviceConnection, 0)
90             }
91         } else {  // Realtime monitoring is disabled.
92             // Cancel the realtime listener work request.
93             WorkManager.getInstance(applicationContext).cancelUniqueWork(applicationContext.getString(R.string.register_listener_work_request))
94         }
95
96         // Return a success.
97         return Result.success()
98     }
99 }