Assigned
Status Update
Comments
da...@gmail.com <da...@gmail.com> #2
Yigit, do you have time to fix it?
reemission of the same liveData is racy
reemission of the same liveData is racy
pm...@google.com <pm...@google.com> #3
yea i'll take it.
ra...@google.com <ra...@google.com> #4
Thanks for the detailed analysis. This may not be an issue anymore since we've started using Main.immediate there but I' not sure; I'll try to create a test case.
ap...@google.com <ap...@google.com> #5
just emitting same live data reproduces the issue.
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
@Test
fun raceTest() {
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData)
emitSource(subLiveData) //crashes
}
subject.addObserver().apply {
testScope.advanceUntilIdle()
}
}
an...@google.com <an...@google.com> #6
With 2.2.0-alpha04 (that use Main.immediate), the issue seems to be still there (I tested it by calling emitSource() twice, like your test case)
mu...@gmail.com <mu...@gmail.com> #7
yea sorry immediate does not fix it.
I actually have a WIP fix for it:
https://android-review.googlesource.com/c/platform/frameworks/support/+/1112186
if your case is the one i found (emitting same LiveData multiple times, as shown in #5) you can work around it by adding a dummy transformation.
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData.map {it })
emitSource(subLiveData.map {it} )
}
I actually have a WIP fix for it:
if your case is the one i found (emitting same LiveData multiple times, as shown in #5) you can work around it by adding a dummy transformation.
val subLiveData = MutableLiveData(1)
val subject = liveData(testScope.coroutineContext) {
emitSource(subLiveData.map {it })
emitSource(subLiveData.map {it} )
}
ra...@google.com <ra...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-master-dev
commit af12e75e6b4110f48e44ca121466943909de8f06
Author: Yigit Boyar <yboyar@google.com>
Date: Tue Sep 03 12:58:11 2019
Fix coroutine livedata race condition
This CL fixes a bug in liveData builder where emitting same
LiveData source twice would make it crash because the second
emission registry could possibly happen before first one is
removed as source.
We fix it by using a suspending dispose function. It does feel
a bit hacky but we cannot make DisposableHandle.dispose async
and we do not want to block there. This does not mean that there
is a problem if developer disposes it manually since our emit
functions take care of making sure it disposes (and there is
no other way to add source to the underlying MediatorLiveData)
Bug: 140249349
Test: BuildLiveDataTest#raceTest_*
Change-Id: I0b464c242a583da4669af195cf2504e2adc4de40
M lifecycle/lifecycle-livedata-ktx/api/2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/current.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
M lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
M lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
https://android-review.googlesource.com/1112186
https://goto.google.com/android-sha1/af12e75e6b4110f48e44ca121466943909de8f06
Branch: androidx-master-dev
commit af12e75e6b4110f48e44ca121466943909de8f06
Author: Yigit Boyar <yboyar@google.com>
Date: Tue Sep 03 12:58:11 2019
Fix coroutine livedata race condition
This CL fixes a bug in liveData builder where emitting same
LiveData source twice would make it crash because the second
emission registry could possibly happen before first one is
removed as source.
We fix it by using a suspending dispose function. It does feel
a bit hacky but we cannot make DisposableHandle.dispose async
and we do not want to block there. This does not mean that there
is a problem if developer disposes it manually since our emit
functions take care of making sure it disposes (and there is
no other way to add source to the underlying MediatorLiveData)
Bug: 140249349
Test: BuildLiveDataTest#raceTest_*
Change-Id: I0b464c242a583da4669af195cf2504e2adc4de40
M lifecycle/lifecycle-livedata-ktx/api/2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/current.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/public_plus_experimental_current.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_2.2.0-alpha05.txt
M lifecycle/lifecycle-livedata-ktx/api/restricted_current.txt
M lifecycle/lifecycle-livedata-ktx/src/main/java/androidx/lifecycle/CoroutineLiveData.kt
M lifecycle/lifecycle-livedata-ktx/src/test/java/androidx/lifecycle/BuildLiveDataTest.kt
mu...@gmail.com <mu...@gmail.com> #9
I'm using version 2.4.0-beta01 of WorkManager. lintDebug doesn't show me any warning about WorkManager.
ra...@google.com <ra...@google.com> #10
Which Studio version are you using? That usually determines if lint rules are correctly picked up.
mu...@gmail.com <mu...@gmail.com> #11
Android Studio 4.0
Build #AI-193.6911.18.40.6514223, built on May 20, 2020
Runtime version: 1.8.0_242-release-1644-b01 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
GC: ParNew, ConcurrentMarkSweep
Memory: 3987M
Cores: 16
Registry: ide.new.welcome.screen.force=true
Non-Bundled Plugins: PythonCore, com.android.tool.sizereduction.plugin, com.google.services.firebase, org.intellij.plugins.markdown
ey...@gmail.com <ey...@gmail.com> #12
if(androidVersionIsAtLeast(Q)) {
setForeground(
ForegroundInfo(
R.id.notification_id,
notifications.createNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION
)
)
}
else {
setForeground(
ForegroundInfo(
R.id.notification_id,
notifications.createNotification()
)
)
}
I don't get a lint warning for the code above. Using 2.4.0-beta01
Android Studio 4.0
Build #AI-193.6911.18.40.6514223, built on May 20, 2020
Runtime version: 1.8.0_242-release-1644-b3-6222593 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Linux 5.7.1-050701-generic
GC: ParNew, ConcurrentMarkSweep
Memory: 4012M
Cores: 12
Registry: ide.new.welcome.screen.force=true, debugger.watches.in.variables=false, debugger.showTypes=false
Non-Bundled Plugins: Key Promoter X, org.jetbrains.kotlin, com.developerphil.adbidea, com.squareup.sqldelight, detekt
ra...@google.com <ra...@google.com> #13
Lint does not have a stable API. So depending on the version of Studio & the WorkManager version, it may not run in the IDE. Have you tried running ./gradlew :app:lintnDebug
?
ps...@google.com <ps...@google.com> #14
I have encountered the same issue, lint in the IDE does not report the problem.
However, if I run ./gradlew :app:lintDebug I get this
Error: Missing dataSync foregroundServiceType in the AndroidManifest.xml [SpecifyForegroundServiceType from androidx.work]
ForegroundInfo(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
I think mentioning it in the doc would be nice.
Description
Version used: 2.2.0-rc04
Devices/Android versions reproduced on: Pixel 4 - Android 10
WorkManager now support long running workers with foreground notification:
And the Javadoc for ForegroundInfo clearly shows that I can specify the foregroundServiceType as I would for a standard foreground service:
Except when I do:
setForegroundAsync(
ForegroundInfo(
NOTIFICATION_ID,
syncNotificationManager.createSyncForegroundNotification(),
ServiceInfo.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
or ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
)
)
from my Work I get this exception as soon as I try to run the work:
java.lang.IllegalArgumentException: foregroundServiceType 0x00000011 is not a subset of foregroundServiceType attribute 0x00000000 in service element of manifest file
at android.os.Parcel.createException(Parcel.java:2075)
at android.os.Parcel.readException(Parcel.java:2039)
at android.os.Parcel.readException(Parcel.java:1987)
at android.app.IActivityManager$Stub$Proxy.setServiceForeground(IActivityManager.java:6136)
at android.app.Service.startForeground(Service.java:742)
at androidx.work.impl.foreground.SystemForegroundService$1.run(SystemForegroundService.java:118)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: android.os.RemoteException: Remote stack trace:
at com.android.server.am.ActiveServices.setServiceForegroundInnerLocked(ActiveServices.java:1276)
at com.android.server.am.ActiveServices.setServiceForegroundLocked(ActiveServices.java:914)
at com.android.server.am.ActivityManagerService.setServiceForeground(ActivityManagerService.java:13964)
at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2784)
at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2741)
The reason is that the work library still rely on the service manifest which has no foregroundServiceType attribute specified (0x00000000) and i'm requesting a specific foregroundServiceType (0x00000011).
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:directBootAware="false"
android:enabled="@bool/enable_system_foreground_service_default"
android:exported="false"
tools:targetApi="n" />
my current workaround is to just copy this in my manifest and add my foregroundServiceType.
I briefly tried and seems like it is working as I want but I'm not sure if this is ok. If this is the correct way it should be documented!
This is what I added to my manifest:
<service
android:name="androidx.work.impl.foreground.SystemForegroundService"
android:directBootAware="false"
android:enabled="@bool/enable_system_foreground_service_default"
android:exported="false"
android:foregroundServiceType="connectedDevice|dataSync"
tools:targetApi="n" />
I copied yours and added
android:foregroundServiceType="connectedDevice|dataSync"
which is what I needed.