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