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.

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

mercurial