blob: d1fbf17d87b41904b6c1daa61237b3dd098179df [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;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800322 cameraService->setCameraBusy(cameraId);
323 cameraService->loadSound();
324 LOG1("Client::Client X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800325}
326
Chih-Chung Change25cc652010-05-06 16:36:58 +0800327static void *unregister_surface(void *arg) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 ISurface *surface = (ISurface *)arg;
329 surface->unregisterBuffers();
330 IPCThreadState::self()->flushCommands();
331 return NULL;
332}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800333
Chih-Chung Change25cc652010-05-06 16:36:58 +0800334// tear down the client
335CameraService::Client::~Client() {
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800336 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800337 LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800338
Chih-Chung Change25cc652010-05-06 16:36:58 +0800339 // set mClientPid to let disconnet() tear down the hardware
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800340 mClientPid = callingPid;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 disconnect();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800342 mCameraService->releaseSound();
343 LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800344}
345
Chih-Chung Change25cc652010-05-06 16:36:58 +0800346// ----------------------------------------------------------------------------
347
348status_t CameraService::Client::checkPid() const {
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800349 int callingPid = getCallingPid();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800350 if (callingPid == mClientPid) return NO_ERROR;
James Dong71d714c2010-06-09 15:57:48 -0700351
Chih-Chung Change25cc652010-05-06 16:36:58 +0800352 LOGW("attempt to use a locked camera from a different process"
353 " (old pid %d, new pid %d)", mClientPid, callingPid);
354 return EBUSY;
355}
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800356
Chih-Chung Change25cc652010-05-06 16:36:58 +0800357status_t CameraService::Client::checkPidAndHardware() const {
358 status_t result = checkPid();
359 if (result != NO_ERROR) return result;
360 if (mHardware == 0) {
361 LOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
362 return INVALID_OPERATION;
363 }
364 return NO_ERROR;
365}
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +0800366
Chih-Chung Change25cc652010-05-06 16:36:58 +0800367status_t CameraService::Client::lock() {
368 int callingPid = getCallingPid();
369 LOG1("lock (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800371
372 // lock camera to this client if the the camera is unlocked
373 if (mClientPid == 0) {
374 mClientPid = callingPid;
375 return NO_ERROR;
376 }
377
378 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
379 return checkPid();
380}
381
382status_t CameraService::Client::unlock() {
383 int callingPid = getCallingPid();
384 LOG1("unlock (pid %d)", callingPid);
385 Mutex::Autolock lock(mLock);
386
387 // allow anyone to use camera (after they lock the camera)
388 status_t result = checkPid();
389 if (result == NO_ERROR) {
390 mClientPid = 0;
391 LOG1("clear mCameraClient (pid %d)", callingPid);
392 // we need to remove the reference to ICameraClient so that when the app
393 // goes away, the reference count goes to 0.
394 mCameraClient.clear();
395 }
396 return result;
397}
398
399// connect a new client to the camera
400status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
401 int callingPid = getCallingPid();
402 LOG1("connect E (pid %d)", callingPid);
403 Mutex::Autolock lock(mLock);
404
405 if (mClientPid != 0 && checkPid() != NO_ERROR) {
406 LOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
407 mClientPid, callingPid);
408 return EBUSY;
409 }
410
411 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
412 LOG1("Connect to the same client");
413 return NO_ERROR;
414 }
415
416 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
417 mClientPid = callingPid;
418 mCameraClient = client;
419
420 LOG1("connect X (pid %d)", callingPid);
421 return NO_ERROR;
422}
423
424void CameraService::Client::disconnect() {
425 int callingPid = getCallingPid();
426 LOG1("disconnect E (pid %d)", callingPid);
427 Mutex::Autolock lock(mLock);
428
429 if (checkPid() != NO_ERROR) {
430 LOGW("different client - don't disconnect");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 return;
432 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800433
434 if (mClientPid <= 0) {
435 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 return;
437 }
438
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800439 // Make sure disconnect() is done once and once only, whether it is called
440 // from the user directly, or called by the destructor.
441 if (mHardware == 0) return;
442
Chih-Chung Change25cc652010-05-06 16:36:58 +0800443 LOG1("hardware teardown");
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800444 // Before destroying mHardware, we must make sure it's in the
445 // idle state.
Chih-Chung Change25cc652010-05-06 16:36:58 +0800446 // Turn off all messages.
447 disableMsgType(CAMERA_MSG_ALL_MSGS);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800448 mHardware->stopPreview();
Benny Wongda83f462009-08-12 12:01:27 -0500449 mHardware->cancelPicture();
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800450 // Release the hardware resources.
451 mHardware->release();
Benny Wong6d2090e2009-07-15 18:44:27 -0500452 // Release the held overlay resources.
Chih-Chung Change25cc652010-05-06 16:36:58 +0800453 if (mUseOverlay) {
Benny Wong6d2090e2009-07-15 18:44:27 -0500454 mOverlayRef = 0;
455 }
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700456 // Release the held ANativeWindow resources.
457 if (mPreviewWindow != 0) {
458 mPreviewWindow = 0;
459 mHardware->setPreviewWindow(mPreviewWindow);
460 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 mHardware.clear();
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800462
Chih-Chung Changd5d1ebd2009-06-24 19:59:31 +0800463 mCameraService->removeClient(mCameraClient);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800464 mCameraService->setCameraFree(mCameraId);
Chih-Chung Chang6fcba312009-06-24 13:44:37 +0800465
Chih-Chung Change25cc652010-05-06 16:36:58 +0800466 LOG1("disconnect X (pid %d)", callingPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467}
468
Chih-Chung Change25cc652010-05-06 16:36:58 +0800469// ----------------------------------------------------------------------------
470
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700471// set the Surface that the preview will use
472status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800473 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800474 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800475 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 if (result != NO_ERROR) return result;
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800477
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800478 result = NO_ERROR;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800479
480 // return if no change in surface.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 // asBinder() is safe on NULL (returns NULL)
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700482 if (getISurface(surface)->asBinder() == mSurface->asBinder()) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800483 return result;
484 }
485
486 if (mSurface != 0) {
487 LOG1("clearing old preview surface %p", mSurface.get());
488 if (mUseOverlay) {
489 // Force the destruction of any previous overlay
490 sp<Overlay> dummy;
491 mHardware->setOverlay(dummy);
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800492 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 }
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700494 if (surface != 0) {
495 mSurface = getISurface(surface);
496 } else {
497 mSurface = 0;
498 }
499 mPreviewWindow = surface;
Chih-Chung Change25cc652010-05-06 16:36:58 +0800500 mOverlayRef = 0;
501 // If preview has been already started, set overlay or register preview
502 // buffers now.
503 if (mHardware->previewEnabled()) {
504 if (mUseOverlay) {
505 result = setOverlay();
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700506 } else if (mPreviewWindow != 0) {
507 result = mHardware->setPreviewWindow(mPreviewWindow);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800508 }
509 }
510
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800511 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512}
513
Chih-Chung Change25cc652010-05-06 16:36:58 +0800514status_t CameraService::Client::setOverlay() {
515 int w, h;
516 CameraParameters params(mHardware->getParameters());
517 params.getPreviewSize(&w, &h);
518
519 if (w != mOverlayW || h != mOverlayH) {
520 // Force the destruction of any previous overlay
521 sp<Overlay> dummy;
522 mHardware->setOverlay(dummy);
523 mOverlayRef = 0;
524 }
525
526 status_t result = NO_ERROR;
527 if (mSurface == 0) {
528 result = mHardware->setOverlay(NULL);
529 } else {
530 if (mOverlayRef == 0) {
531 // FIXME:
532 // Surfaceflinger may hold onto the previous overlay reference for some
533 // time after we try to destroy it. retry a few times. In the future, we
534 // should make the destroy call block, or possibly specify that we can
535 // wait in the createOverlay call if the previous overlay is in the
536 // process of being destroyed.
537 for (int retry = 0; retry < 50; ++retry) {
538 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
539 mOrientation);
540 if (mOverlayRef != 0) break;
541 LOGW("Overlay create failed - retrying");
542 usleep(20000);
543 }
544 if (mOverlayRef == 0) {
545 LOGE("Overlay Creation Failed!");
546 return -EINVAL;
547 }
548 result = mHardware->setOverlay(new Overlay(mOverlayRef));
549 }
550 }
551 if (result != NO_ERROR) {
552 LOGE("mHardware->setOverlay() failed with status %d\n", result);
553 return result;
554 }
555
556 mOverlayW = w;
557 mOverlayH = h;
558
559 return result;
560}
561
562// set the preview callback flag to affect how the received frames from
563// preview are handled.
564void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
565 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
566 Mutex::Autolock lock(mLock);
567 if (checkPidAndHardware() != NO_ERROR) return;
568
569 mPreviewCallbackFlag = callback_flag;
570
571 // If we don't use overlay, we always need the preview frame for display.
572 // If we do use overlay, we only need the preview frame if the user
573 // wants the data.
574 if (mUseOverlay) {
575 if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK) {
576 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
577 } else {
578 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
579 }
580 }
581}
582
583// start preview mode
584status_t CameraService::Client::startPreview() {
585 LOG1("startPreview (pid %d)", getCallingPid());
586 return startCameraMode(CAMERA_PREVIEW_MODE);
587}
588
589// start recording mode
590status_t CameraService::Client::startRecording() {
591 LOG1("startRecording (pid %d)", getCallingPid());
592 return startCameraMode(CAMERA_RECORDING_MODE);
593}
594
595// start preview or recording
596status_t CameraService::Client::startCameraMode(camera_mode mode) {
597 LOG1("startCameraMode(%d)", mode);
598 Mutex::Autolock lock(mLock);
599 status_t result = checkPidAndHardware();
600 if (result != NO_ERROR) return result;
601
602 switch(mode) {
603 case CAMERA_PREVIEW_MODE:
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700604 if (mSurface == 0 && mPreviewWindow == 0) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800605 LOG1("mSurface is not set yet.");
606 // still able to start preview in this case.
607 }
608 return startPreviewMode();
609 case CAMERA_RECORDING_MODE:
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700610 if (mSurface == 0 && mPreviewWindow == 0) {
611 LOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
Chih-Chung Change25cc652010-05-06 16:36:58 +0800612 return INVALID_OPERATION;
613 }
614 return startRecordingMode();
615 default:
616 return UNKNOWN_ERROR;
617 }
618}
619
620status_t CameraService::Client::startPreviewMode() {
621 LOG1("startPreviewMode");
622 status_t result = NO_ERROR;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623
624 // if preview has been enabled, nothing needs to be done
625 if (mHardware->previewEnabled()) {
626 return NO_ERROR;
627 }
628
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 if (mUseOverlay) {
Wu-cheng Lib8a10fe2009-06-23 23:37:36 +0800630 // If preview display has been set, set overlay now.
631 if (mSurface != 0) {
Chih-Chung Change25cc652010-05-06 16:36:58 +0800632 result = setOverlay();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800634 if (result != NO_ERROR) return result;
635 result = mHardware->startPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 } else {
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700637 // XXX: Set the orientation of the ANativeWindow.
638 mHardware->setPreviewWindow(mPreviewWindow);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800639 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
640 result = mHardware->startPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 }
Chih-Chung Change25cc652010-05-06 16:36:58 +0800642 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643}
644
Chih-Chung Change25cc652010-05-06 16:36:58 +0800645status_t CameraService::Client::startRecordingMode() {
646 LOG1("startRecordingMode");
647 status_t result = NO_ERROR;
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700648
Chih-Chung Change25cc652010-05-06 16:36:58 +0800649 // if recording has been enabled, nothing needs to be done
650 if (mHardware->recordingEnabled()) {
651 return NO_ERROR;
652 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800653
Chih-Chung Change25cc652010-05-06 16:36:58 +0800654 // if preview has not been started, start preview first
655 if (!mHardware->previewEnabled()) {
656 result = startPreviewMode();
657 if (result != NO_ERROR) {
658 return result;
Eric Laurent524dc042009-11-27 05:07:55 -0800659 }
Jason Samsb18b6912009-03-24 20:21:36 -0700660 }
Benny Wongda83f462009-08-12 12:01:27 -0500661
Chih-Chung Change25cc652010-05-06 16:36:58 +0800662 // start recording mode
663 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
664 mCameraService->playSound(SOUND_RECORDING);
665 result = mHardware->startRecording();
666 if (result != NO_ERROR) {
667 LOGE("mHardware->startRecording() failed with status %d", result);
668 }
669 return result;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800670}
671
672// stop preview mode
Chih-Chung Change25cc652010-05-06 16:36:58 +0800673void CameraService::Client::stopPreview() {
674 LOG1("stopPreview (pid %d)", getCallingPid());
675 Mutex::Autolock lock(mLock);
676 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800677
Jamie Gennis85cfdd02010-08-10 16:37:53 -0700678
Chih-Chung Change25cc652010-05-06 16:36:58 +0800679 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
680 mHardware->stopPreview();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800681
Chih-Chung Change25cc652010-05-06 16:36:58 +0800682 mPreviewBuffer.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683}
684
685// stop recording mode
Chih-Chung Change25cc652010-05-06 16:36:58 +0800686void CameraService::Client::stopRecording() {
687 LOG1("stopRecording (pid %d)", getCallingPid());
688 Mutex::Autolock lock(mLock);
689 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800690
Chih-Chung Change25cc652010-05-06 16:36:58 +0800691 mCameraService->playSound(SOUND_RECORDING);
692 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
693 mHardware->stopRecording();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800694
Chih-Chung Change25cc652010-05-06 16:36:58 +0800695 mPreviewBuffer.clear();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696}
697
698// release a recording frame
Chih-Chung Change25cc652010-05-06 16:36:58 +0800699void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800700 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800701 if (checkPidAndHardware() != NO_ERROR) return;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800702 mHardware->releaseRecordingFrame(mem);
703}
704
Chih-Chung Change25cc652010-05-06 16:36:58 +0800705bool CameraService::Client::previewEnabled() {
706 LOG1("previewEnabled (pid %d)", getCallingPid());
707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800709 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800710 return mHardware->previewEnabled();
711}
712
Chih-Chung Change25cc652010-05-06 16:36:58 +0800713bool CameraService::Client::recordingEnabled() {
714 LOG1("recordingEnabled (pid %d)", getCallingPid());
715
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800717 if (checkPidAndHardware() != NO_ERROR) return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800718 return mHardware->recordingEnabled();
719}
720
Chih-Chung Change25cc652010-05-06 16:36:58 +0800721status_t CameraService::Client::autoFocus() {
722 LOG1("autoFocus (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800723
724 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800725 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 if (result != NO_ERROR) return result;
727
Benny Wongda83f462009-08-12 12:01:27 -0500728 return mHardware->autoFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800729}
730
Chih-Chung Change25cc652010-05-06 16:36:58 +0800731status_t CameraService::Client::cancelAutoFocus() {
732 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800733
734 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800735 status_t result = checkPidAndHardware();
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800736 if (result != NO_ERROR) return result;
737
Chih-Chung Chang244f8c22009-09-15 14:51:56 +0800738 return mHardware->cancelAutoFocus();
739}
740
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741// take a picture - image is returned in callback
Chih-Chung Change25cc652010-05-06 16:36:58 +0800742status_t CameraService::Client::takePicture() {
743 LOG1("takePicture (pid %d)", getCallingPid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800744
745 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800746 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 if (result != NO_ERROR) return result;
748
Chih-Chung Change25cc652010-05-06 16:36:58 +0800749 enableMsgType(CAMERA_MSG_SHUTTER |
750 CAMERA_MSG_POSTVIEW_FRAME |
751 CAMERA_MSG_RAW_IMAGE |
752 CAMERA_MSG_COMPRESSED_IMAGE);
Benny Wongda83f462009-08-12 12:01:27 -0500753
754 return mHardware->takePicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800755}
756
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800757// set preview/capture parameters - key/value pairs
Chih-Chung Change25cc652010-05-06 16:36:58 +0800758status_t CameraService::Client::setParameters(const String8& params) {
759 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800760
761 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800762 status_t result = checkPidAndHardware();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 if (result != NO_ERROR) return result;
764
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765 CameraParameters p(params);
James Dong6085b4e2009-09-13 17:10:24 -0700766 return mHardware->setParameters(p);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800767}
768
769// get preview/capture parameters - key/value pairs
Chih-Chung Change25cc652010-05-06 16:36:58 +0800770String8 CameraService::Client::getParameters() const {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800771 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800772 if (checkPidAndHardware() != NO_ERROR) return String8();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800773
Wu-cheng Liab5b4242009-04-22 16:21:26 +0800774 String8 params(mHardware->getParameters().flatten());
Chih-Chung Change25cc652010-05-06 16:36:58 +0800775 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
Wu-cheng Liab5b4242009-04-22 16:21:26 +0800776 return params;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800777}
778
Chih-Chung Change25cc652010-05-06 16:36:58 +0800779status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
780 LOG1("sendCommand (pid %d)", getCallingPid());
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700781 Mutex::Autolock lock(mLock);
Chih-Chung Change25cc652010-05-06 16:36:58 +0800782 status_t result = checkPidAndHardware();
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700783 if (result != NO_ERROR) return result;
784
Chih-Chung Changd1d77062010-01-22 17:49:48 -0800785 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
786 // The orientation cannot be set during preview.
787 if (mHardware->previewEnabled()) {
788 return INVALID_OPERATION;
789 }
790 switch (arg1) {
791 case 0:
792 mOrientation = ISurface::BufferHeap::ROT_0;
793 break;
794 case 90:
795 mOrientation = ISurface::BufferHeap::ROT_90;
796 break;
797 case 180:
798 mOrientation = ISurface::BufferHeap::ROT_180;
799 break;
800 case 270:
801 mOrientation = ISurface::BufferHeap::ROT_270;
802 break;
803 default:
804 return BAD_VALUE;
805 }
806 return OK;
807 }
808
Wu-cheng Li36f68b82009-09-28 16:14:58 -0700809 return mHardware->sendCommand(cmd, arg1, arg2);
810}
811
Chih-Chung Change25cc652010-05-06 16:36:58 +0800812// ----------------------------------------------------------------------------
813
814void CameraService::Client::enableMsgType(int32_t msgType) {
815 android_atomic_or(msgType, &mMsgEnabled);
816 mHardware->enableMsgType(msgType);
817}
818
819void CameraService::Client::disableMsgType(int32_t msgType) {
820 android_atomic_and(~msgType, &mMsgEnabled);
821 mHardware->disableMsgType(msgType);
822}
823
824#define CHECK_MESSAGE_INTERVAL 10 // 10ms
825bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
826 int sleepCount = 0;
827 while (mMsgEnabled & msgType) {
828 if (mLock.tryLock() == NO_ERROR) {
829 if (sleepCount > 0) {
830 LOG1("lockIfMessageWanted(%d): waited for %d ms",
831 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
832 }
833 return true;
834 }
835 if (sleepCount++ == 0) {
836 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
837 }
838 usleep(CHECK_MESSAGE_INTERVAL * 1000);
839 }
840 LOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
841 return false;
842}
843
844// ----------------------------------------------------------------------------
845
846// Converts from a raw pointer to the client to a strong pointer during a
847// hardware callback. This requires the callbacks only happen when the client
848// is still alive.
849sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user) {
850 sp<Client> client = gCameraService->getClientById((int) user);
851
852 // This could happen if the Client is in the process of shutting down (the
853 // last strong reference is gone, but the destructor hasn't finished
854 // stopping the hardware).
855 if (client == 0) return NULL;
856
857 // The checks below are not necessary and are for debugging only.
858 if (client->mCameraService.get() != gCameraService) {
859 LOGE("mismatch service!");
860 return NULL;
861 }
862
863 if (client->mHardware == 0) {
864 LOGE("mHardware == 0: callback after disconnect()?");
865 return NULL;
866 }
867
868 return client;
869}
870
871// Callback messages can be dispatched to internal handlers or pass to our
872// client's callback functions, depending on the message type.
873//
874// notifyCallback:
875// CAMERA_MSG_SHUTTER handleShutter
876// (others) c->notifyCallback
877// dataCallback:
878// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
879// CAMERA_MSG_POSTVIEW_FRAME handlePostview
880// CAMERA_MSG_RAW_IMAGE handleRawPicture
881// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
882// (others) c->dataCallback
883// dataCallbackTimestamp
884// (others) c->dataCallbackTimestamp
885//
886// NOTE: the *Callback functions grab mLock of the client before passing
887// control to handle* functions. So the handle* functions must release the
888// lock before calling the ICameraClient's callbacks, so those callbacks can
889// invoke methods in the Client class again (For example, the preview frame
890// callback may want to releaseRecordingFrame). The handle* functions must
891// release the lock after all accesses to member variables, so it must be
892// handled very carefully.
893
894void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
895 int32_t ext2, void* user) {
896 LOG2("notifyCallback(%d)", msgType);
897
898 sp<Client> client = getClientFromCookie(user);
899 if (client == 0) return;
900 if (!client->lockIfMessageWanted(msgType)) return;
901
902 switch (msgType) {
903 case CAMERA_MSG_SHUTTER:
904 // ext1 is the dimension of the yuv picture.
905 client->handleShutter((image_rect_type *)ext1);
906 break;
907 default:
908 client->handleGenericNotify(msgType, ext1, ext2);
909 break;
910 }
911}
912
913void CameraService::Client::dataCallback(int32_t msgType,
914 const sp<IMemory>& dataPtr, void* user) {
915 LOG2("dataCallback(%d)", msgType);
916
917 sp<Client> client = getClientFromCookie(user);
918 if (client == 0) return;
919 if (!client->lockIfMessageWanted(msgType)) return;
920
921 if (dataPtr == 0) {
922 LOGE("Null data returned in data callback");
923 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
924 return;
925 }
926
927 switch (msgType) {
928 case CAMERA_MSG_PREVIEW_FRAME:
929 client->handlePreviewData(dataPtr);
930 break;
931 case CAMERA_MSG_POSTVIEW_FRAME:
932 client->handlePostview(dataPtr);
933 break;
934 case CAMERA_MSG_RAW_IMAGE:
935 client->handleRawPicture(dataPtr);
936 break;
937 case CAMERA_MSG_COMPRESSED_IMAGE:
938 client->handleCompressedPicture(dataPtr);
939 break;
940 default:
941 client->handleGenericData(msgType, dataPtr);
942 break;
943 }
944}
945
946void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
947 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
948 LOG2("dataCallbackTimestamp(%d)", msgType);
949
950 sp<Client> client = getClientFromCookie(user);
951 if (client == 0) return;
952 if (!client->lockIfMessageWanted(msgType)) return;
953
954 if (dataPtr == 0) {
955 LOGE("Null data returned in data with timestamp callback");
956 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
957 return;
958 }
959
960 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
961}
962
963// snapshot taken callback
964// "size" is the width and height of yuv picture for registerBuffer.
965// If it is NULL, use the picture size from parameters.
966void CameraService::Client::handleShutter(image_rect_type *size) {
967 mCameraService->playSound(SOUND_SHUTTER);
968
Chih-Chung Change25cc652010-05-06 16:36:58 +0800969 sp<ICameraClient> c = mCameraClient;
970 if (c != 0) {
971 mLock.unlock();
972 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
973 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
974 }
975 disableMsgType(CAMERA_MSG_SHUTTER);
976
977 // It takes some time before yuvPicture callback to be called.
978 // Register the buffer for raw image here to reduce latency.
979 if (mSurface != 0 && !mUseOverlay) {
980 int w, h;
981 CameraParameters params(mHardware->getParameters());
982 if (size == NULL) {
983 params.getPictureSize(&w, &h);
984 } else {
985 w = size->width;
986 h = size->height;
987 w &= ~1;
988 h &= ~1;
989 LOG1("Snapshot image width=%d, height=%d", w, h);
990 }
991 // FIXME: don't use hardcoded format constants here
992 ISurface::BufferHeap buffers(w, h, w, h,
993 HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
994 mHardware->getRawHeap());
995
Chih-Chung Chang3ef6ebe2010-07-02 07:48:03 -0700996 IPCThreadState::self()->flushCommands();
Chih-Chung Change25cc652010-05-06 16:36:58 +0800997 }
998
999 mLock.unlock();
1000}
1001
1002// preview callback - frame buffer update
1003void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) {
1004 ssize_t offset;
1005 size_t size;
1006 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1007
Chih-Chung Change25cc652010-05-06 16:36:58 +08001008 // local copy of the callback flags
1009 int flags = mPreviewCallbackFlag;
1010
1011 // is callback enabled?
1012 if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
1013 // If the enable bit is off, the copy-out and one-shot bits are ignored
1014 LOG2("frame callback is disabled");
1015 mLock.unlock();
1016 return;
1017 }
1018
1019 // hold a strong pointer to the client
1020 sp<ICameraClient> c = mCameraClient;
1021
1022 // clear callback flags if no client or one-shot mode
1023 if (c == 0 || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
1024 LOG2("Disable preview callback");
1025 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1026 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1027 FRAME_CALLBACK_FLAG_ENABLE_MASK);
1028 if (mUseOverlay) {
1029 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
1030 }
1031 }
1032
1033 if (c != 0) {
1034 // Is the received frame copied out or not?
1035 if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1036 LOG2("frame is copied");
1037 copyFrameAndPostCopiedFrame(c, heap, offset, size);
1038 } else {
1039 LOG2("frame is forwarded");
1040 mLock.unlock();
1041 c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
1042 }
1043 } else {
1044 mLock.unlock();
1045 }
1046}
1047
1048// picture callback - postview image ready
1049void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
1050 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1051
1052 sp<ICameraClient> c = mCameraClient;
1053 mLock.unlock();
1054 if (c != 0) {
1055 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1056 }
1057}
1058
1059// picture callback - raw image ready
1060void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
1061 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1062
1063 ssize_t offset;
1064 size_t size;
1065 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1066
Chih-Chung Change25cc652010-05-06 16:36:58 +08001067 sp<ICameraClient> c = mCameraClient;
1068 mLock.unlock();
1069 if (c != 0) {
1070 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1071 }
1072}
1073
1074// picture callback - compressed picture ready
1075void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
1076 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1077
1078 sp<ICameraClient> c = mCameraClient;
1079 mLock.unlock();
1080 if (c != 0) {
1081 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1082 }
1083}
1084
1085
1086void CameraService::Client::handleGenericNotify(int32_t msgType,
1087 int32_t ext1, int32_t ext2) {
1088 sp<ICameraClient> c = mCameraClient;
1089 mLock.unlock();
1090 if (c != 0) {
1091 c->notifyCallback(msgType, ext1, ext2);
1092 }
1093}
1094
1095void CameraService::Client::handleGenericData(int32_t msgType,
1096 const sp<IMemory>& dataPtr) {
1097 sp<ICameraClient> c = mCameraClient;
1098 mLock.unlock();
1099 if (c != 0) {
1100 c->dataCallback(msgType, dataPtr);
1101 }
1102}
1103
1104void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
1105 int32_t msgType, const sp<IMemory>& dataPtr) {
1106 sp<ICameraClient> c = mCameraClient;
1107 mLock.unlock();
1108 if (c != 0) {
1109 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1110 }
1111}
1112
1113void CameraService::Client::copyFrameAndPostCopiedFrame(
1114 const sp<ICameraClient>& client, const sp<IMemoryHeap>& heap,
1115 size_t offset, size_t size) {
1116 LOG2("copyFrameAndPostCopiedFrame");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001117 // It is necessary to copy out of pmem before sending this to
1118 // the callback. For efficiency, reuse the same MemoryHeapBase
1119 // provided it's big enough. Don't allocate the memory or
1120 // perform the copy if there's no callback.
Dave Sparks05fd0df2009-11-10 17:08:08 -08001121 // hold the preview lock while we grab a reference to the preview buffer
Dave Sparksc8093c12009-11-06 11:47:13 -08001122 sp<MemoryHeapBase> previewBuffer;
Chih-Chung Change25cc652010-05-06 16:36:58 +08001123
1124 if (mPreviewBuffer == 0) {
1125 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1126 } else if (size > mPreviewBuffer->virtualSize()) {
1127 mPreviewBuffer.clear();
1128 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 }
Chih-Chung Change25cc652010-05-06 16:36:58 +08001130 if (mPreviewBuffer == 0) {
1131 LOGE("failed to allocate space for preview buffer");
1132 mLock.unlock();
1133 return;
1134 }
1135 previewBuffer = mPreviewBuffer;
1136
1137 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138
Dave Sparksc8093c12009-11-06 11:47:13 -08001139 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140 if (frame == 0) {
1141 LOGE("failed to allocate space for frame callback");
Chih-Chung Change25cc652010-05-06 16:36:58 +08001142 mLock.unlock();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143 return;
1144 }
Chih-Chung Change25cc652010-05-06 16:36:58 +08001145
1146 mLock.unlock();
Dave Sparksdd158c92009-10-15 10:02:22 -07001147 client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001148}
1149
Chih-Chung Change25cc652010-05-06 16:36:58 +08001150// ----------------------------------------------------------------------------
1151
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001152static const int kDumpLockRetries = 50;
1153static const int kDumpLockSleep = 60000;
1154
1155static bool tryLock(Mutex& mutex)
1156{
1157 bool locked = false;
1158 for (int i = 0; i < kDumpLockRetries; ++i) {
1159 if (mutex.tryLock() == NO_ERROR) {
1160 locked = true;
1161 break;
1162 }
1163 usleep(kDumpLockSleep);
1164 }
1165 return locked;
1166}
1167
Chih-Chung Change25cc652010-05-06 16:36:58 +08001168status_t CameraService::dump(int fd, const Vector<String16>& args) {
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001169 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 const size_t SIZE = 256;
1172 char buffer[SIZE];
1173 String8 result;
1174 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1175 snprintf(buffer, SIZE, "Permission Denial: "
1176 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Chang1f25ec82009-06-22 16:03:41 +08001177 getCallingPid(),
Chih-Chung Change25cc652010-05-06 16:36:58 +08001178 getCallingUid());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 result.append(buffer);
1180 write(fd, result.string(), result.size());
1181 } else {
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001182 bool locked = tryLock(mServiceLock);
1183 // failed to lock - CameraService is probably deadlocked
1184 if (!locked) {
1185 String8 result(kDeadlockedString);
1186 write(fd, result.string(), result.size());
1187 }
1188
Chih-Chung Change25cc652010-05-06 16:36:58 +08001189 bool hasClient = false;
Chih-Chung Changb8bb78f2010-06-10 13:32:16 +08001190 for (int i = 0; i < mNumberOfCameras; i++) {
Chih-Chung Change25cc652010-05-06 16:36:58 +08001191 sp<Client> client = mClient[i].promote();
1192 if (client == 0) continue;
1193 hasClient = true;
1194 sprintf(buffer, "Client[%d] (%p) PID: %d\n",
1195 i,
1196 client->getCameraClient()->asBinder().get(),
1197 client->mClientPid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 result.append(buffer);
1199 write(fd, result.string(), result.size());
Chih-Chung Change25cc652010-05-06 16:36:58 +08001200 client->mHardware->dump(fd, args);
1201 }
1202 if (!hasClient) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 result.append("No camera client yet.\n");
1204 write(fd, result.string(), result.size());
1205 }
Chih-Chung Change86ae1b2010-03-05 11:33:03 -08001206
1207 if (locked) mServiceLock.unlock();
Chih-Chung Change25cc652010-05-06 16:36:58 +08001208
1209 // change logging level
1210 int n = args.size();
1211 for (int i = 0; i + 1 < n; i++) {
1212 if (args[i] == String16("-v")) {
1213 String8 levelStr(args[i+1]);
1214 int level = atoi(levelStr.string());
1215 sprintf(buffer, "Set Log Level to %d", level);
1216 result.append(buffer);
1217 setLogLevel(level);
1218 }
1219 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 }
1221 return NO_ERROR;
1222}
1223
Jamie Gennis85cfdd02010-08-10 16:37:53 -07001224sp<ISurface> CameraService::getISurface(const sp<Surface>& surface) {
1225 if (surface != 0) {
1226 return surface->getISurface();
1227 } else {
1228 return sp<ISurface>(0);
1229 }
1230}
1231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232}; // namespace android