dom/camera/GonkCameraHwMgr.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 /*
     2  * Copyright (C) 2012-2014 Mozilla Foundation
     3  *
     4  * Licensed under the Apache License, Version 2.0 (the "License");
     5  * you may not use this file except in compliance with the License.
     6  * You may obtain a copy of the License at
     7  *
     8  *      http://www.apache.org/licenses/LICENSE-2.0
     9  *
    10  * Unless required by applicable law or agreed to in writing, software
    11  * distributed under the License is distributed on an "AS IS" BASIS,
    12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  * See the License for the specific language governing permissions and
    14  * limitations under the License.
    15  */
    17 #include "GonkCameraHwMgr.h"
    18 #include "TestGonkCameraHardware.h"
    20 #include <binder/IPCThreadState.h>
    21 #include <sys/system_properties.h>
    23 #include "base/basictypes.h"
    24 #include "nsDebug.h"
    25 #include "mozilla/layers/TextureClient.h"
    26 #include "mozilla/Preferences.h"
    27 #include "mozilla/RefPtr.h"
    28 #include "GonkCameraControl.h"
    29 #include "GonkNativeWindow.h"
    30 #include "CameraCommon.h"
    32 using namespace mozilla;
    33 using namespace mozilla::layers;
    34 using namespace android;
    36 GonkCameraHardware::GonkCameraHardware(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId, const sp<Camera>& aCamera)
    37   : mCameraId(aCameraId)
    38   , mClosing(false)
    39   , mNumFrames(0)
    40   , mCamera(aCamera)
    41   , mTarget(aTarget)
    42   , mSensorOrientation(0)
    43 {
    44   DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n", __func__, __LINE__, (void*)this, (void*)aTarget);
    45 }
    47 void
    48 GonkCameraHardware::OnNewFrame()
    49 {
    50   if (mClosing) {
    51     return;
    52   }
    53   RefPtr<TextureClient> buffer = mNativeWindow->getCurrentBuffer();
    54   if (!buffer) {
    55     DOM_CAMERA_LOGW("received null frame");
    56     return;
    57   }
    58   OnNewPreviewFrame(mTarget, buffer);
    59 }
    61 // Android data callback
    62 void
    63 GonkCameraHardware::postData(int32_t aMsgType, const sp<IMemory>& aDataPtr, camera_frame_metadata_t* metadata)
    64 {
    65   if (mClosing) {
    66     return;
    67   }
    69   switch (aMsgType) {
    70     case CAMERA_MSG_PREVIEW_FRAME:
    71       // Do nothing
    72       break;
    74     case CAMERA_MSG_COMPRESSED_IMAGE:
    75       if (aDataPtr != nullptr) {
    76         OnTakePictureComplete(mTarget, static_cast<uint8_t*>(aDataPtr->pointer()), aDataPtr->size());
    77       } else {
    78         OnTakePictureError(mTarget);
    79       }
    80       break;
    82     case CAMERA_MSG_PREVIEW_METADATA:
    83       OnFacesDetected(mTarget, metadata);
    84       break;
    86     default:
    87       DOM_CAMERA_LOGE("Unhandled data callback event %d\n", aMsgType);
    88       break;
    89   }
    90 }
    92 // Android notify callback
    93 void
    94 GonkCameraHardware::notify(int32_t aMsgType, int32_t ext1, int32_t ext2)
    95 {
    96   if (mClosing) {
    97     return;
    98   }
   100   switch (aMsgType) {
   101     case CAMERA_MSG_FOCUS:
   102       OnAutoFocusComplete(mTarget, !!ext1);
   103       break;
   105 #if ANDROID_VERSION >= 16
   106     case CAMERA_MSG_FOCUS_MOVE:
   107       OnAutoFocusMoving(mTarget, !!ext1);
   108       break;
   109 #endif
   111     case CAMERA_MSG_SHUTTER:
   112       OnShutter(mTarget);
   113       break;
   115     case CAMERA_MSG_ERROR:
   116       OnError(mTarget, CameraControlListener::kErrorServiceFailed, ext1, ext2);
   117       break;
   119     default:
   120       DOM_CAMERA_LOGE("Unhandled notify callback event %d\n", aMsgType);
   121       break;
   122   }
   123 }
   125 void
   126 GonkCameraHardware::postDataTimestamp(nsecs_t aTimestamp, int32_t aMsgType, const sp<IMemory>& aDataPtr)
   127 {
   128   DOM_CAMERA_LOGI("%s",__func__);
   129   if (mClosing) {
   130     return;
   131   }
   133   if (mListener.get()) {
   134     DOM_CAMERA_LOGI("Listener registered, posting recording frame!");
   135     mListener->postDataTimestamp(aTimestamp, aMsgType, aDataPtr);
   136   } else {
   137     DOM_CAMERA_LOGW("No listener was set. Drop a recording frame.");
   138     mCamera->releaseRecordingFrame(aDataPtr);
   139   }
   140 }
   142 nsresult
   143 GonkCameraHardware::Init()
   144 {
   145   DOM_CAMERA_LOGT("%s: this=%p\n", __func__, (void* )this);
   147   CameraInfo info;
   148   int rv = Camera::getCameraInfo(mCameraId, &info);
   149   if (rv != 0) {
   150     DOM_CAMERA_LOGE("%s: failed to get CameraInfo mCameraId %d\n", __func__, mCameraId);
   151     return NS_ERROR_FAILURE;
   152    }
   154   mRawSensorOrientation = info.orientation;
   155   mSensorOrientation = mRawSensorOrientation;
   157   /**
   158    * Non-V4L2-based camera driver adds extra offset onto picture orientation
   159    * set by gecko, so we have to adjust it back.
   160    */
   161   char propname[PROP_NAME_MAX];
   162   char prop[PROP_VALUE_MAX];
   163   int offset = 0;
   164   snprintf(propname, sizeof(propname), "ro.moz.cam.%d.sensor_offset", mCameraId);
   165   if (__system_property_get(propname, prop) > 0) {
   166     offset = clamped(atoi(prop), 0, 270);
   167     mSensorOrientation += offset;
   168     mSensorOrientation %= 360;
   169   }
   170   DOM_CAMERA_LOGI("Sensor orientation: base=%d, offset=%d, final=%d\n", info.orientation, offset, mSensorOrientation);
   172   // Disable shutter sound in android CameraService because gaia camera app will play it
   173   mCamera->sendCommand(CAMERA_CMD_ENABLE_SHUTTER_SOUND, 0, 0);
   175   mNativeWindow = new GonkNativeWindow();
   176   mNativeWindow->setNewFrameCallback(this);
   177   mCamera->setListener(this);
   179 #if defined(MOZ_WIDGET_GONK)
   181 #if ANDROID_VERSION >= 19
   182   mCamera->setPreviewTarget(mNativeWindow->getBufferQueue());
   183 #elif (ANDROID_VERSION == 17) || (ANDROID_VERSION == 18)
   184   mCamera->setPreviewTexture(mNativeWindow->getBufferQueue());
   185 #else
   186   mCamera->setPreviewTexture(mNativeWindow);
   187 #endif
   189 #if ANDROID_VERSION >= 16
   190   rv = mCamera->sendCommand(CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG, 1, 0);
   191   if (rv != OK) {
   192     NS_WARNING("Failed to send command CAMERA_CMD_ENABLE_FOCUS_MOVE_MSG");
   193   }
   194 #endif
   196 #endif
   198   return NS_OK;
   199 }
   201 sp<GonkCameraHardware>
   202 GonkCameraHardware::Connect(mozilla::nsGonkCameraControl* aTarget, uint32_t aCameraId)
   203 {
   204 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 18
   205   sp<Camera> camera = Camera::connect(aCameraId, /* clientPackageName */String16("gonk.camera"), Camera::USE_CALLING_UID);
   206 #else
   207   sp<Camera> camera = Camera::connect(aCameraId);
   208 #endif
   210   if (camera.get() == nullptr) {
   211     return nullptr;
   212   }
   214   const nsAdoptingCString& test =
   215     mozilla::Preferences::GetCString("camera.control.test.enabled");
   216   sp<GonkCameraHardware> cameraHardware;
   217   if (test.EqualsASCII("hardware")) {
   218     NS_WARNING("Using test Gonk hardware layer");
   219     cameraHardware = new TestGonkCameraHardware(aTarget, aCameraId, camera);
   220   } else {
   221     cameraHardware = new GonkCameraHardware(aTarget, aCameraId, camera);
   222   }
   224   nsresult rv = cameraHardware->Init();
   225   if (NS_FAILED(rv)) {
   226     DOM_CAMERA_LOGE("Failed to initialize camera hardware (0x%X)\n", rv);
   227     return nullptr;
   228   }
   230   return cameraHardware;
   231 }
   233 void
   234 GonkCameraHardware::Close()
   235 {
   236   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this);
   238   mClosing = true;
   239   mCamera->stopPreview();
   240   mCamera->disconnect();
   241   if (mNativeWindow.get()) {
   242     mNativeWindow->abandon();
   243   }
   244   mCamera.clear();
   245   mNativeWindow.clear();
   247   // Ensure that ICamera's destructor is actually executed
   248   IPCThreadState::self()->flushCommands();
   249 }
   251 GonkCameraHardware::~GonkCameraHardware()
   252 {
   253   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, (void*)this);
   254   mCamera.clear();
   255   mNativeWindow.clear();
   257   if (mClosing) {
   258     return;
   259   }
   261   /**
   262    * Trigger the OnClosed event; the upper layers can't do anything
   263    * with the hardware layer once they receive this event.
   264    */
   265   if (mTarget) {
   266     OnClosed(mTarget);
   267   }
   268 }
   270 int
   271 GonkCameraHardware::GetSensorOrientation(uint32_t aType)
   272 {
   273   DOM_CAMERA_LOGI("%s\n", __func__);
   275   switch (aType) {
   276     case OFFSET_SENSOR_ORIENTATION:
   277       return mSensorOrientation;
   279     case RAW_SENSOR_ORIENTATION:
   280       return mRawSensorOrientation;
   282     default:
   283       DOM_CAMERA_LOGE("%s:%d : unknown aType=%d\n", __func__, __LINE__, aType);
   284       return 0;
   285   }
   286 }
   288 int
   289 GonkCameraHardware::AutoFocus()
   290 {
   291   DOM_CAMERA_LOGI("%s\n", __func__);
   292   return mCamera->autoFocus();
   293 }
   295 int
   296 GonkCameraHardware::CancelAutoFocus()
   297 {
   298   DOM_CAMERA_LOGI("%s\n", __func__);
   299   return mCamera->cancelAutoFocus();
   300 }
   302 int
   303 GonkCameraHardware::StartFaceDetection()
   304 {
   305   DOM_CAMERA_LOGI("%s\n", __func__);
   306   int rv = INVALID_OPERATION;
   308 #if ANDROID_VERSION >= 15
   309   rv = mCamera->sendCommand(CAMERA_CMD_START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
   310 #endif
   311   if (rv != OK) {
   312     DOM_CAMERA_LOGE("Start face detection failed with status %d", rv);
   313   }
   315   return rv;
   316 }
   318 int
   319 GonkCameraHardware::StopFaceDetection()
   320 {
   321   DOM_CAMERA_LOGI("%s\n", __func__);
   322   int rv = INVALID_OPERATION;
   324 #if ANDROID_VERSION >= 15
   325   rv = mCamera->sendCommand(CAMERA_CMD_STOP_FACE_DETECTION, 0, 0);
   326 #endif
   327   if (rv != OK) {
   328     DOM_CAMERA_LOGE("Stop face detection failed with status %d", rv);
   329   }
   331   return rv;
   332 }
   334 int
   335 GonkCameraHardware::TakePicture()
   336 {
   337   return mCamera->takePicture(CAMERA_MSG_SHUTTER | CAMERA_MSG_COMPRESSED_IMAGE);
   338 }
   340 void
   341 GonkCameraHardware::CancelTakePicture()
   342 {
   343   DOM_CAMERA_LOGW("%s: android::Camera do not provide this capability\n", __func__);
   344 }
   346 int
   347 GonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
   348 {
   349   const String8 s = aParams.Flatten();
   350   return mCamera->setParameters(s);
   351 }
   353 int
   354 GonkCameraHardware::PushParameters(const CameraParameters& aParams)
   355 {
   356   String8 s = aParams.flatten();
   357   return mCamera->setParameters(s);
   358 }
   360 nsresult
   361 GonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
   362 {
   363   const String8 s = mCamera->getParameters();
   364   return aParams.Unflatten(s);
   365 }
   367 void
   368 GonkCameraHardware::PullParameters(CameraParameters& aParams)
   369 {
   370   const String8 s = mCamera->getParameters();
   371   aParams.unflatten(s);
   372 }
   374 int
   375 GonkCameraHardware::StartPreview()
   376 {
   377   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   378   return mCamera->startPreview();
   379 }
   381 void
   382 GonkCameraHardware::StopPreview()
   383 {
   384   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   385   mCamera->stopPreview();
   386 }
   388 int
   389 GonkCameraHardware::StartRecording()
   390 {
   391   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   392   int rv = OK;
   394   rv = mCamera->startRecording();
   395   if (rv != OK) {
   396     DOM_CAMERA_LOGE("mHardware->startRecording() failed with status %d", rv);
   397   }
   398   return rv;
   399 }
   401 int
   402 GonkCameraHardware::StopRecording()
   403 {
   404   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   405   mCamera->stopRecording();
   406   return OK;
   407 }
   409 int
   410 GonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
   411 {
   412   mListener = aListener;
   413   return OK;
   414 }
   416 void
   417 GonkCameraHardware::ReleaseRecordingFrame(const sp<IMemory>& aFrame)
   418 {
   419   mCamera->releaseRecordingFrame(aFrame);
   420 }
   422 int
   423 GonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)
   424 {
   425   return mCamera->storeMetaDataInBuffers(aEnabled);
   426 }

mercurial