Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions lottie/src/main/java/com/airbnb/lottie/L.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class L {
public static final String TAG = "LOTTIE";

private static boolean traceEnabled = false;
private static boolean lightTracingEnabled = false;
private static boolean networkCacheEnabled = true;
private static boolean disablePathInterpolatorCache = false;
private static AsyncUpdates defaultAsyncUpdates = AsyncUpdates.AUTOMATIC;
Expand Down Expand Up @@ -53,19 +54,40 @@ public static boolean isTraceEnabled(){
return traceEnabled;
}

/**
* Enable light tracing.
*
* Unlike {@link #setTraceEnabled}, this does not trace every layer draw.
* It is safe to always enable this in production with near zero performance issues.
*/
public static void setLightTracingEnabled(boolean enabled) {
lightTracingEnabled = enabled;
if (lightTracingEnabled && lottieTrace == null) {
lottieTrace = new ThreadLocal<>();
}
}

public static boolean isLightTracingEnabled() {
return lightTracingEnabled;
}

public static boolean isAnyTracingEnabled() {
return traceEnabled || lightTracingEnabled;
}

public static void setNetworkCacheEnabled(boolean enabled) {
networkCacheEnabled = enabled;
}

public static void beginSection(String section) {
if (!traceEnabled) {
if (!isAnyTracingEnabled()) {
return;
}
getTrace().beginSection(section);
}

public static float endSection(String section) {
if (!traceEnabled) {
if (!isAnyTracingEnabled()) {
return 0;
}
return getTrace().endSection(section);
Expand Down
1 change: 1 addition & 0 deletions lottie/src/main/java/com/airbnb/lottie/Lottie.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ public static void initialize(@NonNull final LottieConfig lottieConfig) {
L.setFetcher(lottieConfig.networkFetcher);
L.setCacheProvider(lottieConfig.cacheProvider);
L.setTraceEnabled(lottieConfig.enableSystraceMarkers);
L.setLightTracingEnabled(lottieConfig.enableLightTracing);
L.setNetworkCacheEnabled(lottieConfig.enableNetworkCache);
L.setDisablePathInterpolatorCache(lottieConfig.disablePathInterpolatorCache);
L.setDefaultAsyncUpdates(lottieConfig.defaultAsyncUpdates);
Expand Down
24 changes: 24 additions & 0 deletions lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ public class LottieComposition {
*/
private int maskAndMatteCount = 0;

/**
* The source name of this composition (resource entry name or asset filename).
* Used for trace identification.
*/
@Nullable
private String sourceName;

private int unscaledWidth;
private int unscaledHeight;

Expand Down Expand Up @@ -245,6 +252,23 @@ public int getUnscaledHeight() {
return unscaledHeight;
}

/**
* Set the source name for this composition, used for trace identification.
* This is typically the resource entry name or asset filename.
*/
public void setSourceName(@Nullable String sourceName) {
this.sourceName = sourceName;
}

/**
* Returns the source name of this composition (e.g., the resource entry name or asset filename).
* May be null if the composition was not loaded via a named source.
*/
@Nullable
public String getSourceName() {
return sourceName;
}

@NonNull
@Override
public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,11 @@ public static LottieResult<LottieComposition> fromAssetSync(Context context, Str
return new LottieResult<>(cachedComposition);
}
try {
return fromInputStreamSync(context, context.getAssets().open(fileName), cacheKey);
LottieResult<LottieComposition> result = fromInputStreamSync(context, context.getAssets().open(fileName), cacheKey);
if (result.getValue() != null) {
result.getValue().setSourceName(fileName);
}
return result;
} catch (IOException e) {
return new LottieResult<>(e);
}
Expand Down Expand Up @@ -366,17 +370,27 @@ public static LottieResult<LottieComposition> fromRawResSync(Context context, @R
}
try {
BufferedSource source = Okio.buffer(source(context.getResources().openRawResource(rawRes)));
LottieResult<LottieComposition> result;
if (isZipCompressed(source)) {
return fromZipStreamSync(context, new ZipInputStream(source.inputStream()), cacheKey);
result = fromZipStreamSync(context, new ZipInputStream(source.inputStream()), cacheKey);
} else if (isGzipCompressed(source)) {
try {
return fromJsonInputStreamSync(new GZIPInputStream(source.inputStream()), cacheKey);
result = fromJsonInputStreamSync(new GZIPInputStream(source.inputStream()), cacheKey);
} catch (IOException e) {
// This shouldn't happen because we check the header for magic bytes.
return new LottieResult<>(e);
}
} else {
result = fromJsonReaderSync(JsonReader.of(source), cacheKey);
}
return fromJsonReaderSync(JsonReader.of(source), cacheKey);
if (result.getValue() != null) {
try {
result.getValue().setSourceName(context.getResources().getResourceEntryName(rawRes));
} catch (Resources.NotFoundException e) {
// Ignore — sourceName is best-effort.
}
}
return result;
} catch (Resources.NotFoundException e) {
return new LottieResult<>(e);
}
Expand Down
19 changes: 17 additions & 2 deletions lottie/src/main/java/com/airbnb/lottie/LottieConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@ public class LottieConfig {
@Nullable final LottieNetworkFetcher networkFetcher;
@Nullable final LottieNetworkCacheProvider cacheProvider;
final boolean enableSystraceMarkers;
final boolean enableLightTracing;
final boolean enableNetworkCache;
final boolean disablePathInterpolatorCache;
final AsyncUpdates defaultAsyncUpdates;
final ReducedMotionOption reducedMotionOption;

private LottieConfig(@Nullable LottieNetworkFetcher networkFetcher, @Nullable LottieNetworkCacheProvider cacheProvider,
boolean enableSystraceMarkers, boolean enableNetworkCache, boolean disablePathInterpolatorCache,
boolean enableSystraceMarkers, boolean enableLightTracing, boolean enableNetworkCache, boolean disablePathInterpolatorCache,
AsyncUpdates defaultAsyncUpdates, ReducedMotionOption reducedMotionOption) {
this.networkFetcher = networkFetcher;
this.cacheProvider = cacheProvider;
this.enableSystraceMarkers = enableSystraceMarkers;
this.enableLightTracing = enableLightTracing;
this.enableNetworkCache = enableNetworkCache;
this.disablePathInterpolatorCache = disablePathInterpolatorCache;
this.defaultAsyncUpdates = defaultAsyncUpdates;
Expand All @@ -44,6 +46,7 @@ public static final class Builder {
@Nullable
private LottieNetworkCacheProvider cacheProvider;
private boolean enableSystraceMarkers = false;
private boolean enableLightTracing = false;
private boolean enableNetworkCache = true;
private boolean disablePathInterpolatorCache = false;
private AsyncUpdates defaultAsyncUpdates = AsyncUpdates.AUTOMATIC;
Expand Down Expand Up @@ -113,6 +116,18 @@ public Builder setEnableSystraceMarkers(boolean enable) {
return this;
}

/**
* Enable light tracing.
*
* Unlike {@link #setEnableSystraceMarkers}, this does not trace every layer draw.
* It has near zero performance overhead and is safe to be always enabled in production.
*/
@NonNull
public Builder setEnableLightTracing(boolean enable) {
enableLightTracing = enable;
return this;
}

/**
* Disable this if you want to completely disable internal Lottie cache for retrieving network animations.
* Internal network cache is enabled by default.
Expand Down Expand Up @@ -164,7 +179,7 @@ public Builder setReducedMotionOption(ReducedMotionOption reducedMotionOption) {

@NonNull
public LottieConfig build() {
return new LottieConfig(networkFetcher, cacheProvider, enableSystraceMarkers, enableNetworkCache, disablePathInterpolatorCache,
return new LottieConfig(networkFetcher, cacheProvider, enableSystraceMarkers, enableLightTracing, enableNetworkCache, disablePathInterpolatorCache,
defaultAsyncUpdates, reducedMotionOption);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class LottieValueAnimator extends BaseLottieAnimator implements Choreogra
@Nullable private LottieComposition composition;
@VisibleForTesting protected boolean running = false;
private boolean useCompositionFrameRate = false;
private String cachedTraceName;

public LottieValueAnimator() {
}
Expand Down Expand Up @@ -84,14 +85,31 @@ public void setUseCompositionFrameRate(boolean useCompositionFrameRate) {
this.useCompositionFrameRate = useCompositionFrameRate;
}

private String getDoFrameTraceName() {
if (cachedTraceName != null) return cachedTraceName;
if (composition != null && composition.getSourceName() != null) {
cachedTraceName = "LottieValueAnimator#doFrame[" + composition.getSourceName() + "]";
}
return cachedTraceName != null ? cachedTraceName : "LottieValueAnimator#doFrame";
}

private String getPlayAnimationTraceSectionName() {
String src = (composition != null && composition.getSourceName() != null)
? composition.getSourceName() : "unknown";
return "LottiePlayAnimation[" + src + "]";
}

@Override public void doFrame(long frameTimeNanos) {
postFrameCallback();
if (composition == null || !isRunning()) {
return;
}

if (L.isTraceEnabled()) {
L.beginSection("LottieValueAnimator#doFrame");
boolean isTracing = L.isAnyTracingEnabled();
String traceSectionName = null;
if (isTracing) {
traceSectionName = getDoFrameTraceName();
L.beginSection(traceSectionName);
}
long timeSinceFrame = lastFrameTimeNs == 0 ? 0 : frameTimeNanos - lastFrameTimeNs;
float frameDuration = getFrameDurationNs();
Expand Down Expand Up @@ -130,8 +148,8 @@ public void setUseCompositionFrameRate(boolean useCompositionFrameRate) {
}

verifyFrame();
if (L.isTraceEnabled()) {
L.endSection("LottieValueAnimator#doFrame");
if (isTracing) {
L.endSection(traceSectionName);
}
}

Expand All @@ -152,12 +170,14 @@ public void clearComposition() {
this.composition = null;
minFrame = Integer.MIN_VALUE;
maxFrame = Integer.MAX_VALUE;
cachedTraceName = null;
}

public void setComposition(LottieComposition composition) {
// Because the initial composition is loaded async, the first min/max frame may be set
boolean keepMinAndMaxFrames = this.composition == null;
this.composition = composition;
cachedTraceName = null;

if (keepMinAndMaxFrames) {
setMinAndMaxFrames(
Expand Down Expand Up @@ -232,12 +252,21 @@ public float getSpeed() {

@MainThread
public void playAnimation() {
boolean isTracing = L.isAnyTracingEnabled();
String traceSectionName = null;
if (isTracing) {
traceSectionName = getPlayAnimationTraceSectionName();
L.beginSection(traceSectionName);
}
running = true;
notifyStart(isReversed());
setFrame((int) (isReversed() ? getMaxFrame() : getMinFrame()));
lastFrameTimeNs = 0;
repeatCount = 0;
postFrameCallback();
if (isTracing) {
L.endSection(traceSectionName);
}
}

@MainThread
Expand Down