blob: 53c77da1e1b7260877dd5f1257a995093cd89e2c [file] [log] [blame]
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
4** Copyright (C) 2008 HTC Inc.
5**
6** Licensed under the Apache License, Version 2.0 (the "License");
7** you may not use this file except in compliance with the License.
8** You may obtain a copy of the License at
9**
10** http://www.apache.org/licenses/LICENSE-2.0
11**
12** Unless required by applicable law or agreed to in writing, software
13** distributed under the License is distributed on an "AS IS" BASIS,
14** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15** See the License for the specific language governing permissions and
16** limitations under the License.
17*/
18
James Dongf06bb982010-04-26 17:48:26 -070019//#define LOG_NDEBUG 0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080020#define LOG_TAG "CameraService"
21#include <utils/Log.h>
22
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070023#include <binder/IServiceManager.h>
24#include <binder/IPCThreadState.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080025#include <utils/String16.h>
26#include <utils/Errors.h>
Mathias Agopianc5b2c0b2009-05-19 19:08:10 -070027#include <binder/MemoryBase.h>
28#include <binder/MemoryHeapBase.h>
Mathias Agopian9cce3252010-02-09 17:46:37 -080029#include <camera/ICameraService.h>
30#include <surfaceflinger/ISurface.h>
31#include <ui/Overlay.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080032
Mathias Agopian54ed4f62010-02-16 17:33:37 -080033#include <hardware/hardware.h>
34
Jason Sams78b877e2009-03-24 20:21:36 -070035#include <media/mediaplayer.h>
36#include <media/AudioSystem.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080037#include "CameraService.h"
38
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +080039#include <cutils/atomic.h>
Eric Laurentcbcb00e2009-03-27 16:27:16 -070040
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080041namespace android {
42
43extern "C" {
44#include <stdio.h>
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <pthread.h>
Chih-Chung Changd98c5162009-06-22 16:03:41 +080049#include <signal.h>
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080050}
51
52// When you enable this, as well as DEBUG_REFS=1 and
53// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
54// references to the CameraService::Client in order to catch the case where the
55// client is being destroyed while a callback from the CameraHardwareInterface
56// is outstanding. This is a serious bug because if we make another call into
57// CameraHardwreInterface that itself triggers a callback, we will deadlock.
58
59#define DEBUG_CLIENT_REFERENCES 0
60
61#define PICTURE_TIMEOUT seconds(5)
62
63#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
64#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
65#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
Benny Wong4c8fb0a2009-08-12 12:01:27 -050066#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080067
68#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
69static int debug_frame_cnt;
70#endif
71
Chih-Chung Changd98c5162009-06-22 16:03:41 +080072static int getCallingPid() {
73 return IPCThreadState::self()->getCallingPid();
74}
75
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080076// ----------------------------------------------------------------------------
77
78void CameraService::instantiate() {
79 defaultServiceManager()->addService(
80 String16("media.camera"), new CameraService());
81}
82
83// ----------------------------------------------------------------------------
84
85CameraService::CameraService() :
86 BnCameraService()
87{
88 LOGI("CameraService started: pid=%d", getpid());
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +080089 mUsers = 0;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -080090}
91
92CameraService::~CameraService()
93{
94 if (mClient != 0) {
95 LOGE("mClient was still connected in destructor!");
96 }
97}
98
99sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
100{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800101 int callingPid = getCallingPid();
Joe Onorato51632e82010-01-07 21:48:32 -0500102 LOGV("CameraService::connect E (pid %d, client %p)", callingPid,
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800103 cameraClient->asBinder().get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800104
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800105 Mutex::Autolock lock(mServiceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800106 sp<Client> client;
107 if (mClient != 0) {
108 sp<Client> currentClient = mClient.promote();
109 if (currentClient != 0) {
110 sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
111 if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800112 // This is the same client reconnecting...
Joe Onorato51632e82010-01-07 21:48:32 -0500113 LOGV("CameraService::connect X (pid %d, same client %p) is reconnecting...",
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800114 callingPid, cameraClient->asBinder().get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800115 return currentClient;
116 } else {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800117 // It's another client... reject it
Joe Onorato51632e82010-01-07 21:48:32 -0500118 LOGV("CameraService::connect X (pid %d, new client %p) rejected. "
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800119 "(old pid %d, old client %p)",
120 callingPid, cameraClient->asBinder().get(),
121 currentClient->mClientPid, currentCameraClient->asBinder().get());
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800122 if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
Joe Onorato51632e82010-01-07 21:48:32 -0500123 LOGV("The old client is dead!");
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800124 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800125 return client;
126 }
127 } else {
128 // can't promote, the previous client has died...
Joe Onorato51632e82010-01-07 21:48:32 -0500129 LOGV("New client (pid %d) connecting, old reference was dangling...",
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800130 callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800131 mClient.clear();
132 }
133 }
134
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800135 if (mUsers > 0) {
Joe Onorato51632e82010-01-07 21:48:32 -0500136 LOGV("Still have client, rejected");
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800137 return client;
138 }
139
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800140 // create a new Client object
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800141 client = new Client(this, cameraClient, callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800142 mClient = client;
143#if DEBUG_CLIENT_REFERENCES
144 // Enable tracking for this object, and track increments and decrements of
145 // the refcount.
146 client->trackMe(true, true);
147#endif
Joe Onorato51632e82010-01-07 21:48:32 -0500148 LOGV("CameraService::connect X");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800149 return client;
150}
151
152void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
153{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800154 int callingPid = getCallingPid();
155
156 // Declare this outside the lock to make absolutely sure the
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800157 // destructor won't be called with the lock held.
158 sp<Client> client;
159
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800160 Mutex::Autolock lock(mServiceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800161
162 if (mClient == 0) {
163 // This happens when we have already disconnected.
Joe Onorato51632e82010-01-07 21:48:32 -0500164 LOGV("removeClient (pid %d): already disconnected", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800165 return;
166 }
167
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800168 // Promote mClient. It can fail if we are called from this path:
169 // Client::~Client() -> disconnect() -> removeClient().
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800170 client = mClient.promote();
171 if (client == 0) {
Joe Onorato51632e82010-01-07 21:48:32 -0500172 LOGV("removeClient (pid %d): no more strong reference", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800173 mClient.clear();
174 return;
175 }
176
177 if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
178 // ugh! that's not our client!!
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800179 LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800180 } else {
181 // okay, good, forget about mClient
182 mClient.clear();
183 }
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800184
Joe Onorato51632e82010-01-07 21:48:32 -0500185 LOGV("removeClient (pid %d) done", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800186}
187
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800188// The reason we need this count is a new CameraService::connect() request may
189// come in while the previous Client's destructor has not been run or is still
190// running. If the last strong reference of the previous Client is gone but
191// destructor has not been run, we should not allow the new Client to be created
192// because we need to wait for the previous Client to tear down the hardware
193// first.
194void CameraService::incUsers() {
195 android_atomic_inc(&mUsers);
196}
197
198void CameraService::decUsers() {
199 android_atomic_dec(&mUsers);
200}
201
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700202static sp<MediaPlayer> newMediaPlayer(const char *file)
Jason Sams78b877e2009-03-24 20:21:36 -0700203{
204 sp<MediaPlayer> mp = new MediaPlayer();
Andreas Huberd4461e72010-01-28 11:19:57 -0800205 if (mp->setDataSource(file, NULL /* headers */) == NO_ERROR) {
Eric Laurent9d91ad52009-07-17 12:17:14 -0700206 mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
Jason Sams78b877e2009-03-24 20:21:36 -0700207 mp->prepare();
208 } else {
209 mp.clear();
210 LOGE("Failed to load CameraService sounds.");
211 }
212 return mp;
213}
214
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800215CameraService::Client::Client(const sp<CameraService>& cameraService,
216 const sp<ICameraClient>& cameraClient, pid_t clientPid)
217{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800218 int callingPid = getCallingPid();
Joe Onorato51632e82010-01-07 21:48:32 -0500219 LOGV("Client::Client E (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800220 mCameraService = cameraService;
221 mCameraClient = cameraClient;
222 mClientPid = clientPid;
223 mHardware = openCameraHardware();
224 mUseOverlay = mHardware->useOverlay();
225
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500226 mHardware->setCallbacks(notifyCallback,
227 dataCallback,
228 dataCallbackTimestamp,
229 mCameraService.get());
230
231 // Enable zoom, error, and focus messages by default
232 mHardware->enableMsgType(CAMERA_MSG_ERROR |
233 CAMERA_MSG_ZOOM |
234 CAMERA_MSG_FOCUS);
235
Jason Sams78b877e2009-03-24 20:21:36 -0700236 mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
237 mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
Benny Wong71f77152009-07-15 18:44:27 -0500238 mOverlayW = 0;
239 mOverlayH = 0;
Jason Sams78b877e2009-03-24 20:21:36 -0700240
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800241 // Callback is disabled by default
242 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800243 mOrientation = 0;
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800244 cameraService->incUsers();
Joe Onorato51632e82010-01-07 21:48:32 -0500245 LOGV("Client::Client X (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800246}
247
248status_t CameraService::Client::checkPid()
249{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800250 int callingPid = getCallingPid();
James Dongf06bb982010-04-26 17:48:26 -0700251 if (mClientPid == callingPid || callingPid == getpid()) return NO_ERROR;
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800252 LOGW("Attempt to use locked camera (client %p) from different process "
253 " (old pid %d, new pid %d)",
254 getCameraClient()->asBinder().get(), mClientPid, callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800255 return -EBUSY;
256}
257
258status_t CameraService::Client::lock()
259{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800260 int callingPid = getCallingPid();
Joe Onorato51632e82010-01-07 21:48:32 -0500261 LOGV("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800262 Mutex::Autolock _l(mLock);
263 // lock camera to this client if the the camera is unlocked
264 if (mClientPid == 0) {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800265 mClientPid = callingPid;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800266 return NO_ERROR;
267 }
268 // returns NO_ERROR if the client already owns the camera, -EBUSY otherwise
269 return checkPid();
270}
271
272status_t CameraService::Client::unlock()
273{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800274 int callingPid = getCallingPid();
Joe Onorato51632e82010-01-07 21:48:32 -0500275 LOGV("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800276 Mutex::Autolock _l(mLock);
277 // allow anyone to use camera
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800278 status_t result = checkPid();
James Dong0ae13e32009-04-20 19:35:28 -0700279 if (result == NO_ERROR) {
280 mClientPid = 0;
Joe Onorato51632e82010-01-07 21:48:32 -0500281 LOGV("clear mCameraClient (pid %d)", callingPid);
James Dong0ae13e32009-04-20 19:35:28 -0700282 // we need to remove the reference so that when app goes
283 // away, the reference count goes to 0.
284 mCameraClient.clear();
285 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800286 return result;
287}
288
289status_t CameraService::Client::connect(const sp<ICameraClient>& client)
290{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800291 int callingPid = getCallingPid();
292
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800293 // connect a new process to the camera
Joe Onorato51632e82010-01-07 21:48:32 -0500294 LOGV("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800295
296 // I hate this hack, but things get really ugly when the media recorder
297 // service is handing back the camera to the app. The ICameraClient
298 // destructor will be called during the same IPC, making it look like
299 // the remote client is trying to disconnect. This hack temporarily
300 // sets the mClientPid to an invalid pid to prevent the hardware from
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800301 // being torn down.
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800302 {
303
304 // hold a reference to the old client or we will deadlock if the client is
305 // in the same process and we hold the lock when we remove the reference
306 sp<ICameraClient> oldClient;
307 {
308 Mutex::Autolock _l(mLock);
Chih-Chung Chang34e5a152009-06-09 13:56:44 +0800309 if (mClientPid != 0 && checkPid() != NO_ERROR) {
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800310 LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
311 mClientPid, callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800312 return -EBUSY;
313 }
314 oldClient = mCameraClient;
315
316 // did the client actually change?
Dave Sparks393eb792009-10-15 10:02:22 -0700317 if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
Joe Onorato51632e82010-01-07 21:48:32 -0500318 LOGV("Connect to the same client");
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800319 return NO_ERROR;
320 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800321
322 mCameraClient = client;
323 mClientPid = -1;
324 mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
Joe Onorato51632e82010-01-07 21:48:32 -0500325 LOGV("Connect to the new client (pid %d, client %p)",
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800326 callingPid, mCameraClient->asBinder().get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800327 }
328
329 }
330 // the old client destructor is called when oldClient goes out of scope
331 // now we set the new PID to lock the interface again
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800332 mClientPid = callingPid;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800333
334 return NO_ERROR;
335}
336
337#if HAVE_ANDROID_OS
338static void *unregister_surface(void *arg)
339{
340 ISurface *surface = (ISurface *)arg;
341 surface->unregisterBuffers();
342 IPCThreadState::self()->flushCommands();
343 return NULL;
344}
345#endif
346
347CameraService::Client::~Client()
348{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800349 int callingPid = getCallingPid();
350
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800351 // tear down client
Joe Onorato51632e82010-01-07 21:48:32 -0500352 LOGV("Client::~Client E (pid %d, client %p)",
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800353 callingPid, getCameraClient()->asBinder().get());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800354 if (mSurface != 0 && !mUseOverlay) {
355#if HAVE_ANDROID_OS
356 pthread_t thr;
357 // We unregister the buffers in a different thread because binder does
358 // not let us make sychronous transactions in a binder destructor (that
359 // is, upon our reaching a refcount of zero.)
360 pthread_create(&thr, NULL,
361 unregister_surface,
362 mSurface.get());
363 pthread_join(thr, NULL);
364#else
365 mSurface->unregisterBuffers();
366#endif
367 }
368
Jason Sams9e431ac2009-03-24 20:36:57 -0700369 if (mMediaPlayerBeep.get() != NULL) {
370 mMediaPlayerBeep->disconnect();
371 mMediaPlayerBeep.clear();
372 }
373 if (mMediaPlayerClick.get() != NULL) {
374 mMediaPlayerClick->disconnect();
375 mMediaPlayerClick.clear();
376 }
Jason Sams78b877e2009-03-24 20:21:36 -0700377
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800378 // make sure we tear down the hardware
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800379 mClientPid = callingPid;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800380 disconnect();
Joe Onorato51632e82010-01-07 21:48:32 -0500381 LOGV("Client::~Client X (pid %d)", mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800382}
383
384void CameraService::Client::disconnect()
385{
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800386 int callingPid = getCallingPid();
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800387
Joe Onorato51632e82010-01-07 21:48:32 -0500388 LOGV("Client::disconnect() E (pid %d client %p)",
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800389 callingPid, getCameraClient()->asBinder().get());
390
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800391 Mutex::Autolock lock(mLock);
392 if (mClientPid <= 0) {
Joe Onorato51632e82010-01-07 21:48:32 -0500393 LOGV("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800394 return;
395 }
396 if (checkPid() != NO_ERROR) {
Joe Onorato51632e82010-01-07 21:48:32 -0500397 LOGV("Different client - don't disconnect");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800398 return;
399 }
400
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800401 // Make sure disconnect() is done once and once only, whether it is called
402 // from the user directly, or called by the destructor.
403 if (mHardware == 0) return;
404
Joe Onorato51632e82010-01-07 21:48:32 -0500405 LOGV("hardware teardown");
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800406 // Before destroying mHardware, we must make sure it's in the
407 // idle state.
408 mHardware->stopPreview();
409 // Cancel all picture callbacks.
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500410 mHardware->disableMsgType(CAMERA_MSG_SHUTTER |
411 CAMERA_MSG_POSTVIEW_FRAME |
412 CAMERA_MSG_RAW_IMAGE |
413 CAMERA_MSG_COMPRESSED_IMAGE);
414 mHardware->cancelPicture();
415 // Turn off remaining messages.
416 mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800417 // Release the hardware resources.
418 mHardware->release();
Benny Wong71f77152009-07-15 18:44:27 -0500419 // Release the held overlay resources.
420 if (mUseOverlay)
421 {
422 mOverlayRef = 0;
423 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800424 mHardware.clear();
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800425
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800426 mCameraService->removeClient(mCameraClient);
Chih-Chung Changfa89f9f2009-06-24 13:44:37 +0800427 mCameraService->decUsers();
428
Joe Onorato51632e82010-01-07 21:48:32 -0500429 LOGV("Client::disconnect() X (pid %d)", callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800430}
431
432// pass the buffered ISurface to the camera service
433status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
434{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800435 LOGV("setPreviewDisplay(%p) (pid %d)",
Wu-cheng Li988fb622009-06-23 23:37:36 +0800436 ((surface == NULL) ? NULL : surface.get()), getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800437 Mutex::Autolock lock(mLock);
438 status_t result = checkPid();
439 if (result != NO_ERROR) return result;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800440
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800441 Mutex::Autolock surfaceLock(mSurfaceLock);
Wu-cheng Li988fb622009-06-23 23:37:36 +0800442 result = NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800443 // asBinder() is safe on NULL (returns NULL)
444 if (surface->asBinder() != mSurface->asBinder()) {
Benny Wong71f77152009-07-15 18:44:27 -0500445 if (mSurface != 0) {
Dave Sparkse7e93f92010-01-04 08:55:04 -0800446 LOGV("clearing old preview surface %p", mSurface.get());
Benny Wong71f77152009-07-15 18:44:27 -0500447 if ( !mUseOverlay)
448 {
449 mSurface->unregisterBuffers();
450 }
451 else
452 {
453 // Force the destruction of any previous overlay
454 sp<Overlay> dummy;
455 mHardware->setOverlay( dummy );
456 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800457 }
458 mSurface = surface;
Benny Wong71f77152009-07-15 18:44:27 -0500459 mOverlayRef = 0;
Wu-cheng Li988fb622009-06-23 23:37:36 +0800460 // If preview has been already started, set overlay or register preview
461 // buffers now.
462 if (mHardware->previewEnabled()) {
463 if (mUseOverlay) {
464 result = setOverlay();
465 } else if (mSurface != 0) {
466 result = registerPreviewBuffers();
467 }
468 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800469 }
Wu-cheng Li988fb622009-06-23 23:37:36 +0800470 return result;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800471}
472
473// set the preview callback flag to affect how the received frames from
474// preview are handled.
475void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
476{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800477 LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800478 Mutex::Autolock lock(mLock);
479 if (checkPid() != NO_ERROR) return;
480 mPreviewCallbackFlag = callback_flag;
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500481
482 if(mUseOverlay) {
483 if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)
484 mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
485 else
486 mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
487 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800488}
489
Wu-cheng Li988fb622009-06-23 23:37:36 +0800490// start preview mode
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800491status_t CameraService::Client::startCameraMode(camera_mode mode)
492{
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800493 int callingPid = getCallingPid();
494
Dave Sparkse7e93f92010-01-04 08:55:04 -0800495 LOGV("startCameraMode(%d) (pid %d)", mode, callingPid);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800496
497 /* we cannot call into mHardware with mLock held because
498 * mHardware has callbacks onto us which acquire this lock
499 */
500
501 Mutex::Autolock lock(mLock);
502 status_t result = checkPid();
503 if (result != NO_ERROR) return result;
504
505 if (mHardware == 0) {
506 LOGE("mHardware is NULL, returning.");
507 return INVALID_OPERATION;
508 }
509
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800510 switch(mode) {
511 case CAMERA_RECORDING_MODE:
Wu-cheng Li988fb622009-06-23 23:37:36 +0800512 if (mSurface == 0) {
513 LOGE("setPreviewDisplay must be called before startRecordingMode.");
514 return INVALID_OPERATION;
515 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800516 return startRecordingMode();
517
518 default: // CAMERA_PREVIEW_MODE
Wu-cheng Li988fb622009-06-23 23:37:36 +0800519 if (mSurface == 0) {
Dave Sparkse7e93f92010-01-04 08:55:04 -0800520 LOGV("mSurface is not set yet.");
Wu-cheng Li988fb622009-06-23 23:37:36 +0800521 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800522 return startPreviewMode();
523 }
524}
525
526status_t CameraService::Client::startRecordingMode()
527{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800528 LOGV("startRecordingMode (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800529
530 status_t ret = UNKNOWN_ERROR;
531
532 // if preview has not been started, start preview first
533 if (!mHardware->previewEnabled()) {
534 ret = startPreviewMode();
535 if (ret != NO_ERROR) {
536 return ret;
537 }
538 }
539
540 // if recording has been enabled, nothing needs to be done
541 if (mHardware->recordingEnabled()) {
542 return NO_ERROR;
543 }
544
545 // start recording mode
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500546 ret = mHardware->startRecording();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800547 if (ret != NO_ERROR) {
548 LOGE("mHardware->startRecording() failed with status %d", ret);
549 }
550 return ret;
551}
552
Wu-cheng Li988fb622009-06-23 23:37:36 +0800553status_t CameraService::Client::setOverlay()
554{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800555 LOGV("setOverlay");
Wu-cheng Li988fb622009-06-23 23:37:36 +0800556 int w, h;
557 CameraParameters params(mHardware->getParameters());
558 params.getPreviewSize(&w, &h);
559
Benny Wong71f77152009-07-15 18:44:27 -0500560 if ( w != mOverlayW || h != mOverlayH )
561 {
562 // Force the destruction of any previous overlay
563 sp<Overlay> dummy;
564 mHardware->setOverlay( dummy );
565 mOverlayRef = 0;
566 }
567
Wu-cheng Li988fb622009-06-23 23:37:36 +0800568 status_t ret = NO_ERROR;
569 if (mSurface != 0) {
Benny Wong71f77152009-07-15 18:44:27 -0500570 if (mOverlayRef.get() == NULL) {
Dave Sparks587f7832009-10-07 19:18:20 -0700571
572 // FIXME:
573 // Surfaceflinger may hold onto the previous overlay reference for some
574 // time after we try to destroy it. retry a few times. In the future, we
575 // should make the destroy call block, or possibly specify that we can
576 // wait in the createOverlay call if the previous overlay is in the
577 // process of being destroyed.
578 for (int retry = 0; retry < 50; ++retry) {
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800579 mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
580 mOrientation);
Dave Sparks587f7832009-10-07 19:18:20 -0700581 if (mOverlayRef != NULL) break;
Dave Sparkse7e93f92010-01-04 08:55:04 -0800582 LOGW("Overlay create failed - retrying");
Dave Sparks587f7832009-10-07 19:18:20 -0700583 usleep(20000);
584 }
Benny Wong71f77152009-07-15 18:44:27 -0500585 if ( mOverlayRef.get() == NULL )
586 {
587 LOGE("Overlay Creation Failed!");
588 return -EINVAL;
589 }
590 ret = mHardware->setOverlay(new Overlay(mOverlayRef));
591 }
Wu-cheng Li988fb622009-06-23 23:37:36 +0800592 } else {
593 ret = mHardware->setOverlay(NULL);
594 }
595 if (ret != NO_ERROR) {
596 LOGE("mHardware->setOverlay() failed with status %d\n", ret);
597 }
Benny Wong71f77152009-07-15 18:44:27 -0500598
599 mOverlayW = w;
600 mOverlayH = h;
601
Wu-cheng Li988fb622009-06-23 23:37:36 +0800602 return ret;
603}
604
605status_t CameraService::Client::registerPreviewBuffers()
606{
607 int w, h;
608 CameraParameters params(mHardware->getParameters());
609 params.getPreviewSize(&w, &h);
610
Mathias Agopian29d17422010-02-16 19:42:32 -0800611 // don't use a hardcoded format here
Wu-cheng Li988fb622009-06-23 23:37:36 +0800612 ISurface::BufferHeap buffers(w, h, w, h,
Mathias Agopian29d17422010-02-16 19:42:32 -0800613 HAL_PIXEL_FORMAT_YCrCb_420_SP,
Chih-Chung Chang52e72002010-01-21 17:31:06 -0800614 mOrientation,
Wu-cheng Li988fb622009-06-23 23:37:36 +0800615 0,
616 mHardware->getPreviewHeap());
617
618 status_t ret = mSurface->registerBuffers(buffers);
619 if (ret != NO_ERROR) {
620 LOGE("registerBuffers failed with status %d", ret);
621 }
622 return ret;
623}
624
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800625status_t CameraService::Client::startPreviewMode()
626{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800627 LOGV("startPreviewMode (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800628
629 // if preview has been enabled, nothing needs to be done
630 if (mHardware->previewEnabled()) {
631 return NO_ERROR;
632 }
633
634 // start preview mode
635#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
636 debug_frame_cnt = 0;
637#endif
Wu-cheng Li988fb622009-06-23 23:37:36 +0800638 status_t ret = NO_ERROR;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800639
640 if (mUseOverlay) {
Wu-cheng Li988fb622009-06-23 23:37:36 +0800641 // If preview display has been set, set overlay now.
642 if (mSurface != 0) {
643 ret = setOverlay();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800644 }
Wu-cheng Li988fb622009-06-23 23:37:36 +0800645 if (ret != NO_ERROR) return ret;
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500646 ret = mHardware->startPreview();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800647 } else {
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500648 mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
649 ret = mHardware->startPreview();
Wu-cheng Li988fb622009-06-23 23:37:36 +0800650 if (ret != NO_ERROR) return ret;
651 // If preview display has been set, register preview buffers now.
652 if (mSurface != 0) {
653 // Unregister here because the surface registered with raw heap.
654 mSurface->unregisterBuffers();
655 ret = registerPreviewBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800656 }
657 }
658 return ret;
659}
660
661status_t CameraService::Client::startPreview()
662{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800663 LOGV("startPreview (pid %d)", getCallingPid());
Wu-cheng Lie6a550d2009-09-28 16:14:58 -0700664
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800665 return startCameraMode(CAMERA_PREVIEW_MODE);
666}
667
668status_t CameraService::Client::startRecording()
669{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800670 LOGV("startRecording (pid %d)", getCallingPid());
Chih-Chung Changd98c5162009-06-22 16:03:41 +0800671
Jason Sams78b877e2009-03-24 20:21:36 -0700672 if (mMediaPlayerBeep.get() != NULL) {
Eric Laurent059b4132009-11-27 05:07:55 -0800673 // do not play record jingle if stream volume is 0
674 // (typically because ringer mode is silent).
675 int index;
676 AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
677 if (index != 0) {
678 mMediaPlayerBeep->seekTo(0);
679 mMediaPlayerBeep->start();
680 }
Jason Sams78b877e2009-03-24 20:21:36 -0700681 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500682
683 mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
684
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800685 return startCameraMode(CAMERA_RECORDING_MODE);
686}
687
688// stop preview mode
689void CameraService::Client::stopPreview()
690{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800691 LOGV("stopPreview (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800692
Dave Sparksff0f38e2009-11-10 17:08:08 -0800693 // hold main lock during state transition
694 {
695 Mutex::Autolock lock(mLock);
696 if (checkPid() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800697
Dave Sparksff0f38e2009-11-10 17:08:08 -0800698 if (mHardware == 0) {
699 LOGE("mHardware is NULL, returning.");
700 return;
701 }
702
703 mHardware->stopPreview();
704 mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
Dave Sparkse7e93f92010-01-04 08:55:04 -0800705 LOGV("stopPreview(), hardware stopped OK");
Dave Sparksff0f38e2009-11-10 17:08:08 -0800706
707 if (mSurface != 0 && !mUseOverlay) {
708 mSurface->unregisterBuffers();
709 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800710 }
711
Dave Sparksff0f38e2009-11-10 17:08:08 -0800712 // hold preview buffer lock
713 {
714 Mutex::Autolock lock(mPreviewLock);
715 mPreviewBuffer.clear();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800716 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800717}
718
719// stop recording mode
720void CameraService::Client::stopRecording()
721{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800722 LOGV("stopRecording (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800723
Dave Sparksff0f38e2009-11-10 17:08:08 -0800724 // hold main lock during state transition
725 {
726 Mutex::Autolock lock(mLock);
727 if (checkPid() != NO_ERROR) return;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800728
Dave Sparksff0f38e2009-11-10 17:08:08 -0800729 if (mHardware == 0) {
730 LOGE("mHardware is NULL, returning.");
731 return;
732 }
733
734 if (mMediaPlayerBeep.get() != NULL) {
735 mMediaPlayerBeep->seekTo(0);
736 mMediaPlayerBeep->start();
737 }
738
739 mHardware->stopRecording();
740 mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
Dave Sparkse7e93f92010-01-04 08:55:04 -0800741 LOGV("stopRecording(), hardware stopped OK");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800742 }
743
Dave Sparksff0f38e2009-11-10 17:08:08 -0800744 // hold preview buffer lock
745 {
746 Mutex::Autolock lock(mPreviewLock);
747 mPreviewBuffer.clear();
Jason Sams78b877e2009-03-24 20:21:36 -0700748 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800749}
750
751// release a recording frame
752void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
753{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800754 Mutex::Autolock lock(mLock);
755 if (checkPid() != NO_ERROR) return;
756
757 if (mHardware == 0) {
758 LOGE("mHardware is NULL, returning.");
759 return;
760 }
761
762 mHardware->releaseRecordingFrame(mem);
763}
764
765bool CameraService::Client::previewEnabled()
766{
767 Mutex::Autolock lock(mLock);
768 if (mHardware == 0) return false;
769 return mHardware->previewEnabled();
770}
771
772bool CameraService::Client::recordingEnabled()
773{
774 Mutex::Autolock lock(mLock);
775 if (mHardware == 0) return false;
776 return mHardware->recordingEnabled();
777}
778
779// Safely retrieves a strong pointer to the client during a hardware callback.
780sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
781{
782 sp<Client> client = 0;
783 CameraService *service = static_cast<CameraService*>(user);
784 if (service != NULL) {
Chih-Chung Changd2d6bc72009-06-24 19:59:31 +0800785 Mutex::Autolock ourLock(service->mServiceLock);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800786 if (service->mClient != 0) {
787 client = service->mClient.promote();
788 if (client == 0) {
789 LOGE("getClientFromCookie: client appears to have died");
790 service->mClient.clear();
791 }
792 } else {
793 LOGE("getClientFromCookie: got callback but client was NULL");
794 }
795 }
796 return client;
797}
798
799
800#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
801 DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
802 DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
803static void dump_to_file(const char *fname,
804 uint8_t *buf, uint32_t size)
805{
806 int nw, cnt = 0;
807 uint32_t written = 0;
808
Joe Onorato51632e82010-01-07 21:48:32 -0500809 LOGV("opening file [%s]\n", fname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800810 int fd = open(fname, O_RDWR | O_CREAT);
811 if (fd < 0) {
812 LOGE("failed to create file [%s]: %s", fname, strerror(errno));
813 return;
814 }
815
Joe Onorato51632e82010-01-07 21:48:32 -0500816 LOGV("writing %d bytes to file [%s]\n", size, fname);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800817 while (written < size) {
818 nw = ::write(fd,
819 buf + written,
820 size - written);
821 if (nw < 0) {
822 LOGE("failed to write to file [%s]: %s",
823 fname, strerror(errno));
824 break;
825 }
826 written += nw;
827 cnt++;
828 }
Joe Onorato51632e82010-01-07 21:48:32 -0500829 LOGV("done writing %d bytes to file [%s] in %d passes\n",
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800830 size, fname, cnt);
831 ::close(fd);
832}
833#endif
834
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800835status_t CameraService::Client::autoFocus()
836{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800837 LOGV("autoFocus (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800838
839 Mutex::Autolock lock(mLock);
840 status_t result = checkPid();
841 if (result != NO_ERROR) return result;
842
843 if (mHardware == 0) {
844 LOGE("mHardware is NULL, returning.");
845 return INVALID_OPERATION;
846 }
847
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500848 return mHardware->autoFocus();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800849}
850
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800851status_t CameraService::Client::cancelAutoFocus()
852{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800853 LOGV("cancelAutoFocus (pid %d)", getCallingPid());
Chih-Chung Chang00900eb2009-09-15 14:51:56 +0800854
855 Mutex::Autolock lock(mLock);
856 status_t result = checkPid();
857 if (result != NO_ERROR) return result;
858
859 if (mHardware == 0) {
860 LOGE("mHardware is NULL, returning.");
861 return INVALID_OPERATION;
862 }
863
864 return mHardware->cancelAutoFocus();
865}
866
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800867// take a picture - image is returned in callback
868status_t CameraService::Client::takePicture()
869{
Dave Sparkse7e93f92010-01-04 08:55:04 -0800870 LOGV("takePicture (pid %d)", getCallingPid());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800871
872 Mutex::Autolock lock(mLock);
873 status_t result = checkPid();
874 if (result != NO_ERROR) return result;
875
876 if (mHardware == 0) {
877 LOGE("mHardware is NULL, returning.");
878 return INVALID_OPERATION;
879 }
880
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500881 mHardware->enableMsgType(CAMERA_MSG_SHUTTER |
882 CAMERA_MSG_POSTVIEW_FRAME |
883 CAMERA_MSG_RAW_IMAGE |
884 CAMERA_MSG_COMPRESSED_IMAGE);
885
886 return mHardware->takePicture();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800887}
888
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500889// snapshot taken
Wu-cheng Li986e0dc2009-10-23 17:39:46 +0800890void CameraService::Client::handleShutter(
891 image_rect_type *size // The width and height of yuv picture for
892 // registerBuffer. If this is NULL, use the picture
893 // size from parameters.
894)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800895{
Wu-cheng Liaab44b82009-03-24 20:39:09 -0700896 // Play shutter sound.
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500897 if (mMediaPlayerClick.get() != NULL) {
Eric Laurent059b4132009-11-27 05:07:55 -0800898 // do not play shutter sound if stream volume is 0
899 // (typically because ringer mode is silent).
900 int index;
901 AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
902 if (index != 0) {
903 mMediaPlayerClick->seekTo(0);
904 mMediaPlayerClick->start();
905 }
Wu-cheng Liaab44b82009-03-24 20:39:09 -0700906 }
907
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800908 // Screen goes black after the buffer is unregistered.
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500909 if (mSurface != 0 && !mUseOverlay) {
910 mSurface->unregisterBuffers();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800911 }
912
Dave Sparks393eb792009-10-15 10:02:22 -0700913 sp<ICameraClient> c = mCameraClient;
914 if (c != NULL) {
915 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
916 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500917 mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800918
919 // It takes some time before yuvPicture callback to be called.
920 // Register the buffer for raw image here to reduce latency.
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500921 if (mSurface != 0 && !mUseOverlay) {
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800922 int w, h;
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500923 CameraParameters params(mHardware->getParameters());
Wu-cheng Li986e0dc2009-10-23 17:39:46 +0800924 if (size == NULL) {
925 params.getPictureSize(&w, &h);
926 } else {
927 w = size->width;
928 h = size->height;
929 w &= ~1;
930 h &= ~1;
Dave Sparkse7e93f92010-01-04 08:55:04 -0800931 LOGV("Snapshot image width=%d, height=%d", w, h);
Wu-cheng Li986e0dc2009-10-23 17:39:46 +0800932 }
Mathias Agopian29d17422010-02-16 19:42:32 -0800933 // FIXME: don't use hardcoded format constants here
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800934 ISurface::BufferHeap buffers(w, h, w, h,
Mathias Agopian29d17422010-02-16 19:42:32 -0800935 HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
Mathias Agopian54ed4f62010-02-16 17:33:37 -0800936 mHardware->getRawHeap());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800937
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500938 mSurface->registerBuffers(buffers);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800939 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800940}
941
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500942// preview callback - frame buffer update
943void CameraService::Client::handlePreviewData(const sp<IMemory>& mem)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800944{
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500945 ssize_t offset;
946 size_t size;
947 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
948
949#if DEBUG_HEAP_LEAKS && 0 // debugging
950 if (gWeakHeap == NULL) {
951 if (gWeakHeap != heap) {
Dave Sparkse7e93f92010-01-04 08:55:04 -0800952 LOGV("SETTING PREVIEW HEAP");
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500953 heap->trackMe(true, true);
954 gWeakHeap = heap;
955 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800956 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500957#endif
958#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
959 {
960 if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
961 dump_to_file("/data/preview.yuv",
962 (uint8_t *)heap->base() + offset, size);
963 }
964 }
965#endif
966
967 if (!mUseOverlay)
968 {
969 Mutex::Autolock surfaceLock(mSurfaceLock);
970 if (mSurface != NULL) {
971 mSurface->postBuffer(offset);
972 }
973 }
974
Dave Sparks393eb792009-10-15 10:02:22 -0700975 // local copy of the callback flags
976 int flags = mPreviewCallbackFlag;
977
978 // is callback enabled?
979 if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500980 // If the enable bit is off, the copy-out and one-shot bits are ignored
981 LOGV("frame callback is diabled");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -0800982 return;
983 }
984
Dave Sparks393eb792009-10-15 10:02:22 -0700985 // hold a strong pointer to the client
986 sp<ICameraClient> c = mCameraClient;
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500987
Dave Sparks393eb792009-10-15 10:02:22 -0700988 // clear callback flags if no client or one-shot mode
989 if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
990 LOGV("Disable preview callback");
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500991 mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
992 FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
993 FRAME_CALLBACK_FLAG_ENABLE_MASK);
Dave Sparks393eb792009-10-15 10:02:22 -0700994 // TODO: Shouldn't we use this API for non-overlay hardware as well?
Benny Wong4c8fb0a2009-08-12 12:01:27 -0500995 if (mUseOverlay)
996 mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
997 }
Dave Sparks393eb792009-10-15 10:02:22 -0700998
999 // Is the received frame copied out or not?
1000 if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
1001 LOGV("frame is copied");
1002 copyFrameAndPostCopiedFrame(c, heap, offset, size);
1003 } else {
1004 LOGV("frame is forwarded");
1005 c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
1006 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001007}
1008
1009// picture callback - postview image ready
1010void CameraService::Client::handlePostview(const sp<IMemory>& mem)
1011{
1012#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only
1013 {
1014 ssize_t offset;
1015 size_t size;
1016 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1017 dump_to_file("/data/postview.yuv",
1018 (uint8_t *)heap->base() + offset, size);
1019 }
1020#endif
1021
Dave Sparks393eb792009-10-15 10:02:22 -07001022 sp<ICameraClient> c = mCameraClient;
1023 if (c != NULL) {
1024 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
1025 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001026 mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1027}
1028
1029// picture callback - raw image ready
1030void CameraService::Client::handleRawPicture(const sp<IMemory>& mem)
1031{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001032 ssize_t offset;
1033 size_t size;
1034 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1035#if DEBUG_HEAP_LEAKS && 0 // debugging
1036 gWeakHeap = heap; // debugging
1037#endif
1038
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001039 //LOGV("handleRawPicture(%d, %d)", offset, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001040#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
1041 dump_to_file("/data/photo.yuv",
1042 (uint8_t *)heap->base() + offset, size);
1043#endif
1044
1045 // Put the YUV version of the snapshot in the preview display.
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001046 if (mSurface != 0 && !mUseOverlay) {
1047 mSurface->postBuffer(offset);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001048 }
1049
Dave Sparks393eb792009-10-15 10:02:22 -07001050 sp<ICameraClient> c = mCameraClient;
1051 if (c != NULL) {
1052 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
1053 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001054 mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001055}
1056
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001057// picture callback - compressed picture ready
1058void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001059{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001060#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
1061 {
1062 ssize_t offset;
1063 size_t size;
1064 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1065 dump_to_file("/data/photo.jpg",
1066 (uint8_t *)heap->base() + offset, size);
1067 }
1068#endif
1069
Dave Sparks393eb792009-10-15 10:02:22 -07001070 sp<ICameraClient> c = mCameraClient;
1071 if (c != NULL) {
1072 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
1073 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001074 mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001075}
1076
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001077void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001078{
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001079 LOGV("notifyCallback(%d)", msgType);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001080
1081 sp<Client> client = getClientFromCookie(user);
1082 if (client == 0) {
1083 return;
1084 }
1085
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001086 switch (msgType) {
1087 case CAMERA_MSG_SHUTTER:
Wu-cheng Li986e0dc2009-10-23 17:39:46 +08001088 // ext1 is the dimension of the yuv picture.
1089 client->handleShutter((image_rect_type *)ext1);
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001090 break;
1091 default:
Dave Sparks393eb792009-10-15 10:02:22 -07001092 sp<ICameraClient> c = client->mCameraClient;
1093 if (c != NULL) {
1094 c->notifyCallback(msgType, ext1, ext2);
1095 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001096 break;
1097 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001098
1099#if DEBUG_CLIENT_REFERENCES
1100 if (client->getStrongCount() == 1) {
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001101 LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!");
1102 client->printRefs();
1103 }
1104#endif
1105}
1106
1107void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)
1108{
1109 LOGV("dataCallback(%d)", msgType);
1110
1111 sp<Client> client = getClientFromCookie(user);
1112 if (client == 0) {
1113 return;
1114 }
1115
Dave Sparks393eb792009-10-15 10:02:22 -07001116 sp<ICameraClient> c = client->mCameraClient;
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001117 if (dataPtr == NULL) {
1118 LOGE("Null data returned in data callback");
Dave Sparks393eb792009-10-15 10:02:22 -07001119 if (c != NULL) {
1120 c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1121 c->dataCallback(msgType, NULL);
1122 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001123 return;
1124 }
1125
1126 switch (msgType) {
1127 case CAMERA_MSG_PREVIEW_FRAME:
1128 client->handlePreviewData(dataPtr);
1129 break;
1130 case CAMERA_MSG_POSTVIEW_FRAME:
1131 client->handlePostview(dataPtr);
1132 break;
1133 case CAMERA_MSG_RAW_IMAGE:
1134 client->handleRawPicture(dataPtr);
1135 break;
1136 case CAMERA_MSG_COMPRESSED_IMAGE:
1137 client->handleCompressedPicture(dataPtr);
1138 break;
1139 default:
Dave Sparks393eb792009-10-15 10:02:22 -07001140 if (c != NULL) {
1141 c->dataCallback(msgType, dataPtr);
1142 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001143 break;
1144 }
1145
1146#if DEBUG_CLIENT_REFERENCES
1147 if (client->getStrongCount() == 1) {
1148 LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
1149 client->printRefs();
1150 }
1151#endif
1152}
1153
1154void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
1155 const sp<IMemory>& dataPtr, void* user)
1156{
1157 LOGV("dataCallbackTimestamp(%d)", msgType);
1158
1159 sp<Client> client = getClientFromCookie(user);
1160 if (client == 0) {
1161 return;
1162 }
Dave Sparks393eb792009-10-15 10:02:22 -07001163 sp<ICameraClient> c = client->mCameraClient;
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001164
1165 if (dataPtr == NULL) {
1166 LOGE("Null data returned in data with timestamp callback");
Dave Sparks393eb792009-10-15 10:02:22 -07001167 if (c != NULL) {
1168 c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1169 c->dataCallbackTimestamp(0, msgType, NULL);
1170 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001171 return;
1172 }
1173
Dave Sparks393eb792009-10-15 10:02:22 -07001174 if (c != NULL) {
1175 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1176 }
Benny Wong4c8fb0a2009-08-12 12:01:27 -05001177
1178#if DEBUG_CLIENT_REFERENCES
1179 if (client->getStrongCount() == 1) {
1180 LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!");
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001181 client->printRefs();
1182 }
1183#endif
1184}
1185
1186// set preview/capture parameters - key/value pairs
1187status_t CameraService::Client::setParameters(const String8& params)
1188{
Joe Onorato51632e82010-01-07 21:48:32 -05001189 LOGV("setParameters(%s)", params.string());
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001190
1191 Mutex::Autolock lock(mLock);
1192 status_t result = checkPid();
1193 if (result != NO_ERROR) return result;
1194
1195 if (mHardware == 0) {
1196 LOGE("mHardware is NULL, returning.");
1197 return INVALID_OPERATION;
1198 }
1199
1200 CameraParameters p(params);
Chih-Chung Chang52e72002010-01-21 17:31:06 -08001201
James Dong102f7772009-09-13 17:10:24 -07001202 return mHardware->setParameters(p);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001203}
1204
1205// get preview/capture parameters - key/value pairs
1206String8 CameraService::Client::getParameters() const
1207{
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001208 Mutex::Autolock lock(mLock);
1209
1210 if (mHardware == 0) {
1211 LOGE("mHardware is NULL, returning.");
1212 return String8();
1213 }
1214
Wu-cheng Li81d763f2009-04-22 16:21:26 +08001215 String8 params(mHardware->getParameters().flatten());
Joe Onorato51632e82010-01-07 21:48:32 -05001216 LOGV("getParameters(%s)", params.string());
Wu-cheng Li81d763f2009-04-22 16:21:26 +08001217 return params;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001218}
1219
Wu-cheng Lie6a550d2009-09-28 16:14:58 -07001220status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
1221{
Dave Sparkse7e93f92010-01-04 08:55:04 -08001222 LOGV("sendCommand (pid %d)", getCallingPid());
Wu-cheng Lie6a550d2009-09-28 16:14:58 -07001223 Mutex::Autolock lock(mLock);
1224 status_t result = checkPid();
1225 if (result != NO_ERROR) return result;
1226
Chih-Chung Changf091e832010-01-22 17:49:48 -08001227 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
1228 // The orientation cannot be set during preview.
1229 if (mHardware->previewEnabled()) {
1230 return INVALID_OPERATION;
1231 }
1232 switch (arg1) {
1233 case 0:
1234 mOrientation = ISurface::BufferHeap::ROT_0;
1235 break;
1236 case 90:
1237 mOrientation = ISurface::BufferHeap::ROT_90;
1238 break;
1239 case 180:
1240 mOrientation = ISurface::BufferHeap::ROT_180;
1241 break;
1242 case 270:
1243 mOrientation = ISurface::BufferHeap::ROT_270;
1244 break;
1245 default:
1246 return BAD_VALUE;
1247 }
1248 return OK;
1249 }
1250
Wu-cheng Lie6a550d2009-09-28 16:14:58 -07001251 if (mHardware == 0) {
1252 LOGE("mHardware is NULL, returning.");
1253 return INVALID_OPERATION;
1254 }
1255
1256 return mHardware->sendCommand(cmd, arg1, arg2);
1257}
1258
Dave Sparks393eb792009-10-15 10:02:22 -07001259void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
1260 const sp<IMemoryHeap>& heap, size_t offset, size_t size)
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001261{
1262 LOGV("copyFrameAndPostCopiedFrame");
1263 // It is necessary to copy out of pmem before sending this to
1264 // the callback. For efficiency, reuse the same MemoryHeapBase
1265 // provided it's big enough. Don't allocate the memory or
1266 // perform the copy if there's no callback.
Dave Sparks23c21ba2009-11-06 11:47:13 -08001267
Dave Sparksff0f38e2009-11-10 17:08:08 -08001268 // hold the preview lock while we grab a reference to the preview buffer
Dave Sparks23c21ba2009-11-06 11:47:13 -08001269 sp<MemoryHeapBase> previewBuffer;
1270 {
Dave Sparksff0f38e2009-11-10 17:08:08 -08001271 Mutex::Autolock lock(mPreviewLock);
Dave Sparks23c21ba2009-11-06 11:47:13 -08001272 if (mPreviewBuffer == 0) {
1273 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1274 } else if (size > mPreviewBuffer->virtualSize()) {
1275 mPreviewBuffer.clear();
1276 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1277 }
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001278 if (mPreviewBuffer == 0) {
1279 LOGE("failed to allocate space for preview buffer");
1280 return;
1281 }
Dave Sparks23c21ba2009-11-06 11:47:13 -08001282 previewBuffer = mPreviewBuffer;
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001283 }
Dave Sparks23c21ba2009-11-06 11:47:13 -08001284 memcpy(previewBuffer->base(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001285 (uint8_t *)heap->base() + offset, size);
1286
Dave Sparks23c21ba2009-11-06 11:47:13 -08001287 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001288 if (frame == 0) {
1289 LOGE("failed to allocate space for frame callback");
1290 return;
1291 }
Dave Sparks393eb792009-10-15 10:02:22 -07001292 client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001293}
1294
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001295static const int kDumpLockRetries = 50;
1296static const int kDumpLockSleep = 60000;
1297
1298static bool tryLock(Mutex& mutex)
1299{
1300 bool locked = false;
1301 for (int i = 0; i < kDumpLockRetries; ++i) {
1302 if (mutex.tryLock() == NO_ERROR) {
1303 locked = true;
1304 break;
1305 }
1306 usleep(kDumpLockSleep);
1307 }
1308 return locked;
1309}
1310
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001311status_t CameraService::dump(int fd, const Vector<String16>& args)
1312{
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001313 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1314
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001315 const size_t SIZE = 256;
1316 char buffer[SIZE];
1317 String8 result;
1318 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1319 snprintf(buffer, SIZE, "Permission Denial: "
1320 "can't dump CameraService from pid=%d, uid=%d\n",
Chih-Chung Changd98c5162009-06-22 16:03:41 +08001321 getCallingPid(),
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001322 IPCThreadState::self()->getCallingUid());
1323 result.append(buffer);
1324 write(fd, result.string(), result.size());
1325 } else {
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001326 bool locked = tryLock(mServiceLock);
1327 // failed to lock - CameraService is probably deadlocked
1328 if (!locked) {
1329 String8 result(kDeadlockedString);
1330 write(fd, result.string(), result.size());
1331 }
1332
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001333 if (mClient != 0) {
1334 sp<Client> currentClient = mClient.promote();
1335 sprintf(buffer, "Client (%p) PID: %d\n",
1336 currentClient->getCameraClient()->asBinder().get(),
1337 currentClient->mClientPid);
1338 result.append(buffer);
1339 write(fd, result.string(), result.size());
1340 currentClient->mHardware->dump(fd, args);
1341 } else {
1342 result.append("No camera client yet.\n");
1343 write(fd, result.string(), result.size());
1344 }
Chih-Chung Changf0252f22010-03-05 11:33:03 -08001345
1346 if (locked) mServiceLock.unlock();
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001347 }
1348 return NO_ERROR;
1349}
1350
1351
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001352status_t CameraService::onTransact(
1353 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
1354{
1355 // permission checks...
1356 switch (code) {
1357 case BnCameraService::CONNECT:
1358 IPCThreadState* ipc = IPCThreadState::self();
1359 const int pid = ipc->getCallingPid();
1360 const int self_pid = getpid();
1361 if (pid != self_pid) {
1362 // we're called from a different process, do the real check
1363 if (!checkCallingPermission(
1364 String16("android.permission.CAMERA")))
1365 {
1366 const int uid = ipc->getCallingUid();
1367 LOGE("Permission Denial: "
1368 "can't use the camera pid=%d, uid=%d", pid, uid);
1369 return PERMISSION_DENIED;
1370 }
1371 }
1372 break;
1373 }
1374
1375 status_t err = BnCameraService::onTransact(code, data, reply, flags);
1376
Dave Sparks998b3292009-05-20 20:02:59 -07001377#if DEBUG_HEAP_LEAKS
Joe Onorato51632e82010-01-07 21:48:32 -05001378 LOGV("+++ onTransact err %d code %d", err, code);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001379
1380 if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
1381 // the 'service' command interrogates this binder for its name, and then supplies it
1382 // even for the debugging commands. that means we need to check for it here, using
1383 // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
1384 // BnSurfaceComposer before falling through to this code).
1385
Joe Onorato51632e82010-01-07 21:48:32 -05001386 LOGV("+++ onTransact code %d", code);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001387
1388 CHECK_INTERFACE(ICameraService, data, reply);
1389
1390 switch(code) {
1391 case 1000:
1392 {
1393 if (gWeakHeap != 0) {
1394 sp<IMemoryHeap> h = gWeakHeap.promote();
1395 IMemoryHeap *p = gWeakHeap.unsafe_get();
Joe Onorato51632e82010-01-07 21:48:32 -05001396 LOGV("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001397 if (h != 0)
1398 h->printRefs();
1399 bool attempt_to_delete = data.readInt32() == 1;
1400 if (attempt_to_delete) {
1401 // NOT SAFE!
Joe Onorato51632e82010-01-07 21:48:32 -05001402 LOGV("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001403 if (p) delete p;
1404 }
1405 return NO_ERROR;
1406 }
1407 }
1408 break;
1409 default:
1410 break;
1411 }
1412 }
Dave Sparks998b3292009-05-20 20:02:59 -07001413#endif // DEBUG_HEAP_LEAKS
Dave Sparksfec880d2009-05-21 09:18:18 -07001414
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001415 return err;
1416}
1417
The Android Open Source Projectedbf3b62009-03-03 19:31:44 -08001418}; // namespace android