summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/jank/JankTracker.java16
-rw-r--r--tests/AppJankTest/Android.bp1
-rw-r--r--tests/AppJankTest/AndroidManifest.xml19
-rw-r--r--tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml47
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java215
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java32
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/JankTrackerActivity.java32
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/JankUtils.java52
-rw-r--r--tests/AppJankTest/src/android/app/jank/tests/TestWidget.java69
9 files changed, 449 insertions, 34 deletions
diff --git a/core/java/android/app/jank/JankTracker.java b/core/java/android/app/jank/JankTracker.java
index 469521668d25..a04f96a9f6e3 100644
--- a/core/java/android/app/jank/JankTracker.java
+++ b/core/java/android/app/jank/JankTracker.java
@@ -29,6 +29,7 @@ import android.view.ViewTreeObserver;
import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
+import java.util.HashMap;
/**
* This class is responsible for registering callbacks that will receive JankData batches.
@@ -174,6 +175,15 @@ public class JankTracker {
}
/**
+ * 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
* in time for tests to pass. This forces them to run immediately.
*/
@@ -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;
}
diff --git a/tests/AppJankTest/Android.bp b/tests/AppJankTest/Android.bp
index acf8dc9aca47..c3cda6a41cbb 100644
--- a/tests/AppJankTest/Android.bp
+++ b/tests/AppJankTest/Android.bp
@@ -30,6 +30,7 @@ android_test {
"androidx.test.core",
"platform-test-annotations",
"flag-junit",
+ "androidx.test.uiautomator_uiautomator",
],
platform_apis: true,
test_suites: ["device-tests"],
diff --git a/tests/AppJankTest/AndroidManifest.xml b/tests/AppJankTest/AndroidManifest.xml
index abed1798c47c..861a79c6f0ed 100644
--- a/tests/AppJankTest/AndroidManifest.xml
+++ b/tests/AppJankTest/AndroidManifest.xml
@@ -19,22 +19,31 @@
package="android.app.jank.tests">
<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"
- android:label="EmptyActivity"
- android:exported="true">
+ android:exported="true"
+ android:label="EmptyActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="android.intent.action.VIEW_PERMISSION_USAGE"/>
</intent-filter>
</activity>
+ <uses-library android:name="android.test.runner"/>
</application>
<!-- self-instrumenting test package. -->
<instrumentation
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>
</manifest> \ No newline at end of file
diff --git a/tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml b/tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml
new file mode 100644
index 000000000000..65def7f2d5b6
--- /dev/null
+++ b/tests/AppJankTest/res/layout/jank_tracker_activity_layout.xml
@@ -0,0 +1,47 @@
+<?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
diff --git a/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java b/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java
new file mode 100644
index 000000000000..34f0c191ecf5
--- /dev/null
+++ b/tests/AppJankTest/src/android/app/jank/tests/IntegrationTests.java
@@ -0,0 +1,215 @@
+/*
+ * 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());
+ }
+}
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java b/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
index 4d495adf727b..30c568be7716 100644
--- a/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankDataProcessorTest.java
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
import android.app.jank.AppJankStats;
import android.app.jank.Flags;
-import android.app.jank.FrameOverrunHistogram;
import android.app.jank.JankDataProcessor;
import android.app.jank.StateTracker;
import android.platform.test.annotations.RequiresFlagsEnabled;
@@ -165,7 +164,7 @@ public class JankDataProcessorTest {
assertEquals(pendingStats.size(), 0);
- AppJankStats jankStats = getAppJankStats();
+ AppJankStats jankStats = JankUtils.getAppJankStats();
mJankDataProcessor.mergeJankStats(jankStats, sActivityName);
pendingStats = mJankDataProcessor.getPendingJankStats();
@@ -182,14 +181,14 @@ public class JankDataProcessorTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
public void mergeAppJankStats_confirmStatsWithMatchingStatesAreCombinedIntoOnePendingStat() {
- AppJankStats jankStats = getAppJankStats();
+ AppJankStats jankStats = JankUtils.getAppJankStats();
mJankDataProcessor.mergeJankStats(jankStats, sActivityName);
HashMap<String, JankDataProcessor.PendingJankStat> pendingStats =
mJankDataProcessor.getPendingJankStats();
assertEquals(pendingStats.size(), 1);
- AppJankStats secondJankStat = getAppJankStats();
+ AppJankStats secondJankStat = JankUtils.getAppJankStats();
mJankDataProcessor.mergeJankStats(secondJankStat, sActivityName);
pendingStats = mJankDataProcessor.getPendingJankStats();
@@ -200,7 +199,7 @@ public class JankDataProcessorTest {
@Test
@RequiresFlagsEnabled(Flags.FLAG_DETAILED_APP_JANK_METRICS_API)
public void mergeAppJankStats_whenStatsWithMatchingStatesMerge_confirmFrameCountsAdded() {
- AppJankStats jankStats = getAppJankStats();
+ AppJankStats jankStats = JankUtils.getAppJankStats();
mJankDataProcessor.mergeJankStats(jankStats, sActivityName);
mJankDataProcessor.mergeJankStats(jankStats, sActivityName);
@@ -345,27 +344,4 @@ public class JankDataProcessorTest {
return mockData;
}
-
- private AppJankStats getAppJankStats() {
- AppJankStats jankStats = new AppJankStats(
- /*App Uid*/APP_ID,
- /*Widget Id*/"test widget id",
- /*Widget Category*/AppJankStats.SCROLL,
- /*Widget State*/AppJankStats.SCROLLING,
- /*Total Frames*/100,
- /*Janky Frames*/25,
- getOverrunHistogram()
- );
- return jankStats;
- }
-
- private FrameOverrunHistogram getOverrunHistogram() {
- FrameOverrunHistogram overrunHistogram = new FrameOverrunHistogram();
- overrunHistogram.addFrameOverrunMillis(-2);
- overrunHistogram.addFrameOverrunMillis(1);
- overrunHistogram.addFrameOverrunMillis(5);
- overrunHistogram.addFrameOverrunMillis(25);
- return overrunHistogram;
- }
-
}
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankTrackerActivity.java b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerActivity.java
new file mode 100644
index 000000000000..80ab6ad3e587
--- /dev/null
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankTrackerActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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 android.app.Activity;
+import android.os.Bundle;
+
+
+public class JankTrackerActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.jank_tracker_activity_layout);
+ }
+}
+
+
diff --git a/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java b/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java
new file mode 100644
index 000000000000..0b4d97ed20d6
--- /dev/null
+++ b/tests/AppJankTest/src/android/app/jank/tests/JankUtils.java
@@ -0,0 +1,52 @@
+/*
+ * 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 android.app.jank.AppJankStats;
+import android.app.jank.FrameOverrunHistogram;
+
+public class JankUtils {
+ private static final int APP_ID = 25;
+
+ /**
+ * Returns a mock AppJankStats object to be used in tests.
+ */
+ public static AppJankStats getAppJankStats() {
+ AppJankStats jankStats = new AppJankStats(
+ /*App Uid*/APP_ID,
+ /*Widget Id*/"test widget id",
+ /*Widget Category*/AppJankStats.SCROLL,
+ /*Widget State*/AppJankStats.SCROLLING,
+ /*Total Frames*/100,
+ /*Janky Frames*/25,
+ getOverrunHistogram()
+ );
+ return jankStats;
+ }
+
+ /**
+ * Returns a mock histogram to be used with an AppJankStats object.
+ */
+ public static FrameOverrunHistogram getOverrunHistogram() {
+ FrameOverrunHistogram overrunHistogram = new FrameOverrunHistogram();
+ overrunHistogram.addFrameOverrunMillis(-2);
+ overrunHistogram.addFrameOverrunMillis(1);
+ overrunHistogram.addFrameOverrunMillis(5);
+ overrunHistogram.addFrameOverrunMillis(25);
+ return overrunHistogram;
+ }
+}
diff --git a/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java b/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java
new file mode 100644
index 000000000000..5fff46038ead
--- /dev/null
+++ b/tests/AppJankTest/src/android/app/jank/tests/TestWidget.java
@@ -0,0 +1,69 @@
+/*
+ * 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 android.app.jank.AppJankStats;
+import android.app.jank.JankTracker;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+public class TestWidget extends View {
+
+ private JankTracker mJankTracker;
+
+ /**
+ * Create JankTrackerView
+ */
+ public TestWidget(Context context) {
+ super(context);
+ }
+
+ /**
+ * Create JankTrackerView, needed by system when inflating views defined in a layout file.
+ */
+ public TestWidget(Context context, AttributeSet attributeSet) {
+ super(context, attributeSet);
+ }
+
+ /**
+ * Mock starting an animation.
+ */
+ public void simulateAnimationStarting() {
+ if (jankTrackerCreated()) {
+ mJankTracker.addUiState(AppJankStats.ANIMATION,
+ Integer.toString(this.getId()), AppJankStats.ANIMATING);
+ }
+ }
+
+ /**
+ * Mock ending an animation.
+ */
+ public void simulateAnimationEnding() {
+ if (jankTrackerCreated()) {
+ mJankTracker.removeUiState(AppJankStats.ANIMATION,
+ Integer.toString(this.getId()), AppJankStats.ANIMATING);
+ }
+ }
+
+ private boolean jankTrackerCreated() {
+ if (mJankTracker == null) {
+ mJankTracker = getJankTracker();
+ }
+ return mJankTracker != null;
+ }
+}