Skip to content

Commit 3990f3a

Browse files
committed
Merge branch 'fireperf-aqs' into fireperf-aqs-bugbash
2 parents e2a8cde + 8b4adac commit 3990f3a

32 files changed

+899
-886
lines changed

firebase-perf/firebase-perf.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,15 @@ android {
7070
buildConfigField("String", "TRANSPORT_LOG_SRC", "String.valueOf(\"FIREPERF\")")
7171
buildConfigField("Boolean", "ENFORCE_DEFAULT_LOG_SRC", "Boolean.valueOf(false)")
7272
buildConfigField("String", "FIREPERF_VERSION_NAME", "String.valueOf(\"" + property("version") + "\")")
73+
buildConfigField("Boolean", "ENFORCE_LEGACY_SESSIONS", "Boolean.valueOf(false)")
7374

7475
if (project.hasProperty("fireperfBuildForAutopush")) {
7576
// This allows the SDK to be built for "Autopush" env when the mentioned flag
7677
// (-PfireperfBuildForAutopush) is passed in the gradle build command (of either the
7778
// SDK or the Test App).
7879
buildConfigField("String", "TRANSPORT_LOG_SRC", "String.valueOf(\"FIREPERF_AUTOPUSH\")")
7980
buildConfigField("Boolean", "ENFORCE_DEFAULT_LOG_SRC", "Boolean.valueOf(true)")
81+
buildConfigField("Boolean", "ENFORCE_LEGACY_SESSIONS", "Boolean.valueOf(true)")
8082
}
8183

8284
minSdkVersion project.minSdkVersion
@@ -118,7 +120,7 @@ dependencies {
118120
api("com.google.firebase:firebase-components:18.0.0")
119121
api("com.google.firebase:firebase-config:21.5.0")
120122
api("com.google.firebase:firebase-installations:17.2.0")
121-
api("com.google.firebase:firebase-sessions:2.0.7") {
123+
api(project(":firebase-sessions")) {
122124
exclude group: 'com.google.firebase', module: 'firebase-common'
123125
exclude group: 'com.google.firebase', module: 'firebase-common-ktx'
124126
exclude group: 'com.google.firebase', module: 'firebase-components'

firebase-perf/src/main/java/com/google/firebase/perf/FirebasePerfRegistrar.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.google.firebase.perf.injection.modules.FirebasePerformanceModule;
3131
import com.google.firebase.platforminfo.LibraryVersionComponent;
3232
import com.google.firebase.remoteconfig.RemoteConfigComponent;
33+
import com.google.firebase.sessions.api.FirebaseSessionsDependencies;
34+
import com.google.firebase.sessions.api.SessionSubscriber;
3335
import java.util.Arrays;
3436
import java.util.List;
3537
import java.util.concurrent.Executor;
@@ -47,6 +49,11 @@ public class FirebasePerfRegistrar implements ComponentRegistrar {
4749
private static final String LIBRARY_NAME = "fire-perf";
4850
private static final String EARLY_LIBRARY_NAME = "fire-perf-early";
4951

52+
static {
53+
// Add Firebase Performance as a dependency of Sessions when this class is loaded into memory.
54+
FirebaseSessionsDependencies.addDependency(SessionSubscriber.Name.PERFORMANCE);
55+
}
56+
5057
@Override
5158
@Keep
5259
public List<Component<?>> getComponents() {

firebase-perf/src/main/java/com/google/firebase/perf/FirebasePerformance.java

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@
3434
import com.google.firebase.perf.config.RemoteConfigManager;
3535
import com.google.firebase.perf.logging.AndroidLogger;
3636
import com.google.firebase.perf.logging.ConsoleUrlGenerator;
37+
import com.google.firebase.perf.logging.FirebaseSessionsEnforcementCheck;
3738
import com.google.firebase.perf.metrics.HttpMetric;
3839
import com.google.firebase.perf.metrics.Trace;
40+
import com.google.firebase.perf.session.FirebasePerformanceSessionSubscriber;
3941
import com.google.firebase.perf.session.SessionManager;
4042
import com.google.firebase.perf.transport.TransportManager;
4143
import com.google.firebase.perf.util.Constants;
4244
import com.google.firebase.perf.util.ImmutableBundle;
4345
import com.google.firebase.perf.util.Timer;
4446
import com.google.firebase.remoteconfig.RemoteConfigComponent;
47+
import com.google.firebase.sessions.api.FirebaseSessionsDependencies;
48+
import com.google.firebase.sessions.api.SessionSubscriber;
4549
import java.lang.annotation.Retention;
4650
import java.lang.annotation.RetentionPolicy;
4751
import java.net.URL;
@@ -92,6 +96,8 @@ public class FirebasePerformance implements FirebasePerformanceAttributable {
9296
// once during initialization and cache it.
9397
private final ImmutableBundle mMetadataBundle;
9498

99+
private final SessionSubscriber sessionSubscriber;
100+
95101
/** Valid HttpMethods for manual network APIs */
96102
@StringDef({
97103
HttpMethod.GET,
@@ -136,11 +142,6 @@ public static FirebasePerformance getInstance() {
136142
// to false if it's been force disabled or it is set to null if neither.
137143
@Nullable private Boolean mPerformanceCollectionForceEnabledState = null;
138144

139-
private final FirebaseApp firebaseApp;
140-
private final Provider<RemoteConfigComponent> firebaseRemoteConfigProvider;
141-
private final FirebaseInstallationsApi firebaseInstallationsApi;
142-
private final Provider<TransportFactory> transportFactoryProvider;
143-
144145
/**
145146
* Constructs the FirebasePerformance class and allows injecting dependencies.
146147
*
@@ -166,23 +167,19 @@ public static FirebasePerformance getInstance() {
166167
ConfigResolver configResolver,
167168
SessionManager sessionManager) {
168169

169-
this.firebaseApp = firebaseApp;
170-
this.firebaseRemoteConfigProvider = firebaseRemoteConfigProvider;
171-
this.firebaseInstallationsApi = firebaseInstallationsApi;
172-
this.transportFactoryProvider = transportFactoryProvider;
173-
174170
if (firebaseApp == null) {
175171
this.mPerformanceCollectionForceEnabledState = false;
176172
this.configResolver = configResolver;
177173
this.mMetadataBundle = new ImmutableBundle(new Bundle());
174+
this.sessionSubscriber = new FirebasePerformanceSessionSubscriber(false);
178175
return;
179176
}
177+
FirebaseSessionsEnforcementCheck.setEnforcement(BuildConfig.ENFORCE_LEGACY_SESSIONS);
180178

181179
TransportManager.getInstance()
182180
.initialize(firebaseApp, firebaseInstallationsApi, transportFactoryProvider);
183181

184182
Context appContext = firebaseApp.getApplicationContext();
185-
// TODO(b/110178816): Explore moving off of main thread.
186183
mMetadataBundle = extractMetadata(appContext);
187184

188185
remoteConfigManager.setFirebaseRemoteConfigProvider(firebaseRemoteConfigProvider);
@@ -192,6 +189,9 @@ public static FirebasePerformance getInstance() {
192189
sessionManager.setApplicationContext(appContext);
193190

194191
mPerformanceCollectionForceEnabledState = configResolver.getIsPerformanceCollectionEnabled();
192+
sessionSubscriber = new FirebasePerformanceSessionSubscriber(isPerformanceCollectionEnabled());
193+
FirebaseSessionsDependencies.register(sessionSubscriber);
194+
195195
if (logger.isLogcatEnabled() && isPerformanceCollectionEnabled()) {
196196
logger.info(
197197
String.format(
@@ -282,7 +282,7 @@ public synchronized void setPerformanceCollectionEnabled(@Nullable Boolean enabl
282282
return;
283283
}
284284

285-
if (configResolver.getIsPerformanceCollectionDeactivated()) {
285+
if (Boolean.TRUE.equals(configResolver.getIsPerformanceCollectionDeactivated())) {
286286
logger.info("Firebase Performance is permanently disabled");
287287
return;
288288
}
@@ -466,4 +466,9 @@ private static ImmutableBundle extractMetadata(Context appContext) {
466466
Boolean getPerformanceCollectionForceEnabledState() {
467467
return mPerformanceCollectionForceEnabledState;
468468
}
469+
470+
@VisibleForTesting
471+
SessionSubscriber getSessionSubscriber() {
472+
return sessionSubscriber;
473+
}
469474
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.perf.logging
18+
19+
import com.google.firebase.perf.session.PerfSession
20+
import com.google.firebase.perf.session.isLegacy
21+
22+
class FirebaseSessionsEnforcementCheck {
23+
companion object {
24+
/** When enabled, failed preconditions will cause assertion errors for debugging. */
25+
@JvmStatic var enforcement: Boolean = false
26+
private var logger: AndroidLogger = AndroidLogger.getInstance()
27+
28+
@JvmStatic
29+
fun checkSession(session: PerfSession, failureMessage: String) {
30+
if (session.isLegacy()) {
31+
logger.debug("legacy session ${session.sessionId()}: $failureMessage")
32+
assert(!enforcement) { failureMessage }
33+
}
34+
}
35+
}
36+
}

firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java

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

1515
package com.google.firebase.perf.metrics;
1616

17+
import static com.google.firebase.perf.util.AppProcessesProvider.getAppProcesses;
18+
1719
import android.annotation.SuppressLint;
1820
import android.app.Activity;
1921
import android.app.ActivityManager;
@@ -509,17 +511,10 @@ public static boolean isAnyAppProcessInForeground(Context appContext) {
509511
if (activityManager == null) {
510512
return true;
511513
}
512-
List<ActivityManager.RunningAppProcessInfo> appProcesses =
513-
activityManager.getRunningAppProcesses();
514-
if (appProcesses != null) {
515-
String appProcessName = appContext.getPackageName();
516-
String allowedAppProcessNamePrefix = appProcessName + ":";
514+
List<ActivityManager.RunningAppProcessInfo> appProcesses = getAppProcesses(appContext);
515+
if (!appProcesses.isEmpty()) {
517516
for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
518-
if (appProcess.importance != ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
519-
continue;
520-
}
521-
if (appProcess.processName.equals(appProcessName)
522-
|| appProcess.processName.startsWith(allowedAppProcessNamePrefix)) {
517+
if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
523518
boolean isAppInForeground = true;
524519

525520
// For the case when the app is in foreground and the device transitions to sleep mode,

firebase-perf/src/main/java/com/google/firebase/perf/metrics/NetworkRequestMetricBuilder.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ public NetworkRequestMetricBuilder setCustomAttributes(Map<String, String> attri
224224
* point depending upon the current {@link PerfSession} verbosity.
225225
*
226226
* @see GaugeManager#collectGaugeMetricOnce(Timer)
227-
* @see PerfSession#isGaugeAndEventCollectionEnabled()
227+
* @see PerfSession#isVerbose()
228228
*/
229229
public NetworkRequestMetricBuilder setRequestStartTimeMicros(long time) {
230230
SessionManager sessionManager = SessionManager.getInstance();
@@ -234,7 +234,7 @@ public NetworkRequestMetricBuilder setRequestStartTimeMicros(long time) {
234234
builder.setClientStartTimeUs(time);
235235
updateSession(perfSession);
236236

237-
if (perfSession.isGaugeAndEventCollectionEnabled()) {
237+
if (perfSession.isVerbose()) {
238238
gaugeManager.collectGaugeMetricOnce(perfSession.getTimer());
239239
}
240240

@@ -265,12 +265,12 @@ public long getTimeToResponseInitiatedMicros() {
265265
* point depending upon the current {@link PerfSession} Verbosity.
266266
*
267267
* @see GaugeManager#collectGaugeMetricOnce(Timer)
268-
* @see PerfSession#isGaugeAndEventCollectionEnabled()
268+
* @see PerfSession#isVerbose()
269269
*/
270270
public NetworkRequestMetricBuilder setTimeToResponseCompletedMicros(long time) {
271271
builder.setTimeToResponseCompletedUs(time);
272272

273-
if (SessionManager.getInstance().perfSession().isGaugeAndEventCollectionEnabled()) {
273+
if (SessionManager.getInstance().perfSession().isVerbose()) {
274274
gaugeManager.collectGaugeMetricOnce(SessionManager.getInstance().perfSession().getTimer());
275275
}
276276

firebase-perf/src/main/java/com/google/firebase/perf/metrics/Trace.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ public void start() {
233233

234234
updateSession(perfSession);
235235

236-
if (perfSession.isGaugeAndEventCollectionEnabled()) {
236+
if (perfSession.isVerbose()) {
237237
gaugeManager.collectGaugeMetricOnce(perfSession.getTimer());
238238
}
239239
}
@@ -259,7 +259,7 @@ public void stop() {
259259
if (!name.isEmpty()) {
260260
transportManager.log(new TraceMetricBuilder(this).build(), getAppState());
261261

262-
if (SessionManager.getInstance().perfSession().isGaugeAndEventCollectionEnabled()) {
262+
if (SessionManager.getInstance().perfSession().isVerbose()) {
263263
gaugeManager.collectGaugeMetricOnce(
264264
SessionManager.getInstance().perfSession().getTimer());
265265
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.perf.session
18+
19+
import com.google.firebase.perf.logging.FirebaseSessionsEnforcementCheck
20+
import com.google.firebase.sessions.api.SessionSubscriber
21+
22+
class FirebasePerformanceSessionSubscriber(override val isDataCollectionEnabled: Boolean) :
23+
SessionSubscriber {
24+
25+
override val sessionSubscriberName: SessionSubscriber.Name = SessionSubscriber.Name.PERFORMANCE
26+
27+
override fun onSessionChanged(sessionDetails: SessionSubscriber.SessionDetails) {
28+
val currentPerfSession = SessionManager.getInstance().perfSession()
29+
// TODO(b/394127311): Add logic to deal with app start gauges.
30+
FirebaseSessionsEnforcementCheck.checkSession(currentPerfSession, "onSessionChanged")
31+
32+
val updatedSession = PerfSession.createWithId(sessionDetails.sessionId)
33+
SessionManager.getInstance().updatePerfSession(updatedSession)
34+
}
35+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright 2025 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.google.firebase.perf.session
18+
19+
import com.google.firebase.perf.util.Constants
20+
import java.util.UUID
21+
22+
/** Identifies whether the [PerfSession] is legacy or not. */
23+
fun PerfSession.isLegacy(): Boolean {
24+
return this.sessionId().isLegacy()
25+
}
26+
27+
/** Identifies whether the string is from a legacy [PerfSession]. */
28+
fun String.isLegacy(): Boolean {
29+
return this.startsWith(Constants.UNDEFINED_AQS_ID_PREFIX)
30+
}
31+
32+
/** Creates a valid session ID for [PerfSession] that can be predictably identified as legacy. */
33+
fun createLegacySessionId(): String {
34+
val uuid = UUID.randomUUID().toString().replace("-", "")
35+
return uuid.replaceRange(
36+
0,
37+
Constants.UNDEFINED_AQS_ID_PREFIX.length,
38+
Constants.UNDEFINED_AQS_ID_PREFIX
39+
)
40+
}

0 commit comments

Comments
 (0)