Only restore services when permitted
This commit is contained in:
@@ -48,6 +48,7 @@ class App : Application() {
|
||||
// alternative to PreferenceManager.getDefaultSharedPreferencesName(this)
|
||||
deviceStorage.moveSharedPreferencesFrom(this, PreferenceManager(this).sharedPreferencesName)
|
||||
deviceStorage.moveDatabaseFrom(this, AppDatabase.DB_NAME)
|
||||
BootReceiver.migrateIfNecessary()
|
||||
} else deviceStorage = this
|
||||
Services.init { this }
|
||||
|
||||
@@ -92,7 +93,6 @@ class App : Application() {
|
||||
})
|
||||
EBegFragment.init()
|
||||
if (DhcpWorkaround.shouldEnable) DhcpWorkaround.enable(true)
|
||||
BootReceiver.init()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
|
||||
@@ -5,13 +5,11 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Parcelable
|
||||
import android.widget.Toast
|
||||
import androidx.annotation.RequiresApi
|
||||
import be.mygod.librootkotlinx.toByteArray
|
||||
import be.mygod.librootkotlinx.toParcelable
|
||||
import be.mygod.vpnhotspot.App.Companion.app
|
||||
import be.mygod.vpnhotspot.util.readableMessage
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import timber.log.Timber
|
||||
import java.io.DataInputStream
|
||||
@@ -30,6 +28,7 @@ class BootReceiver : BroadcastReceiver() {
|
||||
set(value) = app.packageManager.setComponentEnabledSetting(componentName,
|
||||
if (value) PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
||||
else PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP)
|
||||
private val userEnabled get() = app.pref.getBoolean(KEY, false)
|
||||
fun onUserSettingUpdated(shouldStart: Boolean) {
|
||||
enabled = shouldStart && try {
|
||||
config
|
||||
@@ -39,7 +38,7 @@ class BootReceiver : BroadcastReceiver() {
|
||||
}?.startables?.isEmpty() == false
|
||||
}
|
||||
private fun onConfigUpdated(isNotEmpty: Boolean) {
|
||||
enabled = isNotEmpty && app.pref.getBoolean(KEY, false)
|
||||
enabled = isNotEmpty && userEnabled
|
||||
}
|
||||
|
||||
private const val FILENAME = "bootconfig"
|
||||
@@ -75,8 +74,8 @@ class BootReceiver : BroadcastReceiver() {
|
||||
inline fun <reified T> add(value: Startable) = add(T::class.java.name, value)
|
||||
inline fun <reified T> delete() = delete(T::class.java.name)
|
||||
|
||||
fun init() {
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
@RequiresApi(24)
|
||||
fun migrateIfNecessary() {
|
||||
val oldFile = File(app.noBackupFilesDir, FILENAME)
|
||||
if (oldFile.canRead()) try {
|
||||
if (!configFile.exists()) oldFile.copyTo(configFile)
|
||||
@@ -85,6 +84,9 @@ class BootReceiver : BroadcastReceiver() {
|
||||
Timber.w(e)
|
||||
}
|
||||
}
|
||||
private var started = false
|
||||
private fun startIfNecessary() {
|
||||
if (started) return
|
||||
val config = try {
|
||||
synchronized(BootReceiver) { config }
|
||||
} catch (e: Exception) {
|
||||
@@ -93,12 +95,11 @@ class BootReceiver : BroadcastReceiver() {
|
||||
}
|
||||
if (config == null || config.startables.isEmpty()) {
|
||||
enabled = false
|
||||
} else for (startable in config.startables.values) try {
|
||||
startable.start(app)
|
||||
} catch (e: IllegalStateException) { // ForegroundServiceStartNotAllowedException
|
||||
Timber.w(e)
|
||||
Toast.makeText(app, e.readableMessage, Toast.LENGTH_LONG).show()
|
||||
} else for (startable in config.startables.values) startable.start(app)
|
||||
started = true
|
||||
}
|
||||
fun startIfEnabled() {
|
||||
if (started && userEnabled) startIfNecessary()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,5 +110,11 @@ class BootReceiver : BroadcastReceiver() {
|
||||
@Parcelize
|
||||
private data class Config(var startables: MutableMap<String, Startable> = mutableMapOf()) : Parcelable
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) { }
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
when (intent.action) {
|
||||
Intent.ACTION_BOOT_COMPLETED, Intent.ACTION_LOCKED_BOOT_COMPLETED, Intent.ACTION_MY_PACKAGE_REPLACED -> {
|
||||
if (userEnabled) startIfNecessary() else enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService(), CoroutineScope {
|
||||
override fun onBind(intent: Intent?) = binder
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
BootReceiver.startIfEnabled()
|
||||
if (binder.iface != null) return START_STICKY
|
||||
binder.iface = ""
|
||||
updateNotification() // show invisible foreground notification to avoid being killed
|
||||
|
||||
@@ -62,6 +62,7 @@ class MainActivity : AppCompatActivity(), NavigationBarView.OnItemSelectedListen
|
||||
SmartSnackbar.Register(binding.fragmentHolder)
|
||||
WifiDoubleLock.ActivityListener(this)
|
||||
lifecycleScope.launch {
|
||||
BootReceiver.startIfEnabled()
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
onAppUpdateAvailable(null)
|
||||
try {
|
||||
|
||||
@@ -354,6 +354,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene
|
||||
* startService Step 1
|
||||
*/
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
BootReceiver.startIfEnabled()
|
||||
if (status != Status.IDLE) return START_NOT_STICKY
|
||||
val channel = channel ?: return START_NOT_STICKY.also { stopSelf() }
|
||||
status = Status.STARTING
|
||||
|
||||
@@ -111,6 +111,7 @@ class TetheringService : IpNeighbourMonitoringService(), TetheringManager.Tether
|
||||
override fun onBind(intent: Intent?) = binder
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
BootReceiver.startIfEnabled()
|
||||
// call this first just in case we are shutting down immediately
|
||||
if (Build.VERSION.SDK_INT >= 26) updateNotification()
|
||||
launch {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package be.mygod.vpnhotspot.util
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.service.quicksettings.Tile
|
||||
import android.service.quicksettings.TileService
|
||||
import androidx.annotation.RequiresApi
|
||||
import be.mygod.vpnhotspot.BootReceiver
|
||||
|
||||
@RequiresApi(24)
|
||||
abstract class KillableTileService : TileService(), ServiceConnection {
|
||||
@@ -25,4 +27,6 @@ abstract class KillableTileService : TileService(), ServiceConnection {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?) = super.onBind(intent).also { BootReceiver.startIfEnabled() }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user