diff --git a/firebase-installations/api.txt b/firebase-installations/api.txt index 630322f0856..4acee522a18 100644 --- a/firebase-installations/api.txt +++ b/firebase-installations/api.txt @@ -79,7 +79,7 @@ package com.google.firebase.installations.local { package com.google.firebase.installations.remote { public class FirebaseInstallationServiceClient { - ctor public FirebaseInstallationServiceClient(@NonNull Context); + ctor public FirebaseInstallationServiceClient(@NonNull Context, @Nullable UserAgentPublisher, @Nullable HeartBeatInfo); method @NonNull public com.google.firebase.installations.remote.InstallationResponse createFirebaseInstallation(@NonNull String, @NonNull String, @NonNull String, @NonNull String); method @NonNull public void deleteFirebaseInstallation(@NonNull String, @NonNull String, @NonNull String, @NonNull String); method @NonNull public com.google.firebase.installations.remote.TokenResult generateAuthToken(@NonNull String, @NonNull String, @NonNull String, @NonNull String); diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java index 9dc2ec666d1..09d5a67d67e 100644 --- a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java +++ b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallations.java @@ -16,6 +16,7 @@ import androidx.annotation.GuardedBy; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import com.google.android.gms.common.internal.Preconditions; import com.google.android.gms.common.util.DefaultClock; @@ -24,6 +25,7 @@ import com.google.android.gms.tasks.Tasks; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseException; +import com.google.firebase.heartbeatinfo.HeartBeatInfo; import com.google.firebase.installations.local.IidStore; import com.google.firebase.installations.local.PersistedInstallation; import com.google.firebase.installations.local.PersistedInstallation.RegistrationStatus; @@ -32,6 +34,7 @@ import com.google.firebase.installations.remote.InstallationResponse; import com.google.firebase.installations.remote.InstallationResponse.ResponseCode; import com.google.firebase.installations.remote.TokenResult; +import com.google.firebase.platforminfo.UserAgentPublisher; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -68,11 +71,15 @@ public class FirebaseInstallations implements FirebaseInstallationsApi { private final List listeners = new ArrayList<>(); /** package private constructor. */ - FirebaseInstallations(FirebaseApp firebaseApp) { + FirebaseInstallations( + FirebaseApp firebaseApp, + @Nullable UserAgentPublisher publisher, + @Nullable HeartBeatInfo heartbeatInfo) { this( new ThreadPoolExecutor(0, 1, 30L, TimeUnit.SECONDS, new LinkedBlockingQueue<>()), firebaseApp, - new FirebaseInstallationServiceClient(firebaseApp.getApplicationContext()), + new FirebaseInstallationServiceClient( + firebaseApp.getApplicationContext(), publisher, heartbeatInfo), new PersistedInstallation(firebaseApp), new Utils(DefaultClock.getInstance()), new IidStore()); diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java index e84168ab4fb..10731b9d11e 100644 --- a/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java +++ b/firebase-installations/src/main/java/com/google/firebase/installations/FirebaseInstallationsRegistrar.java @@ -19,7 +19,9 @@ import com.google.firebase.components.Component; import com.google.firebase.components.ComponentRegistrar; import com.google.firebase.components.Dependency; +import com.google.firebase.heartbeatinfo.HeartBeatInfo; import com.google.firebase.platforminfo.LibraryVersionComponent; +import com.google.firebase.platforminfo.UserAgentPublisher; import java.util.Arrays; import java.util.List; @@ -32,7 +34,14 @@ public List> getComponents() { return Arrays.asList( Component.builder(FirebaseInstallationsApi.class) .add(Dependency.required(FirebaseApp.class)) - .factory(c -> new FirebaseInstallations(c.get(FirebaseApp.class))) + .add(Dependency.required(HeartBeatInfo.class)) + .add(Dependency.required(UserAgentPublisher.class)) + .factory( + c -> + new FirebaseInstallations( + c.get(FirebaseApp.class), + c.get(UserAgentPublisher.class), + c.get(HeartBeatInfo.class))) .build(), LibraryVersionComponent.create("fire-installations", BuildConfig.VERSION_NAME)); } diff --git a/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java b/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java index bc5947bbe7c..a981635c02c 100644 --- a/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java +++ b/firebase-installations/src/main/java/com/google/firebase/installations/remote/FirebaseInstallationServiceClient.java @@ -22,11 +22,15 @@ import android.util.JsonReader; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.google.android.gms.common.util.AndroidUtilsLight; import com.google.android.gms.common.util.Hex; import com.google.android.gms.common.util.VisibleForTesting; import com.google.firebase.FirebaseException; +import com.google.firebase.heartbeatinfo.HeartBeatInfo; +import com.google.firebase.heartbeatinfo.HeartBeatInfo.HeartBeat; import com.google.firebase.installations.remote.InstallationResponse.ResponseCode; +import com.google.firebase.platforminfo.UserAgentPublisher; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; @@ -55,6 +59,12 @@ public class FirebaseInstallationServiceClient { private static final String CONTENT_ENCODING_HEADER_KEY = "Content-Encoding"; private static final String GZIP_CONTENT_ENCODING = "gzip"; + /** Heartbeat tag for firebase installations. */ + private static final String FIREBASE_INSTALLATIONS_ID_HEARTBEAT_TAG = "fire-installations-id"; + + private static final String HEART_BEAT_HEADER = "x-firebase-client-log-type"; + private static final String USER_AGENT_HEADER = "x-firebase-client"; + private static final String INTERNAL_SERVER_ERROR_MESSAGE = "There was an internal server error."; private static final String NETWORK_ERROR_MESSAGE = "The server returned an unexpected error: %s"; @@ -72,9 +82,16 @@ public class FirebaseInstallationServiceClient { static final String PARSING_EXPIRATION_TIME_ERROR_MESSAGE = "Invalid Expiration Timestamp."; private final Context context; + private final UserAgentPublisher userAgentPublisher; + private final HeartBeatInfo heartbeatInfo; - public FirebaseInstallationServiceClient(@NonNull Context context) { + public FirebaseInstallationServiceClient( + @NonNull Context context, + @Nullable UserAgentPublisher publisher, + @Nullable HeartBeatInfo heartBeatInfo) { this.context = context; + this.userAgentPublisher = publisher; + this.heartbeatInfo = heartBeatInfo; } /** @@ -261,6 +278,14 @@ private HttpsURLConnection openHttpsURLConnection(URL url) throws IOException { httpsURLConnection.addRequestProperty(ACCEPT_HEADER_KEY, JSON_CONTENT_TYPE); httpsURLConnection.addRequestProperty(CONTENT_ENCODING_HEADER_KEY, GZIP_CONTENT_ENCODING); httpsURLConnection.addRequestProperty(X_ANDROID_PACKAGE_HEADER_KEY, context.getPackageName()); + if (heartbeatInfo != null && userAgentPublisher != null) { + HeartBeat heartbeat = heartbeatInfo.getHeartBeatCode(FIREBASE_INSTALLATIONS_ID_HEARTBEAT_TAG); + if (heartbeat != HeartBeat.NONE) { + httpsURLConnection.addRequestProperty(USER_AGENT_HEADER, userAgentPublisher.getUserAgent()); + httpsURLConnection.addRequestProperty( + HEART_BEAT_HEADER, Integer.toString(heartbeat.getCode())); + } + } httpsURLConnection.addRequestProperty( X_ANDROID_CERT_HEADER_KEY, getFingerprintHashForPackage()); return httpsURLConnection; diff --git a/tools/measurement/apksize/src/inappmessagingdisplay/java/com.google.apksize/InAppMessagingDisplay.java b/tools/measurement/apksize/src/inappmessagingdisplay/java/com.google.apksize/InAppMessagingDisplay.java index ec6c284dab4..59ac8525a50 100644 --- a/tools/measurement/apksize/src/inappmessagingdisplay/java/com.google.apksize/InAppMessagingDisplay.java +++ b/tools/measurement/apksize/src/inappmessagingdisplay/java/com.google.apksize/InAppMessagingDisplay.java @@ -16,16 +16,16 @@ import android.app.Activity; import android.content.Context; +import androidx.annotation.NonNull; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.TaskCompletionSource; import com.google.firebase.inappmessaging.FirebaseInAppMessagingDisplayCallbacks; +import com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay; import com.google.firebase.inappmessaging.model.Action; import com.google.firebase.inappmessaging.model.CampaignMetadata; +import com.google.firebase.inappmessaging.model.InAppMessage; import com.google.firebase.inappmessaging.model.ModalMessage; import com.google.firebase.inappmessaging.model.Text; -import com.google.firebase.inappmessaging.display.FirebaseInAppMessagingDisplay; -import androidx.annotation.NonNull; -import com.google.firebase.inappmessaging.model.InAppMessage; public class InAppMessagingDisplay implements SampleCode { private static final String SAMPLE_TEXT = "My sample text";