Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalStateException after backgrounding and coming back to the app #40

Closed
yasith opened this issue Sep 21, 2023 · 2 comments · Fixed by #63 or #71
Closed

IllegalStateException after backgrounding and coming back to the app #40

yasith opened this issue Sep 21, 2023 · 2 comments · Fixed by #63 or #71
Assignees

Comments

@yasith
Copy link
Member

yasith commented Sep 21, 2023

Steps to reproduce:

  • Start the app
  • Double tap on screen to flip camera
  • Background the app (observe camera green light at top-right corner is on - meaning camera is running)
  • Foreground the app

Expected:

  • User backgrounds the app
  • Camera stops running
  • User comes back to the app
  • Camera starts running

Observed:

  • User backgrounds the app
  • Camera continues running
  • User comes back to the app
  • Camera tries to run, and we get a crash
FATAL EXCEPTION: main
Process: com.google.jetpackcamera, PID: 10962
java.lang.IllegalStateException: Use case Preview:androidx.camera.core.Preview-f44934f5-30e4-4fd7-a14c-f8ad26e06060 already bound to a different lifecycle.
	at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:605)
	at androidx.camera.lifecycle.ProcessCameraProvider.bindToLifecycle(ProcessCameraProvider.java:415)
	at com.google.jetpackcamera.domain.camera.CoroutineCameraProviderKt$runWith$2.invokeSuspend(CoroutineCameraProvider.kt:43)
	at com.google.jetpackcamera.domain.camera.CoroutineCameraProviderKt$runWith$2.invoke(Unknown Source:8)
	at com.google.jetpackcamera.domain.camera.CoroutineCameraProviderKt$runWith$2.invoke(Unknown Source:4)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
	at com.google.jetpackcamera.domain.camera.CoroutineCameraProviderKt.runWith(CoroutineCameraProvider.kt:41)
	at com.google.jetpackcamera.domain.camera.CameraXCameraUseCase$runCamera$2.invokeSuspend(CameraXCameraUseCase.kt:123)
	at com.google.jetpackcamera.domain.camera.CameraXCameraUseCase$runCamera$2.invoke(Unknown Source:8)
	at com.google.jetpackcamera.domain.camera.CameraXCameraUseCase$runCamera$2.invoke(Unknown Source:4)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
	at com.google.jetpackcamera.domain.camera.CameraXCameraUseCase.runCamera(CameraXCameraUseCase.kt:115)
	at com.google.jetpackcamera.feature.preview.PreviewViewModel$runCamera$1.invokeSuspend(PreviewViewModel.kt:88)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:367)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30)
	at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch(Builders.common.kt:56)
	at kotlinx.coroutines.BuildersKt.launch(Unknown Source:1)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.launch$default(Builders.common.kt:47)
	at kotlinx.coroutines.BuildersKt.launch$default(Unknown Source:1)
	at com.google.jetpackcamera.feature.preview.PreviewViewModel.runCamera(PreviewViewModel.kt:86)
	at com.google.jetpackcamera.feature.preview.PreviewScreenKt$PreviewScreen$1$1.invokeSuspend(PreviewScreen.kt:113)
	at com.google.jetpackcamera.feature.preview.PreviewScreenKt$PreviewScreen$1$1.invoke(Unknown Source:8)
	at com.google.jetpackcamera.feature.preview.PreviewScreenKt$PreviewScreen$1$1.invoke(Unknown Source:4)
	at androidx.lifecycle.RepeatOnLifecycleKt$repeatOnLifecycle$3$1$1$1$1$1$1.invokeSuspend(RepeatOnLifecycle.kt:111)
	at androidx.lifecycle.RepeatOnLifecycleKt$repeatOnLifecycle$3$1$1$1$1$1$1.invoke(Unknown Source:8)
	at androidx.lifecycle.RepeatOnLifecycleKt$repeatOnLifecycle$3$1$1$1$1$1$1.invoke(Unknown Source:4)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:264)
	at androidx.lifecycle.RepeatOnLifecycleKt$repeatOnLifecycle$3$1$1$1$1.invokeSuspend(RepeatOnLifecycle.kt:110)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.android.kt:81)
	at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.android.kt:41)

@yasith
Copy link
Member Author

yasith commented Sep 21, 2023

I observed that when the app is backgrounded viewModel.stopCamera() gets called. However camera is not shut down, it's possible that runningCameraJob is null, or already cancelled.

We might be switching the active Job when we rebind the camera. The ViewModel should be updated with the active Job.

@temcguir temcguir linked a pull request Oct 12, 2023 that will close this issue
@yasith yasith closed this as completed Oct 12, 2023
@temcguir
Copy link
Collaborator

I'm this occurring again on main with 1 additional step of changing the aspect ratio.

Repro steps:

  1. Change aspect ratio to 1:1 in quick settings
  2. Background app by going to home screen
  3. Return to JCA and observe crash

We should create a test using UiAutomator to background the app and return to the app. We can also add another test to do the same but set the aspect ratio to 1:1 before backgrounding to catch this new issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants