4

While testing performance of Android Camera2 API I noticed bug connected with ImageReader.

When application is launched onImageAvailable() function is being invoked correctly but after locking and unlocking screen it is not invoked at all. The part of my application which deals with camera is based on Camera2Basic Google tutorial.

What is more, I have installed Camera2Basic Android demo app which presents Camera2 API and I find out that even this app made by Google has the same problem.

Is there some kind of solution to this problem?

After some time spend while using Debug tool in Android Studio I found that the problem with onImageAvailable() function being called occurs only if TextureView that is used to preview is available in onResume() function.

@Override
public void onResume() {
    super.onResume();
    startBackgroundThread();

    // When the screen is turned off and turned back on, the SurfaceTexture is already
    // available, and "onSurfaceTextureAvailable" will not be called. In that case, we can open
    // a camera and start preview from here (otherwise, we wait until the surface is ready in
    // the SurfaceTextureListener).
    if (mTextureView.isAvailable()) {
        openCamera(mTextureView.getWidth(), mTextureView.getHeight());
    } else {
        mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
    }
}

If mTextureView.isAvailable() returns false and SurfaceTextureListener is set on mTextureView then onImageAvailable() is called properly but if function openCamera(mTextureView.getWidth(), mTextureView.getHeight()) is invoked in onResume() the problem occurs.

wkurek
  • 43
  • 6
  • You expect the ImageReader to deliver preview frames at 30 fps (or whatever frame rate you request when you build the capture session), don't you? One of the reasons it stops after screen unlock, could be that the preview surface used as preview builder target is gone. In this case, you should start preview in your activity onResume(). – Alex Cohn Feb 05 '18 at 20:19
  • I start background thread, create `ImageReader`, open camera and start preview in `onResume()` method. In `onPause` method I close camera, close ImageReader and stop background thread. – wkurek Feb 05 '18 at 21:41
  • I have checked **Camera2Basic** and for me the **onImageAvailable()** callback is invoked after unlock. But for me, to lock the screen, I turn it off; so, unlock involves also screen wakeup. – Alex Cohn Feb 06 '18 at 10:15
  • I have cloned [Camera2Basic](https://github.com/googlesamples/android-Camera2Basic) repository to Android Studio and examined function `onImageAvailable()` being called using Debuger tool. The function seems not to be called after locking and then unlocking screen. – wkurek Feb 06 '18 at 12:38
  • How do you lock the screen? – Alex Cohn Feb 06 '18 at 13:17
  • 1
    I just simply click the lock button on my smartphone. I'm not sure if you've noticed additional observations that i included in main post. – wkurek Feb 06 '18 at 13:40
  • The lock button turns the screen black, doesn't it? And then you click the same button to see the lock screen, and swipe it to proceed (or enter PIN code, or whatever)? – Alex Cohn Feb 06 '18 at 15:14
  • Yes, exactly. Has it some bad impact on Camera2 API? I consider this scenario of locking and unlocking smartphone while using app as rather common. – wkurek Feb 06 '18 at 15:30
  • No, this has nothing to do with **camera2**, but all about the **Surface** lifecycle. Unfortunately, I could not reproduce the scenario when **onResume()** comes with `mTextureView.isAvailable() == true`. One possible workaround is to force the surface to be gone. – Alex Cohn Feb 06 '18 at 21:44
  • 1
    I found out that if i set `SurfaceTextureListener` to `mTextureView` then `onSurfaceTextureAvailable()` function is always called even if `mTextureView.isAvailable() == true`. It solved problem but I still do not fully understand why it is in this way. – wkurek Feb 07 '18 at 08:31
  • After fine-tuning the phone settings I could arrive to onResume() with mTextureView.isAvailable(), and my Camera2Basic went through the 'fast' route (calling `openCamera()` directly). Even in this case, onImageAvailable() callback was invoked after resume. – Alex Cohn Feb 07 '18 at 09:26
  • So in your case, it looks like your **mTextureView** still holds a non-null **mSurface**, but it is dead. I suggest that you check what `mTextureView.getSurfaceTextureListener()` returns inside **onResume()**. I would say, `mTextureView.setSurfaceTextureListener(mSurfaceTextureListener);` line can never hurt. But the clause `if (mTextureView.isAvailable()) { openCamera(mTextureView.getWidth(), mTextureView.getHeight()); }` also cannot hurt. – Alex Cohn Feb 07 '18 at 09:32
  • One possible problem could be that your camera activity runs in Landscape, but lock screen forces portrait orientation. Such 'screen rotation on wakeup' leads sometimes to weird effects, if not treated correctly, and on some devices this scenario may be buggy. – Alex Cohn Feb 07 '18 at 09:50
  • At any rate, please do open an [*issue*](https://github.com/googlesamples/android-Camera2Basic/issues) about what you found for Camera2Basic sample. – Alex Cohn Feb 07 '18 at 10:02

0 Answers0