Merge remote-tracking branch 'origin/master' into gpeal/time-remap-callback
diff --git a/.travis.yml b/.travis.yml
index 34b2930..675e173 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,8 +19,8 @@
   - tools
   - platform-tools
   - tools
-  - build-tools-28.0.2
-  - android-28
+  - build-tools-28.0.3
+  - android-29
   - extra-android-m2repository
 jdk:
 - oraclejdk8
diff --git a/LottieSample/build.gradle b/LottieSample/build.gradle
index a2f7d91..f797e29 100644
--- a/LottieSample/build.gradle
+++ b/LottieSample/build.gradle
@@ -7,11 +7,11 @@
 }
 
 android {
-  compileSdkVersion 28
+  compileSdkVersion 29
   defaultConfig {
     applicationId "com.airbnb.lottie"
     minSdkVersion 16
-    targetSdkVersion 28
+    targetSdkVersion 29
     versionCode 67
     versionName VERSION_NAME
     multiDexEnabled true
@@ -41,8 +41,11 @@
     baseline file("lint-baseline.xml")
   }
   compileOptions {
-    sourceCompatibility JavaVersion.VERSION_1_7
-    targetCompatibility JavaVersion.VERSION_1_7
+    sourceCompatibility JavaVersion.VERSION_1_8
+    targetCompatibility JavaVersion.VERSION_1_8
+  }
+  kotlinOptions {
+    jvmTarget = "1.8"
   }
   sourceSets {
     main.java.srcDirs += 'src/main/kotlin'
@@ -57,30 +60,27 @@
 
 dependencies {
   implementation project(':lottie')
-  implementation "androidx.fragment:fragment:1.1.0-alpha09"
-  implementation("androidx.appcompat:appcompat:1.1.0-alpha05") {
-    exclude group: 'androidx.fragment'
-  }
-  implementation "androidx.recyclerview:recyclerview:1.0.0"
-  implementation "com.google.android.material:material:1.0.0"
-  implementation "androidx.cardview:cardview:1.0.0"
-  implementation 'androidx.core:core:1.2.0-alpha01'
-  implementation 'androidx.core:core-ktx:1.1.0-beta01'
-  implementation "androidx.browser:browser:1.0.0"
   implementation 'androidx.multidex:multidex:2.0.1'
+
+  implementation "androidx.fragment:fragment:1.2.0-rc04"
+  implementation("androidx.appcompat:appcompat:1.1.0")
+  implementation "androidx.recyclerview:recyclerview:1.0.0"
+  implementation "androidx.cardview:cardview:1.0.0"
+  implementation 'androidx.core:core-ktx:1.2.0-rc01'
+  implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
+  implementation "androidx.browser:browser:1.0.0"
   implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0-beta01'
   kapt "androidx.lifecycle:lifecycle-common-java8:2.1.0-beta01"
+  implementation "com.google.android.material:material:1.0.0"
+
   implementation 'com.airbnb.android:epoxy:2.17.0'
   kapt 'com.airbnb.android:epoxy-processor:2.17.0'
   implementation 'com.airbnb.android:mvrx:0.5.0'
-  implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1'
   implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
   implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
   implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
   implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.0'
   implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
-  implementation 'com.jakewharton:butterknife:9.0.0-rc1'
-  kapt 'com.jakewharton:butterknife-compiler:9.0.0-rc1'
   implementation 'com.matthew-tamlin:sliding-intro-screen:3.2.0'
   implementation 'com.dlazaro66.qrcodereaderview:qrcodereaderview:2.0.2'
   implementation 'com.github.PhilJay:MPAndroidChart:v3.0.2'
@@ -96,18 +96,15 @@
   implementation 'io.reactivex.rxjava2:rxjava:2.2.1'
   implementation 'com.github.bumptech.glide:glide:4.8.0'
 
-  debugImplementation("androidx.fragment:fragment-testing:1.1.0-alpha09") {
-    exclude group: 'androidx.test'
-  }
+  debugImplementation("androidx.fragment:fragment-testing:1.2.0-rc04")
 
   testImplementation 'junit:junit:4.12'
 
   androidTestImplementation 'androidx.test:core:1.2.0'
-  androidTestImplementation "org.robolectric:robolectric:4.0-alpha-3"
   androidTestImplementation 'androidx.test.ext:junit:1.1.0'
   androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
   androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.1.0-alpha4'
-  androidTestImplementation "androidx.fragment:fragment-testing:1.1.0-alpha09"
+  androidTestImplementation "androidx.fragment:fragment-testing:1.2.0-rc04"
   androidTestImplementation 'androidx.test:rules:1.2.0'
   androidTestImplementation 'io.reactivex.rxjava2:rxjava:2.2.1'
   androidTestImplementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/BitmapPool.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/BitmapPool.kt
index 9cff898..e2244d1 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/BitmapPool.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/BitmapPool.kt
@@ -27,13 +27,11 @@
             return TRANSPARENT_1X1_BITMAP
         }
 
-        var blockedStartTime = 0L
-        if (semaphore.isFull()) {
-            blockedStartTime = System.currentTimeMillis()
-        }
+        var blockedStartTime = System.currentTimeMillis()
         semaphore.acquire()
-        if (blockedStartTime > 0) {
-            Log.d(L.TAG, "Waited ${System.currentTimeMillis() - blockedStartTime}ms for a bitmap.")
+        val waitingTimeMs = System.currentTimeMillis() - blockedStartTime
+        if (waitingTimeMs > 100) {
+            Log.d(L.TAG, "Waited ${waitingTimeMs}ms for a bitmap.")
         }
 
         val bitmap = synchronized(bitmaps) {
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.java b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.java
deleted file mode 100644
index cb3a831..0000000
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.java
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.airbnb.lottie.samples;
-
-import android.app.Activity;
-import android.view.LayoutInflater;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.robolectric.Robolectric;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.annotation.Config;
-
-@RunWith(RobolectricTestRunner.class)
-@Config
-@Ignore
-public class LottieAnimationViewTest {
-
-  private Activity activity;
-
-  @Before
-  public void setup(){
-    activity = Robolectric.buildActivity(Activity.class).create().get();
-  }
-
-  @Test
-  public void inflateShouldNotCrash() {
-    LayoutInflater.from(activity).inflate(R.layout.lottie_activity_main, null);
-  }
-}
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.kt
new file mode 100644
index 0000000..976bc4a
--- /dev/null
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/LottieAnimationViewTest.kt
@@ -0,0 +1,24 @@
+package com.airbnb.lottie.samples
+
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.testing.launchFragmentInContainer
+import androidx.test.espresso.Espresso.onView
+import androidx.test.espresso.assertion.ViewAssertions.matches
+import androidx.test.espresso.matcher.ViewMatchers
+import androidx.test.espresso.matcher.ViewMatchers.isDisplayed
+import androidx.test.espresso.matcher.ViewMatchers.withId
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class LottieAnimationViewTest {
+    @Test
+    fun inflateShouldNotCrash() {
+        class TestFragment : Fragment(R.layout.lottie_activity_main)
+        launchFragmentInContainer<TestFragment>()
+        onView(withId(R.id.animation_view)).check(matches(isDisplayed()))
+    }
+}
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/ObjectPool.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/ObjectPool.kt
index bc61143..79d1c63 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/ObjectPool.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/ObjectPool.kt
@@ -14,13 +14,11 @@
 
     @ExperimentalCoroutinesApi
     fun acquire(): T {
-        var blockedStartTime = 0L
-        if (semaphore.isFull()) {
-            blockedStartTime = System.currentTimeMillis()
-        }
+        var blockedStartTime = System.currentTimeMillis()
         semaphore.acquire()
-        if (blockedStartTime > 0) {
-            Log.d(L.TAG, "Waited ${System.currentTimeMillis() - blockedStartTime}ms for an object.")
+        val waitingTimeMs = System.currentTimeMillis() - blockedStartTime
+        if (waitingTimeMs > 100) {
+            Log.d(L.TAG, "Waited ${waitingTimeMs}ms for an object.")
         }
 
         val obj = synchronized(objects) {
diff --git a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/SuspendingSemaphore.kt b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/SuspendingSemaphore.kt
index ed8b870..6826ea9 100644
--- a/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/SuspendingSemaphore.kt
+++ b/LottieSample/src/androidTest/java/com/airbnb/lottie/samples/SuspendingSemaphore.kt
@@ -29,7 +29,4 @@
             bufferedChannel.receive()
         }
     }
-
-    @ExperimentalCoroutinesApi
-    fun isFull() = bufferedChannel.isFull
 }
\ No newline at end of file
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FilmStripSnapshotActivity.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FilmStripSnapshotActivity.kt
index 77e0408..6157758 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FilmStripSnapshotActivity.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FilmStripSnapshotActivity.kt
@@ -24,6 +24,8 @@
 
 class FilmStripSnapshotActivity : AppCompatActivity() {
 
+    // TODO: fix this.
+    @Suppress("DEPRECATION")
     private val rootDir = "${Environment.getExternalStorageDirectory()}/lottie"
     private val animationsDir = File("$rootDir/animations")
     private val snapshotsDir = File("$rootDir/snapshots")
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FontFragment.java b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FontFragment.java
deleted file mode 100644
index c01e666..0000000
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/FontFragment.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.airbnb.lottie.samples;
-
-import android.os.Bundle;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.airbnb.lottie.LottieAnimationView;
-import com.airbnb.lottie.TextDelegate;
-
-import butterknife.BindView;
-import butterknife.ButterKnife;
-import butterknife.OnTextChanged;
-
-public class FontFragment extends Fragment {
-
-  public static FontFragment newInstance() {
-      return new FontFragment();
-  }
-
-  @BindView(R.id.dynamic_text) LottieAnimationView nameAnimationView;
-
-  private TextDelegate textDelegate;
-
-  @Nullable @Override
-  public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
-      @Nullable Bundle savedInstanceState) {
-    View view = inflater.inflate(R.layout.fragment_font, container, false);
-    ButterKnife.bind(this, view);
-
-    textDelegate = new TextDelegate(nameAnimationView);
-    nameAnimationView.setTextDelegate(textDelegate);
-
-    return view;
-  }
-
-  @OnTextChanged(R.id.name_edit_text) void onNameChanged(CharSequence name) {
-    textDelegate.setText("NAME", name.toString());
-  }
-}
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
index 57018fb..dcd63ed 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerFragment.kt
@@ -105,8 +105,6 @@
         (requireActivity() as AppCompatActivity).supportActionBar?.setDisplayShowTitleEnabled(false)
         setHasOptionsMenu(true)
 
-        L.setTraceEnabled(true)
-
         lottieVersionView.text = getString(R.string.lottie_version, com.airbnb.lottie.BuildConfig.VERSION_NAME)
 
         animationView.setFontAssetDelegate(object : FontAssetDelegate() {
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
index 46e414e..7b6b6bc 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PlayerViewModel.kt
@@ -43,7 +43,7 @@
             url != null -> LottieCompositionFactory.fromUrl(application, url, null)
             args.fileUri != null -> taskForUri(args.fileUri)
             args.asset != null -> LottieCompositionFactory.fromAsset(application, args.asset, null)
-            else -> throw IllegalArgumentException("Don't know how to fetch animation for $args")
+            else -> error("Don't know how to fetch animation for $args")
         }
                 .addListener {
                     setState {
@@ -54,14 +54,10 @@
     }
 
     private fun taskForUri(uri: Uri): LottieTask<LottieComposition> {
-        val fis = try {
-            when (uri.scheme) {
-                "file" -> FileInputStream(uri.path)
-                "content" -> application.contentResolver.openInputStream(uri)
-                else -> return LottieTask() { throw IllegalArgumentException("Unknown scheme ${uri.scheme}") }
-            }
-        } catch (e: FileNotFoundException) {
-            return LottieTask { throw e }
+        val fis = when (uri.scheme) {
+            "file" -> FileInputStream(uri.path ?: error("File has no path!"))
+            "content" -> application.contentResolver.openInputStream(uri)
+            else -> error("Unknown scheme ${uri.scheme}")
         }
 
         return LottieCompositionFactory.fromJsonInputStream(fis, null)
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PreviewFragment.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PreviewFragment.kt
index 89011c6..47961ca 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PreviewFragment.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/PreviewFragment.kt
@@ -84,9 +84,9 @@
             icon(R.drawable.ic_storage)
             clickListener { _ ->
                 val adapter = ArrayAdapter<String>(requireContext(), android.R.layout.select_dialog_item)
-                requireContext().assets.list("").asSequence()
-                        .filter { it.endsWith(".json") || it.endsWith(".zip") }
-                        .forEach { adapter.add(it) }
+                requireContext().assets.list("")?.asSequence()
+                        ?.filter { it.endsWith(".json") || it.endsWith(".zip") }
+                        ?.forEach { adapter.add(it) }
                 AlertDialog.Builder(context)
                         .setAdapter(adapter) { _, which ->
                             val args = CompositionArgs(asset = adapter.getItem(which))
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SimpleAnimationActivity.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SimpleAnimationActivity.kt
index 5404a52..047dbaf 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SimpleAnimationActivity.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/SimpleAnimationActivity.kt
@@ -23,9 +23,8 @@
         var composition: LottieComposition? = null
         parse.setOnClickListener {
             val assetName = intent.extras?.getString("animation") ?: ""
-            LottieCompositionCache.getInstance().clear()
             val start = System.currentTimeMillis()
-            composition = LottieCompositionFactory.fromAssetSync(this, assetName).value
+            composition = LottieCompositionFactory.fromAssetSync(this, assetName, null).value
                     ?: throw IllegalArgumentException("Invalid composition $assetName")
             Toast.makeText(this@SimpleAnimationActivity, "Done ${System.currentTimeMillis() - start}", Toast.LENGTH_SHORT).show()
         }
diff --git a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/SectionHeaderView.kt b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/SectionHeaderView.kt
index 66aa8eb..47a4806 100644
--- a/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/SectionHeaderView.kt
+++ b/LottieSample/src/main/kotlin/com/airbnb/lottie/samples/views/SectionHeaderView.kt
@@ -28,7 +28,7 @@
     }
 
     @ModelProp(options = [ModelProp.Option.DoNotHash])
-    override fun setOnClickListener(listener: View.OnClickListener) {
+    override fun setOnClickListener(listener: OnClickListener?) {
         super.setOnClickListener(listener)
     }
 }
\ No newline at end of file
diff --git a/LottieSample/src/main/res/layout/item_view_animation.xml b/LottieSample/src/main/res/layout/item_view_animation.xml
index 73f129c..9231cb0 100644
--- a/LottieSample/src/main/res/layout/item_view_animation.xml
+++ b/LottieSample/src/main/res/layout/item_view_animation.xml
@@ -1,18 +1,21 @@
 <?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                                                   xmlns:app="http://schemas.android.com/apk/res-auto"
-                                                   xmlns:tools="http://schemas.android.com/tools"
-                                                   android:layout_marginLeft="24dp"
-                                                   android:layout_marginRight="24dp"
-                                                   android:layout_width="match_parent"
-                                                   android:layout_height="wrap_content">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginLeft="24dp"
+    android:layout_marginRight="24dp">
 
     <ImageView
         android:id="@+id/animationView"
         android:layout_width="match_parent"
-        android:layout_height="0dp"
         android:background="@drawable/list_item_animation_background"
-        app:layout_constraintDimensionRatio="1"/>
+        app:layout_constraintBottom_toTopOf="@id/titleView"
+        app:layout_constraintDimensionRatio="1"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
     <TextView
         android:id="@+id/titleView"
@@ -24,7 +27,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/animationView"
-        tools:text="Loading Animation 1"/>
+        tools:text="Loading Animation 1" />
 
     <TextView
         android:id="@+id/authorView"
@@ -38,7 +41,7 @@
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="@+id/titleView"
         app:layout_constraintTop_toBottomOf="@+id/titleView"
-        tools:text="Gabriel Peal"/>
+        tools:text="Gabriel Peal" />
 
     <View
         android:id="@+id/clickOverlay"
@@ -48,7 +51,7 @@
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="@+id/animationView"/>
+        app:layout_constraintTop_toTopOf="@+id/animationView" />
 
 
 </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/LottieSample/src/main/res/layout/lottie_activity_main.xml b/LottieSample/src/main/res/layout/lottie_activity_main.xml
index dc12301..cb974f2 100644
--- a/LottieSample/src/main/res/layout/lottie_activity_main.xml
+++ b/LottieSample/src/main/res/layout/lottie_activity_main.xml
@@ -5,8 +5,9 @@
     android:layout_height="match_parent">
 
     <com.airbnb.lottie.LottieAnimationView
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
+        android:id="@+id/animation_view"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
         android:layout_gravity="center"
         android:scaleType="fitCenter"
         app:lottie_autoPlay="true"
diff --git a/build.gradle b/build.gradle
index 671c556..38fcd03 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,7 +1,7 @@
 import org.ajoberstar.grgit.Grgit
 
 buildscript {
-  ext.kotlinVersion = '1.3.31'
+  ext.kotlinVersion = '1.3.41'
 
   repositories {
     jcenter()
@@ -12,7 +12,7 @@
   }
   dependencies {
     classpath 'org.ajoberstar:grgit:1.9.3'
-    classpath 'com.android.tools.build:gradle:3.2.0'
+    classpath 'com.android.tools.build:gradle:3.5.3'
     classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
     classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlinVersion"
     classpath 'org.ajoberstar:grgit:1.9.3'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 4caf1df..feee4a3 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip
diff --git a/issue-repro/build.gradle b/issue-repro/build.gradle
index 89edceb..d2f9e21 100755
--- a/issue-repro/build.gradle
+++ b/issue-repro/build.gradle
@@ -3,11 +3,11 @@
 apply plugin: 'kotlin-android-extensions'
 
 android {
-    compileSdkVersion 28
+    compileSdkVersion 29
     defaultConfig {
         applicationId "com.airbnb.lottie.issues"
         minSdkVersion 16
-        targetSdkVersion 28
+        targetSdkVersion 29
         versionCode 1
         versionName "1.0"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/lottie/build.gradle b/lottie/build.gradle
index d97eef3..95b4754 100644
--- a/lottie/build.gradle
+++ b/lottie/build.gradle
@@ -5,12 +5,12 @@
 apply plugin: 'net.ltgt.errorprone'
 
 android {
-  compileSdkVersion 28
+  compileSdkVersion 29
   resourcePrefix 'lottie_'
 
   defaultConfig {
     minSdkVersion 16
-    targetSdkVersion 28
+    targetSdkVersion 29
   }
   lintOptions {
     abortOnError true
@@ -32,7 +32,7 @@
   implementation "androidx.appcompat:appcompat:1.0.0"
   testImplementation "org.mockito:mockito-core:2.15.0"
   testImplementation 'junit:junit:4.12'
-  testImplementation "org.robolectric:robolectric:4.0-alpha-3"
+  testImplementation "org.robolectric:robolectric:4.3.1"
   // Do not ugprade to 2.0 because it will bring in Kotlin as a transitive dependency.
   implementation("com.squareup.okio:okio:1.17.4")
   annotationProcessor "com.uber.nullaway:nullaway:0.7.5"
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
index b974506..1b65d31 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieComposition.java
@@ -141,12 +141,12 @@
     return (long) (getDurationFrames() / frameRate * 1000);
   }
 
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
+  @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
   public float getStartFrame() {
     return startFrame;
   }
 
-  @RestrictTo(RestrictTo.Scope.LIBRARY)
+  @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
   public float getEndFrame() {
     return endFrame;
   }
diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
index d77b550..aac65d1 100644
--- a/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
+++ b/lottie/src/main/java/com/airbnb/lottie/LottieProperty.java
@@ -103,7 +103,7 @@
   /** [0,100] */
   Float TRANSFORM_START_OPACITY = 12f;
   /** [0,100] */
-  Float TRANSFORM_END_OPACITY = 12f;
+  Float TRANSFORM_END_OPACITY = 12.1f;
   /** The time value in seconds */
   Float TIME_REMAP = 13f;
   /** In Dp */
diff --git a/lottie/src/test/java/com/airbnb/lottie/BaseTest.java b/lottie/src/test/java/com/airbnb/lottie/BaseTest.java
index 33ec1eb..a672a0d 100644
--- a/lottie/src/test/java/com/airbnb/lottie/BaseTest.java
+++ b/lottie/src/test/java/com/airbnb/lottie/BaseTest.java
@@ -1,12 +1,14 @@
 package com.airbnb.lottie;
 
+import android.os.Build;
+
 import org.junit.Ignore;
 import org.junit.runner.RunWith;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.annotation.Config;
 
 @RunWith(RobolectricTestRunner.class)
-@Config
+@Config(sdk = Build.VERSION_CODES.P)
 @Ignore
 public class BaseTest {
 }