2 * Copyright (C) 2013-2014 Mozilla Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "TestGonkCameraHardware.h"
19 #include "CameraPreferences.h"
20 #include "nsThreadUtils.h"
22 using namespace android
;
23 using namespace mozilla
;
25 TestGonkCameraHardware::TestGonkCameraHardware(nsGonkCameraControl
* aTarget
,
27 const sp
<Camera
>& aCamera
)
28 : GonkCameraHardware(aTarget
, aCameraId
, aCamera
)
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
);
36 TestGonkCameraHardware::~TestGonkCameraHardware()
38 MOZ_COUNT_DTOR(TestGonkCameraHardware
);
39 DOM_CAMERA_LOGA("^===== Destroyed TestGonkCameraHardware =====^\n");
43 TestGonkCameraHardware::Init()
45 if (IsTestCase("init-failure")) {
46 return NS_ERROR_NOT_INITIALIZED
;
49 return GonkCameraHardware::Init();
53 TestGonkCameraHardware::TestCase()
56 CameraPreferences::GetPref("camera.control.test.hardware", test
);
61 TestGonkCameraHardware::GetExtraParameters()
64 * The contents of this pref are appended to the flattened string of
65 * parameters stuffed into GonkCameraParameters by the camera library.
66 * It consists of semicolon-delimited key=value pairs, e.g.
68 * focus-mode=auto;flash-mode=auto;preview-size=1024x768
70 * The unflattening process breaks this string up on semicolon boundaries
71 * and sets an entry in a hashtable of strings with the token before
72 * the equals sign as the key, and the token after as the value. Because
73 * the string is parsed in order, key=value pairs occuring later in the
74 * string will replace value pairs appearing earlier, making it easy to
75 * inject fake, testable values into the parameters table.
77 * One constraint of this approach is that neither the key nor the value
78 * may contain equals signs or semicolons. We don't enforce that here
79 * so that we can also test correct handling of improperly-formatted values.
82 CameraPreferences::GetPref("camera.control.test.hardware.gonk.parameters", parameters
);
83 DOM_CAMERA_LOGA("TestGonkCameraHardware : extra-parameters '%s'\n",
89 TestGonkCameraHardware::IsTestCaseInternal(const char* aTest
, const char* aFile
, int aLine
)
91 if (TestCase().EqualsASCII(aTest
)) {
92 DOM_CAMERA_LOGA("TestGonkCameraHardware : test-case '%s' (%s:%d)\n",
101 TestGonkCameraHardware::TestCaseError(int aDefaultError
)
103 // for now, just return the default error
104 return aDefaultError
;
108 TestGonkCameraHardware::AutoFocus()
110 class AutoFocusFailure
: public nsRunnable
113 AutoFocusFailure(nsGonkCameraControl
* aTarget
)
120 OnAutoFocusComplete(mTarget
, false);
125 nsGonkCameraControl
* mTarget
;
128 if (IsTestCase("auto-focus-failure")) {
129 return TestCaseError(UNKNOWN_ERROR
);
131 if (IsTestCase("auto-focus-process-failure")) {
132 nsresult rv
= NS_DispatchToCurrentThread(new AutoFocusFailure(mTarget
));
133 if (NS_SUCCEEDED(rv
)) {
136 DOM_CAMERA_LOGE("Failed to dispatch AutoFocusFailure runnable (0x%08x)\n", rv
);
137 return UNKNOWN_ERROR
;
140 return GonkCameraHardware::AutoFocus();
143 // These classes have to be external to StartFaceDetection(), at least
144 // until we pick up gcc 4.5, which supports local classes as template
146 class FaceDetected
: public nsRunnable
149 FaceDetected(nsGonkCameraControl
* aTarget
)
162 OnFacesDetected(mTarget
, &mMetaData
);
167 virtual nsresult
InitMetaData() = 0;
170 AllocateFacesArray(uint32_t num
)
172 mMetaData
.faces
= new camera_face_t
[num
];
179 delete [] mMetaData
.faces
;
180 mMetaData
.faces
= nullptr;
184 nsRefPtr
<nsGonkCameraControl
> mTarget
;
185 camera_frame_metadata_t mMetaData
;
188 class OneFaceDetected
: public FaceDetected
191 OneFaceDetected(nsGonkCameraControl
* aTarget
)
192 : FaceDetected(aTarget
)
196 InitMetaData() MOZ_OVERRIDE
198 mMetaData
.number_of_faces
= 1;
199 AllocateFacesArray(1);
200 mMetaData
.faces
[0].id
= 1;
201 mMetaData
.faces
[0].score
= 2;
202 mMetaData
.faces
[0].rect
[0] = 3;
203 mMetaData
.faces
[0].rect
[1] = 4;
204 mMetaData
.faces
[0].rect
[2] = 5;
205 mMetaData
.faces
[0].rect
[3] = 6;
206 mMetaData
.faces
[0].left_eye
[0] = 7;
207 mMetaData
.faces
[0].left_eye
[1] = 8;
208 mMetaData
.faces
[0].right_eye
[0] = 9;
209 mMetaData
.faces
[0].right_eye
[1] = 10;
210 mMetaData
.faces
[0].mouth
[0] = 11;
211 mMetaData
.faces
[0].mouth
[1] = 12;
217 class TwoFacesDetected
: public FaceDetected
220 TwoFacesDetected(nsGonkCameraControl
* aTarget
)
221 : FaceDetected(aTarget
)
225 InitMetaData() MOZ_OVERRIDE
227 mMetaData
.number_of_faces
= 2;
228 AllocateFacesArray(2);
229 mMetaData
.faces
[0].id
= 1;
230 mMetaData
.faces
[0].score
= 2;
231 mMetaData
.faces
[0].rect
[0] = 3;
232 mMetaData
.faces
[0].rect
[1] = 4;
233 mMetaData
.faces
[0].rect
[2] = 5;
234 mMetaData
.faces
[0].rect
[3] = 6;
235 mMetaData
.faces
[0].left_eye
[0] = 7;
236 mMetaData
.faces
[0].left_eye
[1] = 8;
237 mMetaData
.faces
[0].right_eye
[0] = 9;
238 mMetaData
.faces
[0].right_eye
[1] = 10;
239 mMetaData
.faces
[0].mouth
[0] = 11;
240 mMetaData
.faces
[0].mouth
[1] = 12;
241 mMetaData
.faces
[1].id
= 13;
242 mMetaData
.faces
[1].score
= 14;
243 mMetaData
.faces
[1].rect
[0] = 15;
244 mMetaData
.faces
[1].rect
[1] = 16;
245 mMetaData
.faces
[1].rect
[2] = 17;
246 mMetaData
.faces
[1].rect
[3] = 18;
247 mMetaData
.faces
[1].left_eye
[0] = 19;
248 mMetaData
.faces
[1].left_eye
[1] = 20;
249 mMetaData
.faces
[1].right_eye
[0] = 21;
250 mMetaData
.faces
[1].right_eye
[1] = 22;
251 mMetaData
.faces
[1].mouth
[0] = 23;
252 mMetaData
.faces
[1].mouth
[1] = 24;
258 class OneFaceNoFeaturesDetected
: public FaceDetected
261 OneFaceNoFeaturesDetected(nsGonkCameraControl
* aTarget
)
262 : FaceDetected(aTarget
)
266 InitMetaData() MOZ_OVERRIDE
268 mMetaData
.number_of_faces
= 1;
269 AllocateFacesArray(1);
270 mMetaData
.faces
[0].id
= 1;
271 // Test clamping 'score' to 100.
272 mMetaData
.faces
[0].score
= 1000;
273 mMetaData
.faces
[0].rect
[0] = 3;
274 mMetaData
.faces
[0].rect
[1] = 4;
275 mMetaData
.faces
[0].rect
[2] = 5;
276 mMetaData
.faces
[0].rect
[3] = 6;
277 // Nullable values set to 'not-supported' specific values
278 mMetaData
.faces
[0].left_eye
[0] = -2000;
279 mMetaData
.faces
[0].left_eye
[1] = -2000;
280 // Test other 'not-supported' values as well. We treat
281 // anything outside the range [-1000, 1000] as invalid.
282 mMetaData
.faces
[0].right_eye
[0] = 1001;
283 mMetaData
.faces
[0].right_eye
[1] = -1001;
284 mMetaData
.faces
[0].mouth
[0] = -2000;
285 mMetaData
.faces
[0].mouth
[1] = 2000;
291 class NoFacesDetected
: public FaceDetected
294 NoFacesDetected(nsGonkCameraControl
* aTarget
)
295 : FaceDetected(aTarget
)
299 InitMetaData() MOZ_OVERRIDE
301 mMetaData
.number_of_faces
= 0;
302 mMetaData
.faces
= nullptr;
309 TestGonkCameraHardware::StartFaceDetection()
311 nsRefPtr
<FaceDetected
> faceDetected
;
313 if (IsTestCase("face-detection-detected-one-face")) {
314 faceDetected
= new OneFaceDetected(mTarget
);
315 } else if (IsTestCase("face-detection-detected-two-faces")) {
316 faceDetected
= new TwoFacesDetected(mTarget
);
317 } else if (IsTestCase("face-detection-detected-one-face-no-features")) {
318 faceDetected
= new OneFaceNoFeaturesDetected(mTarget
);
319 } else if (IsTestCase("face-detection-no-faces-detected")) {
320 faceDetected
= new NoFacesDetected(mTarget
);
324 return GonkCameraHardware::StartFaceDetection();
327 nsresult rv
= NS_DispatchToCurrentThread(faceDetected
);
329 DOM_CAMERA_LOGE("Failed to dispatch FaceDetected runnable (0x%08x)\n", rv
);
330 return UNKNOWN_ERROR
;
337 TestGonkCameraHardware::StopFaceDetection()
339 if (IsTestCase("face-detection-detected-one-face") ||
340 IsTestCase("face-detection-detected-two-faces") ||
341 IsTestCase("face-detection-detected-one-face-no-features") ||
342 IsTestCase("face-detection-no-faces-detected"))
347 return GonkCameraHardware::StopFaceDetection();
351 TestGonkCameraHardware::TakePicture()
353 class TakePictureFailure
: public nsRunnable
356 TakePictureFailure(nsGonkCameraControl
* aTarget
)
363 OnTakePictureError(mTarget
);
368 nsGonkCameraControl
* mTarget
;
371 if (IsTestCase("take-picture-failure")) {
372 return TestCaseError(UNKNOWN_ERROR
);
374 if (IsTestCase("take-picture-process-failure")) {
375 nsresult rv
= NS_DispatchToCurrentThread(new TakePictureFailure(mTarget
));
376 if (NS_SUCCEEDED(rv
)) {
379 DOM_CAMERA_LOGE("Failed to dispatch TakePictureFailure runnable (0x%08x)\n", rv
);
380 return UNKNOWN_ERROR
;
383 return GonkCameraHardware::TakePicture();
387 TestGonkCameraHardware::StartPreview()
389 if (IsTestCase("start-preview-failure")) {
390 return TestCaseError(UNKNOWN_ERROR
);
393 return GonkCameraHardware::StartPreview();
397 TestGonkCameraHardware::StartAutoFocusMoving(bool aIsMoving
)
399 class AutoFocusMoving
: public nsRunnable
402 AutoFocusMoving(nsGonkCameraControl
* aTarget
, bool aIsMoving
)
404 , mIsMoving(aIsMoving
)
410 OnAutoFocusMoving(mTarget
, mIsMoving
);
415 nsGonkCameraControl
* mTarget
;
419 nsresult rv
= NS_DispatchToCurrentThread(new AutoFocusMoving(mTarget
, aIsMoving
));
420 if (NS_SUCCEEDED(rv
)) {
423 DOM_CAMERA_LOGE("Failed to dispatch AutoFocusMoving runnable (0x%08x)\n", rv
);
424 return UNKNOWN_ERROR
;
428 TestGonkCameraHardware::PushParameters(const GonkCameraParameters
& aParams
)
430 if (IsTestCase("push-parameters-failure")) {
431 return TestCaseError(UNKNOWN_ERROR
);
435 GonkCameraParameters
& params
= const_cast<GonkCameraParameters
&>(aParams
);
436 params
.Get(CAMERA_PARAM_FOCUSMODE
, focusMode
);
437 if (focusMode
.EqualsASCII("continuous-picture") ||
438 focusMode
.EqualsASCII("continuous-video"))
440 if (IsTestCase("autofocus-moving-true")) {
441 return StartAutoFocusMoving(true);
442 } else if (IsTestCase("autofocus-moving-false")) {
443 return StartAutoFocusMoving(false);
447 return GonkCameraHardware::PushParameters(aParams
);
451 TestGonkCameraHardware::PullParameters(GonkCameraParameters
& aParams
)
453 if (IsTestCase("pull-parameters-failure")) {
454 return static_cast<nsresult
>(TestCaseError(UNKNOWN_ERROR
));
457 String8 s
= mCamera
->getParameters();
458 nsCString extra
= GetExtraParameters();
459 if (!extra
.IsEmpty()) {
464 return aParams
.Unflatten(s
);
468 TestGonkCameraHardware::StartRecording()
470 if (IsTestCase("start-recording-failure")) {
471 return TestCaseError(UNKNOWN_ERROR
);
474 return GonkCameraHardware::StartRecording();
478 TestGonkCameraHardware::StopRecording()
480 if (IsTestCase("stop-recording-failure")) {
481 return TestCaseError(UNKNOWN_ERROR
);
484 return GonkCameraHardware::StopRecording();
488 TestGonkCameraHardware::SetListener(const sp
<GonkCameraListener
>& aListener
)
490 if (IsTestCase("set-listener-failure")) {
491 return TestCaseError(UNKNOWN_ERROR
);
494 return GonkCameraHardware::SetListener(aListener
);
498 TestGonkCameraHardware::StoreMetaDataInBuffers(bool aEnabled
)
500 if (IsTestCase("store-metadata-in-buffers-failure")) {
501 return TestCaseError(UNKNOWN_ERROR
);
504 return GonkCameraHardware::StoreMetaDataInBuffers(aEnabled
);