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