OSDN Git Service

Check for a potentially destroyed activity before startPreview.
authorPaul Rohde <codelogic@google.com>
Thu, 30 Apr 2015 18:08:23 +0000 (11:08 -0700)
committerPaul Rohde <codelogic@google.com>
Fri, 1 May 2015 21:59:29 +0000 (14:59 -0700)
There is a small chance that the activity can be destroyed
between the time the camera is created and the preview is started.
This can lead to unchecked NPE's across the app because most code
assumes that there will never be a case where activity objects
are accessed after onDestroy.

Bug: 20097425
Change-Id: I2904ffba451ded2417a806c83fd12e4f62611150

src/com/android/camera/CameraActivity.java
src/com/android/camera/CaptureModule.java
src/com/android/camera/captureintent/event/EventOnOpenCameraSucceeded.java
src/com/android/camera/captureintent/state/StateOpeningCamera.java
src/com/android/camera/one/OneCamera.java
src/com/android/camera/one/v2/Camera2OneCameraOpenerImpl.java

index 0b65b3e..024cce3 100644 (file)
@@ -2076,6 +2076,9 @@ public class CameraActivity extends QuickActivity
             unregisterReceiver(mShutdownReceiver);
         }
 
+        // Ensure anything that checks for "isPaused" returns true.
+        mPaused = true;
+
         mSettingsManager.removeAllListeners();
         mCameraController.removeCallbackReceiver();
         mCameraController.setCameraExceptionHandler(null);
index 3e96ad3..91619eb 100644 (file)
@@ -92,6 +92,8 @@ import com.google.common.logging.eventprotos;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 
+import javax.annotation.Nonnull;
+
 /**
  * New Capture module that is made to support photo and video capture on top of
  * the OneCamera API, to transparently support GCam.
@@ -1366,10 +1368,19 @@ public class CaptureModule extends CameraModule implements
                   }
 
                   @Override
-                  public void onCameraOpened(final OneCamera camera) {
+                  public void onCameraOpened(@Nonnull final OneCamera camera) {
                       Log.d(TAG, "onCameraOpened: " + camera);
                       mCamera = camera;
 
+                      // A race condition exists where the camera may be in the process
+                      // of opening (blocked), but the activity gets destroyed. If the
+                      // preview is initialized or callbacks are invoked on a destroyed
+                      // activity, bad things can happen.
+                      if (mAppController.isPaused()) {
+                          onFailure();
+                          return;
+                      }
+
                       // When camera is opened, the zoom is implicitly reset to 1.0f
                       mZoomValue = 1.0f;
 
index 30ce371..a3b0884 100644 (file)
@@ -19,10 +19,12 @@ package com.android.camera.captureintent.event;
 import com.android.camera.captureintent.stateful.Event;
 import com.android.camera.one.OneCamera;
 
+import javax.annotation.Nonnull;
+
 public class EventOnOpenCameraSucceeded implements Event {
     private final OneCamera mCamera;
 
-    public EventOnOpenCameraSucceeded(OneCamera camera) {
+    public EventOnOpenCameraSucceeded(@Nonnull OneCamera camera) {
         mCamera = camera;
     }
 
index 563507f..1b27c6c 100644 (file)
@@ -48,6 +48,8 @@ import com.android.camera.util.Size;
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
 
+import javax.annotation.Nonnull;
+
 /**
  * Represents a state that the module is waiting for a camera to be opened.
  */
@@ -81,7 +83,7 @@ public final class StateOpeningCamera extends StateImpl {
         }
 
         @Override
-        public void onCameraOpened(final OneCamera camera) {
+        public void onCameraOpened(@Nonnull final OneCamera camera) {
             getStateMachine().processEvent(new EventOnOpenCameraSucceeded(camera));
         }
     };
index 218c1e4..1f2cb66 100644 (file)
@@ -81,7 +81,7 @@ public interface OneCamera {
          *
          * @param camera the camera instance that was successfully opened
          */
-        public void onCameraOpened(OneCamera camera);
+        public void onCameraOpened(@Nonnull OneCamera camera);
 
         /**
          * Called if opening the camera failed.
index 1ddf69d..3529310 100644 (file)
@@ -175,7 +175,13 @@ public class Camera2OneCameraOpenerImpl implements OneCameraOpener {
                                     imageRotationCalculator,
                                     burstController,
                                     soundPlayer, fatalErrorHandler);
-                            openCallback.onCameraOpened(oneCamera);
+
+                            if (oneCamera != null) {
+                                openCallback.onCameraOpened(oneCamera);
+                            } else {
+                                Log.d(TAG, "Could not construct a OneCamera object!");
+                                openCallback.onFailure();
+                            }
                         } catch (CameraAccessException e) {
                             Log.d(TAG, "Could not get camera characteristics", e);
                             openCallback.onFailure();