-
Notifications
You must be signed in to change notification settings - Fork 7
/
EmbracePowerSaveModeService.kt
122 lines (104 loc) · 4.46 KB
/
EmbracePowerSaveModeService.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package io.embrace.android.embracesdk.capture.powersave
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.PowerManager
import android.os.PowerManager.ACTION_POWER_SAVE_MODE_CHANGED
import io.embrace.android.embracesdk.internal.Systrace
import io.embrace.android.embracesdk.internal.clock.Clock
import io.embrace.android.embracesdk.internal.utils.Provider
import io.embrace.android.embracesdk.logging.InternalStaticEmbraceLogger
import io.embrace.android.embracesdk.logging.InternalStaticEmbraceLogger.Companion.logDebug
import io.embrace.android.embracesdk.logging.InternalStaticEmbraceLogger.Companion.logDeveloper
import io.embrace.android.embracesdk.payload.PowerModeInterval
import io.embrace.android.embracesdk.session.lifecycle.ProcessStateListener
import io.embrace.android.embracesdk.worker.BackgroundWorker
internal class EmbracePowerSaveModeService(
private val context: Context,
private val backgroundWorker: BackgroundWorker,
private val clock: Clock,
powerManagerProvider: Provider<PowerManager?>
) : BroadcastReceiver(), PowerSaveModeService, ProcessStateListener {
private companion object {
private const val MAX_CAPTURED_POWER_MODE_INTERVALS = 100
}
private val tag = "EmbracePowerSaveModeService"
private val powerSaveIntentFilter = IntentFilter(ACTION_POWER_SAVE_MODE_CHANGED)
private val powerSaveModeIntervals = mutableListOf<PowerChange>()
private val powerManager: PowerManager? by lazy(powerManagerProvider)
init {
registerPowerSaveModeReceiver()
}
private fun registerPowerSaveModeReceiver() {
backgroundWorker.submit {
Systrace.traceSynchronous("power-service-registration") {
try {
if (powerManager != null) {
context.registerReceiver(this, powerSaveIntentFilter)
logDeveloper(tag, "registered power save mode changed")
}
} catch (ex: Exception) {
InternalStaticEmbraceLogger.logError(
"Failed to register: $tag broadcast receiver. Power save mode status will be unavailable.",
ex
)
}
}
}
}
override fun onForeground(coldStart: Boolean, timestamp: Long) {
if (powerManager?.isPowerSaveMode == true) {
addPowerChange(PowerChange(timestamp, Kind.START))
}
}
override fun onReceive(context: Context, intent: Intent) {
logDeveloper(tag, "onReceive")
try {
when (intent.action) {
ACTION_POWER_SAVE_MODE_CHANGED ->
addPowerChange(
PowerChange(
clock.now(),
if (powerManager?.isPowerSaveMode == true) Kind.START else Kind.END
)
)
}
} catch (ex: Exception) {
InternalStaticEmbraceLogger.logError("Failed to handle " + intent.action, ex)
}
}
private fun addPowerChange(powerChange: PowerChange) {
if (powerSaveModeIntervals.size < MAX_CAPTURED_POWER_MODE_INTERVALS) {
powerSaveModeIntervals.add(powerChange)
}
}
override fun getCapturedData(): List<PowerModeInterval> {
val intervals = mutableListOf<PowerModeInterval>()
for (powerChange in powerSaveModeIntervals) {
if (powerChange.time >= 0) {
when (powerChange.kind) {
Kind.START -> {
intervals.add(PowerModeInterval(powerChange.time))
}
Kind.END -> {
if (intervals.isNotEmpty() && intervals.last().startTime != 0L) {
intervals[intervals.size - 1] =
intervals.last().copy(endTime = powerChange.time)
} else {
intervals.add(PowerModeInterval(0, powerChange.time))
}
}
}
}
}
return intervals
}
override fun close() {
logDebug("Stopping $tag")
context.unregisterReceiver(this)
}
override fun cleanCollections() = powerSaveModeIntervals.clear()
data class PowerChange(val time: Long, val kind: Kind)
enum class Kind { START, END }
}