Bug 850845 - don't dereference null mCameraHw pointer, r=sotaro
authorMike Habicher <mikeh@mozilla.com>
Thu, 14 Mar 2013 17:30:38 -0400
changeset 135367 6d3f1e3ccf5cf8d6256bab68a7de4c6205b925b5
parent 135366 9421582028249b1c37602bc3806bf4e8794829cc
child 135368 0d24c96dfd4dde40260c97603d56d157938ab7c6
push id2452
push userlsblakk@mozilla.com
push dateMon, 13 May 2013 16:59:38 +0000
treeherdermozilla-beta@d4b152d29d8d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs850845
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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);