Bug 850845 - don't dereference null mCameraHw pointer, r=sotaro
authorMike Habicher <mikeh@mozilla.com>
Thu, 14 Mar 2013 17:30:38 -0400
changeset 124969 6d3f1e3ccf5cf8d6256bab68a7de4c6205b925b5
parent 124968 9421582028249b1c37602bc3806bf4e8794829cc
child 124970 0d24c96dfd4dde40260c97603d56d157938ab7c6
push idunknown
push userunknown
push dateunknown
reviewerssotaro
bugs850845
milestone22.0a1
Bug 850845 - don't dereference null mCameraHw pointer, r=sotaro
dom/camera/GonkCameraControl.cpp
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -52,16 +52,24 @@ using namespace android;
  * support 'yuv420p' as a preview format, actually ignore this setting
  * and return 'yuv420sp' data anyway.  We have come across a new implementation
  * that, while reporting that 'yuv420p' is supported *and* has been accepted,
  * still returns the frame data in 'yuv420sp' anyway.  So for now, since
  * everyone seems to return this format, we just force it.
  */
 #define FORCE_PREVIEW_FORMAT_YUV420SP   1
 
+#define RETURN_IF_NO_CAMERA_HW()                                          \
+  do {                                                                    \
+    if (!mCameraHw.get()) {                                               \
+      DOM_CAMERA_LOGE("%s:%d : mCameraHw is null\n", __func__, __LINE__); \
+      return NS_ERROR_NOT_AVAILABLE;                                      \
+    }                                                                     \
+  } while(0)
+
 static const char* getKeyText(uint32_t aKey)
 {
   switch (aKey) {
     case CAMERA_PARAM_EFFECT:
       return CameraParameters::KEY_EFFECT;
     case CAMERA_PARAM_WHITEBALANCE:
       return CameraParameters::KEY_WHITE_BALANCE;
     case CAMERA_PARAM_SCENEMODE:
@@ -224,16 +232,21 @@ void nsGonkCameraControl::DispatchInit(n
   nsCOMPtr<nsIRunnable> init = new InitGonkCameraControl(this, aDOMCameraControl, onSuccess, onError, aWindowId);
   mCameraThread->Dispatch(init, NS_DISPATCH_NORMAL);
 }
 
 nsresult
 nsGonkCameraControl::Init()
 {
   mCameraHw = GonkCameraHardware::Connect(this, mCameraId);
+  if (!mCameraHw.get()) {
+    DOM_CAMERA_LOGE("Failed to connect to camera %d (this=%p)\n", mCameraId, this);
+    return NS_ERROR_FAILURE;
+  }
+
   DOM_CAMERA_LOGI("Initializing camera %d (this=%p, mCameraHw=%p)\n", mCameraId, this, mCameraHw.get());
 
   // Initialize our camera configuration database.
   PullParametersImpl();
 
   // Try to set preferred image format and frame rate
 #if !FORCE_PREVIEW_FORMAT_YUV420SP
   DOM_CAMERA_LOGI("Camera preview formats: %s\n", mParams.get(mParams.KEY_SUPPORTED_PREVIEW_FORMATS));
@@ -275,17 +288,17 @@ nsGonkCameraControl::Init()
   mMaxMeteringAreas = mParams.getInt(mParams.KEY_MAX_NUM_METERING_AREAS);
   mMaxFocusAreas = mParams.getInt(mParams.KEY_MAX_NUM_FOCUS_AREAS);
 
   DOM_CAMERA_LOGI(" - minimum exposure compensation: %f\n", mExposureCompensationMin);
   DOM_CAMERA_LOGI(" - exposure compensation step:    %f\n", mExposureCompensationStep);
   DOM_CAMERA_LOGI(" - maximum metering areas:        %d\n", mMaxMeteringAreas);
   DOM_CAMERA_LOGI(" - maximum focus areas:           %d\n", mMaxFocusAreas);
 
-  return mCameraHw.get() != nullptr ? NS_OK : NS_ERROR_FAILURE;
+  return NS_OK;
 }
 
 nsGonkCameraControl::~nsGonkCameraControl()
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p, mCameraHw = %p\n", __func__, __LINE__, this, mCameraHw.get());
 
   ReleaseHardwareImpl(nullptr);
   if (mRwLock) {
@@ -646,16 +659,18 @@ nsGonkCameraControl::StartPreviewImpl(St
   if (aStartPreview->mDOMPreview) {
     StopPreviewInternal(true /* forced */);
     mDOMPreview = aStartPreview->mDOMPreview;
   } else if (!mDOMPreview) {
     return NS_ERROR_INVALID_ARG;
   }
 
   DOM_CAMERA_LOGI("%s: starting preview (mDOMPreview=%p)\n", __func__, mDOMPreview);
+
+  RETURN_IF_NO_CAMERA_HW();
   if (mCameraHw->StartPreview() != OK) {
     DOM_CAMERA_LOGE("%s: failed to start preview\n", __func__);
     return NS_ERROR_FAILURE;
   }
 
   if (aStartPreview->mDOMPreview) {
     mDOMPreview->Started();
   }
@@ -665,17 +680,19 @@ nsGonkCameraControl::StartPreviewImpl(St
 nsresult
 nsGonkCameraControl::StopPreviewInternal(bool aForced)
 {
   DOM_CAMERA_LOGI("%s: stopping preview (mDOMPreview=%p)\n", __func__, mDOMPreview);
 
   // StopPreview() is a synchronous call--it doesn't return
   // until the camera preview thread exits.
   if (mDOMPreview) {
-    mCameraHw->StopPreview();
+    if (mCameraHw.get()) {
+      mCameraHw->StopPreview();
+    }
     mDOMPreview->Stopped(aForced);
     mDOMPreview = nullptr;
   }
 
   return NS_OK;
 }
 
 nsresult
@@ -683,22 +700,25 @@ nsGonkCameraControl::StopPreviewImpl(Sto
 {
   return StopPreviewInternal();
 }
 
 nsresult
 nsGonkCameraControl::AutoFocusImpl(AutoFocusTask* aAutoFocus)
 {
   if (aAutoFocus->mCancel) {
-    mCameraHw->CancelAutoFocus();
+    if (mCameraHw.get()) {
+      mCameraHw->CancelAutoFocus();
+    }
   }
 
   mAutoFocusOnSuccessCb = aAutoFocus->mOnSuccessCb;
   mAutoFocusOnErrorCb = aAutoFocus->mOnErrorCb;
 
+  RETURN_IF_NO_CAMERA_HW();
   if (mCameraHw->AutoFocus() != OK) {
     return NS_ERROR_FAILURE;
   }
   return NS_OK;
 }
 
 void
 nsGonkCameraControl::SetupThumbnail(uint32_t aPictureWidth, uint32_t aPictureHeight, uint32_t aPercentQuality)
@@ -738,22 +758,26 @@ nsGonkCameraControl::SetupThumbnail(uint
     SetParameter(CAMERA_PARAM_THUMBNAILHEIGHT, static_cast<int>(h));
   }
 }
 
 nsresult
 nsGonkCameraControl::TakePictureImpl(TakePictureTask* aTakePicture)
 {
   if (aTakePicture->mCancel) {
-    mCameraHw->CancelTakePicture();
+    if (mCameraHw.get()) {
+      mCameraHw->CancelTakePicture();
+    }
   }
 
   mTakePictureOnSuccessCb = aTakePicture->mOnSuccessCb;
   mTakePictureOnErrorCb = aTakePicture->mOnErrorCb;
 
+  RETURN_IF_NO_CAMERA_HW();
+
   // batch-update camera configuration
   mDeferConfigUpdate = true;
 
   if (aTakePicture->mSize.width != mLastPictureWidth || aTakePicture->mSize.height != mLastPictureHeight) {
     /**
      * height and width: some drivers are less friendly about getting one of
      * these set to zero, so if either is not specified, ignore both and go
      * with current or default settings.
@@ -839,28 +863,32 @@ nsGonkCameraControl::TakePictureImpl(Tak
   }
   return NS_OK;
 }
 
 nsresult
 nsGonkCameraControl::PushParametersImpl()
 {
   DOM_CAMERA_LOGI("Pushing camera parameters\n");
+  RETURN_IF_NO_CAMERA_HW();
+
   RwAutoLockRead lock(mRwLock);
   if (mCameraHw->PushParameters(mParams) != OK) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 nsresult
 nsGonkCameraControl::PullParametersImpl()
 {
   DOM_CAMERA_LOGI("Pulling camera parameters\n");
+  RETURN_IF_NO_CAMERA_HW();
+
   RwAutoLockWrite lock(mRwLock);
   mCameraHw->PullParameters(mParams);
   return NS_OK;
 }
 
 nsresult
 nsGonkCameraControl::StartRecordingImpl(StartRecordingTask* aStartRecording)
 {
@@ -1239,16 +1267,18 @@ nsGonkCameraControl::HandleRecorderEvent
 
   // All unhandled cases wind up here
   DOM_CAMERA_LOGW("recorder-event : unhandled: msg=%d, ext1=%d, ext2=%d\n", msg, ext1, ext2);
 }
 
 nsresult
 nsGonkCameraControl::SetupRecording(int aFd, int aRotation, int64_t aMaxFileSizeBytes, int64_t aMaxVideoLengthMs)
 {
+  RETURN_IF_NO_CAMERA_HW();
+
   // choosing a size big enough to hold the params
   const size_t SIZE = 256;
   char buffer[SIZE];
 
   mRecorder = new GonkRecorder();
   CHECK_SETARG(mRecorder->init());
 
   nsresult rv = mRecorderProfile->ConfigureRecorder(mRecorder);