Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 593f1735 authored by wenbinw's avatar wenbinw Committed by Steve Kondik
Browse files

Camera: Fix camcorder crash during pause and resume

When camcorder is suspended in background, if it receives resume
and pause event in very short interval, crash will happen.
After receiving resume event, the onresume method will be called,
and it will start another thread for starting preview. And soon,
the main thread receives pause event, the onpause method which will
close camera is called.
There will be a racing between the main thread and start preview
thread. If close camera get done first, crash will be observed.
To avoid the racing, the close camera operation should wait for the
start preview operation, and the join method is used here for
synchronization.

CRs-Fixed: 526007
Change-Id: Idf6a8660378bf1a65af1f5194a35d30822f1dcf6
parent 2c0ca4de
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -236,6 +236,15 @@ public class CameraScreenNail extends SurfaceTextureScreenNail {
        mListener.requestRender();
    }

    public void cancelAcquire() {
         synchronized (mLock) {
            if (mAcquireTexture) {
                mAcquireTexture = false;
                mLock.notifyAll();
            }
         }
    }

    @Override
    public void releaseSurfaceTexture() {
        synchronized (mLock) {
+46 −13
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ public class VideoModule implements CameraModule,
    private static final int SWITCH_CAMERA_START_ANIMATION = 9;
    private static final int HIDE_SURFACE_VIEW = 10;
    private static final int CAPTURE_ANIMATION_DONE = 11;
    private static final int START_PREVIEW_DONE = 12;

    private static final int SCREEN_DELAY = 2 * 60 * 1000;

@@ -192,6 +193,8 @@ public class VideoModule implements CameraModule,
    private int mVideoWidth;
    private int mVideoHeight;

    private StartPreviewThread mStartPreviewThread;

    private final MediaSaveService.OnMediaSavedListener mOnVideoSavedListener =
            new MediaSaveService.OnMediaSavedListener() {
                @Override
@@ -223,6 +226,16 @@ public class VideoModule implements CameraModule,
        }
    }

    private class StartPreviewThread extends Thread {
        @Override
        public void run() {
            try {
                startPreview();
            }catch (Exception e) {
            }
        }
    }

    private void openCamera() {
        try {
            synchronized(mCameraOpened) {
@@ -305,6 +318,11 @@ public class VideoModule implements CameraModule,
                    break;
                }

                case START_PREVIEW_DONE: {
                    mStartPreviewThread = null;
                    break;
                }

                default:
                    Log.v(TAG, "Unhandled message: " + msg.what);
                    break;
@@ -408,14 +426,16 @@ public class VideoModule implements CameraModule,
            // ignore
        }

        CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
        if (screenNail.getSurfaceTexture() == null) {
            screenNail.acquireSurfaceTexture();
        }

        readVideoPreferences();
        mUI.setPrefChangedListener(this);
        new Thread(new Runnable() {
            @Override
            public void run() {
                startPreview();
            }
        }).start();

        mStartPreviewThread = new StartPreviewThread();
        mStartPreviewThread.start();

        mQuickCapture = mActivity.getIntent().getBooleanExtra(EXTRA_QUICK_CAPTURE, false);
        mLocationManager = new LocationManager(mActivity, null);
@@ -790,12 +810,14 @@ public class VideoModule implements CameraModule,
            }
            readVideoPreferences();
            resizeForPreviewAspectRatio();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    startPreview();

            CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
            screenNail.cancelAcquire();
            if (screenNail.getSurfaceTexture() == null) {
                screenNail.acquireSurfaceTexture();
            }
            }).start();
            mStartPreviewThread = new StartPreviewThread();
            mStartPreviewThread.start();
        } else {
            // preview already started
            mUI.enableShutter(true);
@@ -906,6 +928,7 @@ public class VideoModule implements CameraModule,

    private void onPreviewStarted() {
        mUI.enableShutter(true);
        mHandler.sendEmptyMessage(START_PREVIEW_DONE);
    }

    @Override
@@ -930,6 +953,16 @@ public class VideoModule implements CameraModule,

    // By default, we want to close the effects as well with the camera.
    private void closeCamera() {
        CameraScreenNail screenNail = (CameraScreenNail) mActivity.mCameraScreenNail;
        screenNail.cancelAcquire();
        try {
            if (mStartPreviewThread != null) {
                mStartPreviewThread.interrupt();
                mStartPreviewThread.join();
                mStartPreviewThread = null;
            }
        } catch (InterruptedException e) {
        }
        closeCamera(true);
    }

@@ -1929,7 +1962,7 @@ public class VideoModule implements CameraModule,
            mActivity.notifyScreenNailChanged();
        }

        if (screenNail.getSurfaceTexture() == null) {
        if (mStartPreviewThread == null && screenNail.getSurfaceTexture() == null) {
            screenNail.acquireSurfaceTexture();
        }
    }