mirror of
https://github.com/signalapp/Signal-Android.git
synced 2025-12-23 20:48:43 +00:00
Allow RemoteConfig to be lazily initialized.
This commit is contained in:
@@ -145,10 +145,6 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
|
|||||||
|
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
if (RemoteConfig.internalUser()) {
|
|
||||||
Tracer.getInstance().setMaxBufferSize(35_000);
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
|
|
||||||
AppStartup.getInstance().addBlocking("sqlcipher-init", () -> {
|
AppStartup.getInstance().addBlocking("sqlcipher-init", () -> {
|
||||||
@@ -183,6 +179,7 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
|
|||||||
.addBlocking("remote-config", RemoteConfig::init)
|
.addBlocking("remote-config", RemoteConfig::init)
|
||||||
.addBlocking("ring-rtc", this::initializeRingRtc)
|
.addBlocking("ring-rtc", this::initializeRingRtc)
|
||||||
.addBlocking("glide", () -> SignalGlideModule.setRegisterGlideComponents(new SignalGlideComponents()))
|
.addBlocking("glide", () -> SignalGlideModule.setRegisterGlideComponents(new SignalGlideComponents()))
|
||||||
|
.addBlocking("tracer", this::initializeTracer)
|
||||||
.addNonBlocking(() -> RegistrationUtil.maybeMarkRegistrationComplete())
|
.addNonBlocking(() -> RegistrationUtil.maybeMarkRegistrationComplete())
|
||||||
.addNonBlocking(() -> Glide.get(this))
|
.addNonBlocking(() -> Glide.get(this))
|
||||||
.addNonBlocking(this::cleanAvatarStorage)
|
.addNonBlocking(this::cleanAvatarStorage)
|
||||||
@@ -423,6 +420,12 @@ public class ApplicationContext extends MultiDexApplication implements AppForegr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeTracer() {
|
||||||
|
if (RemoteConfig.internalUser()) {
|
||||||
|
Tracer.getInstance().setMaxBufferSize(35_000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initializePeriodicTasks() {
|
private void initializePeriodicTasks() {
|
||||||
RotateSignedPreKeyListener.schedule(this);
|
RotateSignedPreKeyListener.schedule(this);
|
||||||
DirectoryRefreshListener.schedule(this);
|
DirectoryRefreshListener.schedule(this);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.util
|
package org.thoughtcrime.securesms.util
|
||||||
|
|
||||||
|
import androidx.annotation.GuardedBy
|
||||||
import androidx.annotation.VisibleForTesting
|
import androidx.annotation.VisibleForTesting
|
||||||
import androidx.annotation.WorkerThread
|
import androidx.annotation.WorkerThread
|
||||||
import org.json.JSONException
|
import org.json.JSONException
|
||||||
@@ -19,6 +20,8 @@ import org.thoughtcrime.securesms.util.RemoteConfig.remoteBoolean
|
|||||||
import org.thoughtcrime.securesms.util.RemoteConfig.remoteValue
|
import org.thoughtcrime.securesms.util.RemoteConfig.remoteValue
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.TreeMap
|
import java.util.TreeMap
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import kotlin.concurrent.withLock
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
@@ -48,18 +51,27 @@ object RemoteConfig {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
val configsByKey: MutableMap<String, Config<*>> = mutableMapOf()
|
val configsByKey: MutableMap<String, Config<*>> = mutableMapOf()
|
||||||
|
|
||||||
|
@GuardedBy("initLock")
|
||||||
|
@Volatile
|
||||||
|
@VisibleForTesting
|
||||||
|
var initialized: Boolean = false
|
||||||
|
private val initLock: ReentrantLock = ReentrantLock()
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
|
||||||
fun init() {
|
fun init() {
|
||||||
val current = parseStoredConfig(SignalStore.remoteConfig.currentConfig)
|
initLock.withLock {
|
||||||
val pending = parseStoredConfig(SignalStore.remoteConfig.pendingConfig)
|
val current = parseStoredConfig(SignalStore.remoteConfig.currentConfig)
|
||||||
val changes = computeChanges(current, pending)
|
val pending = parseStoredConfig(SignalStore.remoteConfig.pendingConfig)
|
||||||
|
val changes = computeChanges(current, pending)
|
||||||
|
|
||||||
SignalStore.remoteConfig.currentConfig = mapToJson(pending)
|
SignalStore.remoteConfig.currentConfig = mapToJson(pending)
|
||||||
REMOTE_VALUES.putAll(pending)
|
REMOTE_VALUES.putAll(pending)
|
||||||
triggerFlagChangeListeners(changes)
|
triggerFlagChangeListeners(changes)
|
||||||
|
|
||||||
Log.i(TAG, "init() $REMOTE_VALUES")
|
Log.i(TAG, "init() $REMOTE_VALUES")
|
||||||
|
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@@ -347,6 +359,15 @@ object RemoteConfig {
|
|||||||
val transformer: (Any?) -> T
|
val transformer: (Any?) -> T
|
||||||
) {
|
) {
|
||||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||||
|
if (!initialized) {
|
||||||
|
Log.w(TAG, "Tried to read $key before initialization. Initializing now.")
|
||||||
|
initLock.withLock {
|
||||||
|
if (!initialized) {
|
||||||
|
init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return transformer(REMOTE_VALUES[key])
|
return transformer(REMOTE_VALUES[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.thoughtcrime.securesms.util
|
package org.thoughtcrime.securesms.util
|
||||||
|
|
||||||
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import kotlin.reflect.KProperty1
|
import kotlin.reflect.KProperty1
|
||||||
import kotlin.reflect.KVisibility
|
import kotlin.reflect.KVisibility
|
||||||
@@ -10,6 +11,11 @@ import kotlin.reflect.full.memberProperties
|
|||||||
*/
|
*/
|
||||||
class RemoteConfig_StaticValuesTest {
|
class RemoteConfig_StaticValuesTest {
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setup() {
|
||||||
|
RemoteConfig.initialized = true
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This test cycles the REMOTE_VALUES through a bunch of different inputs, then looks at all of the public getters and checks to see if they return different
|
* This test cycles the REMOTE_VALUES through a bunch of different inputs, then looks at all of the public getters and checks to see if they return different
|
||||||
* values when the inputs change. If they don't, then it's likely that the getter is returning a static value, which was likely introduced during testing
|
* values when the inputs change. If they don't, then it's likely that the getter is returning a static value, which was likely introduced during testing
|
||||||
@@ -34,6 +40,7 @@ class RemoteConfig_StaticValuesTest {
|
|||||||
val configKeys = RemoteConfig.configsByKey.keys
|
val configKeys = RemoteConfig.configsByKey.keys
|
||||||
|
|
||||||
val ignoreList = setOf(
|
val ignoreList = setOf(
|
||||||
|
"initialized",
|
||||||
"REMOTE_VALUES",
|
"REMOTE_VALUES",
|
||||||
"configsByKey",
|
"configsByKey",
|
||||||
"debugMemoryValues",
|
"debugMemoryValues",
|
||||||
|
|||||||
Reference in New Issue
Block a user