blob: 4f684b7ba3d3ada990e16b800bb2618dc3f2eb64 [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
4** Copyright (C) 2008 HTC Inc.
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080019#define LOG_TAG "CameraService"
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080021#include <stdio.h>
22#include <sys/types.h>
23#include <pthread.h>
24
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070025#include <binder/IPCThreadState.h>
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080026#include <binder/IServiceManager.h>
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070027#include <binder/MemoryBase.h>
28#include <binder/MemoryHeapBase.h>
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080029#include <cutils/atomic.h>
30#include <hardware/hardware.h>
31#include <media/AudioSystem.h>
32#include <media/mediaplayer.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080033#include <surfaceflinger/ISurface.h>
34#include <ui/Overlay.h>
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080035#include <utils/Errors.h>
36#include <utils/Log.h>
37#include <utils/String16.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080038
39#include "CameraService.h"
Chih-Chung Chang84761852010-05-10 14:36:24 +080040#ifdef INCLUDE_CAMERA_STUB
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080041#include "CameraHardwareStub.h"
42#endif
Eric Laurentcbcb00e2009-03-27 16:27:16 -070043
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080044namespace android {
45
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080046/* This determines the number of cameras available */
Chih-Chung Chang84761852010-05-10 14:36:24 +080047#if defined(INCLUDE_CAMERA_HARDWARE) && defined(INCLUDE_CAMERA_STUB)
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080048 #define NUM_CAMERAS 2
Chih-Chung Chang84761852010-05-10 14:36:24 +080049#elif defined(INCLUDE_CAMERA_HARDWARE) || defined(INCLUDE_CAMERA_STUB)
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080050 #define NUM_CAMERAS 1
51#else
52 #error "Should have at least one camera"
53#endif
54
55/* Make sure we have enough array space allocated */
56#if NUM_CAMERAS > MAX_CAMERAS
57 #error "Need to increase MAX_CAMERAS"
58#endif
59
60/* This defines the "open" function for each camera */
61extern "C" typedef sp<CameraHardwareInterface> (*OpenCameraHardwareFunction)();
62static OpenCameraHardwareFunction sOpenCameraTable[] = {
Chih-Chung Chang84761852010-05-10 14:36:24 +080063#ifdef INCLUDE_CAMERA_HARDWARE
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080064 &openCameraHardware,
65#endif
Chih-Chung Chang84761852010-05-10 14:36:24 +080066#ifdef INCLUDE_CAMERA_STUB
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080067 &openCameraHardwareStub,
68#endif
69};
70
71// ----------------------------------------------------------------------------
72// Logging support -- this is for debugging only
73// Use "adb shell dumpsys media.camera -v 1" to change it.
74static volatile int32_t gLogLevel = 0;
75
76#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__);
77#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__);
78
79static void setLogLevel(int level) {
80 android_atomic_write(level, &gLogLevel);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080081}
82
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080083// ----------------------------------------------------------------------------
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080084
Chih-Chung Changd98c5162009-06-22 16:03:41 +080085static int getCallingPid() {
86 return IPCThreadState::self()->getCallingPid();
87}
88
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080089static int getCallingUid() {
90 return IPCThreadState::self()->getCallingUid();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080091}
92
93// ----------------------------------------------------------------------------
94
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080095// This is ugly and only safe if we never re-create the CameraService, but
96// should be ok for now.
97static CameraService *gCameraService;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080098
Chih-Chung Chang5997faf2010-05-06 16:36:58 +080099CameraService::CameraService()
100:mSoundRef(0)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800101{
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800102 LOGI("CameraService started (pid=%d)", getpid());
103
104 for (int i = 0; i < NUM_CAMERAS; i++) {
105 setCameraFree(i);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800107
108 gCameraService = this;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800109}
110
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800111CameraService::~CameraService() {
112 for (int i = 0; i < NUM_CAMERAS; i++) {
113 if (mBusy[i]) {
114 LOGE("camera %d is still in use in destructor!", i);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800115 }
116 }
117
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800118 gCameraService = NULL;
119}
120
121int32_t CameraService::getNumberOfCameras() {
122 return NUM_CAMERAS;
123}
124
125sp<ICamera> CameraService::connect(
126 const sp<ICameraClient>& cameraClient, int cameraId) {
127 int callingPid = getCallingPid();
128 LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
129
130 sp<Client> client;
131 if (cameraId < 0 || cameraId >= NUM_CAMERAS) {
132 LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
133 callingPid, cameraId);
134 return NULL;
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800135 }
136
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800137 Mutex::Autolock lock(mServiceLock);
138 if (mClient[cameraId] != 0) {
139 client = mClient[cameraId].promote();
140 if (client != 0) {
141 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
142 LOG1("CameraService::connect X (pid %d) (the same client)",
143 callingPid);
144 return client;
145 } else {
146 LOGW("CameraService::connect X (pid %d) rejected (existing client).",
147 callingPid);
148 return NULL;
149 }
150 }
151 mClient[cameraId].clear();
152 }
153
154 if (mBusy[cameraId]) {
155 LOGW("CameraService::connect X (pid %d) rejected"
156 " (camera %d is still busy).", callingPid, cameraId);
157 return NULL;
158 }
159
160 client = new Client(this, cameraClient, cameraId, callingPid);
161 mClient[cameraId] = client;
162 LOG1("CameraService::connect X");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800163 return client;
164}
165
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800166void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800167 int callingPid = getCallingPid();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800168 LOG1("CameraService::removeClient E (pid %d)", callingPid);
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800169
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800170 for (int i = 0; i < NUM_CAMERAS; i++) {
171 // Declare this before the lock to make absolutely sure the
172 // destructor won't be called with the lock held.
173 sp<Client> client;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800174
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800175 Mutex::Autolock lock(mServiceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800176
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800177 // This happens when we have already disconnected (or this is
178 // just another unused camera).
179 if (mClient[i] == 0) continue;
180
181 // Promote mClient. It can fail if we are called from this path:
182 // Client::~Client() -> disconnect() -> removeClient().
183 client = mClient[i].promote();
184
185 if (client == 0) {
186 mClient[i].clear();
187 continue;
188 }
189
190 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
191 // Found our camera, clear and leave.
192 LOG1("removeClient: clear camera %d", i);
193 mClient[i].clear();
194 break;
195 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800196 }
197
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800198 LOG1("CameraService::removeClient X (pid %d)", callingPid);
199}
200
201sp<CameraService::Client> CameraService::getClientById(int cameraId) {
202 if (cameraId < 0 || cameraId >= NUM_CAMERAS) return NULL;
203 return mClient[cameraId].promote();
204}
205
206void CameraService::instantiate() {
207 defaultServiceManager()->addService(String16("media.camera"),
208 new CameraService());
209}
210
211status_t CameraService::onTransact(
212 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
213 // Permission checks
214 switch (code) {
215 case BnCameraService::CONNECT:
216 const int pid = getCallingPid();
217 const int self_pid = getpid();
218 if (pid != self_pid) {
219 // we're called from a different process, do the real check
220 if (!checkCallingPermission(
221 String16("android.permission.CAMERA"))) {
222 const int uid = getCallingUid();
223 LOGE("Permission Denial: "
224 "can't use the camera pid=%d, uid=%d", pid, uid);
225 return PERMISSION_DENIED;
226 }
227 }
228 break;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800229 }
230
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800231 return BnCameraService::onTransact(code, data, reply, flags);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800232}
233
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800234// The reason we need this busy bit is a new CameraService::connect() request
235// may come in while the previous Client's destructor has not been run or is
236// still running. If the last strong reference of the previous Client is gone
237// but the destructor has not been finished, we should not allow the new Client
238// to be created because we need to wait for the previous Client to tear down
239// the hardware first.
240void CameraService::setCameraBusy(int cameraId) {
241 android_atomic_write(1, &mBusy[cameraId]);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800242}
243
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800244void CameraService::setCameraFree(int cameraId) {
245 android_atomic_write(0, &mBusy[cameraId]);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800246}
247
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800248// We share the media players for shutter and recording sound for all clients.
249// A reference count is kept to determine when we will actually release the
250// media players.
251
252static MediaPlayer* newMediaPlayer(const char *file) {
253 MediaPlayer* mp = new MediaPlayer();
254 if (mp->setDataSource(file, NULL) == NO_ERROR) {
Eric Laurent9d91ad52009-07-17 12:17:14 -0700255 mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
Jason Sams78b877e2009-03-24 20:21:36 -0700256 mp->prepare();
257 } else {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800258 LOGE("Failed to load CameraService sounds: %s", file);
259 return NULL;
Jason Sams78b877e2009-03-24 20:21:36 -0700260 }
261 return mp;
262}
263
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800264void CameraService::loadSound() {
265 Mutex::Autolock lock(mSoundLock);
266 LOG1("CameraService::loadSound ref=%d", mSoundRef);
267 if (mSoundRef++) return;
268
269 mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
270 mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
271}
272
273void CameraService::releaseSound() {
274 Mutex::Autolock lock(mSoundLock);
275 LOG1("CameraService::releaseSound ref=%d", mSoundRef);
276 if (--mSoundRef) return;
277
278 for (int i = 0; i < NUM_SOUNDS; i++) {
279 if (mSoundPlayer[i] != 0) {
280 mSoundPlayer[i]->disconnect();
281 mSoundPlayer[i].clear();
282 }
283 }
284}
285
286void CameraService::playSound(sound_kind kind) {
287 LOG1("playSound(%d)", kind);
288 Mutex::Autolock lock(mSoundLock);
289 sp<MediaPlayer> player = mSoundPlayer[kind];
290 if (player != 0) {
291 // do not play the sound if stream volume is 0
292 // (typically because ringer mode is silent).
293 int index;
294 AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
295 if (index != 0) {
296 player->seekTo(0);
297 player->start();
298 }
299 }
300}
301
302// ----------------------------------------------------------------------------
303
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800304CameraService::Client::Client(const sp<CameraService>& cameraService,
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800305 const sp<ICameraClient>& cameraClient, int cameraId, int clientPid) {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800306 int callingPid = getCallingPid();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800307 LOG1("Client::Client E (pid %d)", callingPid);
308
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800309 mCameraService = cameraService;
310 mCameraClient = cameraClient;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800311 mCameraId = cameraId;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800312 mClientPid = clientPid;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800313
314 mHardware = sOpenCameraTable[cameraId]();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800315 mUseOverlay = mHardware->useOverlay();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800316 mMsgEnabled = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800317
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500318 mHardware->setCallbacks(notifyCallback,
319 dataCallback,
320 dataCallbackTimestamp,
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800321 (void *)cameraId);
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500322
323 // Enable zoom, error, and focus messages by default
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800324 enableMsgType(CAMERA_MSG_ERROR |
325 CAMERA_MSG_ZOOM |
326 CAMERA_MSG_FOCUS);
Benny Wong71f77152009-07-15 18:44:27 -0500327 mOverlayW = 0;
328 mOverlayH = 0;
Jason Sams78b877e2009-03-24 20:21:36 -0700329
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800330 // Callback is disabled by default
331 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800332 mOrientation = 0;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800333 cameraService->setCameraBusy(cameraId);
334 cameraService->loadSound();
335 LOG1("Client::Client X (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800336}
337
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800338static void *unregister_surface(void *arg) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800339 ISurface *surface = (ISurface *)arg;
340 surface->unregisterBuffers();
341 IPCThreadState::self()->flushCommands();
342 return NULL;
343}
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800344
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800345// tear down the client
346CameraService::Client::~Client() {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800347 int callingPid = getCallingPid();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800348 LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800349
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800350 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 pthread_t thr;
352 // We unregister the buffers in a different thread because binder does
353 // not let us make sychronous transactions in a binder destructor (that
354 // is, upon our reaching a refcount of zero.)
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800355 pthread_create(&thr,
356 NULL, // attr
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800357 unregister_surface,
358 mSurface.get());
359 pthread_join(thr, NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800360 }
361
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800362 // set mClientPid to let disconnet() tear down the hardware
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800363 mClientPid = callingPid;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800364 disconnect();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800365 mCameraService->releaseSound();
366 LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800367}
368
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800369// ----------------------------------------------------------------------------
370
371status_t CameraService::Client::checkPid() const {
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800372 int callingPid = getCallingPid();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800373 if (callingPid == mClientPid) return NO_ERROR;
374 if (callingPid == getpid()) {
375 LOGW("FIXME: use camera from mediaserver without permission.");
376 return NO_ERROR;
377 }
378 LOGW("attempt to use a locked camera from a different process"
379 " (old pid %d, new pid %d)", mClientPid, callingPid);
380 return EBUSY;
381}
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800382
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800383status_t CameraService::Client::checkPidAndHardware() const {
384 status_t result = checkPid();
385 if (result != NO_ERROR) return result;
386 if (mHardware == 0) {
387 LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
388 return INVALID_OPERATION;
389 }
390 return NO_ERROR;
391}
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800392
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800393status_t CameraService::Client::lock() {
394 int callingPid = getCallingPid();
395 LOG1("lock (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800396 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800397
398 // lock camera to this client if the the camera is unlocked
399 if (mClientPid == 0) {
400 mClientPid = callingPid;
401 return NO_ERROR;
402 }
403
404 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
405 return checkPid();
406}
407
408status_t CameraService::Client::unlock() {
409 int callingPid = getCallingPid();
410 LOG1("unlock (pid %d)", callingPid);
411 Mutex::Autolock lock(mLock);
412
413 // allow anyone to use camera (after they lock the camera)
414 status_t result = checkPid();
415 if (result == NO_ERROR) {
416 mClientPid = 0;
417 LOG1("clear mCameraClient (pid %d)", callingPid);
418 // we need to remove the reference to ICameraClient so that when the app
419 // goes away, the reference count goes to 0.
420 mCameraClient.clear();
421 }
422 return result;
423}
424
425// connect a new client to the camera
426status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
427 int callingPid = getCallingPid();
428 LOG1("connect E (pid %d)", callingPid);
429 Mutex::Autolock lock(mLock);
430
431 if (mClientPid != 0 && checkPid() != NO_ERROR) {
432 LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
433 mClientPid, callingPid);
434 return EBUSY;
435 }
436
437 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
438 LOG1("Connect to the same client");
439 return NO_ERROR;
440 }
441
442 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
443 mClientPid = callingPid;
444 mCameraClient = client;
445
446 LOG1("connect X (pid %d)", callingPid);
447 return NO_ERROR;
448}
449
450void CameraService::Client::disconnect() {
451 int callingPid = getCallingPid();
452 LOG1("disconnect E (pid %d)", callingPid);
453 Mutex::Autolock lock(mLock);
454
455 if (checkPid() != NO_ERROR) {
456 LOGW("different client - don't disconnect");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800457 return;
458 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800459
460 if (mClientPid <= 0) {
461 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800462 return;
463 }
464
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800465 // Make sure disconnect() is done once and once only, whether it is called
466 // from the user directly, or called by the destructor.
467 if (mHardware == 0) return;
468
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800469 LOG1("hardware teardown");
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800470 // Before destroying mHardware, we must make sure it's in the
471 // idle state.
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800472 // Turn off all messages.
473 disableMsgType(CAMERA_MSG_ALL_MSGS);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800474 mHardware->stopPreview();
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500475 mHardware->cancelPicture();
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800476 // Release the hardware resources.
477 mHardware->release();
Benny Wong71f77152009-07-15 18:44:27 -0500478 // Release the held overlay resources.
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800479 if (mUseOverlay) {
Benny Wong71f77152009-07-15 18:44:27 -0500480 mOverlayRef = 0;
481 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800482 mHardware.clear();
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800483
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800484 mCameraService->removeClient(mCameraClient);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800485 mCameraService->setCameraFree(mCameraId);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800486
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800487 LOG1("disconnect X (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800488}
489
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800490// ----------------------------------------------------------------------------
491
492// set the ISurface that the preview will use
493status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
494 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800495 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800496 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800497 if (result != NO_ERROR) return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800498
Wu-cheng Li988fb622009-06-23 23:37:36 +0800499 result = NO_ERROR;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800500
501 // return if no change in surface.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800502 // asBinder() is safe on NULL (returns NULL)
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800503 if (surface->asBinder() == mSurface->asBinder()) {
504 return result;
505 }
506
507 if (mSurface != 0) {
508 LOG1("clearing old preview surface %p", mSurface.get());
509 if (mUseOverlay) {
510 // Force the destruction of any previous overlay
511 sp<Overlay> dummy;
512 mHardware->setOverlay(dummy);
513 } else {
514 mSurface->unregisterBuffers();
Wu-cheng Li988fb622009-06-23 23:37:36 +0800515 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800516 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800517 mSurface = surface;
518 mOverlayRef = 0;
519 // If preview has been already started, set overlay or register preview
520 // buffers now.
521 if (mHardware->previewEnabled()) {
522 if (mUseOverlay) {
523 result = setOverlay();
524 } else if (mSurface != 0) {
525 result = registerPreviewBuffers();
526 }
527 }
528
Wu-cheng Li988fb622009-06-23 23:37:36 +0800529 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800530}
531
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800532status_t CameraService::Client::registerPreviewBuffers() {
Wu-cheng Li988fb622009-06-23 23:37:36 +0800533 int w, h;
534 CameraParameters params(mHardware->getParameters());
535 params.getPreviewSize(&w, &h);
536
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800537 // FIXME: don't use a hardcoded format here.
Wu-cheng Li988fb622009-06-23 23:37:36 +0800538 ISurface::BufferHeap buffers(w, h, w, h,
Mathias Agopian29d17422010-02-16 19:42:32 -0800539 HAL_PIXEL_FORMAT_YCrCb_420_SP,
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800540 mOrientation,
Wu-cheng Li988fb622009-06-23 23:37:36 +0800541 0,
542 mHardware->getPreviewHeap());
543
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800544 status_t result = mSurface->registerBuffers(buffers);
545 if (result != NO_ERROR) {
546 LOGE("registerBuffers failed with status %d", result);
Wu-cheng Li988fb622009-06-23 23:37:36 +0800547 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800548 return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800549}
550
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800551status_t CameraService::Client::setOverlay() {
552 int w, h;
553 CameraParameters params(mHardware->getParameters());
554 params.getPreviewSize(&w, &h);
555
556 if (w != mOverlayW || h != mOverlayH) {
557 // Force the destruction of any previous overlay
558 sp<Overlay> dummy;
559 mHardware->setOverlay(dummy);
560 mOverlayRef = 0;
561 }
562
563 status_t result = NO_ERROR;
564 if (mSurface == 0) {
565 result = mHardware->setOverlay(NULL);
566 } else {
567 if (mOverlayRef == 0) {
568 // FIXME:
569 // Surfaceflinger may hold onto the previous overlay reference for some
570 // time after we try to destroy it. retry a few times. In the future, we
571 // should make the destroy call block, or possibly specify that we can
572 // wait in the createOverlay call if the previous overlay is in the
573 // process of being destroyed.
574 for (int retry = 0; retry < 50; ++retry) {
575 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
576 mOrientation);
577 if (mOverlayRef != 0) break;
578 LOGW("Overlay create failed - retrying");
579 usleep(20000);
580 }
581 if (mOverlayRef == 0) {
582 LOGE("Overlay Creation Failed!");
583 return -EINVAL;
584 }
585 result = mHardware->setOverlay(new Overlay(mOverlayRef));
586 }
587 }
588 if (result != NO_ERROR) {
589 LOGE("mHardware->setOverlay() failed with status %d\n", result);
590 return result;
591 }
592
593 mOverlayW = w;
594 mOverlayH = h;
595
596 return result;
597}
598
599// set the preview callback flag to affect how the received frames from
600// preview are handled.
601void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
602 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
603 Mutex::Autolock lock(mLock);
604 if (checkPidAndHardware() != NO_ERROR) return;
605
606 mPreviewCallbackFlag = callback_flag;
607
608 // If we don't use overlay, we always need the preview frame for display.
609 // If we do use overlay, we only need the preview frame if the user
610 // wants the data.
611 if (mUseOverlay) {
612 if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
613 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
614 } else {
615 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
616 }
617 }
618}
619
620// start preview mode
621status_t CameraService::Client::startPreview() {
622 LOG1("startPreview (pid %d)", getCallingPid());
623 return startCameraMode(CAMERA_PREVIEW_MODE);
624}
625
626// start recording mode
627status_t CameraService::Client::startRecording() {
628 LOG1("startRecording (pid %d)", getCallingPid());
629 return startCameraMode(CAMERA_RECORDING_MODE);
630}
631
632// start preview or recording
633status_t CameraService::Client::startCameraMode(camera_mode mode) {
634 LOG1("startCameraMode(%d)", mode);
635 Mutex::Autolock lock(mLock);
636 status_t result = checkPidAndHardware();
637 if (result != NO_ERROR) return result;
638
639 switch(mode) {
640 case CAMERA_PREVIEW_MODE:
641 if (mSurface == 0) {
642 LOG1("mSurface is not set yet.");
643 // still able to start preview in this case.
644 }
645 return startPreviewMode();
646 case CAMERA_RECORDING_MODE:
647 if (mSurface == 0) {
648 LOGE("mSurface must be set before startRecordingMode.");
649 return INVALID_OPERATION;
650 }
651 return startRecordingMode();
652 default:
653 return UNKNOWN_ERROR;
654 }
655}
656
657status_t CameraService::Client::startPreviewMode() {
658 LOG1("startPreviewMode");
659 status_t result = NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800660
661 // if preview has been enabled, nothing needs to be done
662 if (mHardware->previewEnabled()) {
663 return NO_ERROR;
664 }
665
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800666 if (mUseOverlay) {
Wu-cheng Li988fb622009-06-23 23:37:36 +0800667 // If preview display has been set, set overlay now.
668 if (mSurface != 0) {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800669 result = setOverlay();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800671 if (result != NO_ERROR) return result;
672 result = mHardware->startPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800673 } else {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800674 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
675 result = mHardware->startPreview();
676 if (result != NO_ERROR) return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800677 // If preview display has been set, register preview buffers now.
678 if (mSurface != 0) {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800679 // Unregister here because the surface may be previously registered
680 // with the raw (snapshot) heap.
Wu-cheng Li988fb622009-06-23 23:37:36 +0800681 mSurface->unregisterBuffers();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800682 result = registerPreviewBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683 }
684 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800685 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800686}
687
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800688status_t CameraService::Client::startRecordingMode() {
689 LOG1("startRecordingMode");
690 status_t result = NO_ERROR;
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700691
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800692 // if recording has been enabled, nothing needs to be done
693 if (mHardware->recordingEnabled()) {
694 return NO_ERROR;
695 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800696
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800697 // if preview has not been started, start preview first
698 if (!mHardware->previewEnabled()) {
699 result = startPreviewMode();
700 if (result != NO_ERROR) {
701 return result;
Eric Laurent059b4132009-11-27 05:07:55 -0800702 }
Jason Sams78b877e2009-03-24 20:21:36 -0700703 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500704
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800705 // start recording mode
706 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
707 mCameraService->playSound(SOUND_RECORDING);
708 result = mHardware->startRecording();
709 if (result != NO_ERROR) {
710 LOGE("mHardware->startRecording() failed with status %d", result);
711 }
712 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800713}
714
715// stop preview mode
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800716void CameraService::Client::stopPreview() {
717 LOG1("stopPreview (pid %d)", getCallingPid());
718 Mutex::Autolock lock(mLock);
719 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800721 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
722 mHardware->stopPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800723
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800724 if (mSurface != 0 && !mUseOverlay) {
725 mSurface->unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800726 }
727
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800728 mPreviewBuffer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800729}
730
731// stop recording mode
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800732void CameraService::Client::stopRecording() {
733 LOG1("stopRecording (pid %d)", getCallingPid());
734 Mutex::Autolock lock(mLock);
735 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800736
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800737 mCameraService->playSound(SOUND_RECORDING);
738 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
739 mHardware->stopRecording();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800740
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800741 mPreviewBuffer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800742}
743
744// release a recording frame
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800745void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800746 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800747 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800748 mHardware->releaseRecordingFrame(mem);
749}
750
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800751bool CameraService::Client::previewEnabled() {
752 LOG1("previewEnabled (pid %d)", getCallingPid());
753
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800754 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800755 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800756 return mHardware->previewEnabled();
757}
758
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800759bool CameraService::Client::recordingEnabled() {
760 LOG1("recordingEnabled (pid %d)", getCallingPid());
761
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800762 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800763 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800764 return mHardware->recordingEnabled();
765}
766
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800767status_t CameraService::Client::autoFocus() {
768 LOG1("autoFocus (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800769
770 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800771 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772 if (result != NO_ERROR) return result;
773
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500774 return mHardware->autoFocus();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800775}
776
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800777status_t CameraService::Client::cancelAutoFocus() {
778 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800779
780 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800781 status_t result = checkPidAndHardware();
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800782 if (result != NO_ERROR) return result;
783
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800784 return mHardware->cancelAutoFocus();
785}
786
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800787// take a picture - image is returned in callback
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800788status_t CameraService::Client::takePicture() {
789 LOG1("takePicture (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790
791 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800792 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800793 if (result != NO_ERROR) return result;
794
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800795 enableMsgType(CAMERA_MSG_SHUTTER |
796 CAMERA_MSG_POSTVIEW_FRAME |
797 CAMERA_MSG_RAW_IMAGE |
798 CAMERA_MSG_COMPRESSED_IMAGE);
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500799
800 return mHardware->takePicture();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800801}
802
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800803// set preview/capture parameters - key/value pairs
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800804status_t CameraService::Client::setParameters(const String8& params) {
805 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800806
807 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800808 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800809 if (result != NO_ERROR) return result;
810
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800811 CameraParameters p(params);
James Dong102f7772009-09-13 17:10:24 -0700812 return mHardware->setParameters(p);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800813}
814
815// get preview/capture parameters - key/value pairs
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800816String8 CameraService::Client::getParameters() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800818 if (checkPidAndHardware() != NO_ERROR) return String8();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800819
Wu-cheng Li81d763f2009-04-22 16:21:26 +0800820 String8 params(mHardware->getParameters().flatten());
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800821 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
Wu-cheng Li81d763f2009-04-22 16:21:26 +0800822 return params;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800823}
824
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800825status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
826 LOG1("sendCommand (pid %d)", getCallingPid());
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700827 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800828 status_t result = checkPidAndHardware();
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700829 if (result != NO_ERROR) return result;
830
Chih-Chung Changf091e832010-01-22 17:49:48 -0800831 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
832 // The orientation cannot be set during preview.
833 if (mHardware->previewEnabled()) {
834 return INVALID_OPERATION;
835 }
836 switch (arg1) {
837 case 0:
838 mOrientation = ISurface::BufferHeap::ROT_0;
839 break;
840 case 90:
841 mOrientation = ISurface::BufferHeap::ROT_90;
842 break;
843 case 180:
844 mOrientation = ISurface::BufferHeap::ROT_180;
845 break;
846 case 270:
847 mOrientation = ISurface::BufferHeap::ROT_270;
848 break;
849 default:
850 return BAD_VALUE;
851 }
852 return OK;
853 }
854
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700855 return mHardware->sendCommand(cmd, arg1, arg2);
856}
857
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800858// ----------------------------------------------------------------------------
859
860void CameraService::Client::enableMsgType(int32_t msgType) {
861 android_atomic_or(msgType, &mMsgEnabled);
862 mHardware->enableMsgType(msgType);
863}
864
865void CameraService::Client::disableMsgType(int32_t msgType) {
866 android_atomic_and(~msgType, &mMsgEnabled);
867 mHardware->disableMsgType(msgType);
868}
869
870#define CHECK_MESSAGE_INTERVAL 10 // 10ms
871bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
872 int sleepCount = 0;
873 while (mMsgEnabled & msgType) {
874 if (mLock.tryLock() == NO_ERROR) {
875 if (sleepCount > 0) {
876 LOG1("lockIfMessageWanted(%d): waited for %d ms",
877 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
878 }
879 return true;
880 }
881 if (sleepCount++ == 0) {
882 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
883 }
884 usleep(CHECK_MESSAGE_INTERVAL * 1000);
885 }
886 LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
887 return false;
888}
889
890// ----------------------------------------------------------------------------
891
892// Converts from a raw pointer to the client to a strong pointer during a
893// hardware callback. This requires the callbacks only happen when the client
894// is still alive.
895sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
896 sp<Client> client = gCameraService->getClientById((int) user);
897
898 // This could happen if the Client is in the process of shutting down (the
899 // last strong reference is gone, but the destructor hasn't finished
900 // stopping the hardware).
901 if (client == 0) return NULL;
902
903 // The checks below are not necessary and are for debugging only.
904 if (client->mCameraService.get() != gCameraService) {
905 LOGE("mismatch service!");
906 return NULL;
907 }
908
909 if (client->mHardware == 0) {
910 LOGE("mHardware == 0: callback after disconnect()?");
911 return NULL;
912 }
913
914 return client;
915}
916
917// Callback messages can be dispatched to internal handlers or pass to our
918// client's callback functions, depending on the message type.
919//
920// notifyCallback:
921// CAMERA_MSG_SHUTTER handleShutter
922// (others) c->notifyCallback
923// dataCallback:
924// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
925// CAMERA_MSG_POSTVIEW_FRAME handlePostview
926// CAMERA_MSG_RAW_IMAGE handleRawPicture
927// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
928// (others) c->dataCallback
929// dataCallbackTimestamp
930// (others) c->dataCallbackTimestamp
931//
932// NOTE: the *Callback functions grab mLock of the client before passing
933// control to handle* functions. So the handle* functions must release the
934// lock before calling the ICameraClient's callbacks, so those callbacks can
935// invoke methods in the Client class again (For example, the preview frame
936// callback may want to releaseRecordingFrame). The handle* functions must
937// release the lock after all accesses to member variables, so it must be
938// handled very carefully.
939
940void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
941 int32_t ext2, void* user) {
942 LOG2("notifyCallback(%d)", msgType);
943
944 sp<Client> client = getClientFromCookie(user);
945 if (client == 0) return;
946 if (!client->lockIfMessageWanted(msgType)) return;
947
948 switch (msgType) {
949 case CAMERA_MSG_SHUTTER:
950 // ext1 is the dimension of the yuv picture.
951 client->handleShutter((image_rect_type *)ext1);
952 break;
953 default:
954 client->handleGenericNotify(msgType, ext1, ext2);
955 break;
956 }
957}
958
959void CameraService::Client::dataCallback(int32_t msgType,
960 const sp<IMemory>& dataPtr, void* user) {
961 LOG2("dataCallback(%d)", msgType);
962
963 sp<Client> client = getClientFromCookie(user);
964 if (client == 0) return;
965 if (!client->lockIfMessageWanted(msgType)) return;
966
967 if (dataPtr == 0) {
968 LOGE("Null data returned in data callback");
969 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
970 return;
971 }
972
973 switch (msgType) {
974 case CAMERA_MSG_PREVIEW_FRAME:
975 client->handlePreviewData(dataPtr);
976 break;
977 case CAMERA_MSG_POSTVIEW_FRAME:
978 client->handlePostview(dataPtr);
979 break;
980 case CAMERA_MSG_RAW_IMAGE:
981 client->handleRawPicture(dataPtr);
982 break;
983 case CAMERA_MSG_COMPRESSED_IMAGE:
984 client->handleCompressedPicture(dataPtr);
985 break;
986 default:
987 client->handleGenericData(msgType, dataPtr);
988 break;
989 }
990}
991
992void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
993 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
994 LOG2("dataCallbackTimestamp(%d)", msgType);
995
996 sp<Client> client = getClientFromCookie(user);
997 if (client == 0) return;
998 if (!client->lockIfMessageWanted(msgType)) return;
999
1000 if (dataPtr == 0) {
1001 LOGE("Null data returned in data with timestamp callback");
1002 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1003 return;
1004 }
1005
1006 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
1007}
1008
1009// snapshot taken callback
1010// "size" is the width and height of yuv picture for registerBuffer.
1011// If it is NULL, use the picture size from parameters.
1012void CameraService::Client::handleShutter(image_rect_type *size) {
1013 mCameraService->playSound(SOUND_SHUTTER);
1014
1015 // Screen goes black after the buffer is unregistered.
1016 if (mSurface != 0 && !mUseOverlay) {
1017 mSurface->unregisterBuffers();
1018 }
1019
1020 sp<ICameraClient> c = mCameraClient;
1021 if (c != 0) {
1022 mLock.unlock();
1023 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
1024 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
1025 }
1026 disableMsgType(CAMERA_MSG_SHUTTER);
1027
1028 // It takes some time before yuvPicture callback to be called.
1029 // Register the buffer for raw image here to reduce latency.
1030 if (mSurface != 0 && !mUseOverlay) {
1031 int w, h;
1032 CameraParameters params(mHardware->getParameters());
1033 if (size == NULL) {
1034 params.getPictureSize(&w, &h);
1035 } else {
1036 w = size->width;
1037 h = size->height;
1038 w &= ~1;
1039 h &= ~1;
1040 LOG1("Snapshot image width=%d, height=%d", w, h);
1041 }
1042 // FIXME: don't use hardcoded format constants here
1043 ISurface::BufferHeap buffers(w, h, w, h,
1044 HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
1045 mHardware->getRawHeap());
1046
1047 mSurface->registerBuffers(buffers);
1048 }
1049
1050 mLock.unlock();
1051}
1052
1053// preview callback - frame buffer update
1054void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
1055 ssize_t offset;
1056 size_t size;
1057 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1058
1059 if (!mUseOverlay) {
1060 if (mSurface != 0) {
1061 mSurface->postBuffer(offset);
1062 }
1063 }
1064
1065 // local copy of the callback flags
1066 int flags = mPreviewCallbackFlag;
1067
1068 // is callback enabled?
1069 if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
1070 // If the enable bit is off, the copy-out and one-shot bits are ignored
1071 LOG2("frame callback is disabled");
1072 mLock.unlock();
1073 return;
1074 }
1075
1076 // hold a strong pointer to the client
1077 sp<ICameraClient> c = mCameraClient;
1078
1079 // clear callback flags if no client or one-shot mode
1080 if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
1081 LOG2("Disable preview callback");
1082 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1083 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1084 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1085 if (mUseOverlay) {
1086 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
1087 }
1088 }
1089
1090 if (c != 0) {
1091 // Is the received frame copied out or not?
1092 if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1093 LOG2("frame is copied");
1094 copyFrameAndPostCopiedFrame(c, heap, offset, size);
1095 } else {
1096 LOG2("frame is forwarded");
1097 mLock.unlock();
1098 c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
1099 }
1100 } else {
1101 mLock.unlock();
1102 }
1103}
1104
1105// picture callback - postview image ready
1106void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
1107 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1108
1109 sp<ICameraClient> c = mCameraClient;
1110 mLock.unlock();
1111 if (c != 0) {
1112 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1113 }
1114}
1115
1116// picture callback - raw image ready
1117void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
1118 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1119
1120 ssize_t offset;
1121 size_t size;
1122 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1123
1124 // Put the YUV version of the snapshot in the preview display.
1125 if (mSurface != 0 && !mUseOverlay) {
1126 mSurface->postBuffer(offset);
1127 }
1128
1129 sp<ICameraClient> c = mCameraClient;
1130 mLock.unlock();
1131 if (c != 0) {
1132 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1133 }
1134}
1135
1136// picture callback - compressed picture ready
1137void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
1138 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1139
1140 sp<ICameraClient> c = mCameraClient;
1141 mLock.unlock();
1142 if (c != 0) {
1143 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1144 }
1145}
1146
1147
1148void CameraService::Client::handleGenericNotify(int32_t msgType,
1149 int32_t ext1, int32_t ext2) {
1150 sp<ICameraClient> c = mCameraClient;
1151 mLock.unlock();
1152 if (c != 0) {
1153 c->notifyCallback(msgType, ext1, ext2);
1154 }
1155}
1156
1157void CameraService::Client::handleGenericData(int32_t msgType,
1158 const sp<IMemory>& dataPtr) {
1159 sp<ICameraClient> c = mCameraClient;
1160 mLock.unlock();
1161 if (c != 0) {
1162 c->dataCallback(msgType, dataPtr);
1163 }
1164}
1165
1166void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
1167 int32_t msgType, const sp<IMemory>& dataPtr) {
1168 sp<ICameraClient> c = mCameraClient;
1169 mLock.unlock();
1170 if (c != 0) {
1171 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1172 }
1173}
1174
1175void CameraService::Client::copyFrameAndPostCopiedFrame(
1176 const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
1177 size_t offset, size_t size) {
1178 LOG2("copyFrameAndPostCopiedFrame");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001179 // It is necessary to copy out of pmem before sending this to
1180 // the callback. For efficiency, reuse the same MemoryHeapBase
1181 // provided it's big enough. Don't allocate the memory or
1182 // perform the copy if there's no callback.
Dave Sparksff0f38e2009-11-10 17:08:08 -08001183 // hold the preview lock while we grab a reference to the preview buffer
Dave Sparks23c21ba2009-11-06 11:47:13 -08001184 sp<MemoryHeapBase> previewBuffer;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001185
1186 if (mPreviewBuffer == 0) {
1187 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1188 } else if (size > mPreviewBuffer->virtualSize()) {
1189 mPreviewBuffer.clear();
1190 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001191 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001192 if (mPreviewBuffer == 0) {
1193 LOGE("failed to allocate space for preview buffer");
1194 mLock.unlock();
1195 return;
1196 }
1197 previewBuffer = mPreviewBuffer;
1198
1199 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001200
Dave Sparks23c21ba2009-11-06 11:47:13 -08001201 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001202 if (frame == 0) {
1203 LOGE("failed to allocate space for frame callback");
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001204 mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001205 return;
1206 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001207
1208 mLock.unlock();
Dave Sparks393eb792009-10-15 10:02:22 -07001209 client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001210}
1211
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001212// ----------------------------------------------------------------------------
1213
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001214static const int kDumpLockRetries = 50;
1215static const int kDumpLockSleep = 60000;
1216
1217static bool tryLock(Mutex& mutex)
1218{
1219 bool locked = false;
1220 for (int i = 0; i < kDumpLockRetries; ++i) {
1221 if (mutex.tryLock() == NO_ERROR) {
1222 locked = true;
1223 break;
1224 }
1225 usleep(kDumpLockSleep);
1226 }
1227 return locked;
1228}
1229
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001230status_t CameraService::dump(int fd, const Vector<String16>& args) {
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001231 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1232
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001233 const size_t SIZE = 256;
1234 char buffer[SIZE];
1235 String8 result;
1236 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1237 snprintf(buffer, SIZE, "Permission Denial: "
1238 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Changd98c5162009-06-22 16:03:41 +08001239 getCallingPid(),
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001240 getCallingUid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001241 result.append(buffer);
1242 write(fd, result.string(), result.size());
1243 } else {
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001244 bool locked = tryLock(mServiceLock);
1245 // failed to lock - CameraService is probably deadlocked
1246 if (!locked) {
1247 String8 result(kDeadlockedString);
1248 write(fd, result.string(), result.size());
1249 }
1250
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001251 bool hasClient = false;
1252 for (int i = 0; i < NUM_CAMERAS; i++) {
1253 sp<Client> client = mClient[i].promote();
1254 if (client == 0) continue;
1255 hasClient = true;
1256 sprintf(buffer, "Client[%d] (%p) PID: %d\n",
1257 i,
1258 client->getCameraClient()->asBinder().get(),
1259 client->mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001260 result.append(buffer);
1261 write(fd, result.string(), result.size());
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001262 client->mHardware->dump(fd, args);
1263 }
1264 if (!hasClient) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001265 result.append("No camera client yet.\n");
1266 write(fd, result.string(), result.size());
1267 }
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001268
1269 if (locked) mServiceLock.unlock();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001270
1271 // change logging level
1272 int n = args.size();
1273 for (int i = 0; i + 1 < n; i++) {
1274 if (args[i] == String16("-v")) {
1275 String8 levelStr(args[i+1]);
1276 int level = atoi(levelStr.string());
1277 sprintf(buffer, "Set Log Level to %d", level);
1278 result.append(buffer);
1279 setLogLevel(level);
1280 }
1281 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001282 }
1283 return NO_ERROR;
1284}
1285
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001286}; // namespace android