diff --git a/play-services-core/src/main/kotlin/org/microg/gms/ui/ExposureNotificationsAppPreferencesFragment.kt b/play-services-core/src/main/kotlin/org/microg/gms/ui/ExposureNotificationsAppPreferencesFragment.kt
index bfdfbe1a..bc54805c 100644
--- a/play-services-core/src/main/kotlin/org/microg/gms/ui/ExposureNotificationsAppPreferencesFragment.kt
+++ b/play-services-core/src/main/kotlin/org/microg/gms/ui/ExposureNotificationsAppPreferencesFragment.kt
@@ -8,10 +8,13 @@ package org.microg.gms.ui
import android.content.Intent
import android.os.Bundle
import android.text.format.DateUtils
+import android.util.JsonReader
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.gms.R
+import org.json.JSONObject
import org.microg.gms.nearby.exposurenotification.ExposureDatabase
+import java.util.concurrent.TimeUnit
class ExposureNotificationsAppPreferencesFragment : PreferenceFragmentCompat() {
private lateinit var open: Preference
@@ -53,6 +56,19 @@ class ExposureNotificationsAppPreferencesFragment : PreferenceFragmentCompat() {
if (lastCheckTime != null && lastCheckTime != 0L) {
str += "\n" + getString(R.string.pref_exposure_app_last_check_summary, DateUtils.getRelativeDateTimeString(context, lastCheckTime, DateUtils.MINUTE_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME))
}
+ val lastExposureSummaryTime = database.lastMethodCall(packageName, "getExposureSummary")
+ val lastExposureSummary = database.lastMethodCallArgs(packageName, "getExposureSummary")
+ if (lastExposureSummaryTime != null && lastExposureSummary != null && System.currentTimeMillis() - lastExposureSummaryTime <= TimeUnit.DAYS.toMillis(1)) {
+ try {
+ val json = JSONObject(lastExposureSummary)
+ val matchedKeys = json.optInt("response_matched_keys")
+ val daysSince = json.optInt("response_days_since", -1)
+ if (matchedKeys > 0 && daysSince >= 0) {
+ str += "\n" + resources.getQuantityString(R.plurals.pref_exposure_app_last_report_summary, matchedKeys, matchedKeys, daysSince)
+ }
+ } catch (ignored: Exception) {
+ }
+ }
checks.summary = str
}
}
diff --git a/play-services-core/src/main/res/values/plurals.xml b/play-services-core/src/main/res/values/plurals.xml
index e12bc924..c5b8ef5a 100644
--- a/play-services-core/src/main/res/values/plurals.xml
+++ b/play-services-core/src/main/res/values/plurals.xml
@@ -32,4 +32,8 @@
- Request missing permission
- Request missing permissions
-
\ No newline at end of file
+
+ - Last report: %1$d match, %2$d days ago
+ - Last report: %1$d matches, latest %2$d days ago
+
+
diff --git a/play-services-core/src/main/res/xml/preferences_exposure_notifications_app.xml b/play-services-core/src/main/res/xml/preferences_exposure_notifications_app.xml
index c5aa4767..26caa9d8 100644
--- a/play-services-core/src/main/res/xml/preferences_exposure_notifications_app.xml
+++ b/play-services-core/src/main/res/xml/preferences_exposure_notifications_app.xml
@@ -16,6 +16,6 @@
+ tools:summary="7 checks in past 14 days\nLast check: 3 hours ago\nLast report: 2 matches, latest 3 days ago" />
diff --git a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureDatabase.kt b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureDatabase.kt
index b8b89527..04515f29 100644
--- a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureDatabase.kt
+++ b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureDatabase.kt
@@ -444,6 +444,16 @@ class ExposureDatabase private constructor(private val context: Context) : SQLit
}
}
+ fun lastMethodCallArgs(packageName: String, method: String): String? = readableDatabase.run {
+ query(TABLE_APP_LOG, arrayOf("args"), "package = ? AND method = ?", arrayOf(packageName, method), null, null, "timestamp DESC", "1").use { cursor ->
+ if (cursor.moveToNext()) {
+ cursor.getString(0)
+ } else {
+ null
+ }
+ }
+ }
+
private val currentTemporaryExposureKey: TemporaryExposureKey
get() = findOwnKeyAt(currentRollingStartNumber.toInt())
?: storeOwnKey(generateCurrentTemporaryExposureKey())
diff --git a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt
index 28aac77b..8d573bb1 100644
--- a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt
+++ b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/ExposureNotificationServiceImpl.kt
@@ -72,24 +72,14 @@ class ExposureNotificationServiceImpl(private val context: Context, private val
}
override fun stop(params: StopParams) {
- if (!ExposurePreferences(context).enabled) {
- params.callback.onResult(Status.SUCCESS)
- return
+ ExposurePreferences(context).enabled = false
+ ExposureDatabase.with(context) { database ->
+ database.noteAppAction(packageName, "stop")
}
- confirm(CONFIRM_ACTION_STOP) { resultCode, _ ->
- if (resultCode == SUCCESS) {
- ExposurePreferences(context).enabled = false
- }
- ExposureDatabase.with(context) { database ->
- database.noteAppAction(packageName, "stop", JSONObject().apply {
- put("result", resultCode)
- }.toString())
- }
- try {
- params.callback.onResult(Status.SUCCESS)
- } catch (e: Exception) {
- Log.w(TAG, "Callback failed", e)
- }
+ try {
+ params.callback.onResult(Status.SUCCESS)
+ } catch (e: Exception) {
+ Log.w(TAG, "Callback failed", e)
}
}
diff --git a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/MeasuredExposure.kt b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/MeasuredExposure.kt
index 415baecf..18113f1f 100644
--- a/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/MeasuredExposure.kt
+++ b/play-services-nearby-core/src/main/kotlin/org/microg/gms/nearby/exposurenotification/MeasuredExposure.kt
@@ -55,7 +55,7 @@ data class MergedExposure internal constructor(val key: TemporaryExposureKey, va
get() = TimeUnit.MILLISECONDS.toDays(System.currentTimeMillis() - timestamp)
val attenuation
- get() = subs.map { it.attenuation }.min()!!
+ get() = (subs.map { it.attenuation * it.duration }.sum().toDouble() / subs.map { it.duration }.sum().toDouble()).toInt()
fun getAttenuationRiskScore(configuration: ExposureConfiguration): Int {
return when {