opentok-android-sdk-samples icon indicating copy to clipboard operation
opentok-android-sdk-samples copied to clipboard

com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1502: Caller "com.company" cannot open camera "3" from background

Open balu-m opened this issue 2 years ago • 49 comments

Caused by : swithing app foreground to background multiple times getting below crash

com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1502: Caller "com.company" (PID 103, UID 255) cannot open camera "3" from background (calling UID 103 proc state 16) at com.opentok.android.Camera2VideoCapturer.initCamera(Unknown Source:101) at com.opentok.android.Camera2VideoCapturer.a(Unknown Source:12) at com.opentok.android.Camera2VideoCapturer.$r8$lambda$EOJ6zJ_KyEal1aLQznxfTJOPcJc(Unknown Source) at com.opentok.android.Camera2VideoCapturer$$ExternalSyntheticLambda3.run(Unknown Source:4) at com.opentok.android.Camera2VideoCapturer$4.onClosed(Unknown Source:44) at android.hardware.camera2.impl.CameraDeviceImpl$5.run(CameraDeviceImpl.java:229) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loopOnce(Looper.java:226) at android.os.Looper.loop(Looper.java:313) at android.app.ActivityThread.main(ActivityThread.java:8663) at java.lang.reflect.Method.invoke(Method.java:-2) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:567) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)

balu-m avatar Jul 12 '22 10:07 balu-m

+1

AndreasKarlzzon avatar Jul 29 '22 04:07 AndreasKarlzzon

any updates on this ? :)

AndreasKarlzzon avatar Aug 09 '22 09:08 AndreasKarlzzon

Same here. Any updates on this?

Panzenbaby avatar Aug 29 '22 07:08 Panzenbaby

Hi 👋,

Is this issue reproducible on the latest version of the SDK? Please advise. Thanks! 🙏

v-kpheng avatar Oct 04 '22 12:10 v-kpheng

for me this only happens on the newest version

AndreasKarlzzon avatar Oct 05 '22 08:10 AndreasKarlzzon

Thanks, @AndreasKarlzzon.

Which models of phone are you able to reproduce this with?

v-kpheng avatar Oct 07 '22 22:10 v-kpheng

https://jira.vonage.com/browse/OPENTOK-49276

v-kpheng avatar Oct 07 '22 22:10 v-kpheng

samsung o1s (Galaxy S21 5G), samsung beyond1 (Galaxy S10), samsung x1s (Galaxy S20 5G) and more :)

AndreasKarlzzon avatar Oct 10 '22 07:10 AndreasKarlzzon

Just wanted to provide an update. We tried to reproduce on an Samsung Galaxy Z Flip 4 but didn't have any luck.

I'll see if someone has one of the devices listed and try again.

v-kpheng avatar Oct 11 '22 20:10 v-kpheng

Just wanted to provide an update. We weren't able reproduce the issue on an Samsung Galaxy S10+ either.

I wonder if we're missing a key step. @AndreasKarlzzon can you provide more detailed steps to reproduce please? Thanks!

v-kpheng avatar Oct 12 '22 16:10 v-kpheng

Just a sample:

  • Pixel 6 Pro
  • Galaxy S21 5G
  • Galaxy A53 5G
  • Galaxy A13 5G
  • moto g stylus 5G
  • Galaxy S9
  • Galaxy Note9
  • Galaxy Note20 5G

Looks like there is no correlation between the error and device. Android 9, 11, 12, 13

troolee avatar Oct 12 '22 20:10 troolee

For us, we saw this on any device that has more than 1 back camera and uses the Camera2 capturer, had to roll back from 2.24 to 2.22.3 and include the Huawei patch in our own code

Iannnr avatar Nov 15 '22 12:11 Iannnr

One of my projects has been experiencing this issue since at least SDK version 2.23.0, but I'm quite sure it happened before then as well.

My phone has four cameras, three on the back and one on the front. The cycleCamera() function switches through these four cameras, but when the last camera is selected and cycleCamera() is called again, the app crashes with a similar log.

To look into this, I ran the following code on my device:

val manager: CameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
manager.cameraIdList.forEach {
            Log.d(
                "camera",
                "id: $it isBackFacing: ${
                    (manager.getCameraCharacteristics(it)
                        .get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK)
                }"
            )
        }

I get the following result in the logs:

D/camera  (13482): id: 0 isBackFacing: true
D/camera  (13482): id: 1 isBackFacing: false
D/camera  (13482): id: 2 isBackFacing: true
D/camera  (13482): id: 3 isBackFacing: true
D/camera  (13482): id: 4 isBackFacing: true
D/camera  (13482): id: 5 isBackFacing: true
D/camera  (13482): id: 6 isBackFacing: true
D/camera  (13482): id: 7 isBackFacing: false

So the CameraManager is returning more cameras than there actually are. I then use a (deprecated) function to set the cameraId to an id of a camera that should exist: publisher?.cameraId = 0 and then one that should not exist: publisher?.cameraId = 7. CameraId 0 works, but CameraId 7 results in a crash.

Logs
E/AndroidRuntime(16771): com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_ERROR (3): endConfigure:559: Camera 7: Error configuring streams: Function not implemented (-38)
E/AndroidRuntime(16771): 	at com.opentok.android.Camera2VideoCapturer.doStartCapture(Unknown Source:173)
E/AndroidRuntime(16771): 	at com.opentok.android.Camera2VideoCapturer.c(Unknown Source:0)
E/AndroidRuntime(16771): 	at com.opentok.android.Camera2VideoCapturer.$r8$lambda$Ja1sVxV4wLYhzOqCHGFwz3iLgIQ(Unknown Source:0)
E/AndroidRuntime(16771): 	at com.opentok.android.Camera2VideoCapturer$$ExternalSyntheticLambda0.run(Unknown Source:2)
E/AndroidRuntime(16771): 	at com.opentok.android.Camera2VideoCapturer$4.onOpened(Unknown Source:40)
E/AndroidRuntime(16771): 	at android.hardware.camera2.impl.CameraDeviceImpl$1.run(CameraDeviceImpl.java:165)
E/AndroidRuntime(16771): 	at android.os.Handler.handleCallback(Handler.java:938)
E/AndroidRuntime(16771): 	at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime(16771): 	at android.os.Looper.loopOnce(Looper.java:201)
E/AndroidRuntime(16771): 	at android.os.Looper.loop(Looper.java:288)
E/AndroidRuntime(16771): 	at android.app.ActivityThread.main(ActivityThread.java:7842)
E/AndroidRuntime(16771): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime(16771): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:550)
E/AndroidRuntime(16771): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)

Notice how the first line says "Camera 7: Error configuring streams: Function not implemented". OpenTok/Vonage should implement a handler that takes care of this issue.


I currently "fix" this issue using the following code:

val manager: CameraManager = getSystemService(CAMERA_SERVICE) as CameraManager
val frontCameraId: String? = manager.cameraIdList.first { id: String ->
     manager.getCameraCharacteristics(id)
           .get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT
     }
val backCameraId: String? = manager.cameraIdList.first { id: String ->
     manager.getCameraCharacteristics(id)
           .get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK
     }

binding.buttonSwitchCam.setOnClickListener {
    if (mPublisher?.cameraId == frontCameraId?.toInt()) {
          backCameraId?.toInt()?.let {
                  mPublisher?.cameraId = it
          }
     } else {
          frontCameraId?.toInt()?.let {
                  mPublisher?.cameraId = it
           }
     }
}

I would like to request OpenTok does not deprecate the getCameraId/setCameraId functionality, but update it to accept strings in stead of integers, as the CameraManager returns camera ids in the form of strings.


Update:

After releasing this code I noticed some crashes. If you use this solution make sure you have the camera permission. Updated code:

val frontCameraIndex: Int = manager.cameraIdList.indexOfFirst { id: String ->
    manager.getCameraCharacteristics(id)
        .get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT
}
val backCameraIndex: Int = manager.cameraIdList.indexOfFirst { id: String ->
    manager.getCameraCharacteristics(id)
        .get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_BACK
}

buttonSwitchCam.setOnClickListener {
    if (mPublisher?.cameraId == frontCameraIndex) {
        if (backCameraIndex != -1) {
            mPublisher?.cameraId = backCameraIndex
        }
    } else {
        if (frontCameraIndex != -1) {
            mPublisher?.cameraId = frontCameraIndex
        }
    }
}

This works better with the implementation of Publisher.getCameraId/setCameraId.

Siarl avatar Nov 22 '22 14:11 Siarl

Any updates on this?

We started seeing this in Crashlytics after updating to the latest version (2.24.0). The problem seems to be indeed caused by cycling the camera and it happened so far on the following devices (according to Crashlytics): Xiaomi Mi 10 lite Xiaomi Redmi Note 10 Pro Samsung Galaxy S10e Galaxy S20 Galaxy Tab S7 FE

Corina777 avatar Nov 30 '22 14:11 Corina777

We have started seeing this issue too, I am not sure if we have seen it before 2.24.0. A recent crash happened on Galaxy S21+ 5G running Android 12.

DanielNovak avatar Dec 02 '22 14:12 DanielNovak

It seems that the latest OpenTok versions don't really play well with devices that have multiple cameras. For example Huawei P30 is broken, but Pixel 4a is fine.

How to reproduce: Use a device with more than 2 cameras. Start a session with camera and then call swapCamera() to switch to the back camera. Now end session. If you start another session again (without restarting the app process) then the camera view will be black.

This has been a bug for so long - we already had a workaround in the past where we would call swapCamera() again to switch back to the front camera when you end the call. But on 2.24.0 this doesn't work because of the multiple camera support bug.

So basically we now use a similar code like posted above, we keep a list of front and back cameras IDs. And when you end the call we check if user.cameraId is an ID from the list of back cameras. If yes then we use user.cameraId = frontCameraIndexes.first() to switch to the front camera again. This fixes the bug when next sessions have a black camara view. But it's just a horrible hack and workaround around OpenTok issues.

DanielNovak avatar Dec 08 '22 09:12 DanielNovak

Also - swapCamera() will iterate over all cameras on the device. So on a Huwaei it will not switch between front and back, it will switch to back normal, back wide, back macro and then front. I think that OpenTok should only switch between the default back and front. You can use user.cameraId to switch to a specific camera.

DanielNovak avatar Dec 08 '22 11:12 DanielNovak

Thanks everyone for all your input.

Someone on the team has a Pixel 6, which has multiple cameras. We'll try to reproduce using that. Will keep you posted.

v-kpheng avatar Dec 14 '22 23:12 v-kpheng

Hi, @v-kpheng I would appreciate if you have any status updates on this.

I work for a large organization that uses OpenTalk and we are suffering from the same issue after using the 2.24.0 version.

Thanks

fpiresca avatar Jan 05 '23 21:01 fpiresca

@fpiresca, sorry for the lack of updates. The "someone" on the team with the Pixel 6 was me and I just came back from vacation.

Issue is still on our sprint. Will provide an update soon.

v-kpheng avatar Jan 05 '23 22:01 v-kpheng

Thanks for the fast response @v-kpheng I appreciate the support.

fpiresca avatar Jan 05 '23 22:01 fpiresca

Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1226: Caller "com.android.phoenix" (PID 10042, UID 25578) cannot open camera "0" from background (calling UID 10042 proc state 12).

can any body help

sudhirchoudhary avatar Jan 07 '23 07:01 sudhirchoudhary

@v-kpheng any updates? We are also seeing this issue in production.

muratke avatar Jan 24 '23 22:01 muratke

Same here. We have an app in production that is affected by this issue, and we have not come up with a way to workaround it.

driq avatar Jan 25 '23 11:01 driq

Hi @v-kpheng, could you please provide an update on this issue? It's been over a month since you promised an update. :disappointed: We see lots of these crashes happening in our production app, and the number of crash-free sessions has plummeted significantly due to this issue.

Roman-hub avatar Feb 13 '23 09:02 Roman-hub

@Roman-hub, sorry, progress was stalled because of my vacation and higher priority items. I have bandwidth to look into this now.

v-kpheng avatar Feb 13 '23 19:02 v-kpheng

Just wanted to share an update. I couldn't reproduce on my Pixel 6. While doing cycleCamera I noticed that only one of the rear cameras appeared. This is probably why I can't reproduce.

I asked my colleague to try to reproduce again on her Samsung Z Fold 4, which has three physical rear cameras.

v-kpheng avatar Feb 13 '23 22:02 v-kpheng

Hello @v-kpheng According to our crash data, 90% of crashes are coming from samsung devices and 100% background. Could you please try to reproduce this from Samsung Note. this is critical issue for us. thanks Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1299/.../cannot open camera "1" from background

pc-anuruddha avatar Feb 15 '23 15:02 pc-anuruddha

Thanks, @pc-anuruddha. We'll need to try to get our hands on a Samsung Note 🤞.

My colleague tried to reproduce again on her Samsung Z Fold 3 but couldn't, despite it having multiple rear cameras. This was her test method:

  • Use "cycleCamera" to iterate through cameras until a rear camera is displayed
  • Send app to background and back to foreground multiple times, to try to get it to crash

The app never crashed. She also tried to set it to a different rear camera, but no luck there either.

v-kpheng avatar Feb 15 '23 19:02 v-kpheng

@v-kpheng Could there be a problem with a session restart? In our app an event can be sent to the signaling channel indicating the need to restart the session. In that case current session is ended, using session.disconnect(), and a new one is started. We don't call cycleCamera() anywhere in our code.

Roman-hub avatar Feb 16 '23 10:02 Roman-hub