dom/camera/TestGonkCameraHardware.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) 2013-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 "TestGonkCameraHardware.h"
michael@0 18
michael@0 19 #include "mozilla/Preferences.h"
michael@0 20 #include "nsThreadUtils.h"
michael@0 21
michael@0 22 using namespace android;
michael@0 23 using namespace mozilla;
michael@0 24
michael@0 25 TestGonkCameraHardware::TestGonkCameraHardware(nsGonkCameraControl* aTarget,
michael@0 26 uint32_t aCameraId,
michael@0 27 const sp<Camera>& aCamera)
michael@0 28 : GonkCameraHardware(aTarget, aCameraId, aCamera)
michael@0 29 {
michael@0 30 DOM_CAMERA_LOGA("v===== Created TestGonkCameraHardware =====v\n");
michael@0 31 DOM_CAMERA_LOGT("%s:%d : this=%p (aTarget=%p)\n",
michael@0 32 __func__, __LINE__, this, aTarget);
michael@0 33 MOZ_COUNT_CTOR(TestGonkCameraHardware);
michael@0 34 }
michael@0 35
michael@0 36 TestGonkCameraHardware::~TestGonkCameraHardware()
michael@0 37 {
michael@0 38 MOZ_COUNT_DTOR(TestGonkCameraHardware);
michael@0 39 DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraHardware =====^\n");
michael@0 40 }
michael@0 41
michael@0 42 nsresult
michael@0 43 TestGonkCameraHardware::Init()
michael@0 44 {
michael@0 45 if (IsTestCase("init-failure")) {
michael@0 46 return NS_ERROR_FAILURE;
michael@0 47 }
michael@0 48
michael@0 49 return GonkCameraHardware::Init();
michael@0 50 }
michael@0 51
michael@0 52 const nsCString
michael@0 53 TestGonkCameraHardware::TestCase()
michael@0 54 {
michael@0 55 const nsCString test = Preferences::GetCString("camera.control.test.hardware");
michael@0 56 return test;
michael@0 57 }
michael@0 58
michael@0 59 const nsCString
michael@0 60 TestGonkCameraHardware::GetExtraParameters()
michael@0 61 {
michael@0 62 /**
michael@0 63 * The contents of this pref are appended to the flattened string of
michael@0 64 * parameters stuffed into GonkCameraParameters by the camera library.
michael@0 65 * It consists of semicolon-delimited key=value pairs, e.g.
michael@0 66 *
michael@0 67 * focus-mode=auto;flash-mode=auto;preview-size=1024x768
michael@0 68 *
michael@0 69 * The unflattening process breaks this string up on semicolon boundaries
michael@0 70 * and sets an entry in a hashtable of strings with the token before
michael@0 71 * the equals sign as the key, and the token after as the value. Because
michael@0 72 * the string is parsed in order, key=value pairs occuring later in the
michael@0 73 * string will replace value pairs appearing earlier, making it easy to
michael@0 74 * inject fake, testable values into the parameters table.
michael@0 75 *
michael@0 76 * One constraint of this approach is that neither the key nor the value
michael@0 77 * may contain equals signs or semicolons. We don't enforce that here
michael@0 78 * so that we can also test correct handling of improperly-formatted values.
michael@0 79 */
michael@0 80 const nsCString parameters = Preferences::GetCString("camera.control.test.hardware.gonk.parameters");
michael@0 81 DOM_CAMERA_LOGA("TestGonkCameraHardware : extra-parameters '%s'\n",
michael@0 82 parameters.get());
michael@0 83 return parameters;
michael@0 84 }
michael@0 85
michael@0 86 bool
michael@0 87 TestGonkCameraHardware::IsTestCaseInternal(const char* aTest, const char* aFile, int aLine)
michael@0 88 {
michael@0 89 if (TestCase().EqualsASCII(aTest)) {
michael@0 90 DOM_CAMERA_LOGA("TestGonkCameraHardware : test-case '%s' (%s:%d)\n",
michael@0 91 aTest, aFile, aLine);
michael@0 92 return true;
michael@0 93 }
michael@0 94
michael@0 95 return false;
michael@0 96 }
michael@0 97
michael@0 98 int
michael@0 99 TestGonkCameraHardware::TestCaseError(int aDefaultError)
michael@0 100 {
michael@0 101 // for now, just return the default error
michael@0 102 return aDefaultError;
michael@0 103 }
michael@0 104
michael@0 105 int
michael@0 106 TestGonkCameraHardware::AutoFocus()
michael@0 107 {
michael@0 108 class AutoFocusFailure : public nsRunnable
michael@0 109 {
michael@0 110 public:
michael@0 111 AutoFocusFailure(nsGonkCameraControl* aTarget)
michael@0 112 : mTarget(aTarget)
michael@0 113 { }
michael@0 114
michael@0 115 NS_IMETHODIMP
michael@0 116 Run()
michael@0 117 {
michael@0 118 OnAutoFocusComplete(mTarget, false);
michael@0 119 return NS_OK;
michael@0 120 }
michael@0 121
michael@0 122 protected:
michael@0 123 nsGonkCameraControl* mTarget;
michael@0 124 };
michael@0 125
michael@0 126 if (IsTestCase("auto-focus-failure")) {
michael@0 127 return TestCaseError(UNKNOWN_ERROR);
michael@0 128 }
michael@0 129 if (IsTestCase("auto-focus-process-failure")) {
michael@0 130 nsresult rv = NS_DispatchToCurrentThread(new AutoFocusFailure(mTarget));
michael@0 131 if (NS_SUCCEEDED(rv)) {
michael@0 132 return OK;
michael@0 133 }
michael@0 134 DOM_CAMERA_LOGE("Failed to dispatch AutoFocusFailure runnable (0x%08x)\n", rv);
michael@0 135 return UNKNOWN_ERROR;
michael@0 136 }
michael@0 137
michael@0 138 return GonkCameraHardware::AutoFocus();
michael@0 139 }
michael@0 140
michael@0 141 // These classes have to be external to StartFaceDetection(), at least
michael@0 142 // until we pick up gcc 4.5, which supports local classes as template
michael@0 143 // arguments.
michael@0 144 class FaceDetected : public nsRunnable
michael@0 145 {
michael@0 146 public:
michael@0 147 FaceDetected(nsGonkCameraControl* aTarget)
michael@0 148 : mTarget(aTarget)
michael@0 149 { }
michael@0 150
michael@0 151 ~FaceDetected()
michael@0 152 {
michael@0 153 ReleaseFacesArray();
michael@0 154 }
michael@0 155
michael@0 156 NS_IMETHODIMP
michael@0 157 Run()
michael@0 158 {
michael@0 159 InitMetaData();
michael@0 160 OnFacesDetected(mTarget, &mMetaData);
michael@0 161 return NS_OK;
michael@0 162 }
michael@0 163
michael@0 164 protected:
michael@0 165 virtual nsresult InitMetaData() = 0;
michael@0 166
michael@0 167 nsresult
michael@0 168 AllocateFacesArray(uint32_t num)
michael@0 169 {
michael@0 170 mMetaData.faces = new camera_face_t[num];
michael@0 171 return NS_OK;
michael@0 172 }
michael@0 173
michael@0 174 nsresult
michael@0 175 ReleaseFacesArray()
michael@0 176 {
michael@0 177 delete [] mMetaData.faces;
michael@0 178 mMetaData.faces = nullptr;
michael@0 179 return NS_OK;
michael@0 180 }
michael@0 181
michael@0 182 nsRefPtr<nsGonkCameraControl> mTarget;
michael@0 183 camera_frame_metadata_t mMetaData;
michael@0 184 };
michael@0 185
michael@0 186 class OneFaceDetected : public FaceDetected
michael@0 187 {
michael@0 188 public:
michael@0 189 OneFaceDetected(nsGonkCameraControl* aTarget)
michael@0 190 : FaceDetected(aTarget)
michael@0 191 { }
michael@0 192
michael@0 193 nsresult
michael@0 194 InitMetaData() MOZ_OVERRIDE
michael@0 195 {
michael@0 196 mMetaData.number_of_faces = 1;
michael@0 197 AllocateFacesArray(1);
michael@0 198 mMetaData.faces[0].id = 1;
michael@0 199 mMetaData.faces[0].score = 2;
michael@0 200 mMetaData.faces[0].rect[0] = 3;
michael@0 201 mMetaData.faces[0].rect[1] = 4;
michael@0 202 mMetaData.faces[0].rect[2] = 5;
michael@0 203 mMetaData.faces[0].rect[3] = 6;
michael@0 204 mMetaData.faces[0].left_eye[0] = 7;
michael@0 205 mMetaData.faces[0].left_eye[1] = 8;
michael@0 206 mMetaData.faces[0].right_eye[0] = 9;
michael@0 207 mMetaData.faces[0].right_eye[1] = 10;
michael@0 208 mMetaData.faces[0].mouth[0] = 11;
michael@0 209 mMetaData.faces[0].mouth[1] = 12;
michael@0 210
michael@0 211 return NS_OK;
michael@0 212 }
michael@0 213 };
michael@0 214
michael@0 215 class TwoFacesDetected : public FaceDetected
michael@0 216 {
michael@0 217 public:
michael@0 218 TwoFacesDetected(nsGonkCameraControl* aTarget)
michael@0 219 : FaceDetected(aTarget)
michael@0 220 { }
michael@0 221
michael@0 222 nsresult
michael@0 223 InitMetaData() MOZ_OVERRIDE
michael@0 224 {
michael@0 225 mMetaData.number_of_faces = 2;
michael@0 226 AllocateFacesArray(2);
michael@0 227 mMetaData.faces[0].id = 1;
michael@0 228 mMetaData.faces[0].score = 2;
michael@0 229 mMetaData.faces[0].rect[0] = 3;
michael@0 230 mMetaData.faces[0].rect[1] = 4;
michael@0 231 mMetaData.faces[0].rect[2] = 5;
michael@0 232 mMetaData.faces[0].rect[3] = 6;
michael@0 233 mMetaData.faces[0].left_eye[0] = 7;
michael@0 234 mMetaData.faces[0].left_eye[1] = 8;
michael@0 235 mMetaData.faces[0].right_eye[0] = 9;
michael@0 236 mMetaData.faces[0].right_eye[1] = 10;
michael@0 237 mMetaData.faces[0].mouth[0] = 11;
michael@0 238 mMetaData.faces[0].mouth[1] = 12;
michael@0 239 mMetaData.faces[1].id = 13;
michael@0 240 mMetaData.faces[1].score = 14;
michael@0 241 mMetaData.faces[1].rect[0] = 15;
michael@0 242 mMetaData.faces[1].rect[1] = 16;
michael@0 243 mMetaData.faces[1].rect[2] = 17;
michael@0 244 mMetaData.faces[1].rect[3] = 18;
michael@0 245 mMetaData.faces[1].left_eye[0] = 19;
michael@0 246 mMetaData.faces[1].left_eye[1] = 20;
michael@0 247 mMetaData.faces[1].right_eye[0] = 21;
michael@0 248 mMetaData.faces[1].right_eye[1] = 22;
michael@0 249 mMetaData.faces[1].mouth[0] = 23;
michael@0 250 mMetaData.faces[1].mouth[1] = 24;
michael@0 251
michael@0 252 return NS_OK;
michael@0 253 }
michael@0 254 };
michael@0 255
michael@0 256 class OneFaceNoFeaturesDetected : public FaceDetected
michael@0 257 {
michael@0 258 public:
michael@0 259 OneFaceNoFeaturesDetected(nsGonkCameraControl* aTarget)
michael@0 260 : FaceDetected(aTarget)
michael@0 261 { }
michael@0 262
michael@0 263 nsresult
michael@0 264 InitMetaData() MOZ_OVERRIDE
michael@0 265 {
michael@0 266 mMetaData.number_of_faces = 1;
michael@0 267 AllocateFacesArray(1);
michael@0 268 mMetaData.faces[0].id = 1;
michael@0 269 // Test clamping 'score' to 100.
michael@0 270 mMetaData.faces[0].score = 1000;
michael@0 271 mMetaData.faces[0].rect[0] = 3;
michael@0 272 mMetaData.faces[0].rect[1] = 4;
michael@0 273 mMetaData.faces[0].rect[2] = 5;
michael@0 274 mMetaData.faces[0].rect[3] = 6;
michael@0 275 // Nullable values set to 'not-supported' specific values
michael@0 276 mMetaData.faces[0].left_eye[0] = -2000;
michael@0 277 mMetaData.faces[0].left_eye[1] = -2000;
michael@0 278 // Test other 'not-supported' values as well. We treat
michael@0 279 // anything outside the range [-1000, 1000] as invalid.
michael@0 280 mMetaData.faces[0].right_eye[0] = 1001;
michael@0 281 mMetaData.faces[0].right_eye[1] = -1001;
michael@0 282 mMetaData.faces[0].mouth[0] = -2000;
michael@0 283 mMetaData.faces[0].mouth[1] = 2000;
michael@0 284
michael@0 285 return NS_OK;
michael@0 286 }
michael@0 287 };
michael@0 288
michael@0 289 class NoFacesDetected : public FaceDetected
michael@0 290 {
michael@0 291 public:
michael@0 292 NoFacesDetected(nsGonkCameraControl* aTarget)
michael@0 293 : FaceDetected(aTarget)
michael@0 294 { }
michael@0 295
michael@0 296 nsresult
michael@0 297 InitMetaData() MOZ_OVERRIDE
michael@0 298 {
michael@0 299 mMetaData.number_of_faces = 0;
michael@0 300 mMetaData.faces = nullptr;
michael@0 301
michael@0 302 return NS_OK;
michael@0 303 }
michael@0 304 };
michael@0 305
michael@0 306 int
michael@0 307 TestGonkCameraHardware::StartFaceDetection()
michael@0 308 {
michael@0 309 nsRefPtr<FaceDetected> faceDetected;
michael@0 310
michael@0 311 if (IsTestCase("face-detection-detected-one-face")) {
michael@0 312 faceDetected = new OneFaceDetected(mTarget);
michael@0 313 } else if (IsTestCase("face-detection-detected-two-faces")) {
michael@0 314 faceDetected = new TwoFacesDetected(mTarget);
michael@0 315 } else if (IsTestCase("face-detection-detected-one-face-no-features")) {
michael@0 316 faceDetected = new OneFaceNoFeaturesDetected(mTarget);
michael@0 317 } else if (IsTestCase("face-detection-no-faces-detected")) {
michael@0 318 faceDetected = new NoFacesDetected(mTarget);
michael@0 319 }
michael@0 320
michael@0 321 if (!faceDetected) {
michael@0 322 return GonkCameraHardware::StartFaceDetection();
michael@0 323 }
michael@0 324
michael@0 325 nsresult rv = NS_DispatchToCurrentThread(faceDetected);
michael@0 326 if (NS_FAILED(rv)) {
michael@0 327 DOM_CAMERA_LOGE("Failed to dispatch FaceDetected runnable (0x%08x)\n", rv);
michael@0 328 return UNKNOWN_ERROR;
michael@0 329 }
michael@0 330
michael@0 331 return OK;
michael@0 332 }
michael@0 333
michael@0 334 int
michael@0 335 TestGonkCameraHardware::StopFaceDetection()
michael@0 336 {
michael@0 337 if (IsTestCase("face-detection-detected-one-face") ||
michael@0 338 IsTestCase("face-detection-detected-two-faces") ||
michael@0 339 IsTestCase("face-detection-detected-one-face-no-features") ||
michael@0 340 IsTestCase("face-detection-no-faces-detected"))
michael@0 341 {
michael@0 342 return OK;
michael@0 343 }
michael@0 344
michael@0 345 return GonkCameraHardware::StopFaceDetection();
michael@0 346 }
michael@0 347
michael@0 348 int
michael@0 349 TestGonkCameraHardware::TakePicture()
michael@0 350 {
michael@0 351 class TakePictureFailure : public nsRunnable
michael@0 352 {
michael@0 353 public:
michael@0 354 TakePictureFailure(nsGonkCameraControl* aTarget)
michael@0 355 : mTarget(aTarget)
michael@0 356 { }
michael@0 357
michael@0 358 NS_IMETHODIMP
michael@0 359 Run()
michael@0 360 {
michael@0 361 OnTakePictureError(mTarget);
michael@0 362 return NS_OK;
michael@0 363 }
michael@0 364
michael@0 365 protected:
michael@0 366 nsGonkCameraControl* mTarget;
michael@0 367 };
michael@0 368
michael@0 369 if (IsTestCase("take-picture-failure")) {
michael@0 370 return TestCaseError(UNKNOWN_ERROR);
michael@0 371 }
michael@0 372 if (IsTestCase("take-picture-process-failure")) {
michael@0 373 nsresult rv = NS_DispatchToCurrentThread(new TakePictureFailure(mTarget));
michael@0 374 if (NS_SUCCEEDED(rv)) {
michael@0 375 return OK;
michael@0 376 }
michael@0 377 DOM_CAMERA_LOGE("Failed to dispatch TakePictureFailure runnable (0x%08x)\n", rv);
michael@0 378 return UNKNOWN_ERROR;
michael@0 379 }
michael@0 380
michael@0 381 return GonkCameraHardware::TakePicture();
michael@0 382 }
michael@0 383
michael@0 384 int
michael@0 385 TestGonkCameraHardware::StartPreview()
michael@0 386 {
michael@0 387 if (IsTestCase("start-preview-failure")) {
michael@0 388 return TestCaseError(UNKNOWN_ERROR);
michael@0 389 }
michael@0 390
michael@0 391 return GonkCameraHardware::StartPreview();
michael@0 392 }
michael@0 393
michael@0 394 int
michael@0 395 TestGonkCameraHardware::StartAutoFocusMoving(bool aIsMoving)
michael@0 396 {
michael@0 397 class AutoFocusMoving : public nsRunnable
michael@0 398 {
michael@0 399 public:
michael@0 400 AutoFocusMoving(nsGonkCameraControl* aTarget, bool aIsMoving)
michael@0 401 : mTarget(aTarget)
michael@0 402 , mIsMoving(aIsMoving)
michael@0 403 { }
michael@0 404
michael@0 405 NS_IMETHODIMP
michael@0 406 Run()
michael@0 407 {
michael@0 408 OnAutoFocusMoving(mTarget, mIsMoving);
michael@0 409 return NS_OK;
michael@0 410 }
michael@0 411
michael@0 412 protected:
michael@0 413 nsGonkCameraControl* mTarget;
michael@0 414 bool mIsMoving;
michael@0 415 };
michael@0 416
michael@0 417 nsresult rv = NS_DispatchToCurrentThread(new AutoFocusMoving(mTarget, aIsMoving));
michael@0 418 if (NS_SUCCEEDED(rv)) {
michael@0 419 return OK;
michael@0 420 }
michael@0 421 DOM_CAMERA_LOGE("Failed to dispatch AutoFocusMoving runnable (0x%08x)\n", rv);
michael@0 422 return UNKNOWN_ERROR;
michael@0 423 }
michael@0 424
michael@0 425 int
michael@0 426 TestGonkCameraHardware::PushParameters(const GonkCameraParameters& aParams)
michael@0 427 {
michael@0 428 if (IsTestCase("push-parameters-failure")) {
michael@0 429 return TestCaseError(UNKNOWN_ERROR);
michael@0 430 }
michael@0 431
michael@0 432 nsString focusMode;
michael@0 433 GonkCameraParameters& params = const_cast<GonkCameraParameters&>(aParams);
michael@0 434 params.Get(CAMERA_PARAM_FOCUSMODE, focusMode);
michael@0 435 if (focusMode.EqualsASCII("continuous-picture") ||
michael@0 436 focusMode.EqualsASCII("continuous-video"))
michael@0 437 {
michael@0 438 if (IsTestCase("autofocus-moving-true")) {
michael@0 439 return StartAutoFocusMoving(true);
michael@0 440 } else if (IsTestCase("autofocus-moving-false")) {
michael@0 441 return StartAutoFocusMoving(false);
michael@0 442 }
michael@0 443 }
michael@0 444
michael@0 445 return GonkCameraHardware::PushParameters(aParams);
michael@0 446 }
michael@0 447
michael@0 448 nsresult
michael@0 449 TestGonkCameraHardware::PullParameters(GonkCameraParameters& aParams)
michael@0 450 {
michael@0 451 if (IsTestCase("pull-parameters-failure")) {
michael@0 452 return static_cast<nsresult>(TestCaseError(UNKNOWN_ERROR));
michael@0 453 }
michael@0 454
michael@0 455 String8 s = mCamera->getParameters();
michael@0 456 nsCString extra = GetExtraParameters();
michael@0 457 if (!extra.IsEmpty()) {
michael@0 458 s += ";";
michael@0 459 s += extra.get();
michael@0 460 }
michael@0 461
michael@0 462 return aParams.Unflatten(s);
michael@0 463 }
michael@0 464
michael@0 465 int
michael@0 466 TestGonkCameraHardware::StartRecording()
michael@0 467 {
michael@0 468 if (IsTestCase("start-recording-failure")) {
michael@0 469 return TestCaseError(UNKNOWN_ERROR);
michael@0 470 }
michael@0 471
michael@0 472 return GonkCameraHardware::StartRecording();
michael@0 473 }
michael@0 474
michael@0 475 int
michael@0 476 TestGonkCameraHardware::StopRecording()
michael@0 477 {
michael@0 478 if (IsTestCase("stop-recording-failure")) {
michael@0 479 return TestCaseError(UNKNOWN_ERROR);
michael@0 480 }
michael@0 481
michael@0 482 return GonkCameraHardware::StopRecording();
michael@0 483 }
michael@0 484
michael@0 485 int
michael@0 486 TestGonkCameraHardware::SetListener(const sp<GonkCameraListener>& aListener)
michael@0 487 {
michael@0 488 if (IsTestCase("set-listener-failure")) {
michael@0 489 return TestCaseError(UNKNOWN_ERROR);
michael@0 490 }
michael@0 491
michael@0 492 return GonkCameraHardware::SetListener(aListener);
michael@0 493 }
michael@0 494
michael@0 495 int
michael@0 496 TestGonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled)
michael@0 497 {
michael@0 498 if (IsTestCase("store-metadata-in-buffers-failure")) {
michael@0 499 return TestCaseError(UNKNOWN_ERROR);
michael@0 500 }
michael@0 501
michael@0 502 return GonkCameraHardware::StoreMetaDataInBuffers(aEnabled);
michael@0 503 }

mercurial