Tue, 06 Jan 2015 21:39:09 +0100
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 }