Skip to content

Commit f8b4b4d

Browse files
committed
add RC wip
1 parent ddb9f8c commit f8b4b4d

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

firebase-perf/dev-app/dev-app.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ apply plugin: 'com.android.application'
1616
// Firebase performance plugin, the relevant dependency is specified in the "buildSrc/build-src.gradle"
1717
apply plugin: 'com.google.firebase.firebase-perf'
1818
apply plugin: com.google.firebase.gradle.plugins.ci.device.FirebaseTestLabPlugin
19+
apply plugin: 'com.google.gms.google-services'
1920

2021
firebaseTestLab {
2122
device 'model=Pixel2,version=28,locale=en,orientation=portrait'

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ public class AppStartTrace implements ActivityLifecycleCallbacks {
7474
private boolean isRegisteredForLifecycleCallbacks = false;
7575
private final TransportManager transportManager;
7676
private final Clock clock;
77+
private final ConfigResolver configResolver;
7778
private Context appContext;
7879
/**
7980
* The first time onCreate() of any activity is called, the activity is saved as launchActivity.
@@ -140,6 +141,7 @@ static AppStartTrace getInstance(TransportManager transportManager, Clock clock)
140141
new AppStartTrace(
141142
transportManager,
142143
clock,
144+
ConfigResolver.getInstance(),
143145
new ThreadPoolExecutor(
144146
CORE_POOL_SIZE,
145147
MAX_POOL_SIZE,
@@ -155,9 +157,11 @@ static AppStartTrace getInstance(TransportManager transportManager, Clock clock)
155157
AppStartTrace(
156158
@NonNull TransportManager transportManager,
157159
@NonNull Clock clock,
160+
@NonNull ConfigResolver configResolver,
158161
@NonNull ExecutorService executorService) {
159162
this.transportManager = transportManager;
160163
this.clock = clock;
164+
this.configResolver = configResolver;
161165
this.executorService = executorService;
162166
}
163167

@@ -244,7 +248,7 @@ public synchronized void onActivityResumed(Activity activity) {
244248
}
245249

246250
// Shadow-launch experiment of new app start time
247-
if (ConfigResolver.getInstance().getIsExperimentTTIDEnabled()) {
251+
if (configResolver.getIsExperimentTTIDEnabled()) {
248252
View rootView = activity.findViewById(android.R.id.content);
249253
FirstDrawDoneListener.registerForNextDraw(rootView, this::recordFirstDrawDone);
250254
}

firebase-perf/src/test/java/com/google/firebase/perf/metrics/AppStartTraceTest.java

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,27 @@
1414

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

17+
import static com.google.common.truth.Truth.assertThat;
1718
import static com.google.firebase.perf.util.TimerTest.getElapsedRealtimeMicros;
19+
import static org.mockito.ArgumentMatchers.isA;
1820
import static org.mockito.Mockito.doAnswer;
1921
import static org.mockito.Mockito.mock;
2022
import static org.mockito.Mockito.times;
2123
import static org.mockito.Mockito.verify;
2224
import static org.mockito.Mockito.when;
2325
import static org.mockito.MockitoAnnotations.initMocks;
26+
import static org.robolectric.Shadows.shadowOf;
2427

2528
import android.app.Activity;
2629
import android.content.pm.ProviderInfo;
2730
import android.os.Bundle;
31+
import android.os.Looper;
32+
import android.os.Process;
33+
import android.os.SystemClock;
34+
import android.view.View;
2835
import androidx.test.core.app.ApplicationProvider;
2936
import com.google.firebase.perf.FirebasePerformanceTestBase;
37+
import com.google.firebase.perf.config.ConfigResolver;
3038
import com.google.firebase.perf.provider.FirebasePerfProvider;
3139
import com.google.firebase.perf.session.SessionManager;
3240
import com.google.firebase.perf.transport.TransportManager;
@@ -36,6 +44,7 @@
3644
import com.google.firebase.perf.v1.ApplicationProcessState;
3745
import com.google.firebase.perf.v1.TraceMetric;
3846
import com.google.testing.timing.FakeScheduledExecutorService;
47+
import java.time.Duration;
3948
import java.util.concurrent.TimeUnit;
4049
import org.junit.After;
4150
import org.junit.Assert;
@@ -48,13 +57,18 @@
4857
import org.mockito.invocation.InvocationOnMock;
4958
import org.mockito.stubbing.Answer;
5059
import org.robolectric.RobolectricTestRunner;
60+
import org.robolectric.annotation.Config;
61+
import org.robolectric.annotation.LooperMode;
62+
import org.robolectric.shadows.ShadowSystemClock;
5163

5264
/** Unit tests for {@link AppStartTrace}. */
5365
@RunWith(RobolectricTestRunner.class)
66+
@LooperMode(LooperMode.Mode.PAUSED)
5467
public class AppStartTraceTest extends FirebasePerformanceTestBase {
5568

5669
@Mock private Clock clock;
5770
@Mock private TransportManager transportManager;
71+
@Mock private ConfigResolver configResolver;
5872
@Mock private Activity activity1;
5973
@Mock private Activity activity2;
6074
@Mock private Bundle bundle;
@@ -94,7 +108,8 @@ public void reset() {
94108
@Test
95109
public void testLaunchActivity() {
96110
FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService();
97-
AppStartTrace trace = new AppStartTrace(transportManager, clock, fakeExecutorService);
111+
AppStartTrace trace =
112+
new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService);
98113
// first activity goes through onCreate()->onStart()->onResume() state change.
99114
currentTime = 1;
100115
trace.onActivityCreated(activity1, bundle);
@@ -171,7 +186,8 @@ private void verifyFinalState(
171186
@Test
172187
public void testInterleavedActivity() {
173188
FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService();
174-
AppStartTrace trace = new AppStartTrace(transportManager, clock, fakeExecutorService);
189+
AppStartTrace trace =
190+
new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService);
175191
// first activity onCreate()
176192
currentTime = 1;
177193
trace.onActivityCreated(activity1, bundle);
@@ -206,7 +222,8 @@ public void testInterleavedActivity() {
206222
@Test
207223
public void testDelayedAppStart() {
208224
FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService();
209-
AppStartTrace trace = new AppStartTrace(transportManager, clock, fakeExecutorService);
225+
AppStartTrace trace =
226+
new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService);
210227
// Delays activity creation after 1 minute from app start time.
211228
currentTime = appStart.getMicros() + TimeUnit.MINUTES.toMicros(1) + 1;
212229
trace.onActivityCreated(activity1, bundle);
@@ -227,7 +244,8 @@ public void testDelayedAppStart() {
227244
@Test
228245
public void testStartFromBackground() {
229246
FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService();
230-
AppStartTrace trace = new AppStartTrace(transportManager, clock, fakeExecutorService);
247+
AppStartTrace trace =
248+
new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService);
231249
trace.setIsStartFromBackground();
232250
trace.onActivityCreated(activity1, bundle);
233251
Assert.assertNull(trace.getOnCreateTime());
@@ -261,4 +279,38 @@ public void testFirebasePerfProviderOnAttachInfo_initializesGaugeCollection() {
261279
Assert.assertEquals(oldSessionId, SessionManager.getInstance().perfSession().sessionId());
262280
verify(mockPerfSession, times(2)).isGaugeAndEventCollectionEnabled();
263281
}
282+
283+
@Test
284+
@Config(sdk = 26)
285+
public void timeToInitialDisplay_isLogged() {
286+
when(clock.getTime()).thenCallRealMethod(); // Use robolectric shadows to manipulate time
287+
long appStartTime = TimeUnit.MILLISECONDS.toMicros(Process.getStartElapsedRealtime());
288+
View testView = new View(ApplicationProvider.getApplicationContext());
289+
when(activity1.findViewById(android.R.id.content)).thenReturn(testView);
290+
when(configResolver.getIsExperimentTTIDEnabled()).thenReturn(true);
291+
FakeScheduledExecutorService fakeExecutorService = new FakeScheduledExecutorService();
292+
AppStartTrace trace =
293+
new AppStartTrace(transportManager, clock, configResolver, fakeExecutorService);
294+
295+
ShadowSystemClock.advanceBy(Duration.ofMillis(1000));
296+
long resumeTime = TimeUnit.NANOSECONDS.toMicros(SystemClock.elapsedRealtimeNanos());
297+
trace.onActivityCreated(activity1, bundle);
298+
trace.onActivityStarted(activity1);
299+
trace.onActivityResumed(activity1);
300+
fakeExecutorService.runAll();
301+
verify(transportManager, times(1))
302+
.log(isA(TraceMetric.class), isA(ApplicationProcessState.class));
303+
ShadowSystemClock.advanceBy(Duration.ofMillis(1000));
304+
long drawTime = TimeUnit.NANOSECONDS.toMicros(SystemClock.elapsedRealtimeNanos());
305+
testView.getViewTreeObserver().dispatchOnDraw();
306+
shadowOf(Looper.getMainLooper()).idle();
307+
fakeExecutorService.runNext();
308+
verify(transportManager, times(2))
309+
.log(traceArgumentCaptor.capture(), isA(ApplicationProcessState.class));
310+
311+
TraceMetric ttid = traceArgumentCaptor.getValue();
312+
assertThat(ttid.getName()).isEqualTo("_experiment_as_ttid");
313+
assertThat(ttid.getDurationUs()).isNotEqualTo(resumeTime - appStartTime);
314+
assertThat(ttid.getDurationUs()).isEqualTo(drawTime - appStartTime);
315+
}
264316
}

0 commit comments

Comments
 (0)