Self grant run_any_in_background if possible

This commit is contained in:
Jonas Lochmann 2024-01-22 01:00:00 +01:00
parent f0b940a7e5
commit 8941639fe5
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
3 changed files with 77 additions and 4 deletions

View file

@ -1,5 +1,5 @@
/* /*
* TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann * TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -50,6 +50,12 @@ object AppOps {
} }
} }
private val setMode by lazy { try {
AppOpsManager::class.java.getMethod("setMode", String::class.java, Int::class.java, String::class.java, Int::class.java)
} catch (ex: ReflectiveOperationException) {
null
} }
fun getOpMode(op: String, appOpsManager: AppOpsManager, context: Context): Mode { fun getOpMode(op: String, appOpsManager: AppOpsManager, context: Context): Mode {
try { try {
val reflectionData = reflectionData ?: return Mode.Unknown val reflectionData = reflectionData ?: return Mode.Unknown
@ -88,6 +94,28 @@ object AppOps {
} }
} }
fun setMode(op: String, appOpsManager: AppOpsManager, context: Context, mode: Mode) {
val setMode = setMode
if (setMode == null) throw SecurityException("blocked by the OS")
val realMode = when (mode) {
Mode.Allowed -> AppOpsManager.MODE_ALLOWED
Mode.Default -> AppOpsManager.MODE_DEFAULT
Mode.Ignored -> AppOpsManager.MODE_IGNORED
Mode.Blocked -> AppOpsManager.MODE_ERRORED
else -> return
}
try {
setMode.invoke(appOpsManager, op, Process.myUid(), context.packageName, realMode)
} catch (ex: InvocationTargetException) {
ex.cause?.let { throw it }
throw ex
}
}
enum class Mode { enum class Mode {
Unknown, Unknown,
Allowed, Allowed,

View file

@ -1,5 +1,5 @@
/* /*
* TimeLimit Copyright <C> 2019 - 2023 Jonas Lochmann * TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -22,7 +22,6 @@ import android.app.admin.DevicePolicyManager
import android.content.ComponentName import android.content.ComponentName
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.os.Build
import android.os.Build.VERSION import android.os.Build.VERSION
import android.os.Build.VERSION_CODES import android.os.Build.VERSION_CODES
import android.os.IBinder import android.os.IBinder
@ -67,7 +66,9 @@ class BackgroundService: Service() {
if (VERSION.SDK_INT >= VERSION_CODES.P) { if (VERSION.SDK_INT >= VERSION_CODES.P) {
if (activityManager.isBackgroundRestricted) { if (activityManager.isBackgroundRestricted) {
return true if (RunInBackgroundPermission.trySelfGrant(context)) {
if (activityManager.isBackgroundRestricted) return true
} else return true
} }
} }

View file

@ -0,0 +1,44 @@
/*
* TimeLimit Copyright <C> 2019 - 2024 Jonas Lochmann
*
* This program 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 version 3 of the License.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*/
package io.timelimit.android.integration.platform.android
import android.app.AppOpsManager
import android.app.admin.DevicePolicyManager
import android.content.Context
import androidx.core.content.getSystemService
import io.timelimit.android.BuildConfig
object RunInBackgroundPermission {
private const val OP = "android:run_any_in_background"
fun trySelfGrant(context: Context): Boolean {
if (BuildConfig.storeCompilant) return false
val devicePolicyManager = context.getSystemService<DevicePolicyManager>() ?: return false
if (!devicePolicyManager.isDeviceOwnerApp(context.packageName)) return false
val appOpsService = context.getSystemService<AppOpsManager>() ?: return false
return try {
AppOps.setMode(OP, appOpsService, context, AppOps.Mode.Allowed)
true
} catch (ex: SecurityException) {
false
}
}
}