blob: 58209fd17c9eb313378418937483026df6273867 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018#define LOG_TAG "CameraService"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019
Chih-Chung Change25cc652010-05-06 16:36:58 +080020#include <stdio.h>
21#include <sys/types.h>
22#include <pthread.h>
23
Mathias Agopian07952722009-05-19 19:08:10 -070024#include <binder/IPCThreadState.h>
Chih-Chung Change25cc652010-05-06 16:36:58 +080025#include <binder/IServiceManager.h>
Mathias Agopian07952722009-05-19 19:08:10 -070026#include <binder/MemoryBase.h>
27#include <binder/MemoryHeapBase.h>
Chih-Chung Change25cc652010-05-06 16:36:58 +080028#include <cutils/atomic.h>
29#include <hardware/hardware.h>
30#include <media/AudioSystem.h>
31#include <media/mediaplayer.h>
Mathias Agopian000479f2010-02-09 17:46:37 -080032#include <surfaceflinger/ISurface.h>
33#include <ui/Overlay.h>
Chih-Chung Change25cc652010-05-06 16:36:58 +080034#include <utils/Errors.h>
35#include <utils/Log.h>
36#include <utils/String16.h>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
38#include "CameraService.h"
Eric Laurenta7f1e5c2009-03-27 16:27:16 -070039
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040namespace android {
41
Chih-Chung Change25cc652010-05-06 16:36:58 +080042// ----------------------------------------------------------------------------
43// Logging support -- this is for debugging only
44// Use "adb shell dumpsys media.camera -v 1" to change it.
45static volatile int32_t gLogLevel = 0;
46
47#define LOG1(...) LOGD_IF(gLogLevel >= 1, __VA_ARGS__);
48#define LOG2(...) LOGD_IF(gLogLevel >= 2, __VA_ARGS__);
49
50static void setLogLevel(int level) {
51 android_atomic_write(level, &gLogLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052}
53
Chih-Chung Change25cc652010-05-06 16:36:58 +080054// ----------------------------------------------------------------------------
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +080056static int getCallingPid() {
57 return IPCThreadState::self()->getCallingPid();
58}
59
Chih-Chung Change25cc652010-05-06 16:36:58 +080060static int getCallingUid() {
61 return IPCThreadState::self()->getCallingUid();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062}
63
64// ----------------------------------------------------------------------------
65
Chih-Chung Change25cc652010-05-06 16:36:58 +080066// This is ugly and only safe if we never re-create the CameraService, but
67// should be ok for now.
68static CameraService *gCameraService;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069
Chih-Chung Change25cc652010-05-06 16:36:58 +080070CameraService::CameraService()
71:mSoundRef(0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072{
Chih-Chung Change25cc652010-05-06 16:36:58 +080073 LOGI("CameraService started (pid=%d)", getpid());
74
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +080075 mNumberOfCameras = HAL_getNumberOfCameras();
76 if (mNumberOfCameras > MAX_CAMERAS) {
77 LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
78 mNumberOfCameras, MAX_CAMERAS);
79 mNumberOfCameras = MAX_CAMERAS;
80 }
81
82 for (int i = 0; i < mNumberOfCameras; i++) {
Chih-Chung Change25cc652010-05-06 16:36:58 +080083 setCameraFree(i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080084 }
Chih-Chung Change25cc652010-05-06 16:36:58 +080085
86 gCameraService = this;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087}
88
Chih-Chung Change25cc652010-05-06 16:36:58 +080089CameraService::~CameraService() {
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +080090 for (int i = 0; i < mNumberOfCameras; i++) {
Chih-Chung Change25cc652010-05-06 16:36:58 +080091 if (mBusy[i]) {
92 LOGE("camera %d is still in use in destructor!", i);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 }
94 }
95
Chih-Chung Change25cc652010-05-06 16:36:58 +080096 gCameraService = NULL;
97}
98
99int32_t CameraService::getNumberOfCameras() {
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800100 return mNumberOfCameras;
101}
102
103status_t CameraService::getCameraInfo(int cameraId,
104 struct CameraInfo* cameraInfo) {
105 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
106 return BAD_VALUE;
107 }
108
109 HAL_getCameraInfo(cameraId, cameraInfo);
110 return OK;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800111}
112
113sp<ICamera> CameraService::connect(
114 const sp<ICameraClient>& cameraClient, int cameraId) {
115 int callingPid = getCallingPid();
116 LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
117
118 sp<Client> client;
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800119 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800120 LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
121 callingPid, cameraId);
122 return NULL;
Chih-Chung Changd5d1ebd2009-06-24 19:59:31 +0800123 }
124
Chih-Chung Change25cc652010-05-06 16:36:58 +0800125 Mutex::Autolock lock(mServiceLock);
126 if (mClient[cameraId] != 0) {
127 client = mClient[cameraId].promote();
128 if (client != 0) {
129 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
130 LOG1("CameraService::connect X (pid %d) (the same client)",
131 callingPid);
132 return client;
133 } else {
134 LOGW("CameraService::connect X (pid %d) rejected (existing client).",
135 callingPid);
136 return NULL;
137 }
138 }
139 mClient[cameraId].clear();
140 }
141
142 if (mBusy[cameraId]) {
143 LOGW("CameraService::connect X (pid %d) rejected"
144 " (camera %d is still busy).", callingPid, cameraId);
145 return NULL;
146 }
147
Wu-cheng Lie7044382010-08-17 15:45:37 -0700148 sp<CameraHardwareInterface> hardware = HAL_openCameraHardware(cameraId);
149 if (hardware == NULL) {
150 LOGE("Fail to open camera hardware (id=%d)", cameraId);
151 return NULL;
152 }
153 client = new Client(this, cameraClient, hardware, cameraId, callingPid);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800154 mClient[cameraId] = client;
155 LOG1("CameraService::connect X");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800156 return client;
157}
158
Chih-Chung Change25cc652010-05-06 16:36:58 +0800159void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800160 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800161 LOG1("CameraService::removeClient E (pid %d)", callingPid);
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800162
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800163 for (int i = 0; i < mNumberOfCameras; i++) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800164 // Declare this before the lock to make absolutely sure the
165 // destructor won't be called with the lock held.
166 sp<Client> client;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800167
Chih-Chung Change25cc652010-05-06 16:36:58 +0800168 Mutex::Autolock lock(mServiceLock);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169
Chih-Chung Change25cc652010-05-06 16:36:58 +0800170 // This happens when we have already disconnected (or this is
171 // just another unused camera).
172 if (mClient[i] == 0) continue;
173
174 // Promote mClient. It can fail if we are called from this path:
175 // Client::~Client() -> disconnect() -> removeClient().
176 client = mClient[i].promote();
177
178 if (client == 0) {
179 mClient[i].clear();
180 continue;
181 }
182
183 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
184 // Found our camera, clear and leave.
185 LOG1("removeClient: clear camera %d", i);
186 mClient[i].clear();
187 break;
188 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 }
190
Chih-Chung Change25cc652010-05-06 16:36:58 +0800191 LOG1("CameraService::removeClient X (pid %d)", callingPid);
192}
193
194sp<CameraService::Client> CameraService::getClientById(int cameraId) {
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +0800195 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800196 return mClient[cameraId].promote();
197}
198
Chih-Chung Change25cc652010-05-06 16:36:58 +0800199status_t CameraService::onTransact(
200 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
201 // Permission checks
202 switch (code) {
203 case BnCameraService::CONNECT:
204 const int pid = getCallingPid();
205 const int self_pid = getpid();
206 if (pid != self_pid) {
207 // we're called from a different process, do the real check
208 if (!checkCallingPermission(
209 String16("android.permission.CAMERA"))) {
210 const int uid = getCallingUid();
211 LOGE("Permission Denial: "
212 "can't use the camera pid=%d, uid=%d", pid, uid);
213 return PERMISSION_DENIED;
214 }
215 }
216 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 }
218
Chih-Chung Change25cc652010-05-06 16:36:58 +0800219 return BnCameraService::onTransact(code, data, reply, flags);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220}
221
Chih-Chung Change25cc652010-05-06 16:36:58 +0800222// The reason we need this busy bit is a new CameraService::connect() request
223// may come in while the previous Client's destructor has not been run or is
224// still running. If the last strong reference of the previous Client is gone
225// but the destructor has not been finished, we should not allow the new Client
226// to be created because we need to wait for the previous Client to tear down
227// the hardware first.
228void CameraService::setCameraBusy(int cameraId) {
229 android_atomic_write(1, &mBusy[cameraId]);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800230}
231
Chih-Chung Change25cc652010-05-06 16:36:58 +0800232void CameraService::setCameraFree(int cameraId) {
233 android_atomic_write(0, &mBusy[cameraId]);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800234}
235
Chih-Chung Change25cc652010-05-06 16:36:58 +0800236// We share the media players for shutter and recording sound for all clients.
237// A reference count is kept to determine when we will actually release the
238// media players.
239
240static MediaPlayer* newMediaPlayer(const char *file) {
241 MediaPlayer* mp = new MediaPlayer();
242 if (mp->setDataSource(file, NULL) == NO_ERROR) {
Eric Laurenta553c252009-07-17 12:17:14 -0700243 mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
Jason Samsb18b6912009-03-24 20:21:36 -0700244 mp->prepare();
245 } else {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800246 LOGE("Failed to load CameraService sounds: %s", file);
247 return NULL;
Jason Samsb18b6912009-03-24 20:21:36 -0700248 }
249 return mp;
250}
251
Chih-Chung Change25cc652010-05-06 16:36:58 +0800252void CameraService::loadSound() {
253 Mutex::Autolock lock(mSoundLock);
254 LOG1("CameraService::loadSound ref=%d", mSoundRef);
255 if (mSoundRef++) return;
256
257 mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
258 mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
259}
260
261void CameraService::releaseSound() {
262 Mutex::Autolock lock(mSoundLock);
263 LOG1("CameraService::releaseSound ref=%d", mSoundRef);
264 if (--mSoundRef) return;
265
266 for (int i = 0; i < NUM_SOUNDS; i++) {
267 if (mSoundPlayer[i] != 0) {
268 mSoundPlayer[i]->disconnect();
269 mSoundPlayer[i].clear();
270 }
271 }
272}
273
274void CameraService::playSound(sound_kind kind) {
275 LOG1("playSound(%d)", kind);
276 Mutex::Autolock lock(mSoundLock);
277 sp<MediaPlayer> player = mSoundPlayer[kind];
278 if (player != 0) {
279 // do not play the sound if stream volume is 0
280 // (typically because ringer mode is silent).
281 int index;
282 AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
283 if (index != 0) {
284 player->seekTo(0);
285 player->start();
286 }
287 }
288}
289
290// ----------------------------------------------------------------------------
291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292CameraService::Client::Client(const sp<CameraService>& cameraService,
Wu-cheng Lie7044382010-08-17 15:45:37 -0700293 const sp<ICameraClient>& cameraClient,
294 const sp<CameraHardwareInterface>& hardware,
295 int cameraId, int clientPid) {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800296 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800297 LOG1("Client::Client E (pid %d)", callingPid);
298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 mCameraService = cameraService;
300 mCameraClient = cameraClient;
Wu-cheng Lie7044382010-08-17 15:45:37 -0700301 mHardware = hardware;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800302 mCameraId = cameraId;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800303 mClientPid = clientPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800304 mUseOverlay = mHardware->useOverlay();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800305 mMsgEnabled = 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306
Benny Wongda83f462009-08-12 12:01:27 -0500307 mHardware->setCallbacks(notifyCallback,
308 dataCallback,
309 dataCallbackTimestamp,
Chih-Chung Change25cc652010-05-06 16:36:58 +0800310 (void *)cameraId);
Benny Wongda83f462009-08-12 12:01:27 -0500311
312 // Enable zoom, error, and focus messages by default
Chih-Chung Change25cc652010-05-06 16:36:58 +0800313 enableMsgType(CAMERA_MSG_ERROR |
314 CAMERA_MSG_ZOOM |
315 CAMERA_MSG_FOCUS);
Benny Wong6d2090e2009-07-15 18:44:27 -0500316 mOverlayW = 0;
317 mOverlayH = 0;
Jason Samsb18b6912009-03-24 20:21:36 -0700318
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800319 // Callback is disabled by default
320 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Chih-Chung Change1ceec22010-01-21 17:31:06 -0800321 mOrientation = 0;
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700322 mOrientationChanged = false;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800323 cameraService->setCameraBusy(cameraId);
324 cameraService->loadSound();
325 LOG1("Client::Client X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326}
327
Chih-Chung Change25cc652010-05-06 16:36:58 +0800328static void *unregister_surface(void *arg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 ISurface *surface = (ISurface *)arg;
330 surface->unregisterBuffers();
331 IPCThreadState::self()->flushCommands();
332 return NULL;
333}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334
Chih-Chung Change25cc652010-05-06 16:36:58 +0800335// tear down the client
336CameraService::Client::~Client() {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800337 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800338 LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800339
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800340 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 pthread_t thr;
342 // We unregister the buffers in a different thread because binder does
343 // not let us make sychronous transactions in a binder destructor (that
344 // is, upon our reaching a refcount of zero.)
Chih-Chung Change25cc652010-05-06 16:36:58 +0800345 pthread_create(&thr,
346 NULL, // attr
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 unregister_surface,
348 mSurface.get());
349 pthread_join(thr, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
351
Chih-Chung Change25cc652010-05-06 16:36:58 +0800352 // set mClientPid to let disconnet() tear down the hardware
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800353 mClientPid = callingPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 disconnect();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800355 mCameraService->releaseSound();
356 LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357}
358
Chih-Chung Change25cc652010-05-06 16:36:58 +0800359// ----------------------------------------------------------------------------
360
361status_t CameraService::Client::checkPid() const {
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800362 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800363 if (callingPid == mClientPid) return NO_ERROR;
James Dong71d714c2010-06-09 15:57:48 -0700364
Chih-Chung Change25cc652010-05-06 16:36:58 +0800365 LOGW("attempt to use a locked camera from a different process"
366 " (old pid %d, new pid %d)", mClientPid, callingPid);
367 return EBUSY;
368}
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800369
Chih-Chung Change25cc652010-05-06 16:36:58 +0800370status_t CameraService::Client::checkPidAndHardware() const {
371 status_t result = checkPid();
372 if (result != NO_ERROR) return result;
373 if (mHardware == 0) {
374 LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
375 return INVALID_OPERATION;
376 }
377 return NO_ERROR;
378}
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800379
Chih-Chung Change25cc652010-05-06 16:36:58 +0800380status_t CameraService::Client::lock() {
381 int callingPid = getCallingPid();
382 LOG1("lock (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800384
385 // lock camera to this client if the the camera is unlocked
386 if (mClientPid == 0) {
387 mClientPid = callingPid;
388 return NO_ERROR;
389 }
390
391 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
392 return checkPid();
393}
394
395status_t CameraService::Client::unlock() {
396 int callingPid = getCallingPid();
397 LOG1("unlock (pid %d)", callingPid);
398 Mutex::Autolock lock(mLock);
399
400 // allow anyone to use camera (after they lock the camera)
401 status_t result = checkPid();
402 if (result == NO_ERROR) {
403 mClientPid = 0;
404 LOG1("clear mCameraClient (pid %d)", callingPid);
405 // we need to remove the reference to ICameraClient so that when the app
406 // goes away, the reference count goes to 0.
407 mCameraClient.clear();
408 }
409 return result;
410}
411
412// connect a new client to the camera
413status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
414 int callingPid = getCallingPid();
415 LOG1("connect E (pid %d)", callingPid);
416 Mutex::Autolock lock(mLock);
417
418 if (mClientPid != 0 && checkPid() != NO_ERROR) {
419 LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
420 mClientPid, callingPid);
421 return EBUSY;
422 }
423
424 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
425 LOG1("Connect to the same client");
426 return NO_ERROR;
427 }
428
429 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
430 mClientPid = callingPid;
431 mCameraClient = client;
432
433 LOG1("connect X (pid %d)", callingPid);
434 return NO_ERROR;
435}
436
437void CameraService::Client::disconnect() {
438 int callingPid = getCallingPid();
439 LOG1("disconnect E (pid %d)", callingPid);
440 Mutex::Autolock lock(mLock);
441
442 if (checkPid() != NO_ERROR) {
443 LOGW("different client - don't disconnect");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800444 return;
445 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800446
447 if (mClientPid <= 0) {
448 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800449 return;
450 }
451
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800452 // Make sure disconnect() is done once and once only, whether it is called
453 // from the user directly, or called by the destructor.
454 if (mHardware == 0) return;
455
Chih-Chung Change25cc652010-05-06 16:36:58 +0800456 LOG1("hardware teardown");
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800457 // Before destroying mHardware, we must make sure it's in the
458 // idle state.
Chih-Chung Change25cc652010-05-06 16:36:58 +0800459 // Turn off all messages.
460 disableMsgType(CAMERA_MSG_ALL_MSGS);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800461 mHardware->stopPreview();
Benny Wongda83f462009-08-12 12:01:27 -0500462 mHardware->cancelPicture();
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800463 // Release the hardware resources.
464 mHardware->release();
Benny Wong6d2090e2009-07-15 18:44:27 -0500465 // Release the held overlay resources.
Chih-Chung Change25cc652010-05-06 16:36:58 +0800466 if (mUseOverlay) {
Benny Wong6d2090e2009-07-15 18:44:27 -0500467 mOverlayRef = 0;
468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 mHardware.clear();
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800470
Chih-Chung Changd5d1ebd2009-06-24 19:59:31 +0800471 mCameraService->removeClient(mCameraClient);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800472 mCameraService->setCameraFree(mCameraId);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800473
Chih-Chung Change25cc652010-05-06 16:36:58 +0800474 LOG1("disconnect X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475}
476
Chih-Chung Change25cc652010-05-06 16:36:58 +0800477// ----------------------------------------------------------------------------
478
479// set the ISurface that the preview will use
480status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) {
481 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800483 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 if (result != NO_ERROR) return result;
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800485
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800486 result = NO_ERROR;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800487
488 // return if no change in surface.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800489 // asBinder() is safe on NULL (returns NULL)
Chih-Chung Change25cc652010-05-06 16:36:58 +0800490 if (surface->asBinder() == mSurface->asBinder()) {
491 return result;
492 }
493
494 if (mSurface != 0) {
495 LOG1("clearing old preview surface %p", mSurface.get());
496 if (mUseOverlay) {
497 // Force the destruction of any previous overlay
498 sp<Overlay> dummy;
499 mHardware->setOverlay(dummy);
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700500 mOverlayRef = 0;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800501 } else {
502 mSurface->unregisterBuffers();
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800503 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800505 mSurface = surface;
506 mOverlayRef = 0;
507 // If preview has been already started, set overlay or register preview
508 // buffers now.
509 if (mHardware->previewEnabled()) {
510 if (mUseOverlay) {
511 result = setOverlay();
512 } else if (mSurface != 0) {
513 result = registerPreviewBuffers();
514 }
515 }
516
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800517 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518}
519
Chih-Chung Change25cc652010-05-06 16:36:58 +0800520status_t CameraService::Client::registerPreviewBuffers() {
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800521 int w, h;
522 CameraParameters params(mHardware->getParameters());
523 params.getPreviewSize(&w, &h);
524
Chih-Chung Change25cc652010-05-06 16:36:58 +0800525 // FIXME: don't use a hardcoded format here.
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800526 ISurface::BufferHeap buffers(w, h, w, h,
Mathias Agopian5a487122010-02-16 19:42:32 -0800527 HAL_PIXEL_FORMAT_YCrCb_420_SP,
Chih-Chung Change1ceec22010-01-21 17:31:06 -0800528 mOrientation,
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800529 0,
530 mHardware->getPreviewHeap());
531
Chih-Chung Change25cc652010-05-06 16:36:58 +0800532 status_t result = mSurface->registerBuffers(buffers);
533 if (result != NO_ERROR) {
534 LOGE("registerBuffers failed with status %d", result);
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800535 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800536 return result;
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800537}
538
Chih-Chung Change25cc652010-05-06 16:36:58 +0800539status_t CameraService::Client::setOverlay() {
540 int w, h;
541 CameraParameters params(mHardware->getParameters());
542 params.getPreviewSize(&w, &h);
543
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700544 if (w != mOverlayW || h != mOverlayH || mOrientationChanged) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800545 // Force the destruction of any previous overlay
546 sp<Overlay> dummy;
547 mHardware->setOverlay(dummy);
548 mOverlayRef = 0;
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700549 mOrientationChanged = false;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800550 }
551
552 status_t result = NO_ERROR;
553 if (mSurface == 0) {
554 result = mHardware->setOverlay(NULL);
555 } else {
556 if (mOverlayRef == 0) {
557 // FIXME:
558 // Surfaceflinger may hold onto the previous overlay reference for some
559 // time after we try to destroy it. retry a few times. In the future, we
560 // should make the destroy call block, or possibly specify that we can
561 // wait in the createOverlay call if the previous overlay is in the
562 // process of being destroyed.
563 for (int retry = 0; retry < 50; ++retry) {
564 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
565 mOrientation);
566 if (mOverlayRef != 0) break;
567 LOGW("Overlay create failed - retrying");
568 usleep(20000);
569 }
570 if (mOverlayRef == 0) {
571 LOGE("Overlay Creation Failed!");
572 return -EINVAL;
573 }
574 result = mHardware->setOverlay(new Overlay(mOverlayRef));
575 }
576 }
577 if (result != NO_ERROR) {
578 LOGE("mHardware->setOverlay() failed with status %d\n", result);
579 return result;
580 }
581
582 mOverlayW = w;
583 mOverlayH = h;
584
585 return result;
586}
587
588// set the preview callback flag to affect how the received frames from
589// preview are handled.
590void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
591 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
592 Mutex::Autolock lock(mLock);
593 if (checkPidAndHardware() != NO_ERROR) return;
594
595 mPreviewCallbackFlag = callback_flag;
596
597 // If we don't use overlay, we always need the preview frame for display.
598 // If we do use overlay, we only need the preview frame if the user
599 // wants the data.
600 if (mUseOverlay) {
601 if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
602 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
603 } else {
604 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
605 }
606 }
607}
608
609// start preview mode
610status_t CameraService::Client::startPreview() {
611 LOG1("startPreview (pid %d)", getCallingPid());
612 return startCameraMode(CAMERA_PREVIEW_MODE);
613}
614
615// start recording mode
616status_t CameraService::Client::startRecording() {
617 LOG1("startRecording (pid %d)", getCallingPid());
618 return startCameraMode(CAMERA_RECORDING_MODE);
619}
620
621// start preview or recording
622status_t CameraService::Client::startCameraMode(camera_mode mode) {
623 LOG1("startCameraMode(%d)", mode);
624 Mutex::Autolock lock(mLock);
625 status_t result = checkPidAndHardware();
626 if (result != NO_ERROR) return result;
627
628 switch(mode) {
629 case CAMERA_PREVIEW_MODE:
630 if (mSurface == 0) {
631 LOG1("mSurface is not set yet.");
632 // still able to start preview in this case.
633 }
634 return startPreviewMode();
635 case CAMERA_RECORDING_MODE:
636 if (mSurface == 0) {
637 LOGE("mSurface must be set before startRecordingMode.");
638 return INVALID_OPERATION;
639 }
640 return startRecordingMode();
641 default:
642 return UNKNOWN_ERROR;
643 }
644}
645
646status_t CameraService::Client::startPreviewMode() {
647 LOG1("startPreviewMode");
648 status_t result = NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649
650 // if preview has been enabled, nothing needs to be done
651 if (mHardware->previewEnabled()) {
652 return NO_ERROR;
653 }
654
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655 if (mUseOverlay) {
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800656 // If preview display has been set, set overlay now.
657 if (mSurface != 0) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800658 result = setOverlay();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800660 if (result != NO_ERROR) return result;
661 result = mHardware->startPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 } else {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800663 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
664 result = mHardware->startPreview();
665 if (result != NO_ERROR) return result;
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800666 // If preview display has been set, register preview buffers now.
667 if (mSurface != 0) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800668 // Unregister here because the surface may be previously registered
669 // with the raw (snapshot) heap.
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800670 mSurface->unregisterBuffers();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800671 result = registerPreviewBuffers();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800672 }
673 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800674 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800675}
676
Chih-Chung Change25cc652010-05-06 16:36:58 +0800677status_t CameraService::Client::startRecordingMode() {
678 LOG1("startRecordingMode");
679 status_t result = NO_ERROR;
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700680
Chih-Chung Change25cc652010-05-06 16:36:58 +0800681 // if recording has been enabled, nothing needs to be done
682 if (mHardware->recordingEnabled()) {
683 return NO_ERROR;
684 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800685
Chih-Chung Change25cc652010-05-06 16:36:58 +0800686 // if preview has not been started, start preview first
687 if (!mHardware->previewEnabled()) {
688 result = startPreviewMode();
689 if (result != NO_ERROR) {
690 return result;
Eric Laurent524dc042009-11-27 05:07:55 -0800691 }
Jason Samsb18b6912009-03-24 20:21:36 -0700692 }
Benny Wongda83f462009-08-12 12:01:27 -0500693
Chih-Chung Change25cc652010-05-06 16:36:58 +0800694 // start recording mode
695 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
696 mCameraService->playSound(SOUND_RECORDING);
697 result = mHardware->startRecording();
698 if (result != NO_ERROR) {
699 LOGE("mHardware->startRecording() failed with status %d", result);
700 }
701 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702}
703
704// stop preview mode
Chih-Chung Change25cc652010-05-06 16:36:58 +0800705void CameraService::Client::stopPreview() {
706 LOG1("stopPreview (pid %d)", getCallingPid());
707 Mutex::Autolock lock(mLock);
708 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800709
Chih-Chung Change25cc652010-05-06 16:36:58 +0800710 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
711 mHardware->stopPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712
Chih-Chung Change25cc652010-05-06 16:36:58 +0800713 if (mSurface != 0 && !mUseOverlay) {
714 mSurface->unregisterBuffers();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 }
716
Chih-Chung Change25cc652010-05-06 16:36:58 +0800717 mPreviewBuffer.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718}
719
720// stop recording mode
Chih-Chung Change25cc652010-05-06 16:36:58 +0800721void CameraService::Client::stopRecording() {
722 LOG1("stopRecording (pid %d)", getCallingPid());
723 Mutex::Autolock lock(mLock);
724 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800725
Chih-Chung Change25cc652010-05-06 16:36:58 +0800726 mCameraService->playSound(SOUND_RECORDING);
727 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
728 mHardware->stopRecording();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729
Chih-Chung Change25cc652010-05-06 16:36:58 +0800730 mPreviewBuffer.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800731}
732
733// release a recording frame
Chih-Chung Change25cc652010-05-06 16:36:58 +0800734void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800736 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800737 mHardware->releaseRecordingFrame(mem);
738}
739
Chih-Chung Change25cc652010-05-06 16:36:58 +0800740bool CameraService::Client::previewEnabled() {
741 LOG1("previewEnabled (pid %d)", getCallingPid());
742
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800743 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800744 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 return mHardware->previewEnabled();
746}
747
Chih-Chung Change25cc652010-05-06 16:36:58 +0800748bool CameraService::Client::recordingEnabled() {
749 LOG1("recordingEnabled (pid %d)", getCallingPid());
750
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800752 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800753 return mHardware->recordingEnabled();
754}
755
Chih-Chung Change25cc652010-05-06 16:36:58 +0800756status_t CameraService::Client::autoFocus() {
757 LOG1("autoFocus (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800758
759 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800760 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800761 if (result != NO_ERROR) return result;
762
Benny Wongda83f462009-08-12 12:01:27 -0500763 return mHardware->autoFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800764}
765
Chih-Chung Change25cc652010-05-06 16:36:58 +0800766status_t CameraService::Client::cancelAutoFocus() {
767 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800768
769 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800770 status_t result = checkPidAndHardware();
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800771 if (result != NO_ERROR) return result;
772
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800773 return mHardware->cancelAutoFocus();
774}
775
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800776// take a picture - image is returned in callback
Chih-Chung Change25cc652010-05-06 16:36:58 +0800777status_t CameraService::Client::takePicture() {
778 LOG1("takePicture (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800779
780 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800781 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 if (result != NO_ERROR) return result;
783
Chih-Chung Change25cc652010-05-06 16:36:58 +0800784 enableMsgType(CAMERA_MSG_SHUTTER |
785 CAMERA_MSG_POSTVIEW_FRAME |
786 CAMERA_MSG_RAW_IMAGE |
787 CAMERA_MSG_COMPRESSED_IMAGE);
Benny Wongda83f462009-08-12 12:01:27 -0500788
789 return mHardware->takePicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800790}
791
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800792// set preview/capture parameters - key/value pairs
Chih-Chung Change25cc652010-05-06 16:36:58 +0800793status_t CameraService::Client::setParameters(const String8& params) {
794 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800795
796 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800797 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800798 if (result != NO_ERROR) return result;
799
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800800 CameraParameters p(params);
James Dong6085b4e2009-09-13 17:10:24 -0700801 return mHardware->setParameters(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800802}
803
804// get preview/capture parameters - key/value pairs
Chih-Chung Change25cc652010-05-06 16:36:58 +0800805String8 CameraService::Client::getParameters() const {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800807 if (checkPidAndHardware() != NO_ERROR) return String8();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808
Wu-cheng Liab5b4242009-04-22 16:21:26 +0800809 String8 params(mHardware->getParameters().flatten());
Chih-Chung Change25cc652010-05-06 16:36:58 +0800810 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
Wu-cheng Liab5b4242009-04-22 16:21:26 +0800811 return params;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812}
813
Chih-Chung Change25cc652010-05-06 16:36:58 +0800814status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
815 LOG1("sendCommand (pid %d)", getCallingPid());
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700816 int orientation;
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700817 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800818 status_t result = checkPidAndHardware();
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700819 if (result != NO_ERROR) return result;
820
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800821 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
822 // The orientation cannot be set during preview.
823 if (mHardware->previewEnabled()) {
824 return INVALID_OPERATION;
825 }
826 switch (arg1) {
827 case 0:
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700828 orientation = ISurface::BufferHeap::ROT_0;
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800829 break;
830 case 90:
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700831 orientation = ISurface::BufferHeap::ROT_90;
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800832 break;
833 case 180:
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700834 orientation = ISurface::BufferHeap::ROT_180;
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800835 break;
836 case 270:
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700837 orientation = ISurface::BufferHeap::ROT_270;
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800838 break;
839 default:
840 return BAD_VALUE;
841 }
Wu-cheng Lib3347bc2010-09-23 17:17:43 -0700842 if (mOrientation != orientation) {
843 mOrientation = orientation;
844 if (mOverlayRef != 0) mOrientationChanged = true;
845 }
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800846 return OK;
847 }
848
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700849 return mHardware->sendCommand(cmd, arg1, arg2);
850}
851
Chih-Chung Change25cc652010-05-06 16:36:58 +0800852// ----------------------------------------------------------------------------
853
854void CameraService::Client::enableMsgType(int32_t msgType) {
855 android_atomic_or(msgType, &mMsgEnabled);
856 mHardware->enableMsgType(msgType);
857}
858
859void CameraService::Client::disableMsgType(int32_t msgType) {
860 android_atomic_and(~msgType, &mMsgEnabled);
861 mHardware->disableMsgType(msgType);
862}
863
864#define CHECK_MESSAGE_INTERVAL 10 // 10ms
865bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
866 int sleepCount = 0;
867 while (mMsgEnabled & msgType) {
868 if (mLock.tryLock() == NO_ERROR) {
869 if (sleepCount > 0) {
870 LOG1("lockIfMessageWanted(%d): waited for %d ms",
871 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
872 }
873 return true;
874 }
875 if (sleepCount++ == 0) {
876 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
877 }
878 usleep(CHECK_MESSAGE_INTERVAL * 1000);
879 }
880 LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
881 return false;
882}
883
884// ----------------------------------------------------------------------------
885
886// Converts from a raw pointer to the client to a strong pointer during a
887// hardware callback. This requires the callbacks only happen when the client
888// is still alive.
889sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
890 sp<Client> client = gCameraService->getClientById((int) user);
891
892 // This could happen if the Client is in the process of shutting down (the
893 // last strong reference is gone, but the destructor hasn't finished
894 // stopping the hardware).
895 if (client == 0) return NULL;
896
897 // The checks below are not necessary and are for debugging only.
898 if (client->mCameraService.get() != gCameraService) {
899 LOGE("mismatch service!");
900 return NULL;
901 }
902
903 if (client->mHardware == 0) {
904 LOGE("mHardware == 0: callback after disconnect()?");
905 return NULL;
906 }
907
908 return client;
909}
910
911// Callback messages can be dispatched to internal handlers or pass to our
912// client's callback functions, depending on the message type.
913//
914// notifyCallback:
915// CAMERA_MSG_SHUTTER handleShutter
916// (others) c->notifyCallback
917// dataCallback:
918// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
919// CAMERA_MSG_POSTVIEW_FRAME handlePostview
920// CAMERA_MSG_RAW_IMAGE handleRawPicture
921// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
922// (others) c->dataCallback
923// dataCallbackTimestamp
924// (others) c->dataCallbackTimestamp
925//
926// NOTE: the *Callback functions grab mLock of the client before passing
927// control to handle* functions. So the handle* functions must release the
928// lock before calling the ICameraClient's callbacks, so those callbacks can
929// invoke methods in the Client class again (For example, the preview frame
930// callback may want to releaseRecordingFrame). The handle* functions must
931// release the lock after all accesses to member variables, so it must be
932// handled very carefully.
933
934void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
935 int32_t ext2, void* user) {
936 LOG2("notifyCallback(%d)", msgType);
937
938 sp<Client> client = getClientFromCookie(user);
939 if (client == 0) return;
940 if (!client->lockIfMessageWanted(msgType)) return;
941
942 switch (msgType) {
943 case CAMERA_MSG_SHUTTER:
944 // ext1 is the dimension of the yuv picture.
945 client->handleShutter((image_rect_type *)ext1);
946 break;
947 default:
948 client->handleGenericNotify(msgType, ext1, ext2);
949 break;
950 }
951}
952
953void CameraService::Client::dataCallback(int32_t msgType,
954 const sp<IMemory>& dataPtr, void* user) {
955 LOG2("dataCallback(%d)", msgType);
956
957 sp<Client> client = getClientFromCookie(user);
958 if (client == 0) return;
959 if (!client->lockIfMessageWanted(msgType)) return;
960
961 if (dataPtr == 0) {
962 LOGE("Null data returned in data callback");
963 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
964 return;
965 }
966
967 switch (msgType) {
968 case CAMERA_MSG_PREVIEW_FRAME:
969 client->handlePreviewData(dataPtr);
970 break;
971 case CAMERA_MSG_POSTVIEW_FRAME:
972 client->handlePostview(dataPtr);
973 break;
974 case CAMERA_MSG_RAW_IMAGE:
975 client->handleRawPicture(dataPtr);
976 break;
977 case CAMERA_MSG_COMPRESSED_IMAGE:
978 client->handleCompressedPicture(dataPtr);
979 break;
980 default:
981 client->handleGenericData(msgType, dataPtr);
982 break;
983 }
984}
985
986void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
987 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
988 LOG2("dataCallbackTimestamp(%d)", msgType);
989
990 sp<Client> client = getClientFromCookie(user);
991 if (client == 0) return;
992 if (!client->lockIfMessageWanted(msgType)) return;
993
994 if (dataPtr == 0) {
995 LOGE("Null data returned in data with timestamp callback");
996 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
997 return;
998 }
999
1000 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
1001}
1002
1003// snapshot taken callback
1004// "size" is the width and height of yuv picture for registerBuffer.
1005// If it is NULL, use the picture size from parameters.
1006void CameraService::Client::handleShutter(image_rect_type *size) {
1007 mCameraService->playSound(SOUND_SHUTTER);
1008
1009 // Screen goes black after the buffer is unregistered.
1010 if (mSurface != 0 && !mUseOverlay) {
1011 mSurface->unregisterBuffers();
1012 }
1013
1014 sp<ICameraClient> c = mCameraClient;
1015 if (c != 0) {
1016 mLock.unlock();
1017 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
1018 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
1019 }
1020 disableMsgType(CAMERA_MSG_SHUTTER);
1021
1022 // It takes some time before yuvPicture callback to be called.
1023 // Register the buffer for raw image here to reduce latency.
1024 if (mSurface != 0 && !mUseOverlay) {
1025 int w, h;
1026 CameraParameters params(mHardware->getParameters());
1027 if (size == NULL) {
1028 params.getPictureSize(&w, &h);
1029 } else {
1030 w = size->width;
1031 h = size->height;
1032 w &= ~1;
1033 h &= ~1;
1034 LOG1("Snapshot image width=%d, height=%d", w, h);
1035 }
1036 // FIXME: don't use hardcoded format constants here
1037 ISurface::BufferHeap buffers(w, h, w, h,
1038 HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
1039 mHardware->getRawHeap());
1040
1041 mSurface->registerBuffers(buffers);
Chih-Chung Chang3ef6ebe2010-07-02 07:48:03 -07001042 IPCThreadState::self()->flushCommands();
Chih-Chung Change25cc652010-05-06 16:36:58 +08001043 }
1044
1045 mLock.unlock();
1046}
1047
1048// preview callback - frame buffer update
1049void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
1050 ssize_t offset;
1051 size_t size;
1052 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1053
1054 if (!mUseOverlay) {
1055 if (mSurface != 0) {
1056 mSurface->postBuffer(offset);
1057 }
1058 }
1059
1060 // local copy of the callback flags
1061 int flags = mPreviewCallbackFlag;
1062
1063 // is callback enabled?
1064 if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
1065 // If the enable bit is off, the copy-out and one-shot bits are ignored
1066 LOG2("frame callback is disabled");
1067 mLock.unlock();
1068 return;
1069 }
1070
1071 // hold a strong pointer to the client
1072 sp<ICameraClient> c = mCameraClient;
1073
1074 // clear callback flags if no client or one-shot mode
1075 if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
1076 LOG2("Disable preview callback");
1077 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1078 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1079 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1080 if (mUseOverlay) {
1081 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
1082 }
1083 }
1084
1085 if (c != 0) {
1086 // Is the received frame copied out or not?
1087 if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1088 LOG2("frame is copied");
1089 copyFrameAndPostCopiedFrame(c, heap, offset, size);
1090 } else {
1091 LOG2("frame is forwarded");
1092 mLock.unlock();
1093 c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
1094 }
1095 } else {
1096 mLock.unlock();
1097 }
1098}
1099
1100// picture callback - postview image ready
1101void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
1102 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1103
1104 sp<ICameraClient> c = mCameraClient;
1105 mLock.unlock();
1106 if (c != 0) {
1107 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1108 }
1109}
1110
1111// picture callback - raw image ready
1112void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
1113 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1114
1115 ssize_t offset;
1116 size_t size;
1117 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1118
1119 // Put the YUV version of the snapshot in the preview display.
1120 if (mSurface != 0 && !mUseOverlay) {
1121 mSurface->postBuffer(offset);
1122 }
1123
1124 sp<ICameraClient> c = mCameraClient;
1125 mLock.unlock();
1126 if (c != 0) {
1127 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1128 }
1129}
1130
1131// picture callback - compressed picture ready
1132void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
1133 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1134
1135 sp<ICameraClient> c = mCameraClient;
1136 mLock.unlock();
1137 if (c != 0) {
1138 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1139 }
1140}
1141
1142
1143void CameraService::Client::handleGenericNotify(int32_t msgType,
1144 int32_t ext1, int32_t ext2) {
1145 sp<ICameraClient> c = mCameraClient;
1146 mLock.unlock();
1147 if (c != 0) {
1148 c->notifyCallback(msgType, ext1, ext2);
1149 }
1150}
1151
1152void CameraService::Client::handleGenericData(int32_t msgType,
1153 const sp<IMemory>& dataPtr) {
1154 sp<ICameraClient> c = mCameraClient;
1155 mLock.unlock();
1156 if (c != 0) {
1157 c->dataCallback(msgType, dataPtr);
1158 }
1159}
1160
1161void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
1162 int32_t msgType, const sp<IMemory>& dataPtr) {
1163 sp<ICameraClient> c = mCameraClient;
1164 mLock.unlock();
1165 if (c != 0) {
1166 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1167 }
1168}
1169
1170void CameraService::Client::copyFrameAndPostCopiedFrame(
1171 const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
1172 size_t offset, size_t size) {
1173 LOG2("copyFrameAndPostCopiedFrame");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001174 // It is necessary to copy out of pmem before sending this to
1175 // the callback. For efficiency, reuse the same MemoryHeapBase
1176 // provided it's big enough. Don't allocate the memory or
1177 // perform the copy if there's no callback.
Dave Sparks05fd0df2009-11-10 17:08:08 -08001178 // hold the preview lock while we grab a reference to the preview buffer
Dave Sparksc8093c12009-11-06 11:47:13 -08001179 sp<MemoryHeapBase> previewBuffer;
Chih-Chung Change25cc652010-05-06 16:36:58 +08001180
1181 if (mPreviewBuffer == 0) {
1182 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1183 } else if (size > mPreviewBuffer->virtualSize()) {
1184 mPreviewBuffer.clear();
1185 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001186 }
Chih-Chung Change25cc652010-05-06 16:36:58 +08001187 if (mPreviewBuffer == 0) {
1188 LOGE("failed to allocate space for preview buffer");
1189 mLock.unlock();
1190 return;
1191 }
1192 previewBuffer = mPreviewBuffer;
1193
1194 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195
Dave Sparksc8093c12009-11-06 11:47:13 -08001196 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 if (frame == 0) {
1198 LOGE("failed to allocate space for frame callback");
Chih-Chung Change25cc652010-05-06 16:36:58 +08001199 mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200 return;
1201 }
Chih-Chung Change25cc652010-05-06 16:36:58 +08001202
1203 mLock.unlock();
Dave Sparksdd158c92009-10-15 10:02:22 -07001204 client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205}
1206
Chih-Chung Change25cc652010-05-06 16:36:58 +08001207// ----------------------------------------------------------------------------
1208
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001209static const int kDumpLockRetries = 50;
1210static const int kDumpLockSleep = 60000;
1211
1212static bool tryLock(Mutex& mutex)
1213{
1214 bool locked = false;
1215 for (int i = 0; i < kDumpLockRetries; ++i) {
1216 if (mutex.tryLock() == NO_ERROR) {
1217 locked = true;
1218 break;
1219 }
1220 usleep(kDumpLockSleep);
1221 }
1222 return locked;
1223}
1224
Chih-Chung Change25cc652010-05-06 16:36:58 +08001225status_t CameraService::dump(int fd, const Vector<String16>& args) {
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001226 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 const size_t SIZE = 256;
1229 char buffer[SIZE];
1230 String8 result;
1231 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1232 snprintf(buffer, SIZE, "Permission Denial: "
1233 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +08001234 getCallingPid(),
Chih-Chung Change25cc652010-05-06 16:36:58 +08001235 getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001236 result.append(buffer);
1237 write(fd, result.string(), result.size());
1238 } else {
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001239 bool locked = tryLock(mServiceLock);
1240 // failed to lock - CameraService is probably deadlocked
1241 if (!locked) {
1242 String8 result(kDeadlockedString);
1243 write(fd, result.string(), result.size());
1244 }
1245
Chih-Chung Change25cc652010-05-06 16:36:58 +08001246 bool hasClient = false;
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +08001247 for (int i = 0; i < mNumberOfCameras; i++) {
Chih-Chung Change25cc652010-05-06 16:36:58 +08001248 sp<Client> client = mClient[i].promote();
1249 if (client == 0) continue;
1250 hasClient = true;
1251 sprintf(buffer, "Client[%d] (%p) PID: %d\n",
1252 i,
1253 client->getCameraClient()->asBinder().get(),
1254 client->mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 result.append(buffer);
1256 write(fd, result.string(), result.size());
Chih-Chung Change25cc652010-05-06 16:36:58 +08001257 client->mHardware->dump(fd, args);
1258 }
1259 if (!hasClient) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 result.append("No camera client yet.\n");
1261 write(fd, result.string(), result.size());
1262 }
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001263
1264 if (locked) mServiceLock.unlock();
Chih-Chung Change25cc652010-05-06 16:36:58 +08001265
1266 // change logging level
1267 int n = args.size();
1268 for (int i = 0; i + 1 < n; i++) {
1269 if (args[i] == String16("-v")) {
1270 String8 levelStr(args[i+1]);
1271 int level = atoi(levelStr.string());
1272 sprintf(buffer, "Set Log Level to %d", level);
1273 result.append(buffer);
1274 setLogLevel(level);
1275 }
1276 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 }
1278 return NO_ERROR;
1279}
1280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001281}; // namespace android