Added more systrace markers and made LottieTrace multi-thread compatible
diff --git a/lottie/src/main/java/com/airbnb/lottie/L.java b/lottie/src/main/java/com/airbnb/lottie/L.java
index 8bfe62c..a27d7da 100644
--- a/lottie/src/main/java/com/airbnb/lottie/L.java
+++ b/lottie/src/main/java/com/airbnb/lottie/L.java
@@ -12,6 +12,7 @@
import com.airbnb.lottie.network.LottieNetworkFetcher;
import com.airbnb.lottie.network.NetworkCache;
import com.airbnb.lottie.network.NetworkFetcher;
+import com.airbnb.lottie.utils.LottieTrace;
import java.io.File;
@@ -21,20 +22,16 @@
public static boolean DBG = false;
public static final String TAG = "LOTTIE";
- private static final int MAX_DEPTH = 20;
private static boolean traceEnabled = false;
private static boolean networkCacheEnabled = true;
private static boolean disablePathInterpolatorCache = true;
- private static String[] sections;
- private static long[] startTimeNs;
- private static int traceDepth = 0;
- private static int depthPastMaxDepth = 0;
private static LottieNetworkFetcher fetcher;
private static LottieNetworkCacheProvider cacheProvider;
private static volatile NetworkFetcher networkFetcher;
private static volatile NetworkCache networkCache;
+ private static ThreadLocal<LottieTrace> lottieTrace;
private L() {
}
@@ -44,9 +41,8 @@
return;
}
traceEnabled = enabled;
- if (traceEnabled) {
- sections = new String[MAX_DEPTH];
- startTimeNs = new long[MAX_DEPTH];
+ if (traceEnabled && lottieTrace == null) {
+ lottieTrace = new ThreadLocal<>();
}
}
@@ -58,34 +54,23 @@
if (!traceEnabled) {
return;
}
- if (traceDepth == MAX_DEPTH) {
- depthPastMaxDepth++;
- return;
- }
- sections[traceDepth] = section;
- startTimeNs[traceDepth] = System.nanoTime();
- TraceCompat.beginSection(section);
- traceDepth++;
+ getTrace().beginSection(section);
}
public static float endSection(String section) {
- if (depthPastMaxDepth > 0) {
- depthPastMaxDepth--;
- return 0;
- }
if (!traceEnabled) {
return 0;
}
- traceDepth--;
- if (traceDepth == -1) {
- throw new IllegalStateException("Can't end trace section. There are none.");
+ return getTrace().endSection(section);
+ }
+
+ private static LottieTrace getTrace() {
+ LottieTrace trace = lottieTrace.get();
+ if (trace == null) {
+ trace = new LottieTrace();
+ lottieTrace.set(trace);
}
- if (!section.equals(sections[traceDepth])) {
- throw new IllegalStateException("Unbalanced trace call " + section +
- ". Expected " + sections[traceDepth] + ".");
- }
- TraceCompat.endSection();
- return (System.nanoTime() - startTimeNs[traceDepth]) / 1000000f;
+ return trace;
}
public static void setFetcher(LottieNetworkFetcher customFetcher) {
@@ -121,11 +106,8 @@
synchronized (NetworkCache.class) {
local = networkCache;
if (local == null) {
- networkCache = local = new NetworkCache(cacheProvider != null ? cacheProvider : new LottieNetworkCacheProvider() {
- @Override @NonNull public File getCacheDir() {
- return new File(appContext.getCacheDir(), "lottie_network_cache");
- }
- });
+ networkCache = local = new NetworkCache(cacheProvider != null ? cacheProvider :
+ () -> new File(appContext.getCacheDir(), "lottie_network_cache"));
}
}
}
diff --git a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
index 8f13143..f664415 100644
--- a/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
+++ b/lottie/src/main/java/com/airbnb/lottie/animation/keyframe/BaseKeyframeAnimation.java
@@ -46,7 +46,9 @@
}
public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
+ L.beginSection("BaseKeyframeAnimation#setProgress");
if (keyframesWrapper.isEmpty()) {
+ L.endSection("BaseKeyframeAnimation#setProgress");
return;
}
if (progress < getStartDelayProgress()) {
@@ -56,18 +58,22 @@
}
if (progress == this.progress) {
+ L.endSection("BaseKeyframeAnimation#setProgress");
return;
}
this.progress = progress;
if (keyframesWrapper.isValueChanged(progress)) {
notifyListeners();
}
+ L.endSection("BaseKeyframeAnimation#setProgress");
}
public void notifyListeners() {
+ L.beginSection("BaseKeyframeAnimation#notifyListeners");
for (int i = 0; i < listeners.size(); i++) {
listeners.get(i).onValueChanged();
}
+ L.endSection("BaseKeyframeAnimation#notifyListeners");
}
protected Keyframe<K> getCurrentKeyframe() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
index 187cfd1..5775c18 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/BaseLayer.java
@@ -571,22 +571,34 @@
}
void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
+ L.beginSection("BaseLayer#setProgress");
// Time stretch should not be applied to the layer transform.
+ L.beginSection("BaseLayer#setProgress.transform");
transform.setProgress(progress);
+ L.endSection("BaseLayer#setProgress.transform");
if (mask != null) {
+ L.beginSection("BaseLayer#setProgress.mask");
for (int i = 0; i < mask.getMaskAnimations().size(); i++) {
mask.getMaskAnimations().get(i).setProgress(progress);
}
+ L.endSection("BaseLayer#setProgress.mask");
}
if (inOutAnimation != null) {
+ L.beginSection("BaseLayer#setProgress.inout");
inOutAnimation.setProgress(progress);
+ L.endSection("BaseLayer#setProgress.inout");
}
if (matteLayer != null) {
+ L.beginSection("BaseLayer#setProgress.matte");
matteLayer.setProgress(progress);
+ L.endSection("BaseLayer#setProgress.matte");
}
+ L.beginSection("BaseLayer#setProgress.animations." + animations.size());
for (int i = 0; i < animations.size(); i++) {
animations.get(i).setProgress(progress);
}
+ L.endSection("BaseLayer#setProgress.animations." + animations.size());
+ L.endSection("BaseLayer#setProgress");
}
private void buildParentLayerListIfNeeded() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
index 6ddd5f7..113c80d 100644
--- a/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
+++ b/lottie/src/main/java/com/airbnb/lottie/model/layer/CompositionLayer.java
@@ -4,6 +4,7 @@
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.RectF;
+import android.util.Log;
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable;
@@ -142,6 +143,7 @@
}
@Override public void setProgress(@FloatRange(from = 0f, to = 1f) float progress) {
+ L.beginSection("CompositionLayer#setProgress");
super.setProgress(progress);
if (timeRemapping != null) {
// The duration has 0.01 frame offset to show end of animation properly.
@@ -162,6 +164,7 @@
for (int i = layers.size() - 1; i >= 0; i--) {
layers.get(i).setProgress(progress);
}
+ L.endSection("CompositionLayer#setProgress");
}
public boolean hasMasks() {
diff --git a/lottie/src/main/java/com/airbnb/lottie/utils/LottieTrace.java b/lottie/src/main/java/com/airbnb/lottie/utils/LottieTrace.java
new file mode 100644
index 0000000..fcac145
--- /dev/null
+++ b/lottie/src/main/java/com/airbnb/lottie/utils/LottieTrace.java
@@ -0,0 +1,42 @@
+package com.airbnb.lottie.utils;
+
+import androidx.core.os.TraceCompat;
+
+public class LottieTrace {
+ private static final int MAX_DEPTH = 20;
+
+ private final String[] sections = new String[MAX_DEPTH];
+ private final long[] startTimeNs = new long[MAX_DEPTH];
+ private int traceDepth = 0;
+ private int depthPastMaxDepth = 0;
+
+ public void beginSection(String section) {
+ if (traceDepth == MAX_DEPTH) {
+ depthPastMaxDepth++;
+ return;
+ }
+ sections[traceDepth] = section;
+ startTimeNs[traceDepth] = System.nanoTime();
+ //noinspection deprecation
+ TraceCompat.beginSection(section);
+ traceDepth++;
+ }
+
+ public float endSection(String section) {
+ if (depthPastMaxDepth > 0) {
+ depthPastMaxDepth--;
+ return 0;
+ }
+ traceDepth--;
+ if (traceDepth == -1) {
+ throw new IllegalStateException("Can't end trace section. There are none.");
+ }
+ if (!section.equals(sections[traceDepth])) {
+ throw new IllegalStateException("Unbalanced trace call " + section +
+ ". Expected " + sections[traceDepth] + ".");
+ }
+ //noinspection deprecation
+ TraceCompat.endSection();
+ return (System.nanoTime() - startTimeNs[traceDepth]) / 1000000f;
+ }
+}