Loading core/java/android/app/jank/JankTracker.java +15 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.ViewTreeObserver; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; /** /** * This class is responsible for registering callbacks that will receive JankData batches. * This class is responsible for registering callbacks that will receive JankData batches. Loading Loading @@ -173,6 +174,15 @@ public class JankTracker { mStateTracker.retrieveAllStates(stateDataList); mStateTracker.retrieveAllStates(stateDataList); } } /** * Retrieve all pending jank stats before they are logged, this is intended for testing * purposes only. */ @VisibleForTesting public HashMap<String, JankDataProcessor.PendingJankStat> getPendingJankStats() { return mJankDataProcessor.getPendingJankStats(); } /** /** * Only intended to be used by tests, the runnable that registers the listeners may not run * Only intended to be used by tests, the runnable that registers the listeners may not run * in time for tests to pass. This forces them to run immediately. * in time for tests to pass. This forces them to run immediately. Loading @@ -192,7 +202,11 @@ public class JankTracker { */ */ } } private boolean shouldTrack() { /** * Returns whether jank tracking is enabled or not. */ @VisibleForTesting public boolean shouldTrack() { return mTrackingEnabled && mListenersRegistered; return mTrackingEnabled && mListenersRegistered; } } Loading tests/AppJankTest/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ android_test { "androidx.test.core", "androidx.test.core", "platform-test-annotations", "platform-test-annotations", "flag-junit", "flag-junit", "androidx.test.uiautomator_uiautomator", ], ], platform_apis: true, platform_apis: true, test_suites: ["device-tests"], test_suites: ["device-tests"], Loading tests/AppJankTest/AndroidManifest.xml +14 −5 Original line number Original line Diff line number Diff line Loading @@ -19,22 +19,31 @@ package="android.app.jank.tests"> package="android.app.jank.tests"> <application android:appCategory="news"> <application android:appCategory="news"> <uses-library android:name="android.test.runner" /> <activity android:name=".JankTrackerActivity" android:exported="true" android:label="JankTrackerActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> </intent-filter> </activity> <activity android:name=".EmptyActivity" <activity android:name=".EmptyActivity" android:label="EmptyActivity" android:exported="true" android:exported="true"> android:label="EmptyActivity"> <intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> </intent-filter> </intent-filter> </activity> </activity> <uses-library android:name="android.test.runner"/> </application> </application> <!-- self-instrumenting test package. --> <!-- self-instrumenting test package. --> <instrumentation <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="android.app.jank.tests" android:label="Core tests of App Jank Tracking" android:label="Core tests of App Jank Tracking"> android:targetPackage="android.app.jank.tests"> </instrumentation> </instrumentation> </manifest> </manifest> No newline at end of file tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml 0 → 100644 +47 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2024 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <LinearLayout android:id="@+id/linear_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEnableTextConversionSuggestions" android:text="Edit Text"/> <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Text View" /> <android.app.jank.tests.TestWidget android:id="@+id/jank_tracker_widget" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView> No newline at end of file tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java 0 → 100644 +215 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.jank.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.Instrumentation; import android.app.jank.AppJankStats; import android.app.jank.Flags; import android.app.jank.JankDataProcessor; import android.app.jank.JankTracker; import android.app.jank.StateTracker; import android.content.Intent; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.widget.EditText; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.Until; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.HashMap; /** * This file contains tests that verify the proper functionality of the Jank Tracking feature. * All tests should obtain references to necessary objects through View type interfaces, rather * than direct instantiation. When operating outside of a testing environment, the expected * behavior is to retrieve the necessary objects using View type interfaces. This approach ensures * that calls are correctly routed down to the activity level. Any modifications to the call * routing should result in test failures, which might happen with direct instantiations. */ @RunWith(AndroidJUnit4.class) public class IntegrationTests { public static final int WAIT_FOR_TIMEOUT_MS = 5000; @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private Activity mEmptyActivity; public UiDevice mDevice; private Instrumentation mInstrumentation; private ActivityTestRule<JankTrackerActivity> mJankTrackerActivityRule = new ActivityTestRule<>( JankTrackerActivity.class, false, false); private ActivityTestRule<EmptyActivity> mEmptyActivityRule = new ActivityTestRule<>(EmptyActivity.class, false , true); @Before public void setUp() { mInstrumentation = InstrumentationRegistry.getInstrumentation(); mDevice = UiDevice.getInstance(mInstrumentation); } /** * Get a JankTracker object from a view and confirm it's not null. */ @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void getJankTacker_confirmNotNull() { Activity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); EditText editText = jankTrackerActivity.findViewById(R.id.edit_text); mDevice.wait(Until.findObject(By.text("Edit Text")), WAIT_FOR_TIMEOUT_MS); JankTracker jankTracker = editText.getJankTracker(); assertTrue(jankTracker != null); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void reportJankStats_confirmPendingStatsIncreases() { Activity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); EditText editText = jankTrackerActivity.findViewById(R.id.edit_text); JankTracker jankTracker = editText.getJankTracker(); HashMap<String, JankDataProcessor.PendingJankStat> pendingStats = jankTracker.getPendingJankStats(); assertEquals(0, pendingStats.size()); editText.reportAppJankStats(JankUtils.getAppJankStats()); // reportAppJankStats performs the work on a background thread, check periodically to see // if the work is complete. for (int i = 0; i < 10; i++) { try { Thread.sleep(100); if (jankTracker.getPendingJankStats().size() > 0) { break; } } catch (InterruptedException exception) { //do nothing and continue } } pendingStats = jankTracker.getPendingJankStats(); assertEquals(1, pendingStats.size()); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void simulateWidgetStateChanges_confirmStateChangesAreTracked() { JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); ArrayList<StateTracker.StateData> uiStates = new ArrayList<>(); // Get the current UI states, at this point only the activity name should be in the UI // states list. jankTracker.getAllUiStates(uiStates); assertEquals(1, uiStates.size()); // This should add a UI state to be tracked. testWidget.simulateAnimationStarting(); uiStates.clear(); jankTracker.getAllUiStates(uiStates); assertEquals(2, uiStates.size()); // Stop the animation testWidget.simulateAnimationEnding(); uiStates.clear(); jankTracker.getAllUiStates(uiStates); assertEquals(2, uiStates.size()); // Confirm the Animation state has a VsyncIdEnd that is not default, indicating the end // of that state. for (int i = 0; i < uiStates.size(); i++) { StateTracker.StateData stateData = uiStates.get(i); if (stateData.mWidgetCategory.equals(AppJankStats.ANIMATION)) { assertNotEquals(Long.MAX_VALUE, stateData.mVsyncIdEnd); } } } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void jankTrackingPaused_whenActivityNoLongerVisible() { JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); assertTrue(jankTracker.shouldTrack()); // Send jankTrackerActivity to the background mDevice.pressHome(); mDevice.waitForIdle(WAIT_FOR_TIMEOUT_MS); assertFalse(jankTracker.shouldTrack()); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void jankTrackingResumed_whenActivityBecomesVisibleAgain() { mEmptyActivityRule.launchActivity(null); mEmptyActivity = mEmptyActivityRule.getActivity(); JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); // Send jankTrackerActivity to the background mDevice.pressHome(); mDevice.waitForIdle(WAIT_FOR_TIMEOUT_MS); assertFalse(jankTracker.shouldTrack()); Intent resumeJankTracker = new Intent(mInstrumentation.getContext(), JankTrackerActivity.class); resumeJankTracker.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); mEmptyActivity.startActivity(resumeJankTracker); mDevice.wait(Until.findObject(By.text("Edit Text")), WAIT_FOR_TIMEOUT_MS); assertTrue(jankTracker.shouldTrack()); } } Loading
core/java/android/app/jank/JankTracker.java +15 −1 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.view.ViewTreeObserver; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.ArrayList; import java.util.HashMap; /** /** * This class is responsible for registering callbacks that will receive JankData batches. * This class is responsible for registering callbacks that will receive JankData batches. Loading Loading @@ -173,6 +174,15 @@ public class JankTracker { mStateTracker.retrieveAllStates(stateDataList); mStateTracker.retrieveAllStates(stateDataList); } } /** * Retrieve all pending jank stats before they are logged, this is intended for testing * purposes only. */ @VisibleForTesting public HashMap<String, JankDataProcessor.PendingJankStat> getPendingJankStats() { return mJankDataProcessor.getPendingJankStats(); } /** /** * Only intended to be used by tests, the runnable that registers the listeners may not run * Only intended to be used by tests, the runnable that registers the listeners may not run * in time for tests to pass. This forces them to run immediately. * in time for tests to pass. This forces them to run immediately. Loading @@ -192,7 +202,11 @@ public class JankTracker { */ */ } } private boolean shouldTrack() { /** * Returns whether jank tracking is enabled or not. */ @VisibleForTesting public boolean shouldTrack() { return mTrackingEnabled && mListenersRegistered; return mTrackingEnabled && mListenersRegistered; } } Loading
tests/AppJankTest/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -30,6 +30,7 @@ android_test { "androidx.test.core", "androidx.test.core", "platform-test-annotations", "platform-test-annotations", "flag-junit", "flag-junit", "androidx.test.uiautomator_uiautomator", ], ], platform_apis: true, platform_apis: true, test_suites: ["device-tests"], test_suites: ["device-tests"], Loading
tests/AppJankTest/AndroidManifest.xml +14 −5 Original line number Original line Diff line number Diff line Loading @@ -19,22 +19,31 @@ package="android.app.jank.tests"> package="android.app.jank.tests"> <application android:appCategory="news"> <application android:appCategory="news"> <uses-library android:name="android.test.runner" /> <activity android:name=".JankTrackerActivity" android:exported="true" android:label="JankTrackerActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> </intent-filter> </activity> <activity android:name=".EmptyActivity" <activity android:name=".EmptyActivity" android:label="EmptyActivity" android:exported="true" android:exported="true"> android:label="EmptyActivity"> <intent-filter> <intent-filter> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> <action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/> </intent-filter> </intent-filter> </activity> </activity> <uses-library android:name="android.test.runner"/> </application> </application> <!-- self-instrumenting test package. --> <!-- self-instrumenting test package. --> <instrumentation <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="android.app.jank.tests" android:label="Core tests of App Jank Tracking" android:label="Core tests of App Jank Tracking"> android:targetPackage="android.app.jank.tests"> </instrumentation> </instrumentation> </manifest> </manifest> No newline at end of file
tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml 0 → 100644 +47 −0 Original line number Original line Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- ~ Copyright (C) 2024 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true"> <LinearLayout android:id="@+id/linear_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <EditText android:id="@+id/edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEnableTextConversionSuggestions" android:text="Edit Text"/> <TextView android:id="@+id/text_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Text View" /> <android.app.jank.tests.TestWidget android:id="@+id/jank_tracker_widget" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> </ScrollView> No newline at end of file
tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java 0 → 100644 +215 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.app.jank.tests; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import android.app.Activity; import android.app.Instrumentation; import android.app.jank.AppJankStats; import android.app.jank.Flags; import android.app.jank.JankDataProcessor; import android.app.jank.JankTracker; import android.app.jank.StateTracker; import android.content.Intent; import android.platform.test.annotations.RequiresFlagsEnabled; import android.platform.test.flag.junit.CheckFlagsRule; import android.platform.test.flag.junit.DeviceFlagsValueProvider; import android.widget.EditText; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.rule.ActivityTestRule; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.Until; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.HashMap; /** * This file contains tests that verify the proper functionality of the Jank Tracking feature. * All tests should obtain references to necessary objects through View type interfaces, rather * than direct instantiation. When operating outside of a testing environment, the expected * behavior is to retrieve the necessary objects using View type interfaces. This approach ensures * that calls are correctly routed down to the activity level. Any modifications to the call * routing should result in test failures, which might happen with direct instantiations. */ @RunWith(AndroidJUnit4.class) public class IntegrationTests { public static final int WAIT_FOR_TIMEOUT_MS = 5000; @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); private Activity mEmptyActivity; public UiDevice mDevice; private Instrumentation mInstrumentation; private ActivityTestRule<JankTrackerActivity> mJankTrackerActivityRule = new ActivityTestRule<>( JankTrackerActivity.class, false, false); private ActivityTestRule<EmptyActivity> mEmptyActivityRule = new ActivityTestRule<>(EmptyActivity.class, false , true); @Before public void setUp() { mInstrumentation = InstrumentationRegistry.getInstrumentation(); mDevice = UiDevice.getInstance(mInstrumentation); } /** * Get a JankTracker object from a view and confirm it's not null. */ @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void getJankTacker_confirmNotNull() { Activity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); EditText editText = jankTrackerActivity.findViewById(R.id.edit_text); mDevice.wait(Until.findObject(By.text("Edit Text")), WAIT_FOR_TIMEOUT_MS); JankTracker jankTracker = editText.getJankTracker(); assertTrue(jankTracker != null); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void reportJankStats_confirmPendingStatsIncreases() { Activity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); EditText editText = jankTrackerActivity.findViewById(R.id.edit_text); JankTracker jankTracker = editText.getJankTracker(); HashMap<String, JankDataProcessor.PendingJankStat> pendingStats = jankTracker.getPendingJankStats(); assertEquals(0, pendingStats.size()); editText.reportAppJankStats(JankUtils.getAppJankStats()); // reportAppJankStats performs the work on a background thread, check periodically to see // if the work is complete. for (int i = 0; i < 10; i++) { try { Thread.sleep(100); if (jankTracker.getPendingJankStats().size() > 0) { break; } } catch (InterruptedException exception) { //do nothing and continue } } pendingStats = jankTracker.getPendingJankStats(); assertEquals(1, pendingStats.size()); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void simulateWidgetStateChanges_confirmStateChangesAreTracked() { JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); ArrayList<StateTracker.StateData> uiStates = new ArrayList<>(); // Get the current UI states, at this point only the activity name should be in the UI // states list. jankTracker.getAllUiStates(uiStates); assertEquals(1, uiStates.size()); // This should add a UI state to be tracked. testWidget.simulateAnimationStarting(); uiStates.clear(); jankTracker.getAllUiStates(uiStates); assertEquals(2, uiStates.size()); // Stop the animation testWidget.simulateAnimationEnding(); uiStates.clear(); jankTracker.getAllUiStates(uiStates); assertEquals(2, uiStates.size()); // Confirm the Animation state has a VsyncIdEnd that is not default, indicating the end // of that state. for (int i = 0; i < uiStates.size(); i++) { StateTracker.StateData stateData = uiStates.get(i); if (stateData.mWidgetCategory.equals(AppJankStats.ANIMATION)) { assertNotEquals(Long.MAX_VALUE, stateData.mVsyncIdEnd); } } } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void jankTrackingPaused_whenActivityNoLongerVisible() { JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); assertTrue(jankTracker.shouldTrack()); // Send jankTrackerActivity to the background mDevice.pressHome(); mDevice.waitForIdle(WAIT_FOR_TIMEOUT_MS); assertFalse(jankTracker.shouldTrack()); } @Test @RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API) public void jankTrackingResumed_whenActivityBecomesVisibleAgain() { mEmptyActivityRule.launchActivity(null); mEmptyActivity = mEmptyActivityRule.getActivity(); JankTrackerActivity jankTrackerActivity = mJankTrackerActivityRule.launchActivity(null); TestWidget testWidget = jankTrackerActivity.findViewById(R.id.jank_tracker_widget); JankTracker jankTracker = testWidget.getJankTracker(); jankTracker.forceListenerRegistration(); // Send jankTrackerActivity to the background mDevice.pressHome(); mDevice.waitForIdle(WAIT_FOR_TIMEOUT_MS); assertFalse(jankTracker.shouldTrack()); Intent resumeJankTracker = new Intent(mInstrumentation.getContext(), JankTrackerActivity.class); resumeJankTracker.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); mEmptyActivity.startActivity(resumeJankTracker); mDevice.wait(Until.findObject(By.text("Edit Text")), WAIT_FOR_TIMEOUT_MS); assertTrue(jankTracker.shouldTrack()); } }