Skip to content

Commit 86ee29c

Browse files
Add support for custom signals
1 parent e6b4ace commit 86ee29c

20 files changed

+198
-95
lines changed

firebase-config/ktx/src/test/kotlin/com/google/firebase/remoteconfig/TestConstructorUtil.kt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,27 @@ import com.google.firebase.installations.FirebaseInstallationsApi
2323
import com.google.firebase.remoteconfig.internal.ConfigCacheClient
2424
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler
2525
import com.google.firebase.remoteconfig.internal.ConfigGetParameterHandler
26-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient
26+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient
2727
import com.google.firebase.remoteconfig.internal.ConfigRealtimeHandler
2828
import com.google.firebase.remoteconfig.internal.rollouts.RolloutsStateSubscriptionsHandler
2929
import java.util.concurrent.Executor
3030

3131
// This method is a workaround for testing. It enable us to create a FirebaseRemoteConfig object
3232
// with mocks using the package-private constructor.
3333
fun createRemoteConfig(
34-
context: Context?,
35-
firebaseApp: FirebaseApp,
36-
firebaseInstallations: FirebaseInstallationsApi,
37-
firebaseAbt: FirebaseABTesting?,
38-
executor: Executor,
39-
fetchedConfigsCache: ConfigCacheClient,
40-
activatedConfigsCache: ConfigCacheClient,
41-
defaultConfigsCache: ConfigCacheClient,
42-
fetchHandler: ConfigFetchHandler,
43-
getHandler: ConfigGetParameterHandler,
44-
frcMetadata: ConfigMetadataClient,
45-
realtimeHandler: ConfigRealtimeHandler,
46-
rolloutsStateSubscriptionsHandler: RolloutsStateSubscriptionsHandler
34+
context: Context?,
35+
firebaseApp: FirebaseApp,
36+
firebaseInstallations: FirebaseInstallationsApi,
37+
firebaseAbt: FirebaseABTesting?,
38+
executor: Executor,
39+
fetchedConfigsCache: ConfigCacheClient,
40+
activatedConfigsCache: ConfigCacheClient,
41+
defaultConfigsCache: ConfigCacheClient,
42+
fetchHandler: ConfigFetchHandler,
43+
getHandler: ConfigGetParameterHandler,
44+
frcMetadata: ConfigSharedPrefsClient,
45+
realtimeHandler: ConfigRealtimeHandler,
46+
rolloutsStateSubscriptionsHandler: RolloutsStateSubscriptionsHandler
4747
): FirebaseRemoteConfig {
4848
return FirebaseRemoteConfig(
4949
context,

firebase-config/ktx/src/test/kotlin/com/google/firebase/remoteconfig/ktx/RemoteConfigTests.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import com.google.firebase.remoteconfig.createRemoteConfig
3232
import com.google.firebase.remoteconfig.internal.ConfigCacheClient
3333
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler
3434
import com.google.firebase.remoteconfig.internal.ConfigGetParameterHandler
35-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient
35+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient
3636
import com.google.firebase.remoteconfig.internal.ConfigRealtimeHandler
3737
import com.google.firebase.remoteconfig.internal.rollouts.RolloutsStateSubscriptionsHandler
3838
import org.junit.After
@@ -142,7 +142,7 @@ class ConfigTests : BaseTestCase() {
142142
defaultConfigsCache = mock(ConfigCacheClient::class.java),
143143
fetchHandler = mock(ConfigFetchHandler::class.java),
144144
getHandler = mockGetHandler,
145-
frcMetadata = mock(ConfigMetadataClient::class.java),
145+
frcMetadata = mock(ConfigSharedPrefsClient::class.java),
146146
realtimeHandler = mock(ConfigRealtimeHandler::class.java),
147147
rolloutsStateSubscriptionsHandler = mock(RolloutsStateSubscriptionsHandler::class.java)
148148
)

firebase-config/src/androidTest/java/com/google/firebase/remoteconfig/FirebaseRemoteConfigIntegrationTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import com.google.firebase.remoteconfig.internal.ConfigContainer;
3636
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler;
3737
import com.google.firebase.remoteconfig.internal.ConfigGetParameterHandler;
38-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient;
38+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient;
3939
import com.google.firebase.remoteconfig.internal.ConfigRealtimeHandler;
4040
import com.google.firebase.remoteconfig.internal.rollouts.RolloutsStateSubscriptionsHandler;
4141
import java.util.Date;
@@ -60,7 +60,7 @@ public class FirebaseRemoteConfigIntegrationTest {
6060
@Mock private ConfigCacheClient mockDefaultsCache;
6161
@Mock private ConfigFetchHandler mockFetchHandler;
6262
@Mock private ConfigGetParameterHandler mockGetHandler;
63-
@Mock private ConfigMetadataClient metadataClient;
63+
@Mock private ConfigSharedPrefsClient metadataClient;
6464
@Mock private ConfigRealtimeHandler mockConfigRealtimeHandler;
6565
@Mock private RolloutsStateSubscriptionsHandler mockRolloutsStateSubscriptionHandler;
6666

firebase-config/src/main/java/com/google/firebase/remoteconfig/FirebaseRemoteConfig.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler;
3434
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler.FetchResponse;
3535
import com.google.firebase.remoteconfig.internal.ConfigGetParameterHandler;
36-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient;
36+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient;
3737
import com.google.firebase.remoteconfig.internal.ConfigRealtimeHandler;
3838
import com.google.firebase.remoteconfig.internal.DefaultsXmlParser;
3939
import com.google.firebase.remoteconfig.internal.rollouts.RolloutsStateSubscriptionsHandler;
@@ -160,7 +160,7 @@ public static FirebaseRemoteConfig getInstance(@NonNull FirebaseApp app) {
160160
private final ConfigCacheClient defaultConfigsCache;
161161
private final ConfigFetchHandler fetchHandler;
162162
private final ConfigGetParameterHandler getHandler;
163-
private final ConfigMetadataClient frcMetadata;
163+
private final ConfigSharedPrefsClient frcMetadata;
164164
private final FirebaseInstallationsApi firebaseInstallations;
165165
private final ConfigRealtimeHandler configRealtimeHandler;
166166
private final RolloutsStateSubscriptionsHandler rolloutsStateSubscriptionsHandler;
@@ -181,7 +181,7 @@ public static FirebaseRemoteConfig getInstance(@NonNull FirebaseApp app) {
181181
ConfigCacheClient defaultConfigsCache,
182182
ConfigFetchHandler fetchHandler,
183183
ConfigGetParameterHandler getHandler,
184-
ConfigMetadataClient frcMetadata,
184+
ConfigSharedPrefsClient frcMetadata,
185185
ConfigRealtimeHandler configRealtimeHandler,
186186
RolloutsStateSubscriptionsHandler rolloutsStateSubscriptionsHandler) {
187187
this.context = context;
@@ -652,6 +652,28 @@ private Task<Void> setDefaultsWithStringsMapAsync(Map<String, String> defaultsSt
652652
FirebaseExecutors.directExecutor(), (unusedContainer) -> Tasks.forResult(null));
653653
}
654654

655+
/**
656+
* Asynchronously changes the custom signals for this {@link FirebaseRemoteConfig} instance.
657+
*
658+
* <p>The values in {@code customSignals} must be one of the following types:
659+
*
660+
* <ul>
661+
* <li><code>Long</code>
662+
* <li><code>String</code>
663+
* </ul>
664+
*
665+
* @param customSignals Map (key, value) of the custom signals to be set for the app instance
666+
*/
667+
@NonNull
668+
public Task<Void> setCustomSignals(@NonNull Map<String, Object> customSignals) {
669+
return Tasks.call(
670+
executor,
671+
() -> {
672+
frcMetadata.setCustomSignals(customSignals);
673+
return null;
674+
});
675+
}
676+
655677
/**
656678
* Notifies the Firebase A/B Testing SDK about activated experiments.
657679
*

firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigComponent.java

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler;
3737
import com.google.firebase.remoteconfig.internal.ConfigFetchHttpClient;
3838
import com.google.firebase.remoteconfig.internal.ConfigGetParameterHandler;
39-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient;
39+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient;
4040
import com.google.firebase.remoteconfig.internal.ConfigRealtimeHandler;
4141
import com.google.firebase.remoteconfig.internal.ConfigStorageClient;
4242
import com.google.firebase.remoteconfig.internal.Personalization;
@@ -166,7 +166,7 @@ public synchronized FirebaseRemoteConfig get(String namespace) {
166166
ConfigCacheClient fetchedCacheClient = getCacheClient(namespace, FETCH_FILE_NAME);
167167
ConfigCacheClient activatedCacheClient = getCacheClient(namespace, ACTIVATE_FILE_NAME);
168168
ConfigCacheClient defaultsCacheClient = getCacheClient(namespace, DEFAULTS_FILE_NAME);
169-
ConfigMetadataClient metadataClient = getMetadataClient(context, appId, namespace);
169+
ConfigSharedPrefsClient metadataClient = getMetadataClient(context, appId, namespace);
170170

171171
ConfigGetParameterHandler getHandler = getGetHandler(activatedCacheClient, defaultsCacheClient);
172172
Personalization personalization =
@@ -206,7 +206,7 @@ synchronized FirebaseRemoteConfig get(
206206
ConfigCacheClient defaultsClient,
207207
ConfigFetchHandler fetchHandler,
208208
ConfigGetParameterHandler getHandler,
209-
ConfigMetadataClient metadataClient,
209+
ConfigSharedPrefsClient metadataClient,
210210
RolloutsStateSubscriptionsHandler rolloutsStateSubscriptionsHandler) {
211211
if (!frcNamespaceInstances.containsKey(namespace)) {
212212
FirebaseRemoteConfig in =
@@ -254,20 +254,21 @@ private ConfigCacheClient getCacheClient(String namespace, String configStoreTyp
254254

255255
@VisibleForTesting
256256
ConfigFetchHttpClient getFrcBackendApiClient(
257-
String apiKey, String namespace, ConfigMetadataClient metadataClient) {
257+
String apiKey, String namespace, ConfigSharedPrefsClient metadataClient) {
258258
String appId = firebaseApp.getOptions().getApplicationId();
259259
return new ConfigFetchHttpClient(
260260
context,
261261
appId,
262262
apiKey,
263263
namespace,
264264
/* connectTimeoutInSeconds= */ metadataClient.getFetchTimeoutInSeconds(),
265-
/* readTimeoutInSeconds= */ metadataClient.getFetchTimeoutInSeconds());
265+
/* readTimeoutInSeconds= */ metadataClient.getFetchTimeoutInSeconds(),
266+
/* customSignals= */ metadataClient.getCustomSignals());
266267
}
267268

268269
@VisibleForTesting
269270
synchronized ConfigFetchHandler getFetchHandler(
270-
String namespace, ConfigCacheClient fetchedCacheClient, ConfigMetadataClient metadataClient) {
271+
String namespace, ConfigCacheClient fetchedCacheClient, ConfigSharedPrefsClient metadataClient) {
271272
return new ConfigFetchHandler(
272273
firebaseInstallations,
273274
isPrimaryApp(firebaseApp) ? analyticsConnector : () -> null,
@@ -287,7 +288,7 @@ synchronized ConfigRealtimeHandler getRealtime(
287288
ConfigCacheClient activatedCacheClient,
288289
Context context,
289290
String namespace,
290-
ConfigMetadataClient metadataClient) {
291+
ConfigSharedPrefsClient metadataClient) {
291292
return new ConfigRealtimeHandler(
292293
firebaseApp,
293294
firebaseInstallations,
@@ -305,13 +306,13 @@ private ConfigGetParameterHandler getGetHandler(
305306
}
306307

307308
@VisibleForTesting
308-
static ConfigMetadataClient getMetadataClient(Context context, String appId, String namespace) {
309+
static ConfigSharedPrefsClient getMetadataClient(Context context, String appId, String namespace) {
309310
String fileName =
310311
String.format(
311312
"%s_%s_%s_%s",
312313
FIREBASE_REMOTE_CONFIG_FILE_NAME_PREFIX, appId, namespace, PREFERENCES_FILE_NAME);
313314
SharedPreferences preferences = context.getSharedPreferences(fileName, Context.MODE_PRIVATE);
314-
return new ConfigMetadataClient(preferences);
315+
return new ConfigSharedPrefsClient(preferences);
315316
}
316317

317318
@Nullable

firebase-config/src/main/java/com/google/firebase/remoteconfig/RemoteConfigConstants.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ public final class RemoteConfigConstants {
5151
RequestFieldKey.PACKAGE_NAME,
5252
RequestFieldKey.SDK_VERSION,
5353
RequestFieldKey.ANALYTICS_USER_PROPERTIES,
54-
RequestFieldKey.FIRST_OPEN_TIME
54+
RequestFieldKey.FIRST_OPEN_TIME,
55+
RequestFieldKey.CUSTOM_SIGNALS
5556
})
5657
@Retention(RetentionPolicy.SOURCE)
5758
public @interface RequestFieldKey {
@@ -68,6 +69,7 @@ public final class RemoteConfigConstants {
6869
String SDK_VERSION = "sdkVersion";
6970
String ANALYTICS_USER_PROPERTIES = "analyticsUserProperties";
7071
String FIRST_OPEN_TIME = "firstOpenTime";
72+
String CUSTOM_SIGNALS = "customSignals";
7173
}
7274

7375
/** Keys of fields in the Fetch response body from the Firebase Remote Config server. */

firebase-config/src/main/java/com/google/firebase/remoteconfig/internal/ConfigFetchHandler.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
package com.google.firebase.remoteconfig.internal;
1616

17-
import static com.google.firebase.remoteconfig.internal.ConfigMetadataClient.LAST_FETCH_TIME_NO_FETCH_YET;
17+
import static com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient.LAST_FETCH_TIME_NO_FETCH_YET;
1818
import static java.net.HttpURLConnection.HTTP_BAD_GATEWAY;
1919
import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
2020
import static java.net.HttpURLConnection.HTTP_GATEWAY_TIMEOUT;
@@ -43,7 +43,7 @@
4343
import com.google.firebase.remoteconfig.FirebaseRemoteConfigFetchThrottledException;
4444
import com.google.firebase.remoteconfig.FirebaseRemoteConfigServerException;
4545
import com.google.firebase.remoteconfig.internal.ConfigFetchHandler.FetchResponse.Status;
46-
import com.google.firebase.remoteconfig.internal.ConfigMetadataClient.BackoffMetadata;
46+
import com.google.firebase.remoteconfig.internal.ConfigSharedPrefsClient.BackoffMetadata;
4747
import java.lang.annotation.Retention;
4848
import java.lang.annotation.RetentionPolicy;
4949
import java.net.HttpURLConnection;
@@ -96,7 +96,7 @@ public class ConfigFetchHandler {
9696
private final Random randomGenerator;
9797
private final ConfigCacheClient fetchedConfigsCache;
9898
private final ConfigFetchHttpClient frcBackendApiClient;
99-
private final ConfigMetadataClient frcMetadata;
99+
private final ConfigSharedPrefsClient frcMetadata;
100100

101101
private final Map<String, String> customHttpHeaders;
102102

@@ -109,7 +109,7 @@ public ConfigFetchHandler(
109109
Random randomGenerator,
110110
ConfigCacheClient fetchedConfigsCache,
111111
ConfigFetchHttpClient frcBackendApiClient,
112-
ConfigMetadataClient frcMetadata,
112+
ConfigSharedPrefsClient frcMetadata,
113113
Map<String, String> customHttpHeaders) {
114114
this.firebaseInstallations = firebaseInstallations;
115115
this.analyticsConnector = analyticsConnector;
@@ -124,7 +124,7 @@ public ConfigFetchHandler(
124124

125125
/**
126126
* Calls {@link #fetch(long)} with the {@link
127-
* ConfigMetadataClient#getMinimumFetchIntervalInSeconds()}.
127+
* ConfigSharedPrefsClient#getMinimumFetchIntervalInSeconds()}.
128128
*/
129129
public Task<FetchResponse> fetch() {
130130
return fetch(frcMetadata.getMinimumFetchIntervalInSeconds());
@@ -228,7 +228,7 @@ public Task<FetchResponse> fetchNowWithTypeAndAttemptNumber(
228228
* currently throttled.
229229
*
230230
* <p>If a fetch request is made to the backend, updates the last fetch status, last successful
231-
* fetch time and {@link BackoffMetadata} in {@link ConfigMetadataClient}.
231+
* fetch time and {@link BackoffMetadata} in {@link ConfigSharedPrefsClient}.
232232
*/
233233
private Task<FetchResponse> fetchIfCacheExpiredAndNotThrottled(
234234
Task<ConfigContainer> cachedFetchConfigsTask,

firebase-config/src/main/java/com/google/firebase/remoteconfig/internal/ConfigFetchHttpClient.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.APP_ID;
2222
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.APP_VERSION;
2323
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.COUNTRY_CODE;
24+
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.CUSTOM_SIGNALS;
2425
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.FIRST_OPEN_TIME;
2526
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.INSTANCE_ID;
2627
import static com.google.firebase.remoteconfig.RemoteConfigConstants.RequestFieldKey.INSTANCE_ID_TOKEN;
@@ -93,6 +94,7 @@ public class ConfigFetchHttpClient {
9394
private final String apiKey;
9495
private final String projectNumber;
9596
private final String namespace;
97+
Map<String, Object> customSignalMap;
9698
private final long connectTimeoutInSeconds;
9799
private final long readTimeoutInSeconds;
98100

@@ -106,14 +108,16 @@ public ConfigFetchHttpClient(
106108
String apiKey,
107109
String namespace,
108110
long connectTimeoutInSeconds,
109-
long readTimeoutInSeconds) {
111+
long readTimeoutInSeconds,
112+
Map<String, Object> customSignalMap) {
110113
this.context = context;
111114
this.appId = appId;
112115
this.apiKey = apiKey;
113116
this.projectNumber = extractProjectNumberFromAppId(appId);
114117
this.namespace = namespace;
115118
this.connectTimeoutInSeconds = connectTimeoutInSeconds;
116119
this.readTimeoutInSeconds = readTimeoutInSeconds;
120+
this.customSignalMap = customSignalMap;
117121
}
118122

119123
/** Used to verify that the timeout is being set correctly. */
@@ -304,7 +308,7 @@ private JSONObject createFetchRequestBody(
304308
String installationAuthToken,
305309
Map<String, String> analyticsUserProperties,
306310
Long firstOpenTime)
307-
throws FirebaseRemoteConfigClientException {
311+
throws FirebaseRemoteConfigClientException {
308312
Map<String, Object> requestBodyMap = new HashMap<>();
309313

310314
if (installationId == null) {
@@ -347,6 +351,8 @@ private JSONObject createFetchRequestBody(
347351

348352
requestBodyMap.put(ANALYTICS_USER_PROPERTIES, new JSONObject(analyticsUserProperties));
349353

354+
requestBodyMap.put(CUSTOM_SIGNALS, new JSONObject(customSignalMap));
355+
350356
if (firstOpenTime != null) {
351357
requestBodyMap.put(FIRST_OPEN_TIME, convertToISOString(firstOpenTime));
352358
}

firebase-config/src/main/java/com/google/firebase/remoteconfig/internal/ConfigRealtimeHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public class ConfigRealtimeHandler {
3939
private final ConfigCacheClient activatedCacheClient;
4040
private final Context context;
4141
private final String namespace;
42-
private final ConfigMetadataClient metadataClient;
42+
private final ConfigSharedPrefsClient metadataClient;
4343
private final ScheduledExecutorService scheduledExecutorService;
4444

4545
public ConfigRealtimeHandler(
@@ -49,7 +49,7 @@ public ConfigRealtimeHandler(
4949
ConfigCacheClient activatedCacheClient,
5050
Context context,
5151
String namespace,
52-
ConfigMetadataClient metadataClient,
52+
ConfigSharedPrefsClient metadataClient,
5353
ScheduledExecutorService scheduledExecutorService) {
5454

5555
this.listeners = new LinkedHashSet<>();

firebase-config/src/main/java/com/google/firebase/remoteconfig/internal/ConfigRealtimeHttpClient.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ public class ConfigRealtimeHttpClient {
110110
private final String namespace;
111111
private final Random random;
112112
private final Clock clock;
113-
private final ConfigMetadataClient metadataClient;
113+
private final ConfigSharedPrefsClient metadataClient;
114114

115115
public ConfigRealtimeHttpClient(
116116
FirebaseApp firebaseApp,
@@ -120,7 +120,7 @@ public ConfigRealtimeHttpClient(
120120
Context context,
121121
String namespace,
122122
Set<ConfigUpdateListener> listeners,
123-
ConfigMetadataClient metadataClient,
123+
ConfigSharedPrefsClient metadataClient,
124124
ScheduledExecutorService scheduledExecutorService) {
125125

126126
this.listeners = listeners;
@@ -473,7 +473,7 @@ public void beginRealtimeHttpStream() {
473473
return;
474474
}
475475

476-
ConfigMetadataClient.RealtimeBackoffMetadata backoffMetadata =
476+
ConfigSharedPrefsClient.RealtimeBackoffMetadata backoffMetadata =
477477
metadataClient.getRealtimeBackoffMetadata();
478478
Date currentTime = new Date(clock.currentTimeMillis());
479479
if (currentTime.before(backoffMetadata.getBackoffEndTime())) {

0 commit comments

Comments
 (0)