Status Update
Comments
wu...@google.com <wu...@google.com> #2
Branch: androidx-master-dev
commit c60f33e229e31ab328ef6b59dab63b264954831c
Author: Alexandre Elias <aelias@google.com>
Date: Fri Jul 10 16:23:09 2020
Semantics no-op cleanups
Partly in response to lmr's broad code review, I did a pass of
superficial API/implementation cleanup. The main changes are:
- I changed each Boolean SemanticsProperty where false is equivalent to
not being present to take "Unit" instead. This is conceptually
clearer: it avoids questions like "can I cancel out a semantics from a
merged child by setting it to false?" Because "property = Unit" looks
weird, I also changed the style of these to "property()".
- I moved the Semantics id generator closer to where it's used, in
SemanticsModifierCore. I made it internal and an AtomicInt.
(Note that integer ids are heavily used in the Android
AccessibilityNodeInfo APIs so I can't simply remove them entirely.)
- I deleted dead code. Some examples include SemanticsHintOverrides,
a public API not connected to anything, and SemanticsPropertyKey
merge() open method which is never called. (In both cases I have
a different plan in mind for accessibility.)
Fixes: 145951226
Fixes: 145955412
Test: existing tests
Relnote: "Single-value semantics properties now use a calling style.
For example, 'semantics { hidden = true }' is now written as:
'semantics { hidden() }'."
Change-Id: Ic1afd12ea22c926babc9662f1804d80b33aa0cfc
M ui/integration-tests/benchmark/src/androidTest/java/androidx/ui/benchmark/test/LayoutNodeModifierBenchmark.kt
M ui/ui-core/api/0.1.0-dev15.txt
M ui/ui-core/api/current.txt
M ui/ui-core/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-core/api/public_plus_experimental_current.txt
M ui/ui-core/api/restricted_0.1.0-dev15.txt
M ui/ui-core/api/restricted_current.txt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/graphics/vector/VectorTest.kt
M ui/ui-core/src/androidAndroidTest/kotlin/androidx/ui/semantics/SemanticsTests.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidActuals.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeView.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidComposeViewAccessibilityDelegateCompat.kt
M ui/ui-core/src/androidMain/kotlin/androidx/ui/core/AndroidPopup.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/Expect.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsConfiguration.kt
D ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsHintOverrides.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsModifier.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsNode.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsOwner.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/core/semantics/SemanticsWrapper.kt
M ui/ui-core/src/commonMain/kotlin/androidx/ui/semantics/SemanticsProperties.kt
M ui/ui-foundation/api/0.1.0-dev15.txt
M ui/ui-foundation/api/current.txt
M ui/ui-foundation/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-foundation/api/public_plus_experimental_current.txt
M ui/ui-foundation/api/restricted_0.1.0-dev15.txt
M ui/ui-foundation/api/restricted_current.txt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Clickable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Dialog.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/Scroller.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Selectable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/selection/Toggleable.kt
M ui/ui-foundation/src/main/java/androidx/ui/foundation/semantics/FoundationSemanticsProperties.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ButtonTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CardTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/CheckboxScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/RadioButtonScreenshotTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ScaffoldTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SnackbarTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/SurfaceTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/ripple/RippleIndicationTest.kt
M ui/ui-material/src/androidTest/java/androidx/ui/material/textfield/TextFieldScreenshotTest.kt
M ui/ui-material/src/main/java/androidx/ui/material/AppBar.kt
M ui/ui-material/src/main/java/androidx/ui/material/TextFieldImpl.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/AssertsTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/CallSemanticsActionTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ErrorMessagesTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/FindersTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/PrintToStringTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/ScrollToTest.kt
M ui/ui-test/src/androidTest/java/androidx/ui/test/TextActionsTest.kt
M ui/ui-test/src/main/java/androidx/ui/test/Actions.kt
M ui/ui-test/src/main/java/androidx/ui/test/Filters.kt
M ui/ui-text/api/0.1.0-dev15.txt
M ui/ui-text/api/current.txt
M ui/ui-text/api/public_plus_experimental_0.1.0-dev15.txt
M ui/ui-text/api/public_plus_experimental_current.txt
M ui/ui-text/api/restricted_0.1.0-dev15.txt
M ui/ui-text/api/restricted_current.txt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/CoreTextField.kt
M ui/ui-text/src/commonMain/kotlin/androidx/ui/text/TextSemanticsProperties.kt
ni...@gmail.com <ni...@gmail.com> #3
No, it's just a simple application with a Screen A going to Screen B, and both are using the camera.
ch...@google.com <ch...@google.com>
ch...@google.com <ch...@google.com> #4
By adding some log info in the library side, the issue happens in the following steps when running the sample project provided in
- Activity is launched and the 1st pair of CameraController and PreviewView is created. The CameraController is set to the PreviewView by PreviewView#setController.
- Press the thumbup button to create the 2nd pair of Camera CameraController and PreviewView.
- The 1st PreviewView will receive onDetachedFromWindow callback. It will call CameraController#clearPreviewSurface() and then ProcessCameraProvider#unbindAll() will be called.
All use cases are unbound so the camera is closed.
The following log is extracted from the attached log when the issue happens:
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.lifecycle.LifecycleCameraRepository.suspendUseCases(LifecycleCameraRepository.java:438)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.lifecycle.LifecycleCameraRepository.setInactive(LifecycleCameraRepository.java:394)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.lifecycle.LifecycleCameraRepository.unbindAll(LifecycleCameraRepository.java:334)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.lifecycle.ProcessCameraProvider.unbindAll(ProcessCameraProvider.java:514)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.view.CameraController.clearPreviewSurface(CameraController.java:514)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.camera.view.PreviewView.onDetachedFromWindow(PreviewView.java:277)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.View.dispatchDetachedFromWindow(View.java:21358)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:4649)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:4641)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.ViewGroup.removeViewInternal(ViewGroup.java:6287)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.ViewGroup.removeViewInternal(ViewGroup.java:6258)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.ViewGroup.removeView(ViewGroup.java:6189)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.platform.AndroidComposeView.removeAndroidView(AndroidComposeView.android.kt:466)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.viewinterop.AndroidViewHolder$layoutNode$1$4.invoke(AndroidViewHolder.android.kt:254)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.viewinterop.AndroidViewHolder$layoutNode$1$4.invoke(AndroidViewHolder.android.kt:253)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.node.LayoutNode.detach$ui_release(LayoutNode.kt:370)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.node.LayoutNode.detach$ui_release(LayoutNode.kt:381)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.node.LayoutNode.detach$ui_release(LayoutNode.kt:381)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.node.LayoutNode.removeAt$ui_release(LayoutNode.kt:257)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.node.UiApplier.remove(UiApplier.android.kt:36)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.runtime.ComposerImpl$realizeMovement$1.invoke(Composer.kt:2903)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.runtime.ComposerImpl$realizeMovement$1.invoke(Composer.kt:2903)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.runtime.CompositionImpl.applyChanges(Composition.kt:629)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:479)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:416)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.Choreographer$CallbackRecord.run(Choreographer.java:997)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.Choreographer.doCallbacks(Choreographer.java:797)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.Choreographer.doFrame(Choreographer.java:728)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:984)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.os.Handler.handleCallback(Handler.java:883)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.os.Handler.dispatchMessage(Handler.java:100)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.os.Looper.loop(Looper.java:237)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at android.app.ActivityThread.main(ActivityThread.java:8167)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at java.lang.reflect.Method.invoke(Native Method)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:496)
10-31 00:49:59.042 10102 2039 2039 D XXXXX : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1100)
The issue disappears if resetting CameraController when new PreviewView is created.
var previewView : PreviewView? = null
@Composable
fun CameraPreview(flashEnabled: Boolean, modifier: Modifier = Modifier) {
val lifecycleOwner = LocalLifecycleOwner.current
val context = LocalContext.current
// Resets CameraController from the previous PreviewView
previewView?.controller = null
val controller = remember {
LifecycleCameraController(context).apply {
cameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
}
}
DisposableEffect(true) {
Log.d("XXXXX","DisposableEffect++ lifecycleOwner: " + lifecycleOwner)
controller.bindToLifecycle(lifecycleOwner)
Log.d("XXXXX","DisposableEffect++")
onDispose {
}
}
controller.enableTorch(flashEnabled)
previewView = PreviewView(context)
previewView!!.controller = controller
AndroidView(
factory = { ctx -> previewView!!
},
modifier = modifier
)
}
The solution in the camera-view side will be only unbinding the use cases created by the CameraController instead of directly calling ProcessorCameraProvider#unbindAll().
ap...@google.com <ap...@google.com> #6
Branch: androidx-main
commit 9e9384994a57d1e94d773d6368c238f4b68db27a
Author: Charcoal Chen <charcoalchen@google.com>
Date: Tue Aug 31 15:02:48 2021
CameraController#clearPreviewSurface unbinds its own use cases only instead of calling unbindAll
When multiple CameraController and PreviewView are used in one Activity, the previous PreviewView might receive the onDetachedFromWindow callback after the new pair of CameraController and PreviewView are created. It will cause the previous CameraController to call unbindAll in clearPreviewSurface function. This will unbind the use cases bound by the new CameraController. CameraController should only unbind its own use cases. Otherwise, it might unexpectedly unbind use cases that belongs to another LifecycleCamera.
Relnote: "Fixed the issue that camera is closed unexpectedly when multiple CameraController and PreviewView are used in one Activity."
Bug: 197539358
Test: buildview='./gradlew camera:camera-view:build' && testview='./gradlew camera:camera-view:connectedAndroidTest'
Change-Id: Ibfd1842890b683ae3db639bf0cc4a2202110fe9f
M camera/camera-view/src/androidTest/java/androidx/camera/view/CameraControllerDeviceTest.kt
M camera/camera-view/src/main/java/androidx/camera/view/CameraController.java
ch...@google.com <ch...@google.com> #7
The issue is fixed by
Description
CAMERAX VERSION 1.1.0-alpha08, also in 1.0.0
DEVICE NAME: Pixel 4XL
DESCRIPTION: An app that display the camera on Screen A, then going to Screen B which also displays the camera. Screen B will be black if using the CameraController class to display the camera on the screen.
STEPS TO REPRODUCE: See sample here (in Compose, sorry) :https://github.com/NitroG42/CameraXSuccessiveCameraController
OBSERVED RESULTS: It seems that when going to the second screen, the lifecycle of first screen is destroyed and it closes the camera, which leaves the second screen in a bad state. When going back to the first screen, the camera is still closed.
EXPECTED RESULTS: The camera doesn't close if it's already used in a new screen.
REPRODUCIBILITY: Always