Push: improve Push history screen, log and stored data (#4601)
* Add adb tools to help with doze mode and app standby * Add info about the device state when an error occurs in push. * Keep more events in the DB. * Push history: add confirmation dialog when resetting the data * Push history: add a filter to see only the errors * Update screenshots * Push history: print out invalid/ignored data received. * Increase log level for push, to make such log more visible. It also appears that sometimes Timber.d are not present in the rageshakes. * Log priority * Do not include device state for invalid/ignored event. * Fix tests. * Fix format issue. * Fix mistake in code blocks and do not filter when not necessary. * Improve formatting and add missing unit test. * Reduce nesting of blocks. --------- Co-authored-by: ElementBot <android@element.io>
This commit is contained in:
@@ -7,8 +7,13 @@
|
||||
|
||||
package io.element.android.libraries.push.impl.history
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Build
|
||||
import android.os.PowerManager
|
||||
import androidx.core.content.getSystemService
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
@@ -21,15 +26,38 @@ import javax.inject.Inject
|
||||
class DefaultPushHistoryService @Inject constructor(
|
||||
private val pushDatabase: PushDatabase,
|
||||
private val systemClock: SystemClock,
|
||||
@ApplicationContext context: Context,
|
||||
) : PushHistoryService {
|
||||
private val powerManager = context.getSystemService<PowerManager>()
|
||||
private val packageName = context.packageName
|
||||
|
||||
override fun onPushReceived(
|
||||
providerInfo: String,
|
||||
eventId: EventId?,
|
||||
roomId: RoomId?,
|
||||
sessionId: SessionId?,
|
||||
hasBeenResolved: Boolean,
|
||||
includeDeviceState: Boolean,
|
||||
comment: String?,
|
||||
) {
|
||||
val finalComment = buildString {
|
||||
append(comment.orEmpty())
|
||||
if (includeDeviceState && powerManager != null) {
|
||||
// Add info about device state
|
||||
append("\n")
|
||||
append(" - Idle: ${powerManager.isDeviceIdleMode}\n")
|
||||
append(" - Power Save Mode: ${powerManager.isPowerSaveMode}\n")
|
||||
append(" - Ignoring Battery Optimizations: ${powerManager.isIgnoringBatteryOptimizations(packageName)}\n")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
append(" - Device Light Idle Mode: ${powerManager.isDeviceLightIdleMode}\n")
|
||||
append(" - Low Power Standby Enabled: ${powerManager.isLowPowerStandbyEnabled}\n")
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
|
||||
append(" - Exempt from Low Power Standby: ${powerManager.isExemptFromLowPowerStandby}\n")
|
||||
}
|
||||
}
|
||||
}.takeIf { it.isNotEmpty() }
|
||||
|
||||
pushDatabase.pushHistoryQueries.insertPushHistory(
|
||||
PushHistory(
|
||||
pushDate = systemClock.epochMillis(),
|
||||
@@ -38,11 +66,11 @@ class DefaultPushHistoryService @Inject constructor(
|
||||
roomId = roomId?.value,
|
||||
sessionId = sessionId?.value,
|
||||
hasBeenResolved = if (hasBeenResolved) 1 else 0,
|
||||
comment = comment,
|
||||
comment = finalComment,
|
||||
)
|
||||
)
|
||||
|
||||
// Keep only the last 100 events
|
||||
pushDatabase.pushHistoryQueries.removeOldest(100)
|
||||
// Keep only the last 1_000 events
|
||||
pushDatabase.pushHistoryQueries.removeOldest(1_000)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,19 +22,22 @@ interface PushHistoryService {
|
||||
roomId: RoomId?,
|
||||
sessionId: SessionId?,
|
||||
hasBeenResolved: Boolean,
|
||||
includeDeviceState: Boolean,
|
||||
comment: String?,
|
||||
)
|
||||
}
|
||||
|
||||
fun PushHistoryService.onInvalidPushReceived(
|
||||
providerInfo: String,
|
||||
data: String,
|
||||
) = onPushReceived(
|
||||
providerInfo = providerInfo,
|
||||
eventId = null,
|
||||
roomId = null,
|
||||
sessionId = null,
|
||||
hasBeenResolved = false,
|
||||
comment = "Invalid push data",
|
||||
includeDeviceState = false,
|
||||
comment = "Invalid or ignored push data:\n$data",
|
||||
)
|
||||
|
||||
fun PushHistoryService.onUnableToRetrieveSession(
|
||||
@@ -48,6 +51,7 @@ fun PushHistoryService.onUnableToRetrieveSession(
|
||||
roomId = roomId,
|
||||
sessionId = null,
|
||||
hasBeenResolved = false,
|
||||
includeDeviceState = true,
|
||||
comment = "Unable to retrieve session: $reason",
|
||||
)
|
||||
|
||||
@@ -63,6 +67,7 @@ fun PushHistoryService.onUnableToResolveEvent(
|
||||
roomId = roomId,
|
||||
sessionId = sessionId,
|
||||
hasBeenResolved = false,
|
||||
includeDeviceState = true,
|
||||
comment = "Unable to resolve event: $reason",
|
||||
)
|
||||
|
||||
@@ -78,6 +83,7 @@ fun PushHistoryService.onSuccess(
|
||||
roomId = roomId,
|
||||
sessionId = sessionId,
|
||||
hasBeenResolved = true,
|
||||
includeDeviceState = false,
|
||||
comment = buildString {
|
||||
append("Success")
|
||||
if (comment.isNullOrBlank().not()) {
|
||||
@@ -94,5 +100,6 @@ fun PushHistoryService.onDiagnosticPush(
|
||||
roomId = null,
|
||||
sessionId = null,
|
||||
hasBeenResolved = true,
|
||||
includeDeviceState = false,
|
||||
comment = "Diagnostic push",
|
||||
)
|
||||
|
||||
@@ -72,9 +72,9 @@ class DefaultPushHandler @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun handleInvalid(providerInfo: String) {
|
||||
override suspend fun handleInvalid(providerInfo: String, data: String) {
|
||||
incrementPushDataStore.incrementPushCounter()
|
||||
pushHistoryService.onInvalidPushReceived(providerInfo)
|
||||
pushHistoryService.onInvalidPushReceived(providerInfo, data)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,8 +19,9 @@ class FakePushHistoryService(
|
||||
RoomId?,
|
||||
SessionId?,
|
||||
Boolean,
|
||||
Boolean,
|
||||
String?
|
||||
) -> Unit = { _, _, _, _, _, _ -> lambdaError() }
|
||||
) -> Unit = { _, _, _, _, _, _, _ -> lambdaError() }
|
||||
) : PushHistoryService {
|
||||
override fun onPushReceived(
|
||||
providerInfo: String,
|
||||
@@ -28,6 +29,7 @@ class FakePushHistoryService(
|
||||
roomId: RoomId?,
|
||||
sessionId: SessionId?,
|
||||
hasBeenResolved: Boolean,
|
||||
includeDeviceState: Boolean,
|
||||
comment: String?,
|
||||
) {
|
||||
onPushReceivedResult(
|
||||
@@ -36,6 +38,7 @@ class FakePushHistoryService(
|
||||
roomId,
|
||||
sessionId,
|
||||
hasBeenResolved,
|
||||
includeDeviceState,
|
||||
comment
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ class DefaultPushHandlerTest {
|
||||
@Test
|
||||
fun `check handleInvalid behavior`() = runTest {
|
||||
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -68,12 +68,12 @@ class DefaultPushHandlerTest {
|
||||
incrementPushCounterResult = incrementPushCounterResult,
|
||||
pushHistoryService = pushHistoryService,
|
||||
)
|
||||
defaultPushHandler.handleInvalid(A_PUSHER_INFO)
|
||||
defaultPushHandler.handleInvalid(A_PUSHER_INFO, "data")
|
||||
incrementPushCounterResult.assertions()
|
||||
.isCalledOnce()
|
||||
onPushReceivedResult.assertions()
|
||||
.isCalledOnce()
|
||||
.with(value(A_PUSHER_INFO), value(null), value(null), value(null), value(false), value("Invalid push data"))
|
||||
.with(value(A_PUSHER_INFO), value(null), value(null), value(null), value(false), value(false), value("Invalid or ignored push data:\ndata"))
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -85,7 +85,7 @@ class DefaultPushHandlerTest {
|
||||
}
|
||||
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -133,7 +133,7 @@ class DefaultPushHandlerTest {
|
||||
unread = 0,
|
||||
clientSecret = A_SECRET,
|
||||
)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -176,7 +176,7 @@ class DefaultPushHandlerTest {
|
||||
unread = 0,
|
||||
clientSecret = A_SECRET,
|
||||
)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -221,7 +221,7 @@ class DefaultPushHandlerTest {
|
||||
unread = 0,
|
||||
clientSecret = A_SECRET,
|
||||
)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -263,7 +263,7 @@ class DefaultPushHandlerTest {
|
||||
unread = 0,
|
||||
clientSecret = A_SECRET,
|
||||
)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -290,7 +290,7 @@ class DefaultPushHandlerTest {
|
||||
.isNeverCalled()
|
||||
onPushReceivedResult.assertions()
|
||||
.isCalledOnce()
|
||||
.with(any(), value(AN_EVENT_ID), value(A_ROOM_ID), value(A_USER_ID), value(false), any())
|
||||
.with(any(), value(AN_EVENT_ID), value(A_ROOM_ID), value(A_USER_ID), value(false), value(true), any())
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -314,7 +314,7 @@ class DefaultPushHandlerTest {
|
||||
> { _, _, _, _, _, _, _, _ -> }
|
||||
val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda)
|
||||
val onNotifiableEventReceived = lambdaRecorder<NotifiableEvent, Unit> {}
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -359,7 +359,7 @@ class DefaultPushHandlerTest {
|
||||
Unit,
|
||||
> { _, _, _, _, _, _, _, _ -> }
|
||||
val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -403,7 +403,7 @@ class DefaultPushHandlerTest {
|
||||
Unit,
|
||||
> { _, _, _, _, _, _, _, _ -> }
|
||||
val elementCallEntryPoint = FakeElementCallEntryPoint(handleIncomingCallResult = handleIncomingCallLambda)
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -444,7 +444,7 @@ class DefaultPushHandlerTest {
|
||||
)
|
||||
val onRedactedEventReceived = lambdaRecorder<ResolvedPushEvent.Redaction, Unit> { }
|
||||
val incrementPushCounterResult = lambdaRecorder<Unit> {}
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
@@ -476,7 +476,7 @@ class DefaultPushHandlerTest {
|
||||
clientSecret = A_SECRET,
|
||||
)
|
||||
val diagnosticPushHandler = DiagnosticPushHandler()
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, String?, Unit> { _, _, _, _, _, _ -> }
|
||||
val onPushReceivedResult = lambdaRecorder<String, EventId?, RoomId?, SessionId?, Boolean, Boolean, String?, Unit> { _, _, _, _, _, _, _ -> }
|
||||
val pushHistoryService = FakePushHistoryService(
|
||||
onPushReceivedResult = onPushReceivedResult,
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user