blob: a7a7a541d601316d37c86501d88733b719ad28df [file] [log] [blame]
package com.google.android.connecteddevice.metrics
import android.content.Context
import com.google.android.connecteddevice.model.Errors
import android.os.RemoteException
import com.google.android.connecteddevice.util.SafeLog.loge
import java.time.Duration
import java.time.Instant
/** Logger to report Companion events to statsd */
class EventMetricLogger(private val context: Context) {
private val uid = context.packageManager.getPackageUid(context.packageName, 0)
/** The time when association or reconnect discovery get started. */
private var discoveryStartedTime = Instant.EPOCH
private var connectedTime = Instant.EPOCH
private val defaultDuration = Duration.ZERO
/** Pushes the association discovery started event to statsd. */
fun pushAssociationStartedEvent() {
pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__ASSOCIATION_STARTED,
defaultDuration
)
}
/** Pushes the reconnection discovery started event to statsd. */
fun pushDiscoveryStartedEvent() {
discoveryStartedTime = Instant.now()
pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__DISCOVERY_STARTED,
defaultDuration
)
}
/** Pushes device get reconnected event to statsd. */
fun pushConnectedEvent() {
connectedTime = Instant.now()
pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__CONNECTED,
Duration.between(discoveryStartedTime, connectedTime)
)
}
/** Pushes the secure channel established event to statsd. */
fun pushSecureChannelEstablishedEvent() {
pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__SECURE_CHANNEL_ESTABLISHED,
Duration.between(connectedTime, Instant.now())
)
}
/** Pushes device disconnected event to statsd. */
fun pushDisconnectedEvent() {
pushEventsWithoutException(
CompanionStatsLog.COMPANION_STATUS_CHANGED__COMPANION_STATUS__DISCONNECTED,
defaultDuration
)
}
// TODO(b/298248724): Reports more errors.
fun pushCompanionErrorEvent(error: Int, duringAssociation: Boolean = false) {
val errorId =
when (error) {
Errors.DEVICE_ERROR_INVALID_HANDSHAKE ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_HANDSHAKE
Errors.DEVICE_ERROR_INVALID_MSG ->
CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_MSG
Errors.DEVICE_ERROR_INVALID_DEVICE_ID ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_DEVICE_ID
Errors.DEVICE_ERROR_INVALID_VERIFICATION ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_VERIFICATION
Errors.DEVICE_ERROR_INVALID_CHANNEL_STATE ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_CHANNEL_STATE
Errors.DEVICE_ERROR_INVALID_ENCRYPTION_KEY ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_ENCRYPTION_KEY
Errors.DEVICE_ERROR_STORAGE_FAILURE ->
CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_STORAGE_FAILURE
Errors.DEVICE_ERROR_INVALID_SECURITY_KEY ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INVALID_SECURITY_KEY
Errors.DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_INSECURE_RECIPIENT_ID_DETECTED
Errors.DEVICE_ERROR_UNEXPECTED_DISCONNECTION ->
CompanionStatsLog
.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNEXPECTED_DISCONNECTION
else ->
CompanionStatsLog.COMPANION_ERROR_REPORTED__COMPANION_ERROR__DEVICE_ERROR_UNSPECIFIED
}
try {
CompanionStatsLog.write(
CompanionStatsLog.COMPANION_ERROR_REPORTED,
uid,
errorId,
duringAssociation
)
} catch (e: NoClassDefFoundError) {
loge(TAG, "Encounter error when pushing Companion error events to statsd; skip.")
}
}
private fun pushEventsWithoutException(eventId: Int, duration: Duration) {
try {
CompanionStatsLog.write(
CompanionStatsLog.COMPANION_STATUS_CHANGED, uid, eventId, duration.toMillis())
} catch (e: NoClassDefFoundError) {
loge(TAG, "Encounter error when pushing Companion events to statsd; skip.")
}
}
companion object {
private const val TAG = "EventMetricLogger"
}
}