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