Fixed
Status Update
Comments
cl...@google.com <cl...@google.com> #2
Apologies Jeremy, I realized we have a tracking ticket for the sheet APIs specifically:
m....@gmail.com <m....@gmail.com> #3
Sounds good. I will make it a dup.
m....@gmail.com <m....@gmail.com> #4
Sorry, but the error has remained. Please, someone help me!
m....@gmail.com <m....@gmail.com> #6
cl...@google.com <cl...@google.com> #7
I'll update this bug with the version it will be released in when the bug is fixed.
ap...@google.com <ap...@google.com> #8
Project: platform/frameworks/support
Branch: androidx-main
commit 87f0b5cf0e9943ab5dc0ee978ee50a1e2e5a5164
Author: Clara Fok <clarafok@google.com>
Date: Tue Jul 02 14:40:39 2024
Fix races between Inserts/Drops and presenters
Two types of races are addressed in this CL
1. RV-specific
Modifications to RV while RV is measuring layout crahes the app. Previously, we addressed crahes from LoadStateUpdate in aosp/2918731 and made loadStateFlow yield if RV is working. This CL we address crashes from list updates/drops by making them yield while getItem (we consider RV to be working if getItem is true).
2. All presenters
This race applies to all presenters. When an insert triggers a drop, the order of operation is `getItem -> handle drop -> handle insert`.
If drop doesn't yield to getItem, what could happen is `presenter.getItem -> pageStore.drop -> pageStore.getItem -> ...` where drop races with internal pageStore.getItem, leading to pageStore.getItem crashing with indexOutOfBounds. We need to ensure that getItem completes before presenter processes the following drop and insert.
Given that AsyncPagingDataDiffer.getItem delegates directly to PagingDataPresenter.getItem, we make insert/drop yield to PagingDataPresenter.getItem to address both races at the same time.
Test: ./gradlew paging:paging-runtime:cC
Bug: 349090863
Change-Id: I4480c7788324d941af103735555015ede2928510
M paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataPresenter.kt
M paging/paging-runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt
M paging/paging-runtime/src/androidTest/java/androidx/paging/ListUpdateCapture.kt
https://android-review.googlesource.com/3156343
Branch: androidx-main
commit 87f0b5cf0e9943ab5dc0ee978ee50a1e2e5a5164
Author: Clara Fok <clarafok@google.com>
Date: Tue Jul 02 14:40:39 2024
Fix races between Inserts/Drops and presenters
Two types of races are addressed in this CL
1. RV-specific
Modifications to RV while RV is measuring layout crahes the app. Previously, we addressed crahes from LoadStateUpdate in aosp/2918731 and made loadStateFlow yield if RV is working. This CL we address crashes from list updates/drops by making them yield while getItem (we consider RV to be working if getItem is true).
2. All presenters
This race applies to all presenters. When an insert triggers a drop, the order of operation is `getItem -> handle drop -> handle insert`.
If drop doesn't yield to getItem, what could happen is `presenter.getItem -> pageStore.drop -> pageStore.getItem -> ...` where drop races with internal pageStore.getItem, leading to pageStore.getItem crashing with indexOutOfBounds. We need to ensure that getItem completes before presenter processes the following drop and insert.
Given that AsyncPagingDataDiffer.getItem delegates directly to PagingDataPresenter.getItem, we make insert/drop yield to PagingDataPresenter.getItem to address both races at the same time.
Test: ./gradlew paging:paging-runtime:cC
Bug: 349090863
Change-Id: I4480c7788324d941af103735555015ede2928510
M paging/paging-common/src/commonMain/kotlin/androidx/paging/PagingDataPresenter.kt
M paging/paging-runtime/src/androidTest/java/androidx/paging/AsyncPagingDataDifferTest.kt
M paging/paging-runtime/src/androidTest/java/androidx/paging/ListUpdateCapture.kt
cl...@google.com <cl...@google.com> #9
Fixed internally and will be available in paging 3.3.1
m....@gmail.com <m....@gmail.com> #10
Sorry, 3.1.1 or 3.3.1?
cl...@google.com <cl...@google.com> #11
3.3.1
- corrected original comment
fe...@500px.com <fe...@500px.com> #12
paging 3.3.1 is not available
cl...@google.com <cl...@google.com> #13
It will be released on July 24.
yu...@gmail.com <yu...@gmail.com> #14
very good.
m....@gmail.com <m....@gmail.com> #15
Will there be a new release today?
Description
androidx.paging:paging-runtime:3.3.0
androidx.paging:paging-guava:3.3.0
androidx.paging:paging-rxjava3:3.3.0
Version used: 3.3.0
Devices/Android versions reproduced on: All devices
In my application I am using PagingDataAdapter. After updating the paging libraries from version 3.2.0 to version 3.3.0, when calling onBindViewHolder, the function:
Long date = getItem(position);
throws an exception: java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView
FATAL EXCEPTION: main Process: monitor.kmv.multinotes, PID: 4355 java.lang.IllegalStateException: Cannot call this method while RecyclerView is computing a layout or scrolling androidx.recyclerview.widget.RecyclerView{e37ff06 VFED..... ......I. 0,0-0,0 #7f0a016b app:id/calendar_recycler}, adapter:monitor.kmv.multinotes.ui.main.CalendarRecyclerAdapter@bc753c9, layout:androidx.recyclerview.widget.LinearLayoutManager@22f99c7, context:monitor.kmv.multinotes.CalendarActivity@4a3b811
at androidx.recyclerview.widget.RecyclerView.assertNotInLayoutOrScroll(RecyclerView.java:3482)
at androidx.recyclerview.widget.RecyclerView$RecyclerViewDataObserver.onItemRangeInserted(RecyclerView.java:6079)
at androidx.recyclerview.widget.RecyclerView$AdapterDataObservable.notifyItemRangeInserted(RecyclerView.java:13229)
at androidx.recyclerview.widget.RecyclerView$Adapter.notifyItemRangeInserted(RecyclerView.java:8232)
at androidx.recyclerview.widget.AdapterListUpdateCallback.onInserted(AdapterListUpdateCallback.java:44)
at androidx.paging.AsyncPagingDataDiffer$presenter$1.presentPagingDataEvent(AsyncPagingDataDiffer.kt:205)
at androidx.paging.PagingDataPresenter$collectFrom$2$1$2.invokeSuspend(PagingDataPresenter.kt:167)
at androidx.paging.PagingDataPresenter$collectFrom$2$1$2.invoke(Unknown Source:8)
at androidx.paging.PagingDataPresenter$collectFrom$2$1$2.invoke(Unknown Source:4)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:78)
at kotlinx.coroutines.BuildersKt__Builders_commonKt.withContext(Builders.common.kt:167)
at kotlinx.coroutines.BuildersKt.withContext(Unknown Source:1)
at androidx.paging.PagingDataPresenter$collectFrom$2$1.emit(PagingDataPresenter.kt:120)
at androidx.paging.PagingDataPresenter$collectFrom$2$1.emit(PagingDataPresenter.kt:118)
at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
at kotlinx.coroutines.flow.internal.SafeCollectorKt$emitFun$1.invoke(SafeCollector.kt:15)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:87)
at kotlinx.coroutines.flow.internal.SafeCollector.emit(SafeCollector.kt:66)
at androidx.paging.CachedPageEventFlow$downstreamFlow$1$2.emit(CachedPageEventFlow.kt:105)
at androidx.paging.CachedPageEventFlow$downstreamFlow$1$2.emit(CachedPageEventFlow.kt:102)
at kotlinx.coroutines.flow.FlowKt__LimitKt$takeWhile$lambda$6$$inlined$collectWhile$1.emit(Limit.kt:143)
at kotlinx.coroutines.flow.SubscribedFlowCollector.emit(Unknown Source:2)
at kotlinx.coroutines.flow.SharedFlowImpl.collect$suspendImpl(SharedFlow.kt:382)
at kotlinx.coroutines.flow.SharedFlowImpl$collect$1.invokeSuspend(Unknown Source:15)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.EventLoop.processUnconfinedEvent(EventLoop.common.kt:68)
at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:245)
at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:163)
at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:474)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:508)
at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:497)
at kotlinx.coroutines.CancellableContinuationImpl.resumeWith(CancellableContinuationImpl.kt:368)
at kotlinx.coroutines.flow.SharedFlowImpl.tryEmit(SharedFlow.kt:399)
at androidx.paging.HintHandler$HintFlow.setValue(HintHandler.kt:136)
at androidx.paging.HintHandler$processHint$1.invoke(HintHandler.kt:88)
at androidx.paging.HintHandler$processHint$1.invoke(HintHandler.kt:82)
at androidx.paging.HintHandler$State.modify(HintHandler.kt:122)
at androidx.paging.HintHandler.processHint(HintHandler.kt:82)
at androidx.paging.PageFetcherSnapshot.accessHint(PageFetcherSnapshot.kt:202)
2024-06-24 22:10:42.440 4355-4355 AndroidRuntime monitor.kmv.multinotes E
at androidx.paging.PageFetcher$PagerHintReceiver.accessHint(PageFetcher.kt:246)
at androidx.paging.PagingDataPresenter.get(PagingDataPresenter.kt:265)
at androidx.paging.AsyncPagingDataDiffer.getItem(AsyncPagingDataDiffer.kt:416)
at androidx.paging.PagingDataAdapter.getItem(PagingDataAdapter.kt:302)
at monitor.kmv.multinotes.ui.main.CalendarRecyclerAdapter.onBindViewHolder(CalendarRecyclerAdapter.java:124)
at monitor.kmv.multinotes.ui.main.CalendarRecyclerAdapter.onBindViewHolder(CalendarRecyclerAdapter.java:78)
at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7747)
at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7847)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6646)
at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6917)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6757)
at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6753)
at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2362)
at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1662)
at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1622)
at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:687)
at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4645)
at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:4022)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:1204)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:723)
at android.view.View.measure(View.java:26563)
at androidx.constraintlayout.widget.ConstraintLayout$Measurer.measure(ConstraintLayout.java:811)
at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:632)
at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.layout(ConstraintWidgetContainer.java:733)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solveLinearSystem(BasicMeasure.java:160)
at androidx.constraintlayout.core.widgets.analyzer.BasicMeasure.solverMeasure(BasicMeasure.java:291)
at androidx.constraintlayout.core.widgets.ConstraintWidgetContainer.measure(ConstraintWidgetContainer.java:120)
at androidx.constraintlayout.widget.ConstraintLayout.resolveSystem(ConstraintLayout.java:1594)
at androidx.constraintlayout.widget.ConstraintLayout.onMeasure(ConstraintLayout.java:1708)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:141)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
2024-06-24 22:10:42.441 4355-4355 AndroidRuntime monitor.kmv.multinotes E
at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
at android.view.View.measure(View.java:26563)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:7093)
at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
at com.android.internal.policy.DecorView.onMeasure(DecorView.java:783)
at android.view.View.measure(View.java:26563)
at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:4115)
at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:2803)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3077)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2519)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9516)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1326)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1334)
at android.view.Choreographer.doCallbacks(Choreographer.java:967)
at android.view.Choreographer.doFrame(Choreographer.java:881)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1309)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:204)
at android.os.Looper.loop(Looper.java:291)
at android.app.ActivityThread.main(ActivityThread.java:8134)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:588)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1019)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@9693360, Dispatchers.Main.immediate]