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