Status Update
Comments
se...@google.com <se...@google.com> #2
Thank you for the report. We will try to fix this soon. In the meantime, could you please start the emulator from the console (see the commands below), open the camera app to crash it and attach the output, it might help to figure out what the problem is:
cd /Users/YOUR_USERNAME/Library/Android/sdk/emulator
./emulator -list-avds
./emulator -verbose -avd YOUR_AVD_FROM_PREVIOUS_STEP
if there is a crash report to send, please send it and attach the report id.
yb...@google.com <yb...@google.com> #3
We got a crash report (thanks JP): 872e3b20bc34905b. It says EXC_BAD_INSTRUCTION / 0x00000001
and the console also says "Illegal hardware instruction". I suspect the new MacOS brought a new hypervizor which causes this behavior. Haitao, could you please take a look?
yb...@google.com <yb...@google.com> #4
We have quite some crashes like this:
product_name="AndroidEmulator" AND crash.Reason="EXC_BAD_INSTRUCTION / 0x00000001" AND cpu.Architecture="arm64"
yb...@google.com <yb...@google.com> #5
The most of crashes happen here:
vVertical_Scale_ARGB_8888_Accelerate
vImageVerticalShear_ARGB8888
vImageVerticalShear_ARGB8888
vImageScale_ARGB8888
vRotateClockwise270Degree_ARGB8888_Accelerate2
vRotate_90_ARGB_8888_270Degree_Accelerate2
da...@gmail.com <da...@gmail.com> #6
I suspect EXC_BAD_INSTRUCTION
happens in vImageRotate90_ARGB8888
and vImageScale_ARGB8888
which are used by webcam on MacOS.
yb...@google.com <yb...@google.com> #7
ap...@google.com <ap...@google.com> #8
Hi rforzani22, I am sorry for this experience. This bug is my top priority. We expect a fix to be merged within a week. You should be able to download a build directly from our build server (
Description
Version used: 2.2.0-alpha01
Devices/Android versions reproduced on: Android 9
I'm having some random crashes due to CoroutineLiveData
```
Fatal Exception: java.lang.IllegalArgumentException: This source was already added with the different observer
at androidx.lifecycle.MediatorLiveData.addSource + 89(MediatorLiveData.java:89)
at androidx.lifecycle.CoroutineLiveDataKt.addDisposableSource + 102(CoroutineLiveDataKt.java:102)
at androidx.lifecycle.CoroutineLiveData.emitSource$lifecycle_livedata_ktx_release + 200(CoroutineLiveData.java:200)
at androidx.lifecycle.LiveDataScopeImpl$emitSource$2.invokeSuspend + 89(LiveDataScopeImpl.java:89)
at androidx.lifecycle.LiveDataScopeImpl$emitSource$2.invoke(LiveDataScopeImpl.java:11)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn + 91(UndispatchedKt.java:91)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext + 156(BuildersKt__Builders_commonKt.java:156)
at kotlinx.coroutines.BuildersKt.withContext + 1(BuildersKt.java:1)
at androidx.lifecycle.LiveDataScopeImpl.emitSource + 88(LiveDataScopeImpl.java:88)
at com.geekorum.ttrss.articles_list.FeedsViewModel$refreshed$1.invokeSuspend + 90(FeedsViewModel.java:90)
at com.geekorum.ttrss.articles_list.FeedsViewModel$refreshed$1.invoke(FeedsViewModel.java:8)
at androidx.lifecycle.BlockRunner$maybeRun$1.invokeSuspend + 147(BlockRunner.java:147)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith + 33(BaseContinuationImpl.java:33)
at kotlinx.coroutines.DispatchedTask.run + 241(DispatchedTask.java:241)
at android.os.Handler.handleCallback + 873(Handler.java:873)
at android.os.Handler.dispatchMessage + 99(Handler.java:99)
at android.os.Looper.loop + 193(Looper.java:193)
at android.app.ActivityThread.main + 6898(ActivityThread.java:6898)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run + 537(RuntimeInit.java:537)
at com.android.internal.os.ZygoteInit.main + 858(ZygoteInit.java:858)
```
From what I understand of CoroutineLiveData source code, when calling `LiveDataScope.emitSource()` the previous source is removed before adding the new one on MediatorLiveData.
```
@MainThread
internal fun emitSource(source: LiveData<T>): DisposableHandle {
clearSource()
val newSource = addDisposableSource(source)
emittedSource = newSource
return newSource
}
```
However the removing is done by launching a new coroutine
```
internal fun <T> MediatorLiveData<T>.addDisposableSource(
source: LiveData<T>
): DisposableHandle {
val disposed = AtomicBoolean(false)
addSource(source) {
if (!disposed.get()) {
value = it
} else {
removeSource(source)
}
}
return object : DisposableHandle {
override fun dispose() {
if (disposed.compareAndSet(false, true)) {
CoroutineScope(Dispatchers.Main).launch {
removeSource(source)
}
}
}
}
}
```
So there is no guarantee that `MediatorLiveData.addSource()` will be called after the removing coroutine is executed. This leads to the IllegalArgumentException in `MediatorLiveData.addSource()`
```
@MainThread
public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
Source<S> e = new Source<>(source, onChanged);
Source<?> existing = mSources.putIfAbsent(source, e);
if (existing != null && existing.mObserver != onChanged) {
throw new IllegalArgumentException(
"This source was already added with the different observer");
}
if (existing != null) {
return;
}
if (hasActiveObservers()) {
e.plug();
}
}
```