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