Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions detekt_custom.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ datadog:
- "android.graphics.drawable.LayerDrawable.getDrawable(kotlin.Int):java.lang.IndexOutOfBoundsException"
- "android.net.ConnectivityManager.registerDefaultNetworkCallback(android.net.ConnectivityManager.NetworkCallback):java.lang.IllegalArgumentException,java.lang.SecurityException"
- "android.net.ConnectivityManager.unregisterNetworkCallback(android.net.ConnectivityManager.NetworkCallback):java.lang.SecurityException"
- "android.provider.Settings.System.getInt(android.content.ContentResolver?, kotlin.String?):android.provider.Settings.SettingNotFoundException"
- "android.util.Base64.encodeToString(kotlin.ByteArray?, kotlin.Int):java.lang.AssertionError"
- "android.view.Choreographer.getInstance():java.lang.IllegalStateException"
- "android.view.Choreographer.postFrameCallback():java.lang.IllegalArgumentException"
Expand Down Expand Up @@ -389,6 +390,7 @@ datadog:
- "android.net.ConnectivityManager.NetworkCallback.onLost(android.net.Network)"
- "android.net.ConnectivityManager.getNetworkCapabilities(android.net.Network?)"
- "android.net.NetworkCapabilities.hasTransport(kotlin.Int)"
- "android.os.BatteryManager.getIntProperty(kotlin.Int)"
- "android.os.Bundle.get(kotlin.String?)"
- "android.os.Bundle.getString(kotlin.String?)"
- "android.os.Bundle.keySet()"
Expand All @@ -411,6 +413,7 @@ datadog:
- "android.os.SystemClock.elapsedRealtime()"
- "android.provider.Settings.Global.getUriFor(kotlin.String?)"
- "android.provider.Settings.Secure.getUriFor(kotlin.String?)"
- "android.provider.Settings.System.getUriFor(kotlin.String?)"
- "android.util.Log.e(kotlin.String?, kotlin.String)"
- "android.util.Log.e(kotlin.String?, kotlin.String?, kotlin.Throwable?)"
- "android.util.Log.getStackTraceString(kotlin.Throwable?)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@ object Rum {
lastInteractionIdentifier = rumFeature.lastInteractionIdentifier,
slowFramesListener = rumFeature.slowFramesListener,
rumSessionTypeOverride = rumFeature.configuration.rumSessionTypeOverride,
accessibilitySnapshotManager = rumFeature.accessibilitySnapshotManager
accessibilitySnapshotManager = rumFeature.accessibilitySnapshotManager,
batteryInfoProvider = rumFeature.batteryInfoProvider,
displayInfoProvider = rumFeature.displayInfoProvider
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,20 @@ import com.datadog.android.rum.configuration.SlowFramesConfiguration
import com.datadog.android.rum.configuration.VitalsUpdateFrequency
import com.datadog.android.rum.internal.anr.ANRDetectorRunnable
import com.datadog.android.rum.internal.debug.UiRumDebugListener
import com.datadog.android.rum.internal.domain.InfoProvider
import com.datadog.android.rum.internal.domain.RumDataWriter
import com.datadog.android.rum.internal.domain.accessibility.AccessibilityReader
import com.datadog.android.rum.internal.domain.accessibility.AccessibilityInfo
import com.datadog.android.rum.internal.domain.accessibility.AccessibilitySnapshotManager
import com.datadog.android.rum.internal.domain.accessibility.DatadogAccessibilityReader
import com.datadog.android.rum.internal.domain.accessibility.DefaultAccessibilityReader
import com.datadog.android.rum.internal.domain.accessibility.DefaultAccessibilitySnapshotManager
import com.datadog.android.rum.internal.domain.accessibility.NoOpAccessibilityReader
import com.datadog.android.rum.internal.domain.accessibility.NoOpAccessibilitySnapshotManager
import com.datadog.android.rum.internal.domain.battery.BatteryInfo
import com.datadog.android.rum.internal.domain.battery.DefaultBatteryInfoProvider
import com.datadog.android.rum.internal.domain.battery.NoOpBatteryInfoProvider
import com.datadog.android.rum.internal.domain.display.DefaultDisplayInfoProvider
import com.datadog.android.rum.internal.domain.display.DisplayInfo
import com.datadog.android.rum.internal.domain.display.NoOpDisplayInfoProvider
import com.datadog.android.rum.internal.domain.event.RumEventMapper
import com.datadog.android.rum.internal.domain.event.RumEventMetaDeserializer
import com.datadog.android.rum.internal.domain.event.RumEventMetaSerializer
Expand Down Expand Up @@ -151,9 +158,11 @@ internal class RumFeature(
internal var initialResourceIdentifier: InitialResourceIdentifier = NoOpInitialResourceIdentifier()
internal var lastInteractionIdentifier: LastInteractionIdentifier? = NoOpLastInteractionIdentifier()
internal var slowFramesListener: SlowFramesListener? = null
internal var accessibilityReader: AccessibilityReader = NoOpAccessibilityReader()
internal var accessibilityReader: InfoProvider<AccessibilityInfo> = NoOpAccessibilityReader()
internal var accessibilitySnapshotManager: AccessibilitySnapshotManager =
NoOpAccessibilitySnapshotManager()
internal var batteryInfoProvider: InfoProvider<BatteryInfo> = NoOpBatteryInfoProvider()
internal var displayInfoProvider: InfoProvider<DisplayInfo> = NoOpDisplayInfoProvider()

private val lateCrashEventHandler by lazy { lateCrashReporterFactory(sdkCore as InternalSdkCore) }

Expand All @@ -166,8 +175,10 @@ internal class RumFeature(
this.appContext = appContext

if (configuration.collectAccessibility) {
accessibilityReader =
DatadogAccessibilityReader(applicationContext = appContext, internalLogger = sdkCore.internalLogger)
accessibilityReader = DefaultAccessibilityReader(
internalLogger = sdkCore.internalLogger,
applicationContext = appContext
)
accessibilitySnapshotManager = DefaultAccessibilitySnapshotManager(accessibilityReader)
}

Expand All @@ -193,6 +204,13 @@ internal class RumFeature(
telemetryConfigurationSampleRate = configuration.telemetryConfigurationSampleRate
backgroundEventTracking = configuration.backgroundEventTracking
trackFrustrations = configuration.trackFrustrations
batteryInfoProvider = DefaultBatteryInfoProvider(
applicationContext = appContext
)
displayInfoProvider = DefaultDisplayInfoProvider(
applicationContext = appContext,
internalLogger = sdkCore.internalLogger
)

configuration.viewTrackingStrategy?.let { viewTrackingStrategy = it }
actionTrackingStrategy = if (configuration.userActionTracking) {
Expand Down Expand Up @@ -306,17 +324,26 @@ internal class RumFeature(
vitalExecutorService = NoOpScheduledExecutorService()
sessionListener = NoOpRumSessionListener()

cleanupInfoProviders()

GlobalRumMonitor.unregister(sdkCore)
}

// endregion

private fun cleanupInfoProviders() {
if (configuration.collectAccessibility) {
accessibilityReader.cleanup()
accessibilityReader = NoOpAccessibilityReader()
accessibilitySnapshotManager = NoOpAccessibilitySnapshotManager()
}

GlobalRumMonitor.unregister(sdkCore)
batteryInfoProvider.cleanup()
batteryInfoProvider = NoOpBatteryInfoProvider()
displayInfoProvider.cleanup()
displayInfoProvider = NoOpDisplayInfoProvider()
}

// endregion

private fun createDataWriter(
configuration: Configuration,
sdkCore: InternalSdkCore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@
* Copyright 2016-Present Datadog, Inc.
*/

package com.datadog.android.rum.internal.domain.accessibility
package com.datadog.android.rum.internal.domain

import com.datadog.tools.annotation.NoOpImplementation
internal interface InfoData

@NoOpImplementation
internal interface AccessibilityReader {
fun getState(): Map<String, Any>
internal interface InfoProvider<T : InfoData> {
fun getState(): T
fun cleanup()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2016-Present Datadog, Inc.
*/

package com.datadog.android.rum.internal.domain.accessibility

import com.datadog.android.rum.internal.domain.InfoData

/**
* Represents the accessibility settings state of the device.
*
* @property textSize The font scale factor (1.0 = normal, >1.0 = larger, <1.0 = smaller)
* @property isScreenReaderEnabled Whether touch exploration is enabled (TalkBack, etc.)
* @property isColorInversionEnabled Whether color inversion is enabled
* @property isClosedCaptioningEnabled Whether closed captions are enabled
* @property isReducedAnimationsEnabled Whether animations are disabled/reduced
* @property isScreenPinningEnabled Whether the device is in single-app mode
* @property isRtlEnabled Whether right to left layout is enabled
*/
internal data class AccessibilityInfo(
val textSize: String? = null,
val isScreenReaderEnabled: Boolean? = null,
val isColorInversionEnabled: Boolean? = null,
val isClosedCaptioningEnabled: Boolean? = null,
val isReducedAnimationsEnabled: Boolean? = null,
val isScreenPinningEnabled: Boolean? = null,
val isRtlEnabled: Boolean? = null
) : InfoData
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ import com.datadog.tools.annotation.NoOpImplementation

@NoOpImplementation
internal interface AccessibilitySnapshotManager {
fun latestSnapshot(): Accessibility
fun latestSnapshot(): AccessibilityInfo
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import android.view.View
import android.view.accessibility.AccessibilityManager
import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener
import com.datadog.android.api.InternalLogger
import java.util.concurrent.atomic.AtomicBoolean
import com.datadog.android.rum.internal.domain.InfoProvider
import java.util.concurrent.atomic.AtomicLong

@Suppress("TooManyFunctions")
internal class DatadogAccessibilityReader(
internal class DefaultAccessibilityReader(
private val internalLogger: InternalLogger,
private val applicationContext: Context,
private val resources: Resources = applicationContext.resources,
Expand All @@ -37,14 +37,7 @@ internal class DatadogAccessibilityReader(
private val secureWrapper: SecureWrapper = SecureWrapper(),
private val globalWrapper: GlobalWrapper = GlobalWrapper(),
private val handler: Handler = Handler(Looper.getMainLooper())
) : AccessibilityReader, ComponentCallbacks {

@Volatile
private var currentState = Accessibility()

private var lastPollTime: AtomicLong = AtomicLong(0)

private var isInitialized = AtomicBoolean(false)
) : InfoProvider<AccessibilityInfo>, ComponentCallbacks {

private val displayInversionListener = object : ContentObserver(handler) {
override fun onChange(selfChange: Boolean, uri: Uri?) {
Expand Down Expand Up @@ -72,15 +65,22 @@ internal class DatadogAccessibilityReader(
updateState { it.copy(isScreenReaderEnabled = newScreenReaderEnabled) }
}

@Volatile
private var currentState = AccessibilityInfo()

private var lastPollTime: AtomicLong = AtomicLong(0)

init {
registerListeners()
buildInitialState()
}

override fun cleanup() {
if (isInitialized.get()) {
accessibilityManager?.removeTouchExplorationStateChangeListener(touchListener)
applicationContext.contentResolver.unregisterContentObserver(animationDurationListener)
applicationContext.contentResolver.unregisterContentObserver(captioningListener)
applicationContext.contentResolver.unregisterContentObserver(displayInversionListener)
applicationContext.unregisterComponentCallbacks(this)
isInitialized.set(false)
}
accessibilityManager?.removeTouchExplorationStateChangeListener(touchListener)
applicationContext.contentResolver.unregisterContentObserver(animationDurationListener)
applicationContext.contentResolver.unregisterContentObserver(captioningListener)
applicationContext.contentResolver.unregisterContentObserver(displayInversionListener)
applicationContext.unregisterComponentCallbacks(this)
}

override fun onLowMemory() {
Expand All @@ -96,34 +96,24 @@ internal class DatadogAccessibilityReader(
}

@Synchronized
override fun getState(): Map<String, Any> {
ensureInitialized()

override fun getState(): AccessibilityInfo {
val currentTime = System.currentTimeMillis()
val shouldPoll = currentTime - lastPollTime.get() >= POLL_THRESHOLD
if (shouldPoll) {
lastPollTime.set(currentTime)
pollForAttributesWithoutListeners()
}

return currentState.toMap()
return currentState
}

@Synchronized
private fun updateState(updater: (Accessibility) -> Accessibility) {
private fun updateState(updater: (AccessibilityInfo) -> AccessibilityInfo) {
currentState = updater(currentState)
}

private fun ensureInitialized() {
if (!isInitialized.get()) {
registerListeners()
currentState = buildInitialState()
isInitialized.set(true)
}
}

private fun buildInitialState(): Accessibility {
return Accessibility(
private fun buildInitialState() {
currentState = AccessibilityInfo(
textSize = getTextSize(),
isScreenReaderEnabled = isScreenReaderEnabled(accessibilityManager),
isColorInversionEnabled = isDisplayInversionEnabled(),
Expand Down
Loading
Loading