Status Update
Comments
er...@google.com <er...@google.com> #2
er...@google.com <er...@google.com>
ni...@google.com <ni...@google.com> #3
Great! Thanks a lot, I'll look for the live updates soon!
er...@google.com <er...@google.com>
to...@google.com <to...@google.com>
wu...@google.com <wu...@google.com>
le...@google.com <le...@google.com> #4
Set the exception on the ListenableFuture from initialization is fine to notify error instead of crash. However, there is a scenario if DND mode is enabled after initialization, then calling CameraManager.getCameraCharacteristics() still crash the app. Need more investigation for such case.
ap...@google.com <ap...@google.com> #5
Branch: androidx-master-dev
commit a3a8ad369856c23f6d475f770586f106da906677
Author: leo huang <leohuang@google.com>
Date: Mon Apr 13 18:09:57 2020
Fix the DND crash when CameraX initialization and open camera.
The crash happens if the following conditions are met.
* An early Android P(28) release
* Camera hardware level is INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
* Device Do Not Disturb (DND) mode is enabled
It will crash by 2 scenarios,
(1) Enable DND mode and trigger CameraX initialization, it will crash during initialization.
(2) After CameraX initialized, enable DND mode and bind use cases, it will crash when try to open camera.
The CL tries to not crash for both scenarios.
For scenario 1, it set a specific exception CameraUnavailableException to the initialization ListenableFuture to notify the user that it is caused by enabling DND mode.
The CL contains
(1) Create checked exception CameraUnavailableException with error code and InitializationException.
(2) Wrap the DND fail exception (CameraAccessExceptionCompat) by the CameraUnavailableException. Set the exception to InitializationException and initialization ListenableFuture instead of crashing the application.
(3) Reset the Camera2CameraImpl internal state when encountering DND fail instead of crashing.
Relnote: "Fix the crash on app startup when initialising CameraX while phone is in Do Not Disturb mode. An InitializationException contains a CameraUnavailableException will be set to the ListenableFuture of the intialization result instead of crashing the application."
Bug: 149413835
Test: ./gradlew camera:camera-camera2:connectedAndroidTest; Simulate the DND fail case by modifying CameraManagerCompat and manually test
Change-Id: I9909af08a8305fcf8e603d709d98b4488f1af69f
M camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/Camera2CameraImplTest.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/Camera2Config.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraFactory.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManager.java
A camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CameraUnavailableExceptionHelper.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/SupportedSurfaceCombination.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompatBaseImpl.java
M camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/Camera2DeviceSurfaceManagerTest.java
M camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/SupportedSurfaceCombinationTest.java
M camera/camera-core/api/1.0.0-beta05.txt
M camera/camera-core/api/current.txt
M camera/camera-core/api/public_plus_experimental_1.0.0-beta05.txt
M camera/camera-core/api/public_plus_experimental_current.txt
M camera/camera-core/api/restricted_1.0.0-beta05.txt
M camera/camera-core/api/restricted_current.txt
M camera/camera-core/src/main/java/androidx/camera/core/CameraExecutor.java
A camera/camera-core/src/main/java/androidx/camera/core/CameraUnavailableException.java
M camera/camera-core/src/main/java/androidx/camera/core/CameraX.java
A camera/camera-core/src/main/java/androidx/camera/core/InitializationException.java
M camera/camera-core/src/main/java/androidx/camera/core/impl/CameraDeviceSurfaceManager.java
M camera/camera-core/src/main/java/androidx/camera/core/impl/CameraFactory.java
M camera/camera-core/src/main/java/androidx/camera/core/impl/CameraRepository.java
M camera/camera-core/src/main/java/androidx/camera/core/impl/UseCaseConfigFactory.java
M camera/camera-core/src/test/java/androidx/camera/core/impl/CameraRepositoryTest.java
M camera/camera-extensions/src/main/java/androidx/camera/extensions/CameraUtil.java
M camera/camera-lifecycle/src/main/java/androidx/camera/lifecycle/ProcessCameraProvider.java
ap...@google.com <ap...@google.com> #6
Branch: androidx-master-dev
commit a68bdb5f29b6875adbd5fa8cace9cc8b79bf7d0a
Author: leo huang <leohuang@google.com>
Date: Mon Apr 13 00:26:17 2020
Add DND fail detection in camera2 compat module
A RuntimeException will be thrown by satisfying the following conditions
* An early Android P(28) release
* Camera hardware level is INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY
* Device Do Not Disturb (DND) mode is enabled
* Invoke API CameraManager.getCameraCharacteristics() or CameraManager.openCamera()
The CL contains
(1) Create a CameraAccessExceptionCompat, it defines DND fail error code combining with original CameraAccessException error.
(2) Catches the DND RuntimeException and rethrow a CameraAccessExceptionCompat.
(3) It caches all CameraCharacteristics in API 28 and returns the cached one only when running into DND fail case. It is a workaround to lower the chance to encounter DND RuntimeException.
Bug: 149413835
Test: ./gradlew camera:camera-camera2:test
Change-Id: Ia04a9cfe61fca9e61dd02ea5f44f6bbb771e9a53
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
A camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraAccessExceptionCompat.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompat.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompatApi28Impl.java
A camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompatApi29Impl.java
M camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/compat/CameraManagerCompatBaseImpl.java
A camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraAccessExceptionCompatTest.java
M camera/camera-camera2/src/test/java/androidx/camera/camera2/internal/compat/CameraManagerCompatTest.java
le...@google.com <le...@google.com>
[Deleted User] <[Deleted User]> #7
I have an update regarding this issue. We've been using the fixed version but still facing crashes. Unfortunately, we don't have the affected devices to get the scenario reproduced, but I have posted a report of them below. Please take a look.
CAMERAX VERSION: 1.0.0-beta06
ANDROID OS BUILD NUMBER: Android 9 and 5.1.1.
DEVICE NAMES: Samsung Galaxy J2, Oppo CPH1893.
LOGS:
Fatal Exception: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:512)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:906)
Caused by java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:906)
Caused by java.util.concurrent.ExecutionException: androidx.camera.core.InitializationException: androidx.camera.core.CameraUnavailableException: androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat: Some API 28 devices cannot access the camera when the device is in "Do Not Disturb" mode. The camera will not be accessible until "Do Not Disturb" mode is disabled.
at androidx.concurrent.futures.AbstractResolvableFuture.getDoneValue(AbstractResolvableFuture.java:518)
at androidx.concurrent.futures.AbstractResolvableFuture.get(AbstractResolvableFuture.java:475)
at androidx.concurrent.futures.CallbackToFutureAdapter$SafeFuture.get(CallbackToFutureAdapter.java:199)
at androidx.camera.core.impl.utils.futures.FutureChain.get(FutureChain.java:155)
at androidx.camera.core.impl.utils.futures.ChainingListenableFuture.get(ChainingListenableFuture.java:105)
at com.xxxxx.xxxxx.ui.fragments.CameraFragment$bindCameraUseCases$1.run(CameraFragment.java:232)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:242)
at android.app.ActivityThread.main(ActivityThread.java:7240)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:502)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:906)
Caused by androidx.camera.core.InitializationException: androidx.camera.core.CameraUnavailableException: androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat: Some API 28 devices cannot access the camera when the device is in "Do Not Disturb" mode. The camera will not be accessible until "Do Not Disturb" mode is disabled.
at androidx.camera.camera2.Camera2Config.lambda$defaultConfig$0(Camera2Config.java:61)
at androidx.camera.camera2.-$$Lambda$Camera2Config$mYXXnxW6sa_oF7xhp51ozRSO_ck.newInstance(-.java)
at androidx.camera.core.CameraX.lambda$initInternal$7$CameraX(CameraX.java:1034)
at androidx.camera.core.-$$Lambda$CameraX$PC4SOFGjuqUVT4bexY644vLmWFE.run(-.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by androidx.camera.core.CameraUnavailableException: androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat: Some API 28 devices cannot access the camera when the device is in "Do Not Disturb" mode. The camera will not be accessible until "Do Not Disturb" mode is disabled.
at androidx.camera.camera2.internal.CameraUnavailableExceptionHelper.createFrom(CameraUnavailableExceptionHelper.java:61)
at androidx.camera.camera2.internal.SupportedSurfaceCombination.<init>(SupportedSurfaceCombination.java:106)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.init(Camera2DeviceSurfaceManager.java:87)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:75)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:67)
at androidx.camera.camera2.Camera2Config.lambda$defaultConfig$0(Camera2Config.java:59)
at androidx.camera.camera2.-$$Lambda$Camera2Config$mYXXnxW6sa_oF7xhp51ozRSO_ck.newInstance(-.java)
at androidx.camera.core.CameraX.lambda$initInternal$7$CameraX(CameraX.java:1034)
at androidx.camera.core.-$$Lambda$CameraX$PC4SOFGjuqUVT4bexY644vLmWFE.run(-.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat: Some API 28 devices cannot access the camera when the device is in "Do Not Disturb" mode. The camera will not be accessible until "Do Not Disturb" mode is disabled.
at androidx.camera.camera2.internal.compat.CameraManagerCompatApi28Impl.throwDndException(CameraManagerCompatApi28Impl.java:120)
at androidx.camera.camera2.internal.compat.CameraManagerCompatApi28Impl.getCameraCharacteristics(CameraManagerCompatApi28Impl.java:112)
at androidx.camera.camera2.internal.compat.CameraManagerCompat.getCameraCharacteristics(CameraManagerCompat.java:155)
at androidx.camera.camera2.internal.SupportedSurfaceCombination.<init>(SupportedSurfaceCombination.java:100)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.init(Camera2DeviceSurfaceManager.java:87)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:75)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:67)
at androidx.camera.camera2.Camera2Config.lambda$defaultConfig$0(Camera2Config.java:59)
at androidx.camera.camera2.-$$Lambda$Camera2Config$mYXXnxW6sa_oF7xhp51ozRSO_ck.newInstance(-.java)
at androidx.camera.core.CameraX.lambda$initInternal$7$CameraX(CameraX.java:1034)
at androidx.camera.core.-$$Lambda$CameraX$PC4SOFGjuqUVT4bexY644vLmWFE.run(-.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
Caused by java.lang.RuntimeException: Camera is being used after Camera.release() was called
at android.hardware.Camera._enableShutterSound(Camera.java)
at android.hardware.Camera.updateAppOpsPlayAudio(Camera.java:1952)
at android.hardware.Camera.initAppOps(Camera.java:691)
at android.hardware.Camera.<init>(Camera.java:684)
at android.hardware.Camera.getEmptyParameters(Camera.java:2350)
at android.hardware.camera2.legacy.LegacyMetadataMapper.createCharacteristics(LegacyMetadataMapper.java:151)
at android.hardware.camera2.CameraManager.getCameraCharacteristics(CameraManager.java:277)
at androidx.camera.camera2.internal.compat.CameraManagerCompatBaseImpl.getCameraCharacteristics(CameraManagerCompatBaseImpl.java:108)
at androidx.camera.camera2.internal.compat.CameraManagerCompatApi28Impl.getCameraCharacteristics(CameraManagerCompatApi28Impl.java:90)
at androidx.camera.camera2.internal.compat.CameraManagerCompat.getCameraCharacteristics(CameraManagerCompat.java:155)
at androidx.camera.camera2.internal.SupportedSurfaceCombination.<init>(SupportedSurfaceCombination.java:100)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.init(Camera2DeviceSurfaceManager.java:87)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:75)
at androidx.camera.camera2.internal.Camera2DeviceSurfaceManager.<init>(Camera2DeviceSurfaceManager.java:67)
at androidx.camera.camera2.Camera2Config.lambda$defaultConfig$0(Camera2Config.java:59)
at androidx.camera.camera2.-$$Lambda$Camera2Config$mYXXnxW6sa_oF7xhp51ozRSO_ck.newInstance(-.java)
at androidx.camera.core.CameraX.lambda$initInternal$7$CameraX(CameraX.java:1034)
at androidx.camera.core.-$$Lambda$CameraX$PC4SOFGjuqUVT4bexY644vLmWFE.run(-.java:8)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
A Screenshot related to the crash has been posted below
le...@google.com <le...@google.com> #8
Hi
Sorry for not attaching detail information when the issue was fixed.
When you get the exception
Caused by java.util.concurrent.ExecutionException:
androidx.camera.core.InitializationException:
androidx.camera.core.CameraUnavailableException:
androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat:
Some API 28 devices cannot access the camera when the device is in "Do Not Disturb" mode. The camera will not be accessible until "Do Not Disturb" mode is disabled.
it means it indeed hits the Do Not Disturb
mode issue and CameraX report it. But unfortunately there is no way to avoid this fail because it is a framework level issue (by camera2 API). Only device FOTA (a newer version of API 28 or 29+) can totally get rid of this issue. What CameraX does is not to crash the application and report a specific exception to let application handle it. For example, app may just want to ignore the camera function because there may be other more important functions, or app can ask user to turn off Do Not Disturb
mode then re-launch the page.
From the call stack, I think your application should be able to handle the exception here
at androidx.camera.core.impl.utils.futures.ChainingListenableFuture.get(ChainingListenableFuture.java:105)
at com.xxxxx.xxxxx.ui.fragments.CameraFragment$bindCameraUseCases$1.run(CameraFragment.java:232)
and it could be something like
ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(context);
cameraProviderFuture.addListener(() -> {
try {
ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
// …
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof InitializationException) {
/*
* If the cause is the CameraUnavailableException, then check the reason.
*/
if (cause.getCause() instanceof CameraUnavailableException) {
CameraUnavailableException cue = (CameraUnavailableException) throwable.getCause();
switch (cue.getReason()) {
case CameraUnavailableException.CAMERA_UNAVAILABLE_DO_NOT_DISTURB:
/*** handle Do Not Disturb mode issue ***/
break;
}
}
}
}
}, ContextCompat.getMainExecutor(context));
Refer to
However, there is still one thing not perfect. Once user has successfully passed the CameraX initialization and then turn on the Do Not Disturb
mode. The camera function will still fail due to the same framework issue and silently since CameraX currently does not provide camera state listener or binding UseCase result listener. The related design is under going but I am not able to provide a specific timeline currently.
Thank you for the feedback and let me know if you still have problem.
[Deleted User] <[Deleted User]> #9
Thanks for sharing the solution to this. I landed here straight from the search with the exception name, didn't browse through the commits. I will definitely update this thread If we still get issues after applying this fix.
I was wondering how this issue came up in API 22. Is this expected?
Also, it would be much appreciative of you If you could share some other reasons for failure - under ExecutionException apart from CameraUnavailableException or any pointers would be helpful.
le...@google.com <le...@google.com> #10
Hi,
The framework issue only occurs on an early version of API 28. It was fixed on the same API level. CameraX also detect the issue and throw CameraUnavailableException.CAMERA_UNAVAILABLE_DO_NOT_DISTURB only on API 28. So theoretically it is impossible to get this exception on API 22. Not sure if there are other reasons?
The future is probably from
Description
Please describe your issue and include details such as the version of CameraX you are using and any relevant logs related to your issue.
# If at all possible, capture an Android logcat (
# the camera is still active.
CAMERAX VERSION (ex - 1.0.0-alpha09)
CAMERA APPLICATION NAME AND VERSION: (Settings > Apps > (app name) > version)
ANDROID OS BUILD NUMBER: (Settings > About > Build number)
Only happens on Android 9
DEVICE NAME: (Nexus 5X, Samsung S6, etc)
ZenFone 5 Lite (ZC600KL) (ASUS_X017D_2)
Nokia 3 (NE1)
Galaxy A9 (2018) (a9y18qlte)
Galaxy J8 (j8y18lte)
DESCRIPTION:
The issue happens when the user has turned on Do Not Disturb mode and tried to open the app. CameraX tries to initialise the camera on startup and within the library code it tries to `enableShutterSound` but fails because of DnD mode.
STEPS TO REPRODUCE:
1. Turn on DnD
2. Open app
3. Observe crash
OBSERVED RESULTS:
EXPECTED RESULTS:
REPRODUCIBILITY: (5 of out 5, 1 out of 100, etc)
For those devices it will happen everytime until the user manually turns of DnD mode and opens the app again.
ADDITIONAL INFORMATION:
Crashlog:
Caused by: java.lang.RuntimeException:
at android.hardware.Camera._enableShutterSound (Camera.java)
at android.hardware.Camera.updateAppOpsPlayAudio (Camera.java:1786)
at android.hardware.Camera.initAppOps (Camera.java:598)
at android.hardware.Camera.<init> (Camera.java:591)
at android.hardware.Camera.getEmptyParameters (Camera.java:2146)
at android.hardware.camera2.legacy.LegacyMetadataMapper.createCharacteristics (LegacyMetadataMapper.java:151)
at android.hardware.camera2.CameraManager.getCameraCharacteristics (CameraManager.java:347)
at androidx.camera.camera2.impl.SupportedSurfaceCombination.generateSupportedCombinationList (SupportedSurfaceCombination.java:1008)
at androidx.camera.camera2.impl.SupportedSurfaceCombination.init (SupportedSurfaceCombination.java:670)
at androidx.camera.camera2.impl.SupportedSurfaceCombination.<init> (SupportedSurfaceCombination.java:95)
at androidx.camera.camera2.impl.Camera2DeviceSurfaceManager.init (Camera2DeviceSurfaceManager.java:192)
at androidx.camera.camera2.impl.Camera2DeviceSurfaceManager.<init> (Camera2DeviceSurfaceManager.java:64)
at androidx.camera.camera2.Camera2AppConfig.create (Camera2AppConfig.java:58)
at androidx.camera.camera2.impl.Camera2Initializer.onCreate (Camera2Initializer.java:45)
at android.content.ContentProvider.attachInfo (ContentProvider.java:1940)
at android.content.ContentProvider.attachInfo (ContentProvider.java:1915)
at android.app.ActivityThread.installProvider (ActivityThread.java:6765)
at android.app.ActivityThread.installContentProviders (ActivityThread.java:6312)
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:6227)
at android.app.ActivityThread.access$1200 (ActivityThread.java:237)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:1792)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:214)
at android.app.ActivityThread.main (ActivityThread.java:7073)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:964)
CODE FRAGMENTS (this will help us troubleshoot your issues):