blob: 5f03a1cefdb7ac2e2bdaf6783ac4bf254be073f5 [file] [log] [blame]
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
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 */
16
17#define LOG_TAG "CameraClient"
18//#define LOG_NDEBUG 0
19
20#include <cutils/properties.h>
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070021#include <gui/Surface.h>
22
23#include "CameraClient.h"
24#include "CameraHardwareInterface.h"
25#include "CameraService.h"
26
27namespace android {
28
29#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
30#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
31
32static int getCallingPid() {
33 return IPCThreadState::self()->getCallingPid();
34}
35
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070036CameraClient::CameraClient(const sp<CameraService>& cameraService,
37 const sp<ICameraClient>& cameraClient,
Igor Murashkin8dcdb952012-10-02 16:05:11 -070038 int cameraId, int cameraFacing, int clientPid, int servicePid):
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070039 Client(cameraService, cameraClient,
Igor Murashkin8dcdb952012-10-02 16:05:11 -070040 cameraId, cameraFacing, clientPid, servicePid)
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070041{
42 int callingPid = getCallingPid();
43 LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
44
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070045 mHardware = NULL;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070046 mMsgEnabled = 0;
47 mSurface = 0;
48 mPreviewWindow = 0;
49 mDestructionStarted = false;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070050
51 // Callback is disabled by default
52 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
53 mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
54 mPlayShutterSound = true;
55 LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
56}
57
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070058status_t CameraClient::initialize(camera_module_t *module) {
59 int callingPid = getCallingPid();
60 LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
61
62 char camera_device_name[10];
63 status_t res;
64 snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
65
66 mHardware = new CameraHardwareInterface(camera_device_name);
67 res = mHardware->initialize(&module->common);
68 if (res != OK) {
69 ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
70 __FUNCTION__, mCameraId, strerror(-res), res);
Igor Murashkind230cc72012-10-09 14:45:37 -070071 mHardware.clear();
Eino-Ville Talvalaf69c70d2012-05-20 15:59:14 -070072 return NO_INIT;
73 }
74
75 mHardware->setCallbacks(notifyCallback,
76 dataCallback,
77 dataCallbackTimestamp,
78 (void *)mCameraId);
79
80 // Enable zoom, error, focus, and metadata messages by default
81 enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
82 CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
83
84 LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
85 return OK;
86}
87
88
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -070089// tear down the client
90CameraClient::~CameraClient() {
91 // this lock should never be NULL
92 Mutex* lock = mCameraService->getClientLockById(mCameraId);
93 lock->lock();
94 mDestructionStarted = true;
95 // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
96 lock->unlock();
97 int callingPid = getCallingPid();
98 LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);
99
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700100 disconnect();
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700101 LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this);
102}
103
104status_t CameraClient::dump(int fd, const Vector<String16>& args) {
105 const size_t SIZE = 256;
106 char buffer[SIZE];
107
108 size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) PID: %d\n",
109 mCameraId,
110 getCameraClient()->asBinder().get(),
111 mClientPid);
112 len = (len > SIZE - 1) ? SIZE - 1 : len;
113 write(fd, buffer, len);
114 return mHardware->dump(fd, args);
115}
116
117// ----------------------------------------------------------------------------
118
119status_t CameraClient::checkPid() const {
120 int callingPid = getCallingPid();
Eino-Ville Talvala61704882012-10-09 22:16:58 -0700121 if (callingPid == mClientPid) return NO_ERROR;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700122
123 ALOGW("attempt to use a locked camera from a different process"
124 " (old pid %d, new pid %d)", mClientPid, callingPid);
125 return EBUSY;
126}
127
128status_t CameraClient::checkPidAndHardware() const {
129 status_t result = checkPid();
130 if (result != NO_ERROR) return result;
131 if (mHardware == 0) {
132 ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
133 return INVALID_OPERATION;
134 }
135 return NO_ERROR;
136}
137
138status_t CameraClient::lock() {
139 int callingPid = getCallingPid();
140 LOG1("lock (pid %d)", callingPid);
141 Mutex::Autolock lock(mLock);
142
143 // lock camera to this client if the the camera is unlocked
144 if (mClientPid == 0) {
145 mClientPid = callingPid;
146 return NO_ERROR;
147 }
148
149 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
150 return checkPid();
151}
152
153status_t CameraClient::unlock() {
154 int callingPid = getCallingPid();
155 LOG1("unlock (pid %d)", callingPid);
156 Mutex::Autolock lock(mLock);
157
158 // allow anyone to use camera (after they lock the camera)
159 status_t result = checkPid();
160 if (result == NO_ERROR) {
161 if (mHardware->recordingEnabled()) {
162 ALOGE("Not allowed to unlock camera during recording.");
163 return INVALID_OPERATION;
164 }
165 mClientPid = 0;
166 LOG1("clear mCameraClient (pid %d)", callingPid);
167 // we need to remove the reference to ICameraClient so that when the app
168 // goes away, the reference count goes to 0.
169 mCameraClient.clear();
170 }
171 return result;
172}
173
174// connect a new client to the camera
175status_t CameraClient::connect(const sp<ICameraClient>& client) {
176 int callingPid = getCallingPid();
177 LOG1("connect E (pid %d)", callingPid);
178 Mutex::Autolock lock(mLock);
179
180 if (mClientPid != 0 && checkPid() != NO_ERROR) {
181 ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
182 mClientPid, callingPid);
183 return EBUSY;
184 }
185
186 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
187 LOG1("Connect to the same client");
188 return NO_ERROR;
189 }
190
191 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
192 mClientPid = callingPid;
193 mCameraClient = client;
194
195 LOG1("connect X (pid %d)", callingPid);
196 return NO_ERROR;
197}
198
199static void disconnectWindow(const sp<ANativeWindow>& window) {
200 if (window != 0) {
201 status_t result = native_window_api_disconnect(window.get(),
202 NATIVE_WINDOW_API_CAMERA);
203 if (result != NO_ERROR) {
204 ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
205 result);
206 }
207 }
208}
209
210void CameraClient::disconnect() {
211 int callingPid = getCallingPid();
212 LOG1("disconnect E (pid %d)", callingPid);
213 Mutex::Autolock lock(mLock);
214
Eino-Ville Talvala61704882012-10-09 22:16:58 -0700215 // Allow both client and the media server to disconnect at all times
216 if (callingPid != mClientPid && callingPid != mServicePid) {
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700217 ALOGW("different client - don't disconnect");
218 return;
219 }
220
221 if (mClientPid <= 0) {
222 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
223 return;
224 }
225
226 // Make sure disconnect() is done once and once only, whether it is called
227 // from the user directly, or called by the destructor.
228 if (mHardware == 0) return;
229
230 LOG1("hardware teardown");
231 // Before destroying mHardware, we must make sure it's in the
232 // idle state.
233 // Turn off all messages.
234 disableMsgType(CAMERA_MSG_ALL_MSGS);
235 mHardware->stopPreview();
236 mHardware->cancelPicture();
237 // Release the hardware resources.
238 mHardware->release();
239
240 // Release the held ANativeWindow resources.
241 if (mPreviewWindow != 0) {
242 disconnectWindow(mPreviewWindow);
243 mPreviewWindow = 0;
244 mHardware->setPreviewWindow(mPreviewWindow);
245 }
246 mHardware.clear();
247
248 CameraService::Client::disconnect();
249
250 LOG1("disconnect X (pid %d)", callingPid);
251}
252
253// ----------------------------------------------------------------------------
254
255status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
256 const sp<ANativeWindow>& window) {
257 Mutex::Autolock lock(mLock);
258 status_t result = checkPidAndHardware();
259 if (result != NO_ERROR) return result;
260
261 // return if no change in surface.
262 if (binder == mSurface) {
263 return NO_ERROR;
264 }
265
266 if (window != 0) {
267 result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
268 if (result != NO_ERROR) {
269 ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
270 result);
271 return result;
272 }
273 }
274
275 // If preview has been already started, register preview buffers now.
276 if (mHardware->previewEnabled()) {
277 if (window != 0) {
278 native_window_set_scaling_mode(window.get(),
279 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
280 native_window_set_buffers_transform(window.get(), mOrientation);
281 result = mHardware->setPreviewWindow(window);
282 }
283 }
284
285 if (result == NO_ERROR) {
286 // Everything has succeeded. Disconnect the old window and remember the
287 // new window.
288 disconnectWindow(mPreviewWindow);
289 mSurface = binder;
290 mPreviewWindow = window;
291 } else {
292 // Something went wrong after we connected to the new window, so
293 // disconnect here.
294 disconnectWindow(window);
295 }
296
297 return result;
298}
299
300// set the Surface that the preview will use
301status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) {
302 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
303
Mathias Agopianb1e7cd12013-02-14 17:11:27 -0800304 sp<IBinder> binder(surface != 0 ? surface->getISurfaceTexture()->asBinder() : 0);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700305 sp<ANativeWindow> window(surface);
306 return setPreviewWindow(binder, window);
307}
308
Andy McFadden484566c2012-12-18 09:46:54 -0800309// set the SurfaceTextureClient that the preview will use
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700310status_t CameraClient::setPreviewTexture(
Andy McFadden484566c2012-12-18 09:46:54 -0800311 const sp<IGraphicBufferProducer>& bufferProducer) {
312 LOG1("setPreviewTexture(%p) (pid %d)", bufferProducer.get(),
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700313 getCallingPid());
314
315 sp<IBinder> binder;
316 sp<ANativeWindow> window;
Andy McFadden484566c2012-12-18 09:46:54 -0800317 if (bufferProducer != 0) {
318 binder = bufferProducer->asBinder();
Mathias Agopianb1e7cd12013-02-14 17:11:27 -0800319 window = new Surface(bufferProducer);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700320 }
321 return setPreviewWindow(binder, window);
322}
323
324// set the preview callback flag to affect how the received frames from
325// preview are handled.
326void CameraClient::setPreviewCallbackFlag(int callback_flag) {
327 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
328 Mutex::Autolock lock(mLock);
329 if (checkPidAndHardware() != NO_ERROR) return;
330
331 mPreviewCallbackFlag = callback_flag;
332 if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
333 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
334 } else {
335 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
336 }
337}
338
339// start preview mode
340status_t CameraClient::startPreview() {
341 LOG1("startPreview (pid %d)", getCallingPid());
342 return startCameraMode(CAMERA_PREVIEW_MODE);
343}
344
345// start recording mode
346status_t CameraClient::startRecording() {
347 LOG1("startRecording (pid %d)", getCallingPid());
348 return startCameraMode(CAMERA_RECORDING_MODE);
349}
350
351// start preview or recording
352status_t CameraClient::startCameraMode(camera_mode mode) {
353 LOG1("startCameraMode(%d)", mode);
354 Mutex::Autolock lock(mLock);
355 status_t result = checkPidAndHardware();
356 if (result != NO_ERROR) return result;
357
358 switch(mode) {
359 case CAMERA_PREVIEW_MODE:
360 if (mSurface == 0 && mPreviewWindow == 0) {
361 LOG1("mSurface is not set yet.");
362 // still able to start preview in this case.
363 }
364 return startPreviewMode();
365 case CAMERA_RECORDING_MODE:
366 if (mSurface == 0 && mPreviewWindow == 0) {
367 ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
368 return INVALID_OPERATION;
369 }
370 return startRecordingMode();
371 default:
372 return UNKNOWN_ERROR;
373 }
374}
375
376status_t CameraClient::startPreviewMode() {
377 LOG1("startPreviewMode");
378 status_t result = NO_ERROR;
379
380 // if preview has been enabled, nothing needs to be done
381 if (mHardware->previewEnabled()) {
382 return NO_ERROR;
383 }
384
385 if (mPreviewWindow != 0) {
386 native_window_set_scaling_mode(mPreviewWindow.get(),
387 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
388 native_window_set_buffers_transform(mPreviewWindow.get(),
389 mOrientation);
390 }
391 mHardware->setPreviewWindow(mPreviewWindow);
392 result = mHardware->startPreview();
393
394 return result;
395}
396
397status_t CameraClient::startRecordingMode() {
398 LOG1("startRecordingMode");
399 status_t result = NO_ERROR;
400
401 // if recording has been enabled, nothing needs to be done
402 if (mHardware->recordingEnabled()) {
403 return NO_ERROR;
404 }
405
406 // if preview has not been started, start preview first
407 if (!mHardware->previewEnabled()) {
408 result = startPreviewMode();
409 if (result != NO_ERROR) {
410 return result;
411 }
412 }
413
414 // start recording mode
415 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
416 mCameraService->playSound(CameraService::SOUND_RECORDING);
417 result = mHardware->startRecording();
418 if (result != NO_ERROR) {
419 ALOGE("mHardware->startRecording() failed with status %d", result);
420 }
421 return result;
422}
423
424// stop preview mode
425void CameraClient::stopPreview() {
426 LOG1("stopPreview (pid %d)", getCallingPid());
427 Mutex::Autolock lock(mLock);
428 if (checkPidAndHardware() != NO_ERROR) return;
429
430
431 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
432 mHardware->stopPreview();
433
434 mPreviewBuffer.clear();
435}
436
437// stop recording mode
438void CameraClient::stopRecording() {
439 LOG1("stopRecording (pid %d)", getCallingPid());
440 Mutex::Autolock lock(mLock);
441 if (checkPidAndHardware() != NO_ERROR) return;
442
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700443 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
444 mHardware->stopRecording();
Patric Frederiksen35f859b2012-07-10 13:38:35 +0200445 mCameraService->playSound(CameraService::SOUND_RECORDING);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700446
447 mPreviewBuffer.clear();
448}
449
450// release a recording frame
451void CameraClient::releaseRecordingFrame(const sp<IMemory>& mem) {
452 Mutex::Autolock lock(mLock);
453 if (checkPidAndHardware() != NO_ERROR) return;
454 mHardware->releaseRecordingFrame(mem);
455}
456
457status_t CameraClient::storeMetaDataInBuffers(bool enabled)
458{
459 LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
460 Mutex::Autolock lock(mLock);
461 if (checkPidAndHardware() != NO_ERROR) {
462 return UNKNOWN_ERROR;
463 }
464 return mHardware->storeMetaDataInBuffers(enabled);
465}
466
467bool CameraClient::previewEnabled() {
468 LOG1("previewEnabled (pid %d)", getCallingPid());
469
470 Mutex::Autolock lock(mLock);
471 if (checkPidAndHardware() != NO_ERROR) return false;
472 return mHardware->previewEnabled();
473}
474
475bool CameraClient::recordingEnabled() {
476 LOG1("recordingEnabled (pid %d)", getCallingPid());
477
478 Mutex::Autolock lock(mLock);
479 if (checkPidAndHardware() != NO_ERROR) return false;
480 return mHardware->recordingEnabled();
481}
482
483status_t CameraClient::autoFocus() {
484 LOG1("autoFocus (pid %d)", getCallingPid());
485
486 Mutex::Autolock lock(mLock);
487 status_t result = checkPidAndHardware();
488 if (result != NO_ERROR) return result;
489
490 return mHardware->autoFocus();
491}
492
493status_t CameraClient::cancelAutoFocus() {
494 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
495
496 Mutex::Autolock lock(mLock);
497 status_t result = checkPidAndHardware();
498 if (result != NO_ERROR) return result;
499
500 return mHardware->cancelAutoFocus();
501}
502
503// take a picture - image is returned in callback
504status_t CameraClient::takePicture(int msgType) {
505 LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
506
507 Mutex::Autolock lock(mLock);
508 status_t result = checkPidAndHardware();
509 if (result != NO_ERROR) return result;
510
511 if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
512 (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
513 ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
514 " cannot be both enabled");
515 return BAD_VALUE;
516 }
517
518 // We only accept picture related message types
519 // and ignore other types of messages for takePicture().
520 int picMsgType = msgType
521 & (CAMERA_MSG_SHUTTER |
522 CAMERA_MSG_POSTVIEW_FRAME |
523 CAMERA_MSG_RAW_IMAGE |
524 CAMERA_MSG_RAW_IMAGE_NOTIFY |
525 CAMERA_MSG_COMPRESSED_IMAGE);
526
527 enableMsgType(picMsgType);
528
529 return mHardware->takePicture();
530}
531
532// set preview/capture parameters - key/value pairs
533status_t CameraClient::setParameters(const String8& params) {
534 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
535
536 Mutex::Autolock lock(mLock);
537 status_t result = checkPidAndHardware();
538 if (result != NO_ERROR) return result;
539
540 CameraParameters p(params);
541 return mHardware->setParameters(p);
542}
543
544// get preview/capture parameters - key/value pairs
545String8 CameraClient::getParameters() const {
546 Mutex::Autolock lock(mLock);
547 if (checkPidAndHardware() != NO_ERROR) return String8();
548
549 String8 params(mHardware->getParameters().flatten());
550 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
551 return params;
552}
553
554// enable shutter sound
555status_t CameraClient::enableShutterSound(bool enable) {
556 LOG1("enableShutterSound (pid %d)", getCallingPid());
557
558 status_t result = checkPidAndHardware();
559 if (result != NO_ERROR) return result;
560
561 if (enable) {
562 mPlayShutterSound = true;
563 return OK;
564 }
565
566 // Disabling shutter sound may not be allowed. In that case only
567 // allow the mediaserver process to disable the sound.
568 char value[PROPERTY_VALUE_MAX];
569 property_get("ro.camera.sound.forced", value, "0");
570 if (strcmp(value, "0") != 0) {
571 // Disabling shutter sound is not allowed. Deny if the current
572 // process is not mediaserver.
573 if (getCallingPid() != getpid()) {
574 ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
575 return PERMISSION_DENIED;
576 }
577 }
578
579 mPlayShutterSound = false;
580 return OK;
581}
582
583status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
584 LOG1("sendCommand (pid %d)", getCallingPid());
585 int orientation;
586 Mutex::Autolock lock(mLock);
587 status_t result = checkPidAndHardware();
588 if (result != NO_ERROR) return result;
589
590 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
591 // Mirror the preview if the camera is front-facing.
592 orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
593 if (orientation == -1) return BAD_VALUE;
594
595 if (mOrientation != orientation) {
596 mOrientation = orientation;
597 if (mPreviewWindow != 0) {
598 native_window_set_buffers_transform(mPreviewWindow.get(),
599 mOrientation);
600 }
601 }
602 return OK;
603 } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
604 switch (arg1) {
605 case 0:
Eino-Ville Talvalaccd795f2012-09-11 11:01:18 -0700606 return enableShutterSound(false);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700607 case 1:
Eino-Ville Talvalaccd795f2012-09-11 11:01:18 -0700608 return enableShutterSound(true);
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700609 default:
610 return BAD_VALUE;
611 }
612 return OK;
613 } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
614 mCameraService->playSound(CameraService::SOUND_RECORDING);
James Dong983cf232012-08-01 16:39:55 -0700615 } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
616 // Silently ignore this command
617 return INVALID_OPERATION;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700618 } else if (cmd == CAMERA_CMD_PING) {
619 // If mHardware is 0, checkPidAndHardware will return error.
620 return OK;
621 }
622
623 return mHardware->sendCommand(cmd, arg1, arg2);
624}
625
626// ----------------------------------------------------------------------------
627
628void CameraClient::enableMsgType(int32_t msgType) {
629 android_atomic_or(msgType, &mMsgEnabled);
630 mHardware->enableMsgType(msgType);
631}
632
633void CameraClient::disableMsgType(int32_t msgType) {
634 android_atomic_and(~msgType, &mMsgEnabled);
635 mHardware->disableMsgType(msgType);
636}
637
638#define CHECK_MESSAGE_INTERVAL 10 // 10ms
639bool CameraClient::lockIfMessageWanted(int32_t msgType) {
640 int sleepCount = 0;
641 while (mMsgEnabled & msgType) {
642 if (mLock.tryLock() == NO_ERROR) {
643 if (sleepCount > 0) {
644 LOG1("lockIfMessageWanted(%d): waited for %d ms",
645 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
646 }
647 return true;
648 }
649 if (sleepCount++ == 0) {
650 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
651 }
652 usleep(CHECK_MESSAGE_INTERVAL * 1000);
653 }
654 ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
655 return false;
656}
657
658// Callback messages can be dispatched to internal handlers or pass to our
659// client's callback functions, depending on the message type.
660//
661// notifyCallback:
662// CAMERA_MSG_SHUTTER handleShutter
663// (others) c->notifyCallback
664// dataCallback:
665// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
666// CAMERA_MSG_POSTVIEW_FRAME handlePostview
667// CAMERA_MSG_RAW_IMAGE handleRawPicture
668// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
669// (others) c->dataCallback
670// dataCallbackTimestamp
671// (others) c->dataCallbackTimestamp
672//
673// NOTE: the *Callback functions grab mLock of the client before passing
674// control to handle* functions. So the handle* functions must release the
675// lock before calling the ICameraClient's callbacks, so those callbacks can
676// invoke methods in the Client class again (For example, the preview frame
677// callback may want to releaseRecordingFrame). The handle* functions must
678// release the lock after all accesses to member variables, so it must be
679// handled very carefully.
680
681void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
682 int32_t ext2, void* user) {
683 LOG2("notifyCallback(%d)", msgType);
684
685 Mutex* lock = getClientLockFromCookie(user);
686 if (lock == NULL) return;
687 Mutex::Autolock alock(*lock);
688
689 CameraClient* client =
690 static_cast<CameraClient*>(getClientFromCookie(user));
691 if (client == NULL) return;
692
693 if (!client->lockIfMessageWanted(msgType)) return;
694
695 switch (msgType) {
696 case CAMERA_MSG_SHUTTER:
697 // ext1 is the dimension of the yuv picture.
698 client->handleShutter();
699 break;
700 default:
701 client->handleGenericNotify(msgType, ext1, ext2);
702 break;
703 }
704}
705
706void CameraClient::dataCallback(int32_t msgType,
707 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
708 LOG2("dataCallback(%d)", msgType);
709
710 Mutex* lock = getClientLockFromCookie(user);
711 if (lock == NULL) return;
712 Mutex::Autolock alock(*lock);
713
714 CameraClient* client =
715 static_cast<CameraClient*>(getClientFromCookie(user));
716 if (client == NULL) return;
717
718 if (!client->lockIfMessageWanted(msgType)) return;
719 if (dataPtr == 0 && metadata == NULL) {
720 ALOGE("Null data returned in data callback");
721 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
722 return;
723 }
724
725 switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
726 case CAMERA_MSG_PREVIEW_FRAME:
727 client->handlePreviewData(msgType, dataPtr, metadata);
728 break;
729 case CAMERA_MSG_POSTVIEW_FRAME:
730 client->handlePostview(dataPtr);
731 break;
732 case CAMERA_MSG_RAW_IMAGE:
733 client->handleRawPicture(dataPtr);
734 break;
735 case CAMERA_MSG_COMPRESSED_IMAGE:
736 client->handleCompressedPicture(dataPtr);
737 break;
738 default:
739 client->handleGenericData(msgType, dataPtr, metadata);
740 break;
741 }
742}
743
744void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
745 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
746 LOG2("dataCallbackTimestamp(%d)", msgType);
747
748 Mutex* lock = getClientLockFromCookie(user);
749 if (lock == NULL) return;
750 Mutex::Autolock alock(*lock);
751
752 CameraClient* client =
753 static_cast<CameraClient*>(getClientFromCookie(user));
754 if (client == NULL) return;
755
756 if (!client->lockIfMessageWanted(msgType)) return;
757
758 if (dataPtr == 0) {
759 ALOGE("Null data returned in data with timestamp callback");
760 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
761 return;
762 }
763
764 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
765}
766
767// snapshot taken callback
768void CameraClient::handleShutter(void) {
769 if (mPlayShutterSound) {
770 mCameraService->playSound(CameraService::SOUND_SHUTTER);
771 }
772
773 sp<ICameraClient> c = mCameraClient;
774 if (c != 0) {
775 mLock.unlock();
776 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
777 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
778 }
779 disableMsgType(CAMERA_MSG_SHUTTER);
780
781 mLock.unlock();
782}
783
784// preview callback - frame buffer update
785void CameraClient::handlePreviewData(int32_t msgType,
786 const sp<IMemory>& mem,
787 camera_frame_metadata_t *metadata) {
788 ssize_t offset;
789 size_t size;
790 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
791
792 // local copy of the callback flags
793 int flags = mPreviewCallbackFlag;
794
795 // is callback enabled?
796 if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
797 // If the enable bit is off, the copy-out and one-shot bits are ignored
798 LOG2("frame callback is disabled");
799 mLock.unlock();
800 return;
801 }
802
803 // hold a strong pointer to the client
804 sp<ICameraClient> c = mCameraClient;
805
806 // clear callback flags if no client or one-shot mode
807 if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
808 LOG2("Disable preview callback");
809 mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
810 CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
811 CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
812 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
813 }
814
815 if (c != 0) {
816 // Is the received frame copied out or not?
817 if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
818 LOG2("frame is copied");
819 copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
820 } else {
821 LOG2("frame is forwarded");
822 mLock.unlock();
823 c->dataCallback(msgType, mem, metadata);
824 }
825 } else {
826 mLock.unlock();
827 }
828}
829
830// picture callback - postview image ready
831void CameraClient::handlePostview(const sp<IMemory>& mem) {
832 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
833
834 sp<ICameraClient> c = mCameraClient;
835 mLock.unlock();
836 if (c != 0) {
837 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
838 }
839}
840
841// picture callback - raw image ready
842void CameraClient::handleRawPicture(const sp<IMemory>& mem) {
843 disableMsgType(CAMERA_MSG_RAW_IMAGE);
844
845 ssize_t offset;
846 size_t size;
847 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
848
849 sp<ICameraClient> c = mCameraClient;
850 mLock.unlock();
851 if (c != 0) {
852 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
853 }
854}
855
856// picture callback - compressed picture ready
857void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
858 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
859
860 sp<ICameraClient> c = mCameraClient;
861 mLock.unlock();
862 if (c != 0) {
863 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
864 }
865}
866
867
868void CameraClient::handleGenericNotify(int32_t msgType,
869 int32_t ext1, int32_t ext2) {
870 sp<ICameraClient> c = mCameraClient;
871 mLock.unlock();
872 if (c != 0) {
873 c->notifyCallback(msgType, ext1, ext2);
874 }
875}
876
877void CameraClient::handleGenericData(int32_t msgType,
878 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
879 sp<ICameraClient> c = mCameraClient;
880 mLock.unlock();
881 if (c != 0) {
882 c->dataCallback(msgType, dataPtr, metadata);
883 }
884}
885
886void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
887 int32_t msgType, const sp<IMemory>& dataPtr) {
888 sp<ICameraClient> c = mCameraClient;
889 mLock.unlock();
890 if (c != 0) {
891 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
892 }
893}
894
895void CameraClient::copyFrameAndPostCopiedFrame(
896 int32_t msgType, const sp<ICameraClient>& client,
897 const sp<IMemoryHeap>& heap, size_t offset, size_t size,
898 camera_frame_metadata_t *metadata) {
899 LOG2("copyFrameAndPostCopiedFrame");
900 // It is necessary to copy out of pmem before sending this to
901 // the callback. For efficiency, reuse the same MemoryHeapBase
902 // provided it's big enough. Don't allocate the memory or
903 // perform the copy if there's no callback.
904 // hold the preview lock while we grab a reference to the preview buffer
905 sp<MemoryHeapBase> previewBuffer;
906
907 if (mPreviewBuffer == 0) {
908 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
909 } else if (size > mPreviewBuffer->virtualSize()) {
910 mPreviewBuffer.clear();
911 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
912 }
913 if (mPreviewBuffer == 0) {
914 ALOGE("failed to allocate space for preview buffer");
915 mLock.unlock();
916 return;
917 }
918 previewBuffer = mPreviewBuffer;
919
920 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
921
922 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
923 if (frame == 0) {
924 ALOGE("failed to allocate space for frame callback");
925 mLock.unlock();
926 return;
927 }
928
929 mLock.unlock();
930 client->dataCallback(msgType, frame, metadata);
931}
932
933int CameraClient::getOrientation(int degrees, bool mirror) {
934 if (!mirror) {
935 if (degrees == 0) return 0;
936 else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
937 else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
938 else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
939 } else { // Do mirror (horizontal flip)
940 if (degrees == 0) { // FLIP_H and ROT_0
941 return HAL_TRANSFORM_FLIP_H;
942 } else if (degrees == 90) { // FLIP_H and ROT_90
943 return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
944 } else if (degrees == 180) { // FLIP_H and ROT_180
945 return HAL_TRANSFORM_FLIP_V;
946 } else if (degrees == 270) { // FLIP_H and ROT_270
947 return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
948 }
949 }
950 ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
951 return -1;
952}
953
954}; // namespace android