opentok / opentok-android-sdk-samples

Sample applications illustrating best practices using OpenTok Android SDK.
https://tokbox.com/developer/sdks/android/
MIT License
210 stars 169 forks source link

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

Closed balu-m closed 6 days ago

balu-m commented 2 years ago

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)

AndreasKarlzzon commented 2 years ago

+1

AndreasKarlzzon commented 1 year ago

any updates on this ? :)

Panzenbaby commented 1 year ago

Same here. Any updates on this?

v-kpheng commented 1 year ago

Hi 👋,

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

AndreasKarlzzon commented 1 year ago

for me this only happens on the newest version

v-kpheng commented 1 year ago

Thanks, @AndreasKarlzzon.

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

v-kpheng commented 1 year ago

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

AndreasKarlzzon commented 1 year ago

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

v-kpheng commented 1 year ago

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 commented 1 year ago

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!

troolee commented 1 year ago

Just a sample:

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

Iannnr commented 1 year ago

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

Siarl commented 1 year ago

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.

Corina777 commented 1 year ago

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

DanielNovak commented 1 year ago

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 commented 1 year ago

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 commented 1 year ago

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.

v-kpheng commented 1 year ago

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.

fpiresca commented 1 year ago

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

v-kpheng commented 1 year ago

@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.

fpiresca commented 1 year ago

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

sudhirchoudhary commented 1 year ago

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

muratke commented 1 year ago

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

driq commented 1 year ago

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.

Roman-hub commented 1 year ago

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.

v-kpheng commented 1 year ago

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

v-kpheng commented 1 year ago

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.

pc-anuruddha commented 1 year ago

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

v-kpheng commented 1 year ago

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:

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

Roman-hub commented 1 year ago

@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.

v-kpheng commented 1 year ago

@Roman-hub, can you please create a PR against one of the sample apps? Hopefully we'll be able to reproduce it this time 🤞

AndreasKarlzzon commented 1 year ago

This can also happen if the app is running the video stream in the background and it swaps the camera

inflamesonly commented 1 year ago

fix this crash, please!

Bro29000 commented 1 year ago

This is a very bad bug that has a bad impact on the user experience, our company gets a lot of negativity. Please raise the priority of the problem.

v-kpheng commented 1 year ago

Can someone please see if the issue goes away with 2.24.2? The crashes might be due to camera resources not being released properly, which was recently fixed.

Roman-hub commented 1 year ago

@v-kpheng We still see these crashes with 2.24.2 library version.

Roman-hub commented 1 year ago

It's even worse in the latest library version. A new crash started popping up, on top of the old ones mentioned in this thread:

Fatal Exception: java.lang.IllegalStateException: Session has been closed; further changes are illegal. at android.hardware.camera2.impl.CameraCaptureSessionImpl.checkNotClosed(CameraCaptureSessionImpl.java:834) at android.hardware.camera2.impl.CameraCaptureSessionImpl.stopRepeating(CameraCaptureSessionImpl.java:402) at com.opentok.android.Camera2VideoCapturer.stopCapture(:29) at com.opentok.android.PublisherKit.d(:4) at com.opentok.android.PublisherKit.$r8$lambda$6BMkMXi2EstSU_HgeV7ZQb4y6yA() at com.opentok.android.PublisherKit$$ExternalSyntheticLambda14.run(:2) at android.os.Handler.handleCallback(Handler.java:873) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:214) at android.app.ActivityThread.main(ActivityThread.java:7050) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:494) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:965)

DanielNovak commented 1 year ago

@Roman-hub

I was able to get rid of this newest crash by making sure that we don't call session.onPause + session.onResume more than once in quick succession. Maybe add logging when you do this calls to see if you are not calling it several times. But - OpenTok should make sure we don't need to add workarounds and they should handle this internally.

Overall the newest version helped us to get rid of all the other workarounds we had in code to get OpenTok to work correctly. But we will see if we keep getting new crashes once we deploy this to production...

Roman-hub commented 1 year ago

@DanielNovak Thanks for the advice! Will check it out.

v-kpheng commented 1 year ago

@DanielNovak, @Roman-hub, or anyone, really...

Can someone please give me an example (maybe as a PR?) of how to reproduce this problem using one of the sample apps?

jrdaher commented 1 year ago

Plus one on the thread. I tried a few things but still couldn't find a workaround for this.

jrdaher commented 1 year ago

I dont know if my logs add any value but I am guessing they could help fix this issue so here goes:

Most affected device: Moto g pure Most affected android version: 13 Place of crash : 95% background

com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_DISABLED (1): validateClientPermissionsLocked:1560: Caller "com.varsitytutors.tutoringtools" (PID 10270, UID 12887) cannot open camera "1" from background (calling UID 10270 proc state 15)
    com.opentok.android.Camera2VideoCapturer.initCamera(SourceFile:70)
    com.opentok.android.Camera2VideoCapturer.$r8$lambda$EOJ6zJ_KyEal1aLQznxfTJOPcJc(SourceFile:15)
    com.opentok.android.Camera2VideoCapturer.$r8$lambda$EOJ6zJ_KyEal1aLQznxfTJOPcJc(SourceFile:0)
    com.opentok.android.Camera2VideoCapturer$$InternalSyntheticLambda$1$a584d3ebc8d132fd4b66cb4078f8bb1f3b20fd84f6152b5277de9aa5ac276da7$0.run(Camera2VideoCapturer.java:4)
    com.opentok.android.Camera2VideoCapturer$4.onClosed(SourceFile:44)
    android.hardware.camera2.impl.CameraDeviceImpl$5.run(CameraDeviceImpl.java:237)
    android.os.Handler.handleCallback(Handler.java:942)
    android.os.Handler.dispatchMessage(Handler.java:99)
    android.os.Looper.loopOnce(Looper.java:226)
    android.os.Looper.loop(Looper.java:313)
    android.app.ActivityThread.main(ActivityThread.java:8757)
    java.lang.reflect.Method.invoke(Method.java:0)
    com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
    com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
intrepid-ab commented 1 year ago

In my case this issue seems to be caused when trying to establish a video call while an app is in the background. So any app on android 11 or higher will see this if there is an attempt to start the video. Here is the android documentation on this.

v-kpheng commented 1 year ago

I'm going to put this back in the backlog. Sorry. If someone can provide a simple sample app to reproduce the issue, we'll look into it again.

AndreasKarlzzon commented 1 year ago

@v-kpheng have you tried changing the camera or starting the call when you have the app goes to/is in the background? seems that it does not consider this and tries = Crash

rohitbhoitevhi commented 1 year ago

+1

advaitsaravade commented 1 year ago

This issue doesn't happen regularly, is difficult to replicate reliably, and in my opinion, is isolated to slower devices. I tested with the emulator, and was not seeing it occur, but when tested on a older, slower device it occurred once every 4 minutes of testing.

I was not able to reproduce this reliably, but one way was to call onResume and onPause on the session object in quick succession. This was my stack trace of the crash on a slow device:

Fatal Exception: com.opentok.android.Camera2VideoCapturer$Camera2Exception: CAMERA_IN_USE (4): connectHelper:1749: Higher-priority client using camera, ID "0" currently unavailable at com.opentok.android.Camera2VideoCapturer.initCamera(Camera2VideoCapturer.java:79) at com.opentok.android.Camera2VideoCapturer.startCapture(Camera2VideoCapturer.java:51) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:250) at android.app.ActivityThread.main(ActivityThread.java:7851) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

derekpitts28 commented 10 months ago

This is happening on production for us also. Device: Pixel 6 Android 13 Vonage SDK: 2.26

We see this occur when closing a previous session and creating a new close together. There seems to be no 'good' or recommended way to close a session other than nulling its reference and hoping that the garbage collector collects. That being said we are trying to use the life cycle methods to gracefully close the vonage session. Currently we are doing the following to close the old session before creating a new one:

If you run this code to close the previous sessions references x3-4 times you will run into the error i got.

session?.onPause()
patientPublisher?.onStop()

The main issue seems to be that vonage is attempting to remove something that does not exist.

The fact that I have to jump though so many hoops just to dispose and ensure vonage is not controlling the camera anymore is a bit crazy to me.

FATAL EXCEPTION: main
Process: com.transcarent.app, PID: 550
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.os.Handler.removeCallbacks(java.lang.Runnable)' on a null object reference
    at com.opentok.android.Camera2VideoCapturer.stopDisplayOrientationCache(Unknown Source:4)
    at com.opentok.android.Camera2VideoCapturer.destroy(Unknown Source:11)
    at com.opentok.android.PublisherKit.a(Unknown Source:4)
    at com.opentok.android.PublisherKit.z(Unknown Source:0)
    at com.opentok.android.m0.run(Unknown Source:2)
    at android.os.Handler.handleCallback(Handler.java:942)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7918)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

It should be noted we have also tried to go directly to the capture of the publisher and stop that however stopping that results in a separate error.

Please give us a guaranteed way to COMPLETELY dispose of a session/publisher this is so frustrating.

sofi-kry commented 8 months ago

We are experiencing this issue too, most devices are Samsung.

jintgeorge commented 6 days ago

Not able to repro on Galaxy M51 and Huawei P30 with latest code. Closing this.