Fixed
Status Update
Comments
ad...@google.com <ad...@google.com>
se...@google.com <se...@google.com> #2
I've double checked that our proguard rules haven't changed since 2.1.0. Ian, do you have any ideas? Going investigate it further.
ja...@jackcheung.com <ja...@jackcheung.com> #3
I don't believe it has to do with proguard, since the same release apk works on Android 9 or below.
Further test indicated that the bug is reproducible on all Android 10 devices, including AVD emulator.
Also, it looks like the bug can be first seen on `androidx.lifecycle:lifecycle-runtime:2.2.0-alpha05`. `2.2.0-alpha04` and earlier work fine.
Further test indicated that the bug is reproducible on all Android 10 devices, including AVD emulator.
Also, it looks like the bug can be first seen on `androidx.lifecycle:lifecycle-runtime:2.2.0-alpha05`. `2.2.0-alpha04` and earlier work fine.
se...@google.com <se...@google.com> #4
It looks if I change targetSdk in your build gradle to 29, everything starts to work. Looks like R8 "optimize the code" by removing this
if check:
https://android.googlesource.com/platform/frameworks/support.git/+/refs/heads/androidx-master-dev/lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/ReportFragment.java#41
if check:
se...@google.com <se...@google.com> #5
Disregard previous comment please it is wrong
se...@google.com <se...@google.com> #6
Ok it is r8 but it is in more complicated manner, methods on ActivityLifecycleCall interface that were added in 29 are removed when you compile with 28.
ch...@google.com <ch...@google.com> #7
That is expected behavior. If these methods are not used by the application itself, then the only reason for R8 to keep them is if they override methods in the library/framework. Therefore, if you are building with an android.jar where these methods are not available, then they will simply be removed by tree shaking.
If these methods should be retained even when compiling against older versions of android.jar, then a keep rule is needed, such as `-keepclassmembers class * implements android.app.Application$ActivityLifecycleCallbacks { void onActivityPostCreated(...); }`.
If these methods should be retained even when compiling against older versions of android.jar, then a keep rule is needed, such as `-keepclassmembers class * implements android.app.Application$ActivityLifecycleCallbacks { void onActivityPostCreated(...); }`.
se...@google.com <se...@google.com> #8
Soren, can you please take a look?
Basically what happens:
1. there is library compiled against android 29.
2. Library implements interface (ActivityLifecycleCallbacks), in which new default methods were added on version 29 (onActivityPostCreated/ onActivityPostStarted etc)
3. an app compiles against android 28 with minification on
4. methods that don't exist on android 28 are removed from ours implementation of ActivityLifecycleCallbacks
5. run an app on android-29 => app is broken because our codepath check it device runs on 29 and try to rely on new codepath, but this code won't work because it needs removed methods.
Basically what happens:
1. there is library compiled against android 29.
2. Library implements interface (ActivityLifecycleCallbacks), in which new default methods were added on version 29 (onActivityPostCreated/ onActivityPostStarted etc)
3. an app compiles against android 28 with minification on
4. methods that don't exist on android 28 are removed from ours implementation of ActivityLifecycleCallbacks
5. run an app on android-29 => app is broken because our codepath check it device runs on 29 and try to rely on new codepath, but this code won't work because it needs removed methods.
se...@google.com <se...@google.com> #9
I'm not really sure that it is expected behavior, because it is impossible for us as library developers to guess that this will happen.
al...@google.com <al...@google.com> #10
This seems like obviously broken "expected" behavior that will affect existing libraries.
We will eventually address this with Gradle metadata indicating a required minimum compileSdkVersion, but that's likely a year out and won't help developers until they update to a newer Studio / AGP version. It also won't help library developers who aren't Google.
Edit: I'll acknowledge that this is _technically_ correct and in the absence of a SDK 29 android.jar the methods are indistinguishable from methods that can be safely pruned; however, we need a better solution here than "add one-off keep rules." Every overridden "new SDK" method should be kept by default.
We will eventually address this with Gradle metadata indicating a required minimum compileSdkVersion, but that's likely a year out and won't help developers until they update to a newer Studio / AGP version. It also won't help library developers who aren't Google.
Edit: I'll acknowledge that this is _technically_ correct and in the absence of a SDK 29 android.jar the methods are indistinguishable from methods that can be safely pruned; however, we need a better solution here than "add one-off keep rules." Every overridden "new SDK" method should be kept by default.
ch...@google.com <ch...@google.com> #11
I am not arguing that this behavior is intended or easy to understand for developers. It is expected from a compilation point of view, though, since the compiler is not given the right inputs and therefore cannot know that methods such as ActivityLifecycleCallbacks.onActivityPostCreated() are any different from MyActivity.entirelyUnusedMethod().
I can think of a few different ways to address this issue until a minimum compileSdkVersion is required.
1) Developers use `compileSdkVersion 29` if their app uses any APIs that are not present in SDK 28. Unfortunately, it is not easy for developers to know that a given library uses APIs that are only available in SDK 29.
2) Library developers add a `-keepclassmembers` rule for the APIs that they use that are only present in SDK 29. This way the implementation of these APIs will not be considered dead even when developers that depend on the library use `compileSdkVersion 28`. The advantage of this is that developers do not need to upgrade to a newer AGP version, only a newer version of the library. The disadvantage is that this only solves the problem for a single library. That may or may not be a problem depending on the number of libraries that actually overrides APIs that are only available in SDK 29. As with (1), it is not easy for library developers to know that they need to add these rules.
3) We add special handling for the APIs that are only available in SDK 29 in AGP/R8 (or the APIs in SDK i+1 that are not in SDK i). There are many ways to do this, but all of them require developers to upgrade to a newer AGP version. One way would be to auto-generate a `-keepclassmembers` rule for each of the (visible, virtual) methods from SDK 29 that are not available in SDK 28. These rules could then be included by AGP, or added to, for example,https://android.googlesource.com/platform/sdk/+/master/files/proguard-android.txt and https://android.googlesource.com/platform/sdk/+/master/files/proguard-android-optimize.txt . One disadvantage is that this only solves the problem up to SDK 29, since we don't know what newer SDKs look like.
4) Note that (3) is largely equivalent to having AGP pass the union of android-28.jar and android-29.jar to R8 instead of android-28.jar. For this reason, it might also be interesting to look into the possibility of having AGP pass the union of all android-x.jar files to R8, instead of the SDK specified in `compileSdkVersion`. This would solve the issue for all APIs that are available in SDK i+1 but not SDK i. For this to work with SDKs that are not available at a given AGP version, AGP would need a mechanism for fetching more recent android-x.jar files, such that it can build the union of android-1.jar to android-x.jar, x > 29, when android-x.jar becomes available. Otherwise developers would have to upgrade to a newer AGP version if they use a library that depends on APIs in an SDK that was not available by the time of the AGP version (which may also be acceptable).
A concern is that both (3) and (4) require developers to upgrade to a newer AGP version and they solve a problem that will be solved when a minimum compileSdkVersion will be required.
I can think of a few different ways to address this issue until a minimum compileSdkVersion is required.
1) Developers use `compileSdkVersion 29` if their app uses any APIs that are not present in SDK 28. Unfortunately, it is not easy for developers to know that a given library uses APIs that are only available in SDK 29.
2) Library developers add a `-keepclassmembers` rule for the APIs that they use that are only present in SDK 29. This way the implementation of these APIs will not be considered dead even when developers that depend on the library use `compileSdkVersion 28`. The advantage of this is that developers do not need to upgrade to a newer AGP version, only a newer version of the library. The disadvantage is that this only solves the problem for a single library. That may or may not be a problem depending on the number of libraries that actually overrides APIs that are only available in SDK 29. As with (1), it is not easy for library developers to know that they need to add these rules.
3) We add special handling for the APIs that are only available in SDK 29 in AGP/R8 (or the APIs in SDK i+1 that are not in SDK i). There are many ways to do this, but all of them require developers to upgrade to a newer AGP version. One way would be to auto-generate a `-keepclassmembers` rule for each of the (visible, virtual) methods from SDK 29 that are not available in SDK 28. These rules could then be included by AGP, or added to, for example,
4) Note that (3) is largely equivalent to having AGP pass the union of android-28.jar and android-29.jar to R8 instead of android-28.jar. For this reason, it might also be interesting to look into the possibility of having AGP pass the union of all android-x.jar files to R8, instead of the SDK specified in `compileSdkVersion`. This would solve the issue for all APIs that are available in SDK i+1 but not SDK i. For this to work with SDKs that are not available at a given AGP version, AGP would need a mechanism for fetching more recent android-x.jar files, such that it can build the union of android-1.jar to android-x.jar, x > 29, when android-x.jar becomes available. Otherwise developers would have to upgrade to a newer AGP version if they use a library that depends on APIs in an SDK that was not available by the time of the AGP version (which may also be acceptable).
A concern is that both (3) and (4) require developers to upgrade to a newer AGP version and they solve a problem that will be solved when a minimum compileSdkVersion will be required.
ap...@google.com <ap...@google.com> #12
Project: platform/frameworks/support
Branch: androidx-master-dev
commit 714063ab71dff7b514b9c5f6489190c9d4fffda9
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Mon Oct 21 11:32:58 2019
Fix lifecycle-runtime for compileSdkVersion 28 + minification
bug: 142778206
Test: manually ran a testcase from b/142778206
Change-Id: I81b47999effbd1e099a8876b9133db4f8a0d899b
M lifecycle/lifecycle-process/build.gradle
A lifecycle/lifecycle-process/proguard-rules.pro
M lifecycle/lifecycle-runtime/proguard-rules.pro
M lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/ReportFragment.java
https://android-review.googlesource.com/1147717
https://goto.google.com/android-sha1/714063ab71dff7b514b9c5f6489190c9d4fffda9
Branch: androidx-master-dev
commit 714063ab71dff7b514b9c5f6489190c9d4fffda9
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Mon Oct 21 11:32:58 2019
Fix lifecycle-runtime for compileSdkVersion 28 + minification
bug: 142778206
Test: manually ran a testcase from
Change-Id: I81b47999effbd1e099a8876b9133db4f8a0d899b
M lifecycle/lifecycle-process/build.gradle
A lifecycle/lifecycle-process/proguard-rules.pro
M lifecycle/lifecycle-runtime/proguard-rules.pro
M lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/ReportFragment.java
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-lifecycle-release
commit 46fef0f000d93c584c46f2a5f764475d3df4824e
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Mon Oct 21 11:32:58 2019
Fix lifecycle-runtime for compileSdkVersion 28 + minification
bug: 142778206
Test: manually ran a testcase from b/142778206
Change-Id: I81b47999effbd1e099a8876b9133db4f8a0d899b
(cherry picked from commit 714063ab71dff7b514b9c5f6489190c9d4fffda9)
M buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
A lifecycle/lifecycle-common-java8/api/2.2.0-rc02.txt
A lifecycle/lifecycle-common-java8/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-common-java8/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/restricted_2.2.0-rc02.txt
M lifecycle/lifecycle-process/build.gradle
A lifecycle/lifecycle-process/proguard-rules.pro
A lifecycle/lifecycle-reactivestreams-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/restricted_2.2.0-rc02.txt
M lifecycle/lifecycle-runtime/proguard-rules.pro
M lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/ReportFragment.java
A lifecycle/lifecycle-service/api/2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/restricted_2.2.0-rc02.txt
https://android-review.googlesource.com/1151593
https://goto.google.com/android-sha1/46fef0f000d93c584c46f2a5f764475d3df4824e
Branch: androidx-lifecycle-release
commit 46fef0f000d93c584c46f2a5f764475d3df4824e
Author: Sergey Vasilinets <sergeyv@google.com>
Date: Mon Oct 21 11:32:58 2019
Fix lifecycle-runtime for compileSdkVersion 28 + minification
bug: 142778206
Test: manually ran a testcase from
Change-Id: I81b47999effbd1e099a8876b9133db4f8a0d899b
(cherry picked from commit 714063ab71dff7b514b9c5f6489190c9d4fffda9)
M buildSrc/src/main/kotlin/androidx/build/LibraryVersions.kt
A lifecycle/lifecycle-common-java8/api/2.2.0-rc02.txt
A lifecycle/lifecycle-common-java8/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-common-java8/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-common/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-extensions/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-core/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-livedata/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-process/api/restricted_2.2.0-rc02.txt
M lifecycle/lifecycle-process/build.gradle
A lifecycle/lifecycle-process/proguard-rules.pro
A lifecycle/lifecycle-reactivestreams-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-reactivestreams/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-runtime-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-runtime/api/restricted_2.2.0-rc02.txt
M lifecycle/lifecycle-runtime/proguard-rules.pro
M lifecycle/lifecycle-runtime/src/main/java/androidx/lifecycle/ReportFragment.java
A lifecycle/lifecycle-service/api/2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-service/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel-ktx/api/restricted_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/public_plus_experimental_2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/res-2.2.0-rc02.txt
A lifecycle/lifecycle-viewmodel/api/restricted_2.2.0-rc02.txt
an...@google.com <an...@google.com> #14
d4...@gmail.com <d4...@gmail.com> #15
The proguard rule for the `ReportFragment` suggested in one of the above commits didn't work for me, I had to use
-keepclassmembers class androidx.lifecycle.ReportFragment$** { *; }
https://stackoverflow.com/questions/58671715
-keepclassmembers class androidx.lifecycle.ReportFragment$** { *; }
ag...@google.com <ag...@google.com> #16
Sergey, doing bug cleanup, is this fixed on your end?
se...@google.com <se...@google.com> #17
Yep, it is fixed on our end
Description
Version used: Android 10
Theme used: Theme.AppCompat.Light.DarkActionBar
Devices/Android versions reproduced on:
## Details
App is stuck on `INITIALIZED` state, even the activity has already finished `onResume()` method call
## Steps to Reproduce
- Build a signed production release `apk` with proguard `minifyEnabled true` (default)
- Install on `Pixel 3a` running `Android 10`
- Tap `UPDATE STATUS` button to examine the retrieved current state
- Note that the expected word shall be `RESUMED`, as is on other devices (even on Android 10 emulator) except `Pixel 3a / Android 10`
## Notes
- `'androidx.lifecycle:lifecycle-runtime:2.1.0'` doesn't have the issue
- disable or removed `proguard` works
- code demonstrating the issue can be checked out here:
-