blob: 562384dffb0a347ffb14eb4d7411584e453f5895 [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);
James Dong983cf232012-08-01 16:39:55 -0700622 } else if (cmd == CAMERA_CMD_SET_VIDEO_BUFFER_COUNT) {
623 // Silently ignore this command
624 return INVALID_OPERATION;
Eino-Ville Talvala5e08d602012-05-16 14:59:25 -0700625 } else if (cmd == CAMERA_CMD_PING) {
626 // If mHardware is 0, checkPidAndHardware will return error.
627 return OK;
628 }
629
630 return mHardware->sendCommand(cmd, arg1, arg2);
631}
632
633// ----------------------------------------------------------------------------
634
635void CameraClient::enableMsgType(int32_t msgType) {
636 android_atomic_or(msgType, &mMsgEnabled);
637 mHardware->enableMsgType(msgType);
638}
639
640void CameraClient::disableMsgType(int32_t msgType) {
641 android_atomic_and(~msgType, &mMsgEnabled);
642 mHardware->disableMsgType(msgType);
643}
644
645#define CHECK_MESSAGE_INTERVAL 10 // 10ms
646bool CameraClient::lockIfMessageWanted(int32_t msgType) {
647 int sleepCount = 0;
648 while (mMsgEnabled & msgType) {
649 if (mLock.tryLock() == NO_ERROR) {
650 if (sleepCount > 0) {
651 LOG1("lockIfMessageWanted(%d): waited for %d ms",
652 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
653 }
654 return true;
655 }
656 if (sleepCount++ == 0) {
657 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
658 }
659 usleep(CHECK_MESSAGE_INTERVAL * 1000);
660 }
661 ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
662 return false;
663}
664
665// Callback messages can be dispatched to internal handlers or pass to our
666// client's callback functions, depending on the message type.
667//
668// notifyCallback:
669// CAMERA_MSG_SHUTTER handleShutter
670// (others) c->notifyCallback
671// dataCallback:
672// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
673// CAMERA_MSG_POSTVIEW_FRAME handlePostview
674// CAMERA_MSG_RAW_IMAGE handleRawPicture
675// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
676// (others) c->dataCallback
677// dataCallbackTimestamp
678// (others) c->dataCallbackTimestamp
679//
680// NOTE: the *Callback functions grab mLock of the client before passing
681// control to handle* functions. So the handle* functions must release the
682// lock before calling the ICameraClient's callbacks, so those callbacks can
683// invoke methods in the Client class again (For example, the preview frame
684// callback may want to releaseRecordingFrame). The handle* functions must
685// release the lock after all accesses to member variables, so it must be
686// handled very carefully.
687
688void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
689 int32_t ext2, void* user) {
690 LOG2("notifyCallback(%d)", msgType);
691
692 Mutex* lock = getClientLockFromCookie(user);
693 if (lock == NULL) return;
694 Mutex::Autolock alock(*lock);
695
696 CameraClient* client =
697 static_cast<CameraClient*>(getClientFromCookie(user));
698 if (client == NULL) return;
699
700 if (!client->lockIfMessageWanted(msgType)) return;
701
702 switch (msgType) {
703 case CAMERA_MSG_SHUTTER:
704 // ext1 is the dimension of the yuv picture.
705 client->handleShutter();
706 break;
707 default:
708 client->handleGenericNotify(msgType, ext1, ext2);
709 break;
710 }
711}
712
713void CameraClient::dataCallback(int32_t msgType,
714 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
715 LOG2("dataCallback(%d)", msgType);
716
717 Mutex* lock = getClientLockFromCookie(user);
718 if (lock == NULL) return;
719 Mutex::Autolock alock(*lock);
720
721 CameraClient* client =
722 static_cast<CameraClient*>(getClientFromCookie(user));
723 if (client == NULL) return;
724
725 if (!client->lockIfMessageWanted(msgType)) return;
726 if (dataPtr == 0 && metadata == NULL) {
727 ALOGE("Null data returned in data callback");
728 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
729 return;
730 }
731
732 switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
733 case CAMERA_MSG_PREVIEW_FRAME:
734 client->handlePreviewData(msgType, dataPtr, metadata);
735 break;
736 case CAMERA_MSG_POSTVIEW_FRAME:
737 client->handlePostview(dataPtr);
738 break;
739 case CAMERA_MSG_RAW_IMAGE:
740 client->handleRawPicture(dataPtr);
741 break;
742 case CAMERA_MSG_COMPRESSED_IMAGE:
743 client->handleCompressedPicture(dataPtr);
744 break;
745 default:
746 client->handleGenericData(msgType, dataPtr, metadata);
747 break;
748 }
749}
750
751void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
752 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
753 LOG2("dataCallbackTimestamp(%d)", msgType);
754
755 Mutex* lock = getClientLockFromCookie(user);
756 if (lock == NULL) return;
757 Mutex::Autolock alock(*lock);
758
759 CameraClient* client =
760 static_cast<CameraClient*>(getClientFromCookie(user));
761 if (client == NULL) return;
762
763 if (!client->lockIfMessageWanted(msgType)) return;
764
765 if (dataPtr == 0) {
766 ALOGE("Null data returned in data with timestamp callback");
767 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
768 return;
769 }
770
771 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
772}
773
774// snapshot taken callback
775void CameraClient::handleShutter(void) {
776 if (mPlayShutterSound) {
777 mCameraService->playSound(CameraService::SOUND_SHUTTER);
778 }
779
780 sp<ICameraClient> c = mCameraClient;
781 if (c != 0) {
782 mLock.unlock();
783 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
784 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
785 }
786 disableMsgType(CAMERA_MSG_SHUTTER);
787
788 mLock.unlock();
789}
790
791// preview callback - frame buffer update
792void CameraClient::handlePreviewData(int32_t msgType,
793 const sp<IMemory>& mem,
794 camera_frame_metadata_t *metadata) {
795 ssize_t offset;
796 size_t size;
797 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
798
799 // local copy of the callback flags
800 int flags = mPreviewCallbackFlag;
801
802 // is callback enabled?
803 if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
804 // If the enable bit is off, the copy-out and one-shot bits are ignored
805 LOG2("frame callback is disabled");
806 mLock.unlock();
807 return;
808 }
809
810 // hold a strong pointer to the client
811 sp<ICameraClient> c = mCameraClient;
812
813 // clear callback flags if no client or one-shot mode
814 if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
815 LOG2("Disable preview callback");
816 mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
817 CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
818 CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
819 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
820 }
821
822 if (c != 0) {
823 // Is the received frame copied out or not?
824 if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
825 LOG2("frame is copied");
826 copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
827 } else {
828 LOG2("frame is forwarded");
829 mLock.unlock();
830 c->dataCallback(msgType, mem, metadata);
831 }
832 } else {
833 mLock.unlock();
834 }
835}
836
837// picture callback - postview image ready
838void CameraClient::handlePostview(const sp<IMemory>& mem) {
839 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
840
841 sp<ICameraClient> c = mCameraClient;
842 mLock.unlock();
843 if (c != 0) {
844 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
845 }
846}
847
848// picture callback - raw image ready
849void CameraClient::handleRawPicture(const sp<IMemory>& mem) {
850 disableMsgType(CAMERA_MSG_RAW_IMAGE);
851
852 ssize_t offset;
853 size_t size;
854 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
855
856 sp<ICameraClient> c = mCameraClient;
857 mLock.unlock();
858 if (c != 0) {
859 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
860 }
861}
862
863// picture callback - compressed picture ready
864void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
865 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
866
867 sp<ICameraClient> c = mCameraClient;
868 mLock.unlock();
869 if (c != 0) {
870 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
871 }
872}
873
874
875void CameraClient::handleGenericNotify(int32_t msgType,
876 int32_t ext1, int32_t ext2) {
877 sp<ICameraClient> c = mCameraClient;
878 mLock.unlock();
879 if (c != 0) {
880 c->notifyCallback(msgType, ext1, ext2);
881 }
882}
883
884void CameraClient::handleGenericData(int32_t msgType,
885 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
886 sp<ICameraClient> c = mCameraClient;
887 mLock.unlock();
888 if (c != 0) {
889 c->dataCallback(msgType, dataPtr, metadata);
890 }
891}
892
893void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
894 int32_t msgType, const sp<IMemory>& dataPtr) {
895 sp<ICameraClient> c = mCameraClient;
896 mLock.unlock();
897 if (c != 0) {
898 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
899 }
900}
901
902void CameraClient::copyFrameAndPostCopiedFrame(
903 int32_t msgType, const sp<ICameraClient>& client,
904 const sp<IMemoryHeap>& heap, size_t offset, size_t size,
905 camera_frame_metadata_t *metadata) {
906 LOG2("copyFrameAndPostCopiedFrame");
907 // It is necessary to copy out of pmem before sending this to
908 // the callback. For efficiency, reuse the same MemoryHeapBase
909 // provided it's big enough. Don't allocate the memory or
910 // perform the copy if there's no callback.
911 // hold the preview lock while we grab a reference to the preview buffer
912 sp<MemoryHeapBase> previewBuffer;
913
914 if (mPreviewBuffer == 0) {
915 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
916 } else if (size > mPreviewBuffer->virtualSize()) {
917 mPreviewBuffer.clear();
918 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
919 }
920 if (mPreviewBuffer == 0) {
921 ALOGE("failed to allocate space for preview buffer");
922 mLock.unlock();
923 return;
924 }
925 previewBuffer = mPreviewBuffer;
926
927 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
928
929 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
930 if (frame == 0) {
931 ALOGE("failed to allocate space for frame callback");
932 mLock.unlock();
933 return;
934 }
935
936 mLock.unlock();
937 client->dataCallback(msgType, frame, metadata);
938}
939
940int CameraClient::getOrientation(int degrees, bool mirror) {
941 if (!mirror) {
942 if (degrees == 0) return 0;
943 else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
944 else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
945 else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
946 } else { // Do mirror (horizontal flip)
947 if (degrees == 0) { // FLIP_H and ROT_0
948 return HAL_TRANSFORM_FLIP_H;
949 } else if (degrees == 90) { // FLIP_H and ROT_90
950 return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
951 } else if (degrees == 180) { // FLIP_H and ROT_180
952 return HAL_TRANSFORM_FLIP_V;
953 } else if (degrees == 270) { // FLIP_H and ROT_270
954 return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
955 }
956 }
957 ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
958 return -1;
959}
960
961}; // namespace android