blob: 690169af8a82b961d19ad4ce5708c193291d9f6e [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;
James Dongfcd193c2010-06-09 15:57:48 -0700374
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800375 LOGW("attempt to use a locked camera from a different process"
376 " (old pid %d, new pid %d)", mClientPid, callingPid);
377 return EBUSY;
378}
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800379
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800380status_t CameraService::Client::checkPidAndHardware() const {
381 status_t result = checkPid();
382 if (result != NO_ERROR) return result;
383 if (mHardware == 0) {
384 LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
385 return INVALID_OPERATION;
386 }
387 return NO_ERROR;
388}
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800389
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800390status_t CameraService::Client::lock() {
391 int callingPid = getCallingPid();
392 LOG1("lock (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800393 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800394
395 // lock camera to this client if the the camera is unlocked
396 if (mClientPid == 0) {
397 mClientPid = callingPid;
398 return NO_ERROR;
399 }
400
401 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
402 return checkPid();
403}
404
405status_t CameraService::Client::unlock() {
406 int callingPid = getCallingPid();
407 LOG1("unlock (pid %d)", callingPid);
408 Mutex::Autolock lock(mLock);
409
410 // allow anyone to use camera (after they lock the camera)
411 status_t result = checkPid();
412 if (result == NO_ERROR) {
413 mClientPid = 0;
414 LOG1("clear mCameraClient (pid %d)", callingPid);
415 // we need to remove the reference to ICameraClient so that when the app
416 // goes away, the reference count goes to 0.
417 mCameraClient.clear();
418 }
419 return result;
420}
421
422// connect a new client to the camera
423status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
424 int callingPid = getCallingPid();
425 LOG1("connect E (pid %d)", callingPid);
426 Mutex::Autolock lock(mLock);
427
428 if (mClientPid != 0 && checkPid() != NO_ERROR) {
429 LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
430 mClientPid, callingPid);
431 return EBUSY;
432 }
433
434 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
435 LOG1("Connect to the same client");
436 return NO_ERROR;
437 }
438
439 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
440 mClientPid = callingPid;
441 mCameraClient = client;
442
443 LOG1("connect X (pid %d)", callingPid);
444 return NO_ERROR;
445}
446
447void CameraService::Client::disconnect() {
448 int callingPid = getCallingPid();
449 LOG1("disconnect E (pid %d)", callingPid);
450 Mutex::Autolock lock(mLock);
451
452 if (checkPid() != NO_ERROR) {
453 LOGW("different client - don't disconnect");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800454 return;
455 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800456
457 if (mClientPid <= 0) {
458 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800459 return;
460 }
461
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800462 // Make sure disconnect() is done once and once only, whether it is called
463 // from the user directly, or called by the destructor.
464 if (mHardware == 0) return;
465
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800466 LOG1("hardware teardown");
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800467 // Before destroying mHardware, we must make sure it's in the
468 // idle state.
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800469 // Turn off all messages.
470 disableMsgType(CAMERA_MSG_ALL_MSGS);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800471 mHardware->stopPreview();
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500472 mHardware->cancelPicture();
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800473 // Release the hardware resources.
474 mHardware->release();
Benny Wong71f77152009-07-15 18:44:27 -0500475 // Release the held overlay resources.
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800476 if (mUseOverlay) {
Benny Wong71f77152009-07-15 18:44:27 -0500477 mOverlayRef = 0;
478 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800479 mHardware.clear();
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800480
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800481 mCameraService->removeClient(mCameraClient);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800482 mCameraService->setCameraFree(mCameraId);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800483
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800484 LOG1("disconnect X (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800485}
486
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800487// ----------------------------------------------------------------------------
488
489// set the ISurface that the preview will use
490status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
491 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800492 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800493 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800494 if (result != NO_ERROR) return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800495
Wu-cheng Li988fb622009-06-23 23:37:36 +0800496 result = NO_ERROR;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800497
498 // return if no change in surface.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800499 // asBinder() is safe on NULL (returns NULL)
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800500 if (surface->asBinder() == mSurface->asBinder()) {
501 return result;
502 }
503
504 if (mSurface != 0) {
505 LOG1("clearing old preview surface %p", mSurface.get());
506 if (mUseOverlay) {
507 // Force the destruction of any previous overlay
508 sp<Overlay> dummy;
509 mHardware->setOverlay(dummy);
510 } else {
511 mSurface->unregisterBuffers();
Wu-cheng Li988fb622009-06-23 23:37:36 +0800512 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800513 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800514 mSurface = surface;
515 mOverlayRef = 0;
516 // If preview has been already started, set overlay or register preview
517 // buffers now.
518 if (mHardware->previewEnabled()) {
519 if (mUseOverlay) {
520 result = setOverlay();
521 } else if (mSurface != 0) {
522 result = registerPreviewBuffers();
523 }
524 }
525
Wu-cheng Li988fb622009-06-23 23:37:36 +0800526 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800527}
528
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800529status_t CameraService::Client::registerPreviewBuffers() {
Wu-cheng Li988fb622009-06-23 23:37:36 +0800530 int w, h;
531 CameraParameters params(mHardware->getParameters());
532 params.getPreviewSize(&w, &h);
533
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800534 // FIXME: don't use a hardcoded format here.
Wu-cheng Li988fb622009-06-23 23:37:36 +0800535 ISurface::BufferHeap buffers(w, h, w, h,
Mathias Agopian29d17422010-02-16 19:42:32 -0800536 HAL_PIXEL_FORMAT_YCrCb_420_SP,
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800537 mOrientation,
Wu-cheng Li988fb622009-06-23 23:37:36 +0800538 0,
539 mHardware->getPreviewHeap());
540
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800541 status_t result = mSurface->registerBuffers(buffers);
542 if (result != NO_ERROR) {
543 LOGE("registerBuffers failed with status %d", result);
Wu-cheng Li988fb622009-06-23 23:37:36 +0800544 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800545 return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800546}
547
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800548status_t CameraService::Client::setOverlay() {
549 int w, h;
550 CameraParameters params(mHardware->getParameters());
551 params.getPreviewSize(&w, &h);
552
553 if (w != mOverlayW || h != mOverlayH) {
554 // Force the destruction of any previous overlay
555 sp<Overlay> dummy;
556 mHardware->setOverlay(dummy);
557 mOverlayRef = 0;
558 }
559
560 status_t result = NO_ERROR;
561 if (mSurface == 0) {
562 result = mHardware->setOverlay(NULL);
563 } else {
564 if (mOverlayRef == 0) {
565 // FIXME:
566 // Surfaceflinger may hold onto the previous overlay reference for some
567 // time after we try to destroy it. retry a few times. In the future, we
568 // should make the destroy call block, or possibly specify that we can
569 // wait in the createOverlay call if the previous overlay is in the
570 // process of being destroyed.
571 for (int retry = 0; retry < 50; ++retry) {
572 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
573 mOrientation);
574 if (mOverlayRef != 0) break;
575 LOGW("Overlay create failed - retrying");
576 usleep(20000);
577 }
578 if (mOverlayRef == 0) {
579 LOGE("Overlay Creation Failed!");
580 return -EINVAL;
581 }
582 result = mHardware->setOverlay(new Overlay(mOverlayRef));
583 }
584 }
585 if (result != NO_ERROR) {
586 LOGE("mHardware->setOverlay() failed with status %d\n", result);
587 return result;
588 }
589
590 mOverlayW = w;
591 mOverlayH = h;
592
593 return result;
594}
595
596// set the preview callback flag to affect how the received frames from
597// preview are handled.
598void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
599 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
600 Mutex::Autolock lock(mLock);
601 if (checkPidAndHardware() != NO_ERROR) return;
602
603 mPreviewCallbackFlag = callback_flag;
604
605 // If we don't use overlay, we always need the preview frame for display.
606 // If we do use overlay, we only need the preview frame if the user
607 // wants the data.
608 if (mUseOverlay) {
609 if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
610 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
611 } else {
612 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
613 }
614 }
615}
616
617// start preview mode
618status_t CameraService::Client::startPreview() {
619 LOG1("startPreview (pid %d)", getCallingPid());
620 return startCameraMode(CAMERA_PREVIEW_MODE);
621}
622
623// start recording mode
624status_t CameraService::Client::startRecording() {
625 LOG1("startRecording (pid %d)", getCallingPid());
626 return startCameraMode(CAMERA_RECORDING_MODE);
627}
628
629// start preview or recording
630status_t CameraService::Client::startCameraMode(camera_mode mode) {
631 LOG1("startCameraMode(%d)", mode);
632 Mutex::Autolock lock(mLock);
633 status_t result = checkPidAndHardware();
634 if (result != NO_ERROR) return result;
635
636 switch(mode) {
637 case CAMERA_PREVIEW_MODE:
638 if (mSurface == 0) {
639 LOG1("mSurface is not set yet.");
640 // still able to start preview in this case.
641 }
642 return startPreviewMode();
643 case CAMERA_RECORDING_MODE:
644 if (mSurface == 0) {
645 LOGE("mSurface must be set before startRecordingMode.");
646 return INVALID_OPERATION;
647 }
648 return startRecordingMode();
649 default:
650 return UNKNOWN_ERROR;
651 }
652}
653
654status_t CameraService::Client::startPreviewMode() {
655 LOG1("startPreviewMode");
656 status_t result = NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800657
658 // if preview has been enabled, nothing needs to be done
659 if (mHardware->previewEnabled()) {
660 return NO_ERROR;
661 }
662
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800663 if (mUseOverlay) {
Wu-cheng Li988fb622009-06-23 23:37:36 +0800664 // If preview display has been set, set overlay now.
665 if (mSurface != 0) {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800666 result = setOverlay();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800667 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800668 if (result != NO_ERROR) return result;
669 result = mHardware->startPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800670 } else {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800671 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
672 result = mHardware->startPreview();
673 if (result != NO_ERROR) return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800674 // If preview display has been set, register preview buffers now.
675 if (mSurface != 0) {
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800676 // Unregister here because the surface may be previously registered
677 // with the raw (snapshot) heap.
Wu-cheng Li988fb622009-06-23 23:37:36 +0800678 mSurface->unregisterBuffers();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800679 result = registerPreviewBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800680 }
681 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800682 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800683}
684
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800685status_t CameraService::Client::startRecordingMode() {
686 LOG1("startRecordingMode");
687 status_t result = NO_ERROR;
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700688
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800689 // if recording has been enabled, nothing needs to be done
690 if (mHardware->recordingEnabled()) {
691 return NO_ERROR;
692 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800693
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800694 // if preview has not been started, start preview first
695 if (!mHardware->previewEnabled()) {
696 result = startPreviewMode();
697 if (result != NO_ERROR) {
698 return result;
Eric Laurent059b4132009-11-27 05:07:55 -0800699 }
Jason Sams78b877e2009-03-24 20:21:36 -0700700 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500701
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800702 // start recording mode
703 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
704 mCameraService->playSound(SOUND_RECORDING);
705 result = mHardware->startRecording();
706 if (result != NO_ERROR) {
707 LOGE("mHardware->startRecording() failed with status %d", result);
708 }
709 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710}
711
712// stop preview mode
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800713void CameraService::Client::stopPreview() {
714 LOG1("stopPreview (pid %d)", getCallingPid());
715 Mutex::Autolock lock(mLock);
716 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800717
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800718 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
719 mHardware->stopPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800720
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800721 if (mSurface != 0 && !mUseOverlay) {
722 mSurface->unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800723 }
724
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800725 mPreviewBuffer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800726}
727
728// stop recording mode
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800729void CameraService::Client::stopRecording() {
730 LOG1("stopRecording (pid %d)", getCallingPid());
731 Mutex::Autolock lock(mLock);
732 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800733
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800734 mCameraService->playSound(SOUND_RECORDING);
735 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
736 mHardware->stopRecording();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800737
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800738 mPreviewBuffer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800739}
740
741// release a recording frame
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800742void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800743 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800744 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800745 mHardware->releaseRecordingFrame(mem);
746}
747
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800748bool CameraService::Client::previewEnabled() {
749 LOG1("previewEnabled (pid %d)", getCallingPid());
750
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800751 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800752 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800753 return mHardware->previewEnabled();
754}
755
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800756bool CameraService::Client::recordingEnabled() {
757 LOG1("recordingEnabled (pid %d)", getCallingPid());
758
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800759 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800760 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800761 return mHardware->recordingEnabled();
762}
763
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800764status_t CameraService::Client::autoFocus() {
765 LOG1("autoFocus (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800766
767 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800768 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800769 if (result != NO_ERROR) return result;
770
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500771 return mHardware->autoFocus();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800772}
773
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800774status_t CameraService::Client::cancelAutoFocus() {
775 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800776
777 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800778 status_t result = checkPidAndHardware();
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800779 if (result != NO_ERROR) return result;
780
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800781 return mHardware->cancelAutoFocus();
782}
783
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800784// take a picture - image is returned in callback
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800785status_t CameraService::Client::takePicture() {
786 LOG1("takePicture (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800787
788 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800789 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800790 if (result != NO_ERROR) return result;
791
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800792 enableMsgType(CAMERA_MSG_SHUTTER |
793 CAMERA_MSG_POSTVIEW_FRAME |
794 CAMERA_MSG_RAW_IMAGE |
795 CAMERA_MSG_COMPRESSED_IMAGE);
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500796
797 return mHardware->takePicture();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800798}
799
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800800// set preview/capture parameters - key/value pairs
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800801status_t CameraService::Client::setParameters(const String8& params) {
802 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800803
804 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800805 status_t result = checkPidAndHardware();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800806 if (result != NO_ERROR) return result;
807
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800808 CameraParameters p(params);
James Dong102f7772009-09-13 17:10:24 -0700809 return mHardware->setParameters(p);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800810}
811
812// get preview/capture parameters - key/value pairs
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800813String8 CameraService::Client::getParameters() const {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800814 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800815 if (checkPidAndHardware() != NO_ERROR) return String8();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800816
Wu-cheng Li81d763f2009-04-22 16:21:26 +0800817 String8 params(mHardware->getParameters().flatten());
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800818 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
Wu-cheng Li81d763f2009-04-22 16:21:26 +0800819 return params;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800820}
821
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800822status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
823 LOG1("sendCommand (pid %d)", getCallingPid());
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700824 Mutex::Autolock lock(mLock);
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800825 status_t result = checkPidAndHardware();
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700826 if (result != NO_ERROR) return result;
827
Chih-Chung Changf091e832010-01-22 17:49:48 -0800828 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
829 // The orientation cannot be set during preview.
830 if (mHardware->previewEnabled()) {
831 return INVALID_OPERATION;
832 }
833 switch (arg1) {
834 case 0:
835 mOrientation = ISurface::BufferHeap::ROT_0;
836 break;
837 case 90:
838 mOrientation = ISurface::BufferHeap::ROT_90;
839 break;
840 case 180:
841 mOrientation = ISurface::BufferHeap::ROT_180;
842 break;
843 case 270:
844 mOrientation = ISurface::BufferHeap::ROT_270;
845 break;
846 default:
847 return BAD_VALUE;
848 }
849 return OK;
850 }
851
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700852 return mHardware->sendCommand(cmd, arg1, arg2);
853}
854
Chih-Chung Chang5997faf2010-05-06 16:36:58 +0800855// ----------------------------------------------------------------------------
856
857void CameraService::Client::enableMsgType(int32_t msgType) {
858 android_atomic_or(msgType, &mMsgEnabled);
859 mHardware->enableMsgType(msgType);
860}
861
862void CameraService::Client::disableMsgType(int32_t msgType) {
863 android_atomic_and(~msgType, &mMsgEnabled);
864 mHardware->disableMsgType(msgType);
865}
866
867#define CHECK_MESSAGE_INTERVAL 10 // 10ms
868bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
869 int sleepCount = 0;
870 while (mMsgEnabled & msgType) {
871 if (mLock.tryLock() == NO_ERROR) {
872 if (sleepCount > 0) {
873 LOG1("lockIfMessageWanted(%d): waited for %d ms",
874 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
875 }
876 return true;
877 }
878 if (sleepCount++ == 0) {
879 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
880 }
881 usleep(CHECK_MESSAGE_INTERVAL * 1000);
882 }
883 LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
884 return false;
885}
886
887// ----------------------------------------------------------------------------
888
889// Converts from a raw pointer to the client to a strong pointer during a
890// hardware callback. This requires the callbacks only happen when the client
891// is still alive.
892sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
893 sp<Client> client = gCameraService->getClientById((int) user);
894
895 // This could happen if the Client is in the process of shutting down (the
896 // last strong reference is gone, but the destructor hasn't finished
897 // stopping the hardware).
898 if (client == 0) return NULL;
899
900 // The checks below are not necessary and are for debugging only.
901 if (client->mCameraService.get() != gCameraService) {
902 LOGE("mismatch service!");
903 return NULL;
904 }
905
906 if (client->mHardware == 0) {
907 LOGE("mHardware == 0: callback after disconnect()?");
908 return NULL;
909 }
910
911 return client;
912}
913
914// Callback messages can be dispatched to internal handlers or pass to our
915// client's callback functions, depending on the message type.
916//
917// notifyCallback:
918// CAMERA_MSG_SHUTTER handleShutter
919// (others) c->notifyCallback
920// dataCallback:
921// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
922// CAMERA_MSG_POSTVIEW_FRAME handlePostview
923// CAMERA_MSG_RAW_IMAGE handleRawPicture
924// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
925// (others) c->dataCallback
926// dataCallbackTimestamp
927// (others) c->dataCallbackTimestamp
928//
929// NOTE: the *Callback functions grab mLock of the client before passing
930// control to handle* functions. So the handle* functions must release the
931// lock before calling the ICameraClient's callbacks, so those callbacks can
932// invoke methods in the Client class again (For example, the preview frame
933// callback may want to releaseRecordingFrame). The handle* functions must
934// release the lock after all accesses to member variables, so it must be
935// handled very carefully.
936
937void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
938 int32_t ext2, void* user) {
939 LOG2("notifyCallback(%d)", msgType);
940
941 sp<Client> client = getClientFromCookie(user);
942 if (client == 0) return;
943 if (!client->lockIfMessageWanted(msgType)) return;
944
945 switch (msgType) {
946 case CAMERA_MSG_SHUTTER:
947 // ext1 is the dimension of the yuv picture.
948 client->handleShutter((image_rect_type *)ext1);
949 break;
950 default:
951 client->handleGenericNotify(msgType, ext1, ext2);
952 break;
953 }
954}
955
956void CameraService::Client::dataCallback(int32_t msgType,
957 const sp<IMemory>& dataPtr, void* user) {
958 LOG2("dataCallback(%d)", msgType);
959
960 sp<Client> client = getClientFromCookie(user);
961 if (client == 0) return;
962 if (!client->lockIfMessageWanted(msgType)) return;
963
964 if (dataPtr == 0) {
965 LOGE("Null data returned in data callback");
966 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
967 return;
968 }
969
970 switch (msgType) {
971 case CAMERA_MSG_PREVIEW_FRAME:
972 client->handlePreviewData(dataPtr);
973 break;
974 case CAMERA_MSG_POSTVIEW_FRAME:
975 client->handlePostview(dataPtr);
976 break;
977 case CAMERA_MSG_RAW_IMAGE:
978 client->handleRawPicture(dataPtr);
979 break;
980 case CAMERA_MSG_COMPRESSED_IMAGE:
981 client->handleCompressedPicture(dataPtr);
982 break;
983 default:
984 client->handleGenericData(msgType, dataPtr);
985 break;
986 }
987}
988
989void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
990 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
991 LOG2("dataCallbackTimestamp(%d)", msgType);
992
993 sp<Client> client = getClientFromCookie(user);
994 if (client == 0) return;
995 if (!client->lockIfMessageWanted(msgType)) return;
996
997 if (dataPtr == 0) {
998 LOGE("Null data returned in data with timestamp callback");
999 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1000 return;
1001 }
1002
1003 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
1004}
1005
1006// snapshot taken callback
1007// "size" is the width and height of yuv picture for registerBuffer.
1008// If it is NULL, use the picture size from parameters.
1009void CameraService::Client::handleShutter(image_rect_type *size) {
1010 mCameraService->playSound(SOUND_SHUTTER);
1011
1012 // Screen goes black after the buffer is unregistered.
1013 if (mSurface != 0 && !mUseOverlay) {
1014 mSurface->unregisterBuffers();
1015 }
1016
1017 sp<ICameraClient> c = mCameraClient;
1018 if (c != 0) {
1019 mLock.unlock();
1020 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
1021 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
1022 }
1023 disableMsgType(CAMERA_MSG_SHUTTER);
1024
1025 // It takes some time before yuvPicture callback to be called.
1026 // Register the buffer for raw image here to reduce latency.
1027 if (mSurface != 0 && !mUseOverlay) {
1028 int w, h;
1029 CameraParameters params(mHardware->getParameters());
1030 if (size == NULL) {
1031 params.getPictureSize(&w, &h);
1032 } else {
1033 w = size->width;
1034 h = size->height;
1035 w &= ~1;
1036 h &= ~1;
1037 LOG1("Snapshot image width=%d, height=%d", w, h);
1038 }
1039 // FIXME: don't use hardcoded format constants here
1040 ISurface::BufferHeap buffers(w, h, w, h,
1041 HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
1042 mHardware->getRawHeap());
1043
1044 mSurface->registerBuffers(buffers);
1045 }
1046
1047 mLock.unlock();
1048}
1049
1050// preview callback - frame buffer update
1051void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
1052 ssize_t offset;
1053 size_t size;
1054 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1055
1056 if (!mUseOverlay) {
1057 if (mSurface != 0) {
1058 mSurface->postBuffer(offset);
1059 }
1060 }
1061
1062 // local copy of the callback flags
1063 int flags = mPreviewCallbackFlag;
1064
1065 // is callback enabled?
1066 if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
1067 // If the enable bit is off, the copy-out and one-shot bits are ignored
1068 LOG2("frame callback is disabled");
1069 mLock.unlock();
1070 return;
1071 }
1072
1073 // hold a strong pointer to the client
1074 sp<ICameraClient> c = mCameraClient;
1075
1076 // clear callback flags if no client or one-shot mode
1077 if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
1078 LOG2("Disable preview callback");
1079 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1080 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1081 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1082 if (mUseOverlay) {
1083 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
1084 }
1085 }
1086
1087 if (c != 0) {
1088 // Is the received frame copied out or not?
1089 if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1090 LOG2("frame is copied");
1091 copyFrameAndPostCopiedFrame(c, heap, offset, size);
1092 } else {
1093 LOG2("frame is forwarded");
1094 mLock.unlock();
1095 c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
1096 }
1097 } else {
1098 mLock.unlock();
1099 }
1100}
1101
1102// picture callback - postview image ready
1103void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
1104 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1105
1106 sp<ICameraClient> c = mCameraClient;
1107 mLock.unlock();
1108 if (c != 0) {
1109 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1110 }
1111}
1112
1113// picture callback - raw image ready
1114void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
1115 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1116
1117 ssize_t offset;
1118 size_t size;
1119 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1120
1121 // Put the YUV version of the snapshot in the preview display.
1122 if (mSurface != 0 && !mUseOverlay) {
1123 mSurface->postBuffer(offset);
1124 }
1125
1126 sp<ICameraClient> c = mCameraClient;
1127 mLock.unlock();
1128 if (c != 0) {
1129 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1130 }
1131}
1132
1133// picture callback - compressed picture ready
1134void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
1135 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1136
1137 sp<ICameraClient> c = mCameraClient;
1138 mLock.unlock();
1139 if (c != 0) {
1140 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1141 }
1142}
1143
1144
1145void CameraService::Client::handleGenericNotify(int32_t msgType,
1146 int32_t ext1, int32_t ext2) {
1147 sp<ICameraClient> c = mCameraClient;
1148 mLock.unlock();
1149 if (c != 0) {
1150 c->notifyCallback(msgType, ext1, ext2);
1151 }
1152}
1153
1154void CameraService::Client::handleGenericData(int32_t msgType,
1155 const sp<IMemory>& dataPtr) {
1156 sp<ICameraClient> c = mCameraClient;
1157 mLock.unlock();
1158 if (c != 0) {
1159 c->dataCallback(msgType, dataPtr);
1160 }
1161}
1162
1163void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
1164 int32_t msgType, const sp<IMemory>& dataPtr) {
1165 sp<ICameraClient> c = mCameraClient;
1166 mLock.unlock();
1167 if (c != 0) {
1168 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1169 }
1170}
1171
1172void CameraService::Client::copyFrameAndPostCopiedFrame(
1173 const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
1174 size_t offset, size_t size) {
1175 LOG2("copyFrameAndPostCopiedFrame");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001176 // It is necessary to copy out of pmem before sending this to
1177 // the callback. For efficiency, reuse the same MemoryHeapBase
1178 // provided it's big enough. Don't allocate the memory or
1179 // perform the copy if there's no callback.
Dave Sparksff0f38e2009-11-10 17:08:08 -08001180 // hold the preview lock while we grab a reference to the preview buffer
Dave Sparks23c21ba2009-11-06 11:47:13 -08001181 sp<MemoryHeapBase> previewBuffer;
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001182
1183 if (mPreviewBuffer == 0) {
1184 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1185 } else if (size > mPreviewBuffer->virtualSize()) {
1186 mPreviewBuffer.clear();
1187 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001188 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001189 if (mPreviewBuffer == 0) {
1190 LOGE("failed to allocate space for preview buffer");
1191 mLock.unlock();
1192 return;
1193 }
1194 previewBuffer = mPreviewBuffer;
1195
1196 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001197
Dave Sparks23c21ba2009-11-06 11:47:13 -08001198 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001199 if (frame == 0) {
1200 LOGE("failed to allocate space for frame callback");
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001201 mLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001202 return;
1203 }
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001204
1205 mLock.unlock();
Dave Sparks393eb792009-10-15 10:02:22 -07001206 client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001207}
1208
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001209// ----------------------------------------------------------------------------
1210
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001211static const int kDumpLockRetries = 50;
1212static const int kDumpLockSleep = 60000;
1213
1214static bool tryLock(Mutex& mutex)
1215{
1216 bool locked = false;
1217 for (int i = 0; i < kDumpLockRetries; ++i) {
1218 if (mutex.tryLock() == NO_ERROR) {
1219 locked = true;
1220 break;
1221 }
1222 usleep(kDumpLockSleep);
1223 }
1224 return locked;
1225}
1226
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001227status_t CameraService::dump(int fd, const Vector<String16>& args) {
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001228 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1229
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001230 const size_t SIZE = 256;
1231 char buffer[SIZE];
1232 String8 result;
1233 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1234 snprintf(buffer, SIZE, "Permission Denial: "
1235 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Changd98c5162009-06-22 16:03:41 +08001236 getCallingPid(),
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001237 getCallingUid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001238 result.append(buffer);
1239 write(fd, result.string(), result.size());
1240 } else {
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001241 bool locked = tryLock(mServiceLock);
1242 // failed to lock - CameraService is probably deadlocked
1243 if (!locked) {
1244 String8 result(kDeadlockedString);
1245 write(fd, result.string(), result.size());
1246 }
1247
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001248 bool hasClient = false;
1249 for (int i = 0; i < NUM_CAMERAS; i++) {
1250 sp<Client> client = mClient[i].promote();
1251 if (client == 0) continue;
1252 hasClient = true;
1253 sprintf(buffer, "Client[%d] (%p) PID: %d\n",
1254 i,
1255 client->getCameraClient()->asBinder().get(),
1256 client->mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001257 result.append(buffer);
1258 write(fd, result.string(), result.size());
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001259 client->mHardware->dump(fd, args);
1260 }
1261 if (!hasClient) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001262 result.append("No camera client yet.\n");
1263 write(fd, result.string(), result.size());
1264 }
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001265
1266 if (locked) mServiceLock.unlock();
Chih-Chung Chang5997faf2010-05-06 16:36:58 +08001267
1268 // change logging level
1269 int n = args.size();
1270 for (int i = 0; i + 1 < n; i++) {
1271 if (args[i] == String16("-v")) {
1272 String8 levelStr(args[i+1]);
1273 int level = atoi(levelStr.string());
1274 sprintf(buffer, "Set Log Level to %d", level);
1275 result.append(buffer);
1276 setLogLevel(level);
1277 }
1278 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001279 }
1280 return NO_ERROR;
1281}
1282
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001283}; // namespace android