Skip to content

Commit 16544a6

Browse files
committed
Merge branch 'ankita_fis' of github.com:firebase/firebase-android-sdk into create_fis
2 parents 68acde5 + e5e0d67 commit 16544a6

File tree

15 files changed

+275
-31
lines changed

15 files changed

+275
-31
lines changed

buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/measurement/apksize/ApkSizeJsonBuilder.groovy

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ package com.google.firebase.gradle.plugins.measurement.apksize
1818
/** A helper class that generates the APK size measurement JSON report. */
1919
class ApkSizeJsonBuilder {
2020

21-
private static final String PULL_REQUEST_TABLE = "PullRequests"
21+
private static final String PULL_REQUEST_TABLE = "AndroidPullRequests"
2222
private static final String PULL_REQUEST_COLUMN = "pull_request_id"
23-
private static final String APK_SIZE_TABLE = "ApkSizes"
23+
private static final String APK_SIZE_TABLE = "AndroidApkSizes"
2424
private static final String SDK_COLUMN = "sdk_id"
2525
private static final String APK_SIZE_COLUMN = "apk_size"
2626

buildSrc/src/test/groovy/com/google/firebase/gradle/plugins/measurement/apksize/ApkSizeJsonBuilderTest.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class ApkSizeJsonBuilderTest {
4141
def prColumns = prTable.getJSONArray("column_names")
4242
def prMeasurements = prTable.getJSONArray("replace_measurements")
4343

44-
assertEquals("Bad table name", "PullRequests", prTable.getString("table_name"))
44+
assertEquals("Bad table name", "AndroidPullRequests", prTable.getString("table_name"))
4545
assertEquals("Bad column name", "pull_request_id", prColumns.getString(0))
4646
assertEquals("Bad pull request number", 117, prMeasurements.getJSONArray(0).getInt(0))
4747
assertEquals("Too many columns", 1, prColumns.length())
@@ -59,7 +59,7 @@ public class ApkSizeJsonBuilderTest {
5959
def asColumns = asTable.getJSONArray("column_names")
6060
def asMeasurements = asTable.getJSONArray("replace_measurements")
6161

62-
assertEquals("Bad table name", "ApkSizes", asTable.getString("table_name"))
62+
assertEquals("Bad table name", "AndroidApkSizes", asTable.getString("table_name"))
6363
assertEquals("Bad column name", "pull_request_id", asColumns.getString(0))
6464
assertEquals("Bad column name", "sdk_id", asColumns.getString(1))
6565
assertEquals("Bad column name", "apk_size", asColumns.getString(2))
@@ -84,7 +84,7 @@ public class ApkSizeJsonBuilderTest {
8484
def asMeasurements = asTable.getJSONArray("replace_measurements")
8585

8686
// The table itself.
87-
assertEquals("Bad table name", "ApkSizes", asTable.getString("table_name"))
87+
assertEquals("Bad table name", "AndroidApkSizes", asTable.getString("table_name"))
8888
assertEquals("Bad column name", "pull_request_id", asColumns.getString(0))
8989
assertEquals("Bad column name", "sdk_id", asColumns.getString(1))
9090
assertEquals("Bad column name", "apk_size", asColumns.getString(2))

firebase-config/api.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ package com.google.firebase.remoteconfig {
2323
method @Deprecated public void setConfigSettings(@NonNull com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings);
2424
method @NonNull public Task<Void> setConfigSettingsAsync(@NonNull com.google.firebase.remoteconfig.FirebaseRemoteConfigSettings);
2525
method @Deprecated public void setDefaults(@NonNull Map<String,Object>);
26-
method public void setDefaults(int);
26+
method @Deprecated public void setDefaults(int);
2727
method @NonNull public Task<Void> setDefaultsAsync(@NonNull Map<String,Object>);
2828
method @NonNull public Task<Void> setDefaultsAsync(int);
2929
field public static final boolean DEFAULT_VALUE_FOR_BOOLEAN = false;

firebase-config/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# limitations under the License.
1515
#
1616

17-
version=18.0.1
18-
latestReleasedVersion=18.0.0
17+
version=19.0.1
18+
latestReleasedVersion=19.0.0
1919
android.enableUnitTestBinaryResources=true
2020

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,7 +582,9 @@ public Task<Void> setDefaultsAsync(@NonNull Map<String, Object> defaults) {
582582
*
583583
* @param resourceId Id for the XML resource, which should be in your application's {@code
584584
* res/xml} folder.
585+
* @deprecated Use {@link #setDefaultsAsync} instead.
585586
*/
587+
@Deprecated
586588
public void setDefaults(@XmlRes int resourceId) {
587589
Map<String, String> xmlDefaults = DefaultsXmlParser.getDefaultsFromXml(context, resourceId);
588590
setDefaultsWithStringsMap(xmlDefaults);

firebase-database/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
version=19.0.1
15+
version=19.1.0
1616
latestReleasedVersion=19.0.0
1717
android.enableUnitTestBinaryResources=true

firebase-firestore/api.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ package com.google.firebase.firestore {
163163
method @NonNull public <TResult> Task<TResult> runTransaction(@NonNull com.google.firebase.firestore.Transaction.Function<TResult>);
164164
method public void setFirestoreSettings(@NonNull com.google.firebase.firestore.FirebaseFirestoreSettings);
165165
method public static void setLoggingEnabled(boolean);
166+
method @NonNull public Task<Void> terminate();
167+
method @NonNull public Task<Void> waitForPendingWrites();
166168
}
167169

168170
public class FirebaseFirestoreException {

firebase-firestore/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=21.0.1
1+
version=21.1.0
22
latestReleasedVersion=21.0.0

firebase-firestore/src/test/java/com/google/firebase/firestore/util/ThrottledForwardingExecutorTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
import java.util.concurrent.Semaphore;
2424
import java.util.concurrent.atomic.AtomicInteger;
2525
import org.junit.Test;
26+
import org.robolectric.annotation.Config;
2627

28+
@org.junit.runner.RunWith(org.robolectric.RobolectricTestRunner.class)
29+
@Config(manifest = Config.NONE)
2730
public class ThrottledForwardingExecutorTest {
2831
@Test
2932
public void limitsNumberOfForwardedTasks() throws InterruptedException {

transport/transport-backend-cct/src/main/java/com/google/android/datatransport/cct/CctTransportBackend.java

Lines changed: 68 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414

1515
package com.google.android.datatransport.cct;
1616

17+
import static com.google.android.datatransport.runtime.retries.Retries.retry;
18+
1719
import android.content.Context;
1820
import android.net.ConnectivityManager;
1921
import android.net.NetworkInfo;
2022
import android.os.Build;
23+
import androidx.annotation.Nullable;
2124
import androidx.annotation.VisibleForTesting;
2225
import com.google.android.datatransport.backend.cct.BuildConfig;
2326
import com.google.android.datatransport.cct.proto.AndroidClientInfo;
@@ -36,7 +39,6 @@
3639
import com.google.android.datatransport.runtime.backends.TransportBackend;
3740
import com.google.android.datatransport.runtime.time.Clock;
3841
import com.google.protobuf.ByteString;
39-
import com.google.protobuf.InvalidProtocolBufferException;
4042
import java.io.ByteArrayOutputStream;
4143
import java.io.IOException;
4244
import java.io.InputStream;
@@ -212,8 +214,9 @@ private BatchedLogRequest getRequestBody(BackendRequest backendRequest) {
212214
return batchedRequestBuilder.build();
213215
}
214216

215-
private BackendResponse doSend(BatchedLogRequest requestBody, String apiKey) throws IOException {
216-
HttpURLConnection connection = (HttpURLConnection) endPoint.openConnection();
217+
private HttpResponse doSend(HttpRequest request) throws IOException {
218+
219+
HttpURLConnection connection = (HttpURLConnection) request.url.openConnection();
217220
connection.setConnectTimeout(CONNECTION_TIME_OUT);
218221
connection.setReadTimeout(readTimeout);
219222
connection.setDoOutput(true);
@@ -224,8 +227,8 @@ private BackendResponse doSend(BatchedLogRequest requestBody, String apiKey) thr
224227
connection.setRequestProperty(CONTENT_ENCODING_HEADER_KEY, GZIP_CONTENT_ENCODING);
225228
connection.setRequestProperty(CONTENT_TYPE_HEADER_KEY, PROTOBUF_CONTENT_TYPE);
226229

227-
if (apiKey != null) {
228-
connection.setRequestProperty(API_KEY_HEADER_KEY, apiKey);
230+
if (request.apiKey != null) {
231+
connection.setRequestProperty(API_KEY_HEADER_KEY, request.apiKey);
229232
}
230233

231234
WritableByteChannel channel = Channels.newChannel(connection.getOutputStream());
@@ -234,32 +237,29 @@ private BackendResponse doSend(BatchedLogRequest requestBody, String apiKey) thr
234237
GZIPOutputStream gzipOutputStream = new GZIPOutputStream(output);
235238

236239
try {
237-
requestBody.writeTo(gzipOutputStream);
240+
request.requestBody.writeTo(gzipOutputStream);
238241
} finally {
239242
gzipOutputStream.close();
240243
}
241244
channel.write(ByteBuffer.wrap(output.toByteArray()));
242245
int responseCode = connection.getResponseCode();
243246
LOGGER.info("Status Code: " + responseCode);
244247

245-
long nextRequestMillis;
248+
if (responseCode == 302 || responseCode == 301) {
249+
String redirect = connection.getHeaderField("Location");
250+
return new HttpResponse(responseCode, new URL(redirect), 0);
251+
}
252+
if (responseCode != 200) {
253+
return new HttpResponse(responseCode, null, 0);
254+
}
255+
246256
InputStream inputStream = connection.getInputStream();
247257
try {
248-
try {
249-
nextRequestMillis = LogResponse.parseFrom(inputStream).getNextRequestWaitMillis();
250-
} catch (InvalidProtocolBufferException e) {
251-
return BackendResponse.fatalError();
252-
}
258+
long nextRequestMillis = LogResponse.parseFrom(inputStream).getNextRequestWaitMillis();
259+
return new HttpResponse(responseCode, null, nextRequestMillis);
253260
} finally {
254261
inputStream.close();
255262
}
256-
if (responseCode == 200) {
257-
return BackendResponse.ok(nextRequestMillis);
258-
} else if (responseCode >= 500 || responseCode == 404) {
259-
return BackendResponse.transientError();
260-
} else {
261-
return BackendResponse.fatalError();
262-
}
263263
} finally {
264264
channel.close();
265265
}
@@ -275,7 +275,27 @@ public BackendResponse send(BackendRequest request) {
275275
request.getExtras() == null ? null : LegacyFlgDestination.decodeExtras(request.getExtras());
276276

277277
try {
278-
return doSend(requestBody, apiKey);
278+
HttpResponse response =
279+
retry(
280+
5,
281+
new HttpRequest(endPoint, requestBody, apiKey),
282+
this::doSend,
283+
(req, resp) -> {
284+
if (resp.redirectUrl != null) {
285+
// retry with different url
286+
return req.withUrl(resp.redirectUrl);
287+
}
288+
// don't retry
289+
return null;
290+
});
291+
292+
if (response.code == 200) {
293+
return BackendResponse.ok(response.nextRequestMillis);
294+
} else if (response.code >= 500 || response.code == 404) {
295+
return BackendResponse.transientError();
296+
} else {
297+
return BackendResponse.fatalError();
298+
}
279299
} catch (IOException e) {
280300
LOGGER.log(Level.SEVERE, "Could not make request to the backend", e);
281301
return BackendResponse.transientError();
@@ -288,4 +308,32 @@ static long getTzOffset() {
288308
TimeZone tz = TimeZone.getDefault();
289309
return tz.getOffset(Calendar.getInstance().getTimeInMillis()) / 1000;
290310
}
311+
312+
static final class HttpResponse {
313+
final int code;
314+
@Nullable final URL redirectUrl;
315+
final long nextRequestMillis;
316+
317+
HttpResponse(int code, @Nullable URL redirectUrl, long nextRequestMillis) {
318+
this.code = code;
319+
this.redirectUrl = redirectUrl;
320+
this.nextRequestMillis = nextRequestMillis;
321+
}
322+
}
323+
324+
static final class HttpRequest {
325+
final URL url;
326+
final BatchedLogRequest requestBody;
327+
@Nullable final String apiKey;
328+
329+
HttpRequest(URL url, BatchedLogRequest requestBody, @Nullable String apiKey) {
330+
this.url = url;
331+
this.requestBody = requestBody;
332+
this.apiKey = apiKey;
333+
}
334+
335+
HttpRequest withUrl(URL newUrl) {
336+
return new HttpRequest(newUrl, requestBody, apiKey);
337+
}
338+
}
291339
}

transport/transport-backend-cct/src/test/java/com/google/android/datatransport/cct/CctTransportBackendTest.java

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ public void testGarbageFromServer() {
237237
verify(
238238
postRequestedFor(urlEqualTo("/api"))
239239
.withHeader("Content-Type", equalTo("application/x-protobuf")));
240-
assertEquals(BackendResponse.fatalError(), response);
240+
assertEquals(BackendResponse.transientError(), response);
241241
}
242242

243243
@Test
@@ -305,6 +305,69 @@ public void decorate_whenOffline_shouldProperlyPopulateNetworkInfo() {
305305
String.valueOf(NetworkConnectionInfo.MobileSubtype.UNKNOWN_MOBILE_SUBTYPE_VALUE));
306306
}
307307

308+
@Test
309+
public void send_whenBackendRedirects_shouldCorrectlyFollowTheRedirectViaPost() {
310+
stubFor(
311+
post(urlEqualTo("/api"))
312+
.willReturn(
313+
aResponse().withStatus(302).withHeader("Location", TEST_ENDPOINT + "/hello")));
314+
stubFor(
315+
post(urlEqualTo("/api/hello"))
316+
.willReturn(
317+
aResponse()
318+
.withStatus(200)
319+
.withHeader("Content-Type", "application/x-protobuf;charset=UTF8;hello=world")
320+
.withBody(
321+
LogResponse.newBuilder()
322+
.setNextRequestWaitMillis(3)
323+
.build()
324+
.toByteArray())));
325+
BackendRequest backendRequest = getCCTBackendRequest();
326+
wallClock.tick();
327+
uptimeClock.tick();
328+
329+
BackendResponse response = BACKEND.send(backendRequest);
330+
331+
verify(
332+
postRequestedFor(urlEqualTo("/api"))
333+
.withHeader("Content-Type", equalTo("application/x-protobuf")));
334+
335+
verify(
336+
postRequestedFor(urlEqualTo("/api/hello"))
337+
.withHeader("Content-Type", equalTo("application/x-protobuf")));
338+
339+
assertEquals(BackendResponse.ok(3), response);
340+
}
341+
342+
@Test
343+
public void send_whenBackendRedirectsMoreThan5Times_shouldOnlyRedirect4Times() {
344+
stubFor(
345+
post(urlEqualTo("/api"))
346+
.willReturn(
347+
aResponse().withStatus(302).withHeader("Location", TEST_ENDPOINT + "/hello")));
348+
stubFor(
349+
post(urlEqualTo("/api/hello"))
350+
.willReturn(
351+
aResponse().withStatus(302).withHeader("Location", TEST_ENDPOINT + "/hello")));
352+
353+
BackendRequest backendRequest = getCCTBackendRequest();
354+
wallClock.tick();
355+
uptimeClock.tick();
356+
357+
BackendResponse response = BACKEND.send(backendRequest);
358+
359+
verify(
360+
postRequestedFor(urlEqualTo("/api"))
361+
.withHeader("Content-Type", equalTo("application/x-protobuf")));
362+
363+
verify(
364+
4,
365+
postRequestedFor(urlEqualTo("/api/hello"))
366+
.withHeader("Content-Type", equalTo("application/x-protobuf")));
367+
368+
assertEquals(BackendResponse.fatalError(), response);
369+
}
370+
308371
// When there is no active network, the ConnectivityManager returns null when
309372
// getActiveNetworkInfo() is called.
310373
@Implements(ConnectivityManager.class)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2019 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.android.datatransport.runtime.retries;
16+
17+
/** Generic functional interface which supports checked exceptions. */
18+
public interface Function<TInput, TResult, TException extends Throwable> {
19+
TResult apply(TInput input) throws TException;
20+
}

0 commit comments

Comments
 (0)