mirror of
https://github.com/YTVanced/VancedMicroG
synced 2024-12-04 00:37:27 +00:00
EN: Make service more robust against exceptions while processing app input
This commit is contained in:
parent
45d4dffb88
commit
91c8e43ab9
1 changed files with 36 additions and 27 deletions
|
@ -12,6 +12,7 @@ import android.content.*
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.LifecycleCoroutineScope
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.google.android.gms.common.api.Status
|
import com.google.android.gms.common.api.Status
|
||||||
|
@ -19,6 +20,8 @@ import com.google.android.gms.nearby.exposurenotification.*
|
||||||
import com.google.android.gms.nearby.exposurenotification.ExposureNotificationStatusCodes.*
|
import com.google.android.gms.nearby.exposurenotification.ExposureNotificationStatusCodes.*
|
||||||
import com.google.android.gms.nearby.exposurenotification.internal.*
|
import com.google.android.gms.nearby.exposurenotification.internal.*
|
||||||
import kotlinx.coroutines.CompletableDeferred
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.withTimeout
|
import kotlinx.coroutines.withTimeout
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
@ -37,6 +40,8 @@ import kotlin.random.Random
|
||||||
|
|
||||||
class ExposureNotificationServiceImpl(private val context: Context, private val lifecycle: Lifecycle, private val packageName: String) : INearbyExposureNotificationService.Stub(), LifecycleOwner {
|
class ExposureNotificationServiceImpl(private val context: Context, private val lifecycle: Lifecycle, private val packageName: String) : INearbyExposureNotificationService.Stub(), LifecycleOwner {
|
||||||
|
|
||||||
|
private fun LifecycleCoroutineScope.launchSafely(block: suspend CoroutineScope.() -> Unit): Job = launchWhenStarted { try { block() } catch (e: Exception) { Log.w(TAG, "Error in coroutine", e) } }
|
||||||
|
|
||||||
override fun getLifecycle(): Lifecycle = lifecycle
|
override fun getLifecycle(): Lifecycle = lifecycle
|
||||||
|
|
||||||
private fun pendingConfirm(permission: String): PendingIntent {
|
private fun pendingConfirm(permission: String): PendingIntent {
|
||||||
|
@ -102,7 +107,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun start(params: StartParams) {
|
override fun start(params: StartParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val isAuthorized = ExposureDatabase.with(context) { it.isAppAuthorized(packageName) }
|
val isAuthorized = ExposureDatabase.with(context) { it.isAppAuthorized(packageName) }
|
||||||
val adapter = BluetoothAdapter.getDefaultAdapter()
|
val adapter = BluetoothAdapter.getDefaultAdapter()
|
||||||
val status = if (isAuthorized && ExposurePreferences(context).enabled) {
|
val status = if (isAuthorized && ExposurePreferences(context).enabled) {
|
||||||
|
@ -131,7 +136,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun stop(params: StopParams) {
|
override fun stop(params: StopParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val isAuthorized = ExposureDatabase.with(context) { database ->
|
val isAuthorized = ExposureDatabase.with(context) { database ->
|
||||||
database.isAppAuthorized(packageName).also {
|
database.isAppAuthorized(packageName).also {
|
||||||
if (it) database.noteAppAction(packageName, "stop")
|
if (it) database.noteAppAction(packageName, "stop")
|
||||||
|
@ -149,7 +154,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isEnabled(params: IsEnabledParams) {
|
override fun isEnabled(params: IsEnabledParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val isAuthorized = ExposureDatabase.with(context) { database ->
|
val isAuthorized = ExposureDatabase.with(context) { database ->
|
||||||
database.isAppAuthorized(packageName)
|
database.isAppAuthorized(packageName)
|
||||||
}
|
}
|
||||||
|
@ -162,7 +167,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTemporaryExposureKeyHistory(params: GetTemporaryExposureKeyHistoryParams) {
|
override fun getTemporaryExposureKeyHistory(params: GetTemporaryExposureKeyHistoryParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val status = confirmPermission(CONFIRM_ACTION_KEYS)
|
val status = confirmPermission(CONFIRM_ACTION_KEYS)
|
||||||
val response = when {
|
val response = when {
|
||||||
status.isSuccess -> ExposureDatabase.with(context) { database ->
|
status.isSuccess -> ExposureDatabase.with(context) { database ->
|
||||||
|
@ -243,7 +248,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
override fun provideDiagnosisKeys(params: ProvideDiagnosisKeysParams) {
|
override fun provideDiagnosisKeys(params: ProvideDiagnosisKeysParams) {
|
||||||
val token = params.token ?: TOKEN_A
|
val token = params.token ?: TOKEN_A
|
||||||
Log.w(TAG, "provideDiagnosisKeys() with $packageName/$token")
|
Log.w(TAG, "provideDiagnosisKeys() with $packageName/$token")
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val tid = ExposureDatabase.with(context) { database ->
|
val tid = ExposureDatabase.with(context) { database ->
|
||||||
val configuration = params.configuration
|
val configuration = params.configuration
|
||||||
if (configuration != null) {
|
if (configuration != null) {
|
||||||
|
@ -259,7 +264,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.w(TAG, "Callback failed", e)
|
Log.w(TAG, "Callback failed", e)
|
||||||
}
|
}
|
||||||
return@launchWhenStarted
|
return@launchSafely
|
||||||
}
|
}
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
|
@ -289,21 +294,25 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
params.keyFileSupplier?.let { keyFileSupplier ->
|
params.keyFileSupplier?.let { keyFileSupplier ->
|
||||||
Log.d(TAG, "Using key file supplier")
|
Log.d(TAG, "Using key file supplier")
|
||||||
while (keyFileSupplier.isAvailable && keyFileSupplier.hasNext()) {
|
try {
|
||||||
try {
|
while (keyFileSupplier.isAvailable && keyFileSupplier.hasNext()) {
|
||||||
val cacheFile = File(context.cacheDir, "en-keyfile-${System.currentTimeMillis()}-${Random.nextInt()}.zip")
|
try {
|
||||||
ParcelFileDescriptor.AutoCloseInputStream(keyFileSupplier.next()).use { it.copyToFile(cacheFile) }
|
val cacheFile = File(context.cacheDir, "en-keyfile-${System.currentTimeMillis()}-${Random.nextInt()}.zip")
|
||||||
val hash = MessageDigest.getInstance("SHA-256").digest(cacheFile)
|
ParcelFileDescriptor.AutoCloseInputStream(keyFileSupplier.next()).use { it.copyToFile(cacheFile) }
|
||||||
val storedKeys = database.storeDiagnosisFileUsed(tid, hash)
|
val hash = MessageDigest.getInstance("SHA-256").digest(cacheFile)
|
||||||
if (storedKeys != null) {
|
val storedKeys = database.storeDiagnosisFileUsed(tid, hash)
|
||||||
keys += storedKeys.toInt()
|
if (storedKeys != null) {
|
||||||
cacheFile.delete()
|
keys += storedKeys.toInt()
|
||||||
} else {
|
cacheFile.delete()
|
||||||
todoKeyFiles.add(cacheFile to hash)
|
} else {
|
||||||
|
todoKeyFiles.add(cacheFile to hash)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Failed parsing file", e)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.w(TAG, "Failed parsing file", e)
|
|
||||||
}
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "Disconnected from key file supplier", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,7 +398,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExposureSummary(params: GetExposureSummaryParams) {
|
override fun getExposureSummary(params: GetExposureSummaryParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val response = buildExposureSummary(params.token)
|
val response = buildExposureSummary(params.token)
|
||||||
|
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
|
@ -413,7 +422,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExposureInformation(params: GetExposureInformationParams) {
|
override fun getExposureInformation(params: GetExposureInformationParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
val pair = database.loadConfiguration(packageName, params.token)
|
val pair = database.loadConfiguration(packageName, params.token)
|
||||||
val response = if (pair != null && database.isAppAuthorized(packageName)) {
|
val response = if (pair != null && database.isAppAuthorized(packageName)) {
|
||||||
|
@ -494,7 +503,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getExposureWindows(params: GetExposureWindowsParams) {
|
override fun getExposureWindows(params: GetExposureWindowsParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val response = getExposureWindowsInternal(params.token ?: TOKEN_A)
|
val response = getExposureWindowsInternal(params.token ?: TOKEN_A)
|
||||||
|
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
|
@ -529,7 +538,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDailySummaries(params: GetDailySummariesParams) {
|
override fun getDailySummaries(params: GetDailySummariesParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val response = getExposureWindowsInternal().groupBy { it.dateMillisSinceEpoch }.map {
|
val response = getExposureWindowsInternal().groupBy { it.dateMillisSinceEpoch }.map {
|
||||||
val map = arrayListOf<DailySummary.ExposureSummaryData>()
|
val map = arrayListOf<DailySummary.ExposureSummaryData>()
|
||||||
for (i in 0 until ReportType.VALUES) {
|
for (i in 0 until ReportType.VALUES) {
|
||||||
|
@ -564,7 +573,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setDiagnosisKeysDataMapping(params: SetDiagnosisKeysDataMappingParams) {
|
override fun setDiagnosisKeysDataMapping(params: SetDiagnosisKeysDataMappingParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
database.storeConfiguration(packageName, TOKEN_A, params.mapping)
|
database.storeConfiguration(packageName, TOKEN_A, params.mapping)
|
||||||
database.noteAppAction(packageName, "setDiagnosisKeysDataMapping")
|
database.noteAppAction(packageName, "setDiagnosisKeysDataMapping")
|
||||||
|
@ -578,7 +587,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDiagnosisKeysDataMapping(params: GetDiagnosisKeysDataMappingParams) {
|
override fun getDiagnosisKeysDataMapping(params: GetDiagnosisKeysDataMappingParams) {
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
val mapping = ExposureDatabase.with(context) { database ->
|
val mapping = ExposureDatabase.with(context) { database ->
|
||||||
val triple = database.loadConfiguration(packageName, TOKEN_A)
|
val triple = database.loadConfiguration(packageName, TOKEN_A)
|
||||||
database.noteAppAction(packageName, "getDiagnosisKeysDataMapping")
|
database.noteAppAction(packageName, "getDiagnosisKeysDataMapping")
|
||||||
|
@ -594,7 +603,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
|
|
||||||
override fun getPackageConfiguration(params: GetPackageConfigurationParams) {
|
override fun getPackageConfiguration(params: GetPackageConfigurationParams) {
|
||||||
Log.w(TAG, "Not yet implemented: getPackageConfiguration")
|
Log.w(TAG, "Not yet implemented: getPackageConfiguration")
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
database.noteAppAction(packageName, "getPackageConfiguration")
|
database.noteAppAction(packageName, "getPackageConfiguration")
|
||||||
}
|
}
|
||||||
|
@ -608,7 +617,7 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
|
||||||
|
|
||||||
override fun getStatus(params: GetStatusParams) {
|
override fun getStatus(params: GetStatusParams) {
|
||||||
Log.w(TAG, "Not yet implemented: getStatus")
|
Log.w(TAG, "Not yet implemented: getStatus")
|
||||||
lifecycleScope.launchWhenStarted {
|
lifecycleScope.launchSafely {
|
||||||
ExposureDatabase.with(context) { database ->
|
ExposureDatabase.with(context) { database ->
|
||||||
database.noteAppAction(packageName, "getStatus")
|
database.noteAppAction(packageName, "getStatus")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue