blob: dc3f0830d91a0b27eec04dfcaf3a94b8f6422c68 [file] [log] [blame]
Mathias Agopian65ab4712010-07-14 17:59:35 -07001/*
2**
3** Copyright (C) 2008, The Android Open Source Project
Mathias Agopian65ab4712010-07-14 17:59:35 -07004**
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
18#define LOG_TAG "CameraService"
Iliyan Malchev8951a972011-04-14 16:55:59 -070019//#define LOG_NDEBUG 0
Mathias Agopian65ab4712010-07-14 17:59:35 -070020
21#include <stdio.h>
22#include <sys/types.h>
23#include <pthread.h>
Wu-cheng Li2fd24402012-02-23 19:01:00 -080024#include <time.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070025
26#include <binder/IPCThreadState.h>
27#include <binder/IServiceManager.h>
28#include <binder/MemoryBase.h>
29#include <binder/MemoryHeapBase.h>
30#include <cutils/atomic.h>
Nipun Kwatrab5ca4612010-09-11 19:31:10 -070031#include <cutils/properties.h>
Jamie Gennisbfa33aa2010-12-20 11:51:31 -080032#include <gui/SurfaceTextureClient.h>
Mathias Agopiandf712ea2012-02-25 18:48:35 -080033#include <gui/Surface.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070034#include <hardware/hardware.h>
35#include <media/AudioSystem.h>
36#include <media/mediaplayer.h>
Wu-cheng Li2fd24402012-02-23 19:01:00 -080037#include <utils/Condition.h>
Mathias Agopian65ab4712010-07-14 17:59:35 -070038#include <utils/Errors.h>
39#include <utils/Log.h>
40#include <utils/String16.h>
41
42#include "CameraService.h"
Iliyan Malchev8951a972011-04-14 16:55:59 -070043#include "CameraHardwareInterface.h"
Mathias Agopian65ab4712010-07-14 17:59:35 -070044
45namespace android {
46
Wu-cheng Li2fd24402012-02-23 19:01:00 -080047#define WAIT_RELEASE_TIMEOUT 250 // 250ms
48
Mathias Agopian65ab4712010-07-14 17:59:35 -070049// ----------------------------------------------------------------------------
50// Logging support -- this is for debugging only
51// Use "adb shell dumpsys media.camera -v 1" to change it.
52static volatile int32_t gLogLevel = 0;
53
Steve Blockb8a80522011-12-20 16:23:08 +000054#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
55#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
Mathias Agopian65ab4712010-07-14 17:59:35 -070056
57static void setLogLevel(int level) {
58 android_atomic_write(level, &gLogLevel);
59}
60
61// ----------------------------------------------------------------------------
62
63static int getCallingPid() {
64 return IPCThreadState::self()->getCallingPid();
65}
66
67static int getCallingUid() {
68 return IPCThreadState::self()->getCallingUid();
69}
70
Wu-cheng Li2fd24402012-02-23 19:01:00 -080071static long long getTimeInMs() {
72 struct timeval t;
73 t.tv_sec = t.tv_usec = 0;
74 gettimeofday(&t, NULL);
75 return t.tv_sec * 1000LL + t.tv_usec / 1000;
76}
77
Mathias Agopian65ab4712010-07-14 17:59:35 -070078// ----------------------------------------------------------------------------
79
80// This is ugly and only safe if we never re-create the CameraService, but
81// should be ok for now.
82static CameraService *gCameraService;
83
84CameraService::CameraService()
Iliyan Malchev8951a972011-04-14 16:55:59 -070085:mSoundRef(0), mModule(0)
Mathias Agopian65ab4712010-07-14 17:59:35 -070086{
Steve Blockdf64d152012-01-04 20:05:49 +000087 ALOGI("CameraService started (pid=%d)", getpid());
Mathias Agopian65ab4712010-07-14 17:59:35 -070088 gCameraService = this;
89}
90
Iliyan Malchev8951a972011-04-14 16:55:59 -070091void CameraService::onFirstRef()
92{
93 BnCameraService::onFirstRef();
94
95 if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,
96 (const hw_module_t **)&mModule) < 0) {
Steve Block29357bc2012-01-06 19:20:56 +000097 ALOGE("Could not load camera HAL module");
Iliyan Malchev8951a972011-04-14 16:55:59 -070098 mNumberOfCameras = 0;
99 }
100 else {
101 mNumberOfCameras = mModule->get_number_of_cameras();
102 if (mNumberOfCameras > MAX_CAMERAS) {
Steve Block29357bc2012-01-06 19:20:56 +0000103 ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
Iliyan Malchev8951a972011-04-14 16:55:59 -0700104 mNumberOfCameras, MAX_CAMERAS);
105 mNumberOfCameras = MAX_CAMERAS;
106 }
107 for (int i = 0; i < mNumberOfCameras; i++) {
108 setCameraFree(i);
109 }
110 }
111}
112
Mathias Agopian65ab4712010-07-14 17:59:35 -0700113CameraService::~CameraService() {
114 for (int i = 0; i < mNumberOfCameras; i++) {
115 if (mBusy[i]) {
Steve Block29357bc2012-01-06 19:20:56 +0000116 ALOGE("camera %d is still in use in destructor!", i);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700117 }
118 }
119
120 gCameraService = NULL;
121}
122
123int32_t CameraService::getNumberOfCameras() {
124 return mNumberOfCameras;
125}
126
127status_t CameraService::getCameraInfo(int cameraId,
128 struct CameraInfo* cameraInfo) {
Iliyan Malchev8951a972011-04-14 16:55:59 -0700129 if (!mModule) {
130 return NO_INIT;
131 }
132
Mathias Agopian65ab4712010-07-14 17:59:35 -0700133 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
134 return BAD_VALUE;
135 }
136
Iliyan Malchev8951a972011-04-14 16:55:59 -0700137 struct camera_info info;
138 status_t rc = mModule->get_camera_info(cameraId, &info);
139 cameraInfo->facing = info.facing;
140 cameraInfo->orientation = info.orientation;
141 return rc;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700142}
143
144sp<ICamera> CameraService::connect(
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800145 const sp<ICameraClient>& cameraClient, int cameraId, bool force, bool keep) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700146 int callingPid = getCallingPid();
Tyler Luu5861a9a2011-10-06 00:00:03 -0500147 sp<CameraHardwareInterface> hardware = NULL;
148
Mathias Agopian65ab4712010-07-14 17:59:35 -0700149 LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
150
Iliyan Malchev8951a972011-04-14 16:55:59 -0700151 if (!mModule) {
Steve Block29357bc2012-01-06 19:20:56 +0000152 ALOGE("Camera HAL module not loaded");
Iliyan Malchev8951a972011-04-14 16:55:59 -0700153 return NULL;
154 }
155
Mathias Agopian65ab4712010-07-14 17:59:35 -0700156 sp<Client> client;
157 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
Steve Block29357bc2012-01-06 19:20:56 +0000158 ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700159 callingPid, cameraId);
160 return NULL;
161 }
162
Wu-cheng Lia3355432011-05-20 14:54:25 +0800163 char value[PROPERTY_VALUE_MAX];
164 property_get("sys.secpolicy.camera.disabled", value, "0");
165 if (strcmp(value, "1") == 0) {
166 // Camera is disabled by DevicePolicyManager.
Steve Blockdf64d152012-01-04 20:05:49 +0000167 ALOGI("Camera is disabled. connect X (pid %d) rejected", callingPid);
Wu-cheng Lia3355432011-05-20 14:54:25 +0800168 return NULL;
169 }
170
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800171 if (keep && !checkCallingPermission(String16("android.permission.KEEP_CAMERA"))) {
172 ALOGE("connect X (pid %d) rejected (no KEEP_CAMERA permission).", callingPid);
173 return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700174 }
175
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800176 Mutex::Autolock lock(mServiceLock);
177 // Check if there is an existing client.
178 client = mClient[cameraId].promote();
179 if (client != 0 &&
180 cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
181 LOG1("connect X (pid %d) (the same client)", callingPid);
182 return client;
183 }
184
185 if (!force) {
186 if (mClient[cameraId].promote() != 0) {
187 ALOGW("connect X (pid %d) rejected (existing client).", callingPid);
188 return NULL;
189 }
190 mClient[cameraId].clear();
191 if (mBusy[cameraId]) {
192 ALOGW("connect X (pid %d) rejected (camera %d is still busy).",
193 callingPid, cameraId);
194 return NULL;
195 }
196 } else { // force == true
197 int i = 0;
198 long long start_time = getTimeInMs();
199 while (i < mNumberOfCameras) {
200 if (getTimeInMs() - start_time >= 3000LL) {
201 ALOGE("connect X (pid %d) rejected (timeout 3s)", callingPid);
202 return NULL;
203 }
204
205 client = mClient[i].promote();
206 if (client != 0) {
207 if (client->keep()) {
208 ALOGW("connect X (pid %d) rejected (existing client wants to keeps the camera)",
209 callingPid);
210 return NULL;
211 } else {
212 ALOGW("New client (pid %d, id=%d). Disconnect the existing client (id=%d).",
213 callingPid, cameraId, i);
214 // Do not hold mServiceLock because disconnect will try to get it.
215 mServiceLock.unlock();
216 client->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0, &i);
217 client->waitRelease(WAIT_RELEASE_TIMEOUT);
218 client->disconnectInternal(false);
219 mServiceLock.lock();
220 // Restart from the first client because a new client may have connected
221 // when mServiceLock is unlocked.
222 i = 0;
223 continue;
224 }
225 }
226
227 if (mBusy[i]) {
228 // Give the client a chance to release the hardware.
229 mServiceLock.unlock();
230 usleep(10 * 1000);
231 mServiceLock.lock();
232 i = 0; // Restart from the first client
233 continue;
234 }
235
236 i++;
237 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700238 }
239
Iliyan Malchev8951a972011-04-14 16:55:59 -0700240 struct camera_info info;
241 if (mModule->get_camera_info(cameraId, &info) != OK) {
Steve Block29357bc2012-01-06 19:20:56 +0000242 ALOGE("Invalid camera id %d", cameraId);
Wu-cheng Lib7a67942010-08-17 15:45:37 -0700243 return NULL;
244 }
Iliyan Malchev8951a972011-04-14 16:55:59 -0700245
246 char camera_device_name[10];
247 snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
248
Tyler Luu5861a9a2011-10-06 00:00:03 -0500249 hardware = new CameraHardwareInterface(camera_device_name);
250 if (hardware->initialize(&mModule->common) != OK) {
251 hardware.clear();
252 return NULL;
253 }
254
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800255 client = new Client(this, cameraClient, hardware, cameraId, info.facing,
256 callingPid, keep);
257 // We need to clear the hardware here. After the destructor of mServiceLock
258 // finishes, a new client may connect and disconnect this client. If this
259 // reference is not cleared, the destructor of CameraHardwareInterface
260 // cannot run. The new client will not be able to connect.
261 hardware.clear();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700262 mClient[cameraId] = client;
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800263 LOG1("CameraService::connect X (id %d)", cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700264 return client;
265}
266
267void CameraService::removeClient(const sp<ICameraClient>& cameraClient) {
268 int callingPid = getCallingPid();
269 LOG1("CameraService::removeClient E (pid %d)", callingPid);
270
271 for (int i = 0; i < mNumberOfCameras; i++) {
272 // Declare this before the lock to make absolutely sure the
273 // destructor won't be called with the lock held.
274 sp<Client> client;
275
276 Mutex::Autolock lock(mServiceLock);
277
278 // This happens when we have already disconnected (or this is
279 // just another unused camera).
280 if (mClient[i] == 0) continue;
281
282 // Promote mClient. It can fail if we are called from this path:
283 // Client::~Client() -> disconnect() -> removeClient().
284 client = mClient[i].promote();
285
286 if (client == 0) {
287 mClient[i].clear();
288 continue;
289 }
290
291 if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
292 // Found our camera, clear and leave.
293 LOG1("removeClient: clear camera %d", i);
294 mClient[i].clear();
295 break;
296 }
297 }
298
299 LOG1("CameraService::removeClient X (pid %d)", callingPid);
300}
301
Keun young Parkd8973a72012-03-28 14:13:09 -0700302CameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700303 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
Keun young Parkd8973a72012-03-28 14:13:09 -0700304 return mClient[cameraId].unsafe_get();
305}
306
307Mutex* CameraService::getClientLockById(int cameraId) {
308 if (cameraId < 0 || cameraId >= mNumberOfCameras) return NULL;
309 return &mClientLock[cameraId];
Mathias Agopian65ab4712010-07-14 17:59:35 -0700310}
311
Mathias Agopian65ab4712010-07-14 17:59:35 -0700312status_t CameraService::onTransact(
313 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
314 // Permission checks
315 switch (code) {
316 case BnCameraService::CONNECT:
317 const int pid = getCallingPid();
318 const int self_pid = getpid();
319 if (pid != self_pid) {
320 // we're called from a different process, do the real check
321 if (!checkCallingPermission(
322 String16("android.permission.CAMERA"))) {
323 const int uid = getCallingUid();
Steve Block29357bc2012-01-06 19:20:56 +0000324 ALOGE("Permission Denial: "
Mathias Agopian65ab4712010-07-14 17:59:35 -0700325 "can't use the camera pid=%d, uid=%d", pid, uid);
326 return PERMISSION_DENIED;
327 }
328 }
329 break;
330 }
331
332 return BnCameraService::onTransact(code, data, reply, flags);
333}
334
335// The reason we need this busy bit is a new CameraService::connect() request
336// may come in while the previous Client's destructor has not been run or is
337// still running. If the last strong reference of the previous Client is gone
338// but the destructor has not been finished, we should not allow the new Client
339// to be created because we need to wait for the previous Client to tear down
340// the hardware first.
341void CameraService::setCameraBusy(int cameraId) {
342 android_atomic_write(1, &mBusy[cameraId]);
343}
344
345void CameraService::setCameraFree(int cameraId) {
346 android_atomic_write(0, &mBusy[cameraId]);
347}
348
349// We share the media players for shutter and recording sound for all clients.
350// A reference count is kept to determine when we will actually release the
351// media players.
352
Chih-Chung Changff4f55c2011-10-17 19:03:12 +0800353MediaPlayer* CameraService::newMediaPlayer(const char *file) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700354 MediaPlayer* mp = new MediaPlayer();
355 if (mp->setDataSource(file, NULL) == NO_ERROR) {
Eino-Ville Talvala60a78ac2012-01-05 15:34:53 -0800356 mp->setAudioStreamType(AUDIO_STREAM_ENFORCED_AUDIBLE);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700357 mp->prepare();
358 } else {
Steve Block29357bc2012-01-06 19:20:56 +0000359 ALOGE("Failed to load CameraService sounds: %s", file);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700360 return NULL;
361 }
362 return mp;
363}
364
365void CameraService::loadSound() {
366 Mutex::Autolock lock(mSoundLock);
367 LOG1("CameraService::loadSound ref=%d", mSoundRef);
368 if (mSoundRef++) return;
369
370 mSoundPlayer[SOUND_SHUTTER] = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
371 mSoundPlayer[SOUND_RECORDING] = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
372}
373
374void CameraService::releaseSound() {
375 Mutex::Autolock lock(mSoundLock);
376 LOG1("CameraService::releaseSound ref=%d", mSoundRef);
377 if (--mSoundRef) return;
378
379 for (int i = 0; i < NUM_SOUNDS; i++) {
380 if (mSoundPlayer[i] != 0) {
381 mSoundPlayer[i]->disconnect();
382 mSoundPlayer[i].clear();
383 }
384 }
385}
386
387void CameraService::playSound(sound_kind kind) {
388 LOG1("playSound(%d)", kind);
389 Mutex::Autolock lock(mSoundLock);
390 sp<MediaPlayer> player = mSoundPlayer[kind];
391 if (player != 0) {
Chih-Chung Chang8888a752011-10-20 10:47:26 +0800392 player->seekTo(0);
393 player->start();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700394 }
395}
396
397// ----------------------------------------------------------------------------
398
399CameraService::Client::Client(const sp<CameraService>& cameraService,
Wu-cheng Lib7a67942010-08-17 15:45:37 -0700400 const sp<ICameraClient>& cameraClient,
401 const sp<CameraHardwareInterface>& hardware,
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800402 int cameraId, int cameraFacing, int clientPid, bool keep) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700403 int callingPid = getCallingPid();
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800404 LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700405
406 mCameraService = cameraService;
407 mCameraClient = cameraClient;
Wu-cheng Lib7a67942010-08-17 15:45:37 -0700408 mHardware = hardware;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700409 mCameraId = cameraId;
Wu-cheng Lie09591e2010-10-14 20:17:44 +0800410 mCameraFacing = cameraFacing;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700411 mClientPid = clientPid;
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800412 mKeep = keep;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700413 mMsgEnabled = 0;
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800414 mSurface = 0;
415 mPreviewWindow = 0;
Keun young Parkd8973a72012-03-28 14:13:09 -0700416 mDestructionStarted = false;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700417 mHardware->setCallbacks(notifyCallback,
418 dataCallback,
419 dataCallbackTimestamp,
420 (void *)cameraId);
421
Wu-cheng Li57c86182011-07-30 05:00:37 +0800422 // Enable zoom, error, focus, and metadata messages by default
423 enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
Wu-cheng Lid6205062011-11-14 20:30:14 +0800424 CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700425
426 // Callback is disabled by default
Iliyan Malchev9e626522011-04-14 16:51:21 -0700427 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
Wu-cheng Lie09591e2010-10-14 20:17:44 +0800428 mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
Nipun Kwatrab5ca4612010-09-11 19:31:10 -0700429 mPlayShutterSound = true;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700430 cameraService->setCameraBusy(cameraId);
431 cameraService->loadSound();
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800432 LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700433}
434
Mathias Agopian65ab4712010-07-14 17:59:35 -0700435// tear down the client
436CameraService::Client::~Client() {
Keun young Parkd8973a72012-03-28 14:13:09 -0700437 // this lock should never be NULL
438 Mutex* lock = mCameraService->getClientLockById(mCameraId);
439 lock->lock();
440 mDestructionStarted = true;
441 // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
442 lock->unlock();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700443 int callingPid = getCallingPid();
444 LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
445
Mathias Agopian65ab4712010-07-14 17:59:35 -0700446 // set mClientPid to let disconnet() tear down the hardware
447 mClientPid = callingPid;
448 disconnect();
449 mCameraService->releaseSound();
450 LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
451}
452
453// ----------------------------------------------------------------------------
454
455status_t CameraService::Client::checkPid() const {
456 int callingPid = getCallingPid();
457 if (callingPid == mClientPid) return NO_ERROR;
458
Steve Block5ff1dd52012-01-05 23:22:43 +0000459 ALOGW("attempt to use a locked camera from a different process"
Mathias Agopian65ab4712010-07-14 17:59:35 -0700460 " (old pid %d, new pid %d)", mClientPid, callingPid);
461 return EBUSY;
462}
463
464status_t CameraService::Client::checkPidAndHardware() const {
465 status_t result = checkPid();
466 if (result != NO_ERROR) return result;
467 if (mHardware == 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000468 ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
Mathias Agopian65ab4712010-07-14 17:59:35 -0700469 return INVALID_OPERATION;
470 }
471 return NO_ERROR;
472}
473
474status_t CameraService::Client::lock() {
475 int callingPid = getCallingPid();
476 LOG1("lock (pid %d)", callingPid);
477 Mutex::Autolock lock(mLock);
478
479 // lock camera to this client if the the camera is unlocked
480 if (mClientPid == 0) {
481 mClientPid = callingPid;
482 return NO_ERROR;
483 }
484
485 // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
486 return checkPid();
487}
488
489status_t CameraService::Client::unlock() {
490 int callingPid = getCallingPid();
491 LOG1("unlock (pid %d)", callingPid);
492 Mutex::Autolock lock(mLock);
493
494 // allow anyone to use camera (after they lock the camera)
495 status_t result = checkPid();
496 if (result == NO_ERROR) {
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800497 if (mHardware->recordingEnabled()) {
Steve Block29357bc2012-01-06 19:20:56 +0000498 ALOGE("Not allowed to unlock camera during recording.");
Wu-cheng Li4ca2c7c2011-06-01 17:22:24 +0800499 return INVALID_OPERATION;
500 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700501 mClientPid = 0;
502 LOG1("clear mCameraClient (pid %d)", callingPid);
503 // we need to remove the reference to ICameraClient so that when the app
504 // goes away, the reference count goes to 0.
505 mCameraClient.clear();
506 }
507 return result;
508}
509
510// connect a new client to the camera
511status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
512 int callingPid = getCallingPid();
513 LOG1("connect E (pid %d)", callingPid);
514 Mutex::Autolock lock(mLock);
515
516 if (mClientPid != 0 && checkPid() != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000517 ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
Mathias Agopian65ab4712010-07-14 17:59:35 -0700518 mClientPid, callingPid);
519 return EBUSY;
520 }
521
522 if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
523 LOG1("Connect to the same client");
524 return NO_ERROR;
525 }
526
Iliyan Malchev9e626522011-04-14 16:51:21 -0700527 mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700528 mClientPid = callingPid;
529 mCameraClient = client;
530
531 LOG1("connect X (pid %d)", callingPid);
532 return NO_ERROR;
533}
534
Wu-cheng Li7574da52011-07-20 05:35:02 +0800535static void disconnectWindow(const sp<ANativeWindow>& window) {
536 if (window != 0) {
Mathias Agopianc3da3432011-07-29 17:55:48 -0700537 status_t result = native_window_api_disconnect(window.get(),
Wu-cheng Li7574da52011-07-20 05:35:02 +0800538 NATIVE_WINDOW_API_CAMERA);
539 if (result != NO_ERROR) {
Steve Block5ff1dd52012-01-05 23:22:43 +0000540 ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
Wu-cheng Li7574da52011-07-20 05:35:02 +0800541 result);
542 }
543 }
544}
545
Mathias Agopian65ab4712010-07-14 17:59:35 -0700546void CameraService::Client::disconnect() {
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800547 disconnectInternal(true);
548}
549
550void CameraService::Client::disconnectInternal(bool needCheckPid) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700551 int callingPid = getCallingPid();
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800552 LOG1("disconnectInternal E (pid %d)", callingPid);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700553 Mutex::Autolock lock(mLock);
554
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800555 if (needCheckPid) {
556 if (checkPid() != NO_ERROR) {
557 ALOGW("different client - don't disconnect");
558 return;
559 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700560
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800561 if (mClientPid <= 0) {
562 LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
563 return;
564 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700565 }
566
567 // Make sure disconnect() is done once and once only, whether it is called
568 // from the user directly, or called by the destructor.
569 if (mHardware == 0) return;
570
571 LOG1("hardware teardown");
572 // Before destroying mHardware, we must make sure it's in the
573 // idle state.
574 // Turn off all messages.
575 disableMsgType(CAMERA_MSG_ALL_MSGS);
576 mHardware->stopPreview();
577 mHardware->cancelPicture();
578 // Release the hardware resources.
579 mHardware->release();
Mathias Agopian03dfce92010-12-07 19:38:17 -0800580
Jamie Gennis4b791682010-08-10 16:37:53 -0700581 // Release the held ANativeWindow resources.
582 if (mPreviewWindow != 0) {
Wu-cheng Li7574da52011-07-20 05:35:02 +0800583 disconnectWindow(mPreviewWindow);
Jamie Gennis4b791682010-08-10 16:37:53 -0700584 mPreviewWindow = 0;
585 mHardware->setPreviewWindow(mPreviewWindow);
586 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700587 mHardware.clear();
588
589 mCameraService->removeClient(mCameraClient);
590 mCameraService->setCameraFree(mCameraId);
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800591 mReleaseCondition.signal();
Mathias Agopian65ab4712010-07-14 17:59:35 -0700592
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800593 LOG1("disconnectInternal X (pid %d)", callingPid);
594}
595
596void CameraService::Client::waitRelease(int ms) {
597 Mutex::Autolock lock(mLock);
598 if (mHardware != 0) {
599 mReleaseCondition.waitRelative(mLock, ms * 1000000);
600 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700601}
602
603// ----------------------------------------------------------------------------
604
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700605status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
606 const sp<ANativeWindow>& window) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700607 Mutex::Autolock lock(mLock);
608 status_t result = checkPidAndHardware();
609 if (result != NO_ERROR) return result;
610
Mathias Agopian65ab4712010-07-14 17:59:35 -0700611 // return if no change in surface.
Mathias Agopian8b1027d2011-04-05 15:44:20 -0700612 if (binder == mSurface) {
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700613 return NO_ERROR;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700614 }
615
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700616 if (window != 0) {
Mathias Agopianc3da3432011-07-29 17:55:48 -0700617 result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700618 if (result != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000619 ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700620 result);
621 return result;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700622 }
623 }
624
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700625 // If preview has been already started, register preview buffers now.
626 if (mHardware->previewEnabled()) {
627 if (window != 0) {
Mathias Agopian9bc7af12011-07-18 16:15:08 -0700628 native_window_set_scaling_mode(window.get(),
629 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700630 native_window_set_buffers_transform(window.get(), mOrientation);
631 result = mHardware->setPreviewWindow(window);
632 }
633 }
634
635 if (result == NO_ERROR) {
636 // Everything has succeeded. Disconnect the old window and remember the
637 // new window.
638 disconnectWindow(mPreviewWindow);
639 mSurface = binder;
640 mPreviewWindow = window;
641 } else {
642 // Something went wrong after we connected to the new window, so
643 // disconnect here.
644 disconnectWindow(window);
645 }
646
Mathias Agopian65ab4712010-07-14 17:59:35 -0700647 return result;
648}
649
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700650// set the Surface that the preview will use
651status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
652 LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
653
654 sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
655 sp<ANativeWindow> window(surface);
656 return setPreviewWindow(binder, window);
657}
658
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800659// set the SurfaceTexture that the preview will use
660status_t CameraService::Client::setPreviewTexture(
661 const sp<ISurfaceTexture>& surfaceTexture) {
662 LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
663 getCallingPid());
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800664
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700665 sp<IBinder> binder;
666 sp<ANativeWindow> window;
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800667 if (surfaceTexture != 0) {
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700668 binder = surfaceTexture->asBinder();
669 window = new SurfaceTextureClient(surfaceTexture);
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800670 }
Jamie Gennis0ed3ec02011-07-13 15:13:14 -0700671 return setPreviewWindow(binder, window);
Jamie Gennisbfa33aa2010-12-20 11:51:31 -0800672}
673
Mathias Agopian65ab4712010-07-14 17:59:35 -0700674// set the preview callback flag to affect how the received frames from
675// preview are handled.
676void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
677 LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
678 Mutex::Autolock lock(mLock);
679 if (checkPidAndHardware() != NO_ERROR) return;
680
681 mPreviewCallbackFlag = callback_flag;
Iliyan Malchev9e626522011-04-14 16:51:21 -0700682 if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
Wu-cheng Li0667de72010-09-03 16:40:32 -0700683 enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
684 } else {
685 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700686 }
687}
688
689// start preview mode
690status_t CameraService::Client::startPreview() {
691 LOG1("startPreview (pid %d)", getCallingPid());
692 return startCameraMode(CAMERA_PREVIEW_MODE);
693}
694
695// start recording mode
696status_t CameraService::Client::startRecording() {
697 LOG1("startRecording (pid %d)", getCallingPid());
698 return startCameraMode(CAMERA_RECORDING_MODE);
699}
700
701// start preview or recording
702status_t CameraService::Client::startCameraMode(camera_mode mode) {
703 LOG1("startCameraMode(%d)", mode);
704 Mutex::Autolock lock(mLock);
705 status_t result = checkPidAndHardware();
706 if (result != NO_ERROR) return result;
707
708 switch(mode) {
709 case CAMERA_PREVIEW_MODE:
Jamie Gennis4b791682010-08-10 16:37:53 -0700710 if (mSurface == 0 && mPreviewWindow == 0) {
Mathias Agopian65ab4712010-07-14 17:59:35 -0700711 LOG1("mSurface is not set yet.");
712 // still able to start preview in this case.
713 }
714 return startPreviewMode();
715 case CAMERA_RECORDING_MODE:
Jamie Gennis4b791682010-08-10 16:37:53 -0700716 if (mSurface == 0 && mPreviewWindow == 0) {
Steve Block29357bc2012-01-06 19:20:56 +0000717 ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
Mathias Agopian65ab4712010-07-14 17:59:35 -0700718 return INVALID_OPERATION;
719 }
720 return startRecordingMode();
721 default:
722 return UNKNOWN_ERROR;
723 }
724}
725
726status_t CameraService::Client::startPreviewMode() {
727 LOG1("startPreviewMode");
728 status_t result = NO_ERROR;
729
730 // if preview has been enabled, nothing needs to be done
731 if (mHardware->previewEnabled()) {
732 return NO_ERROR;
733 }
734
Mathias Agopian03dfce92010-12-07 19:38:17 -0800735 if (mPreviewWindow != 0) {
Mathias Agopian9bc7af12011-07-18 16:15:08 -0700736 native_window_set_scaling_mode(mPreviewWindow.get(),
737 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
Mathias Agopian03dfce92010-12-07 19:38:17 -0800738 native_window_set_buffers_transform(mPreviewWindow.get(),
739 mOrientation);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700740 }
Mathias Agopian03dfce92010-12-07 19:38:17 -0800741 mHardware->setPreviewWindow(mPreviewWindow);
742 result = mHardware->startPreview();
743
Mathias Agopian65ab4712010-07-14 17:59:35 -0700744 return result;
745}
746
747status_t CameraService::Client::startRecordingMode() {
748 LOG1("startRecordingMode");
749 status_t result = NO_ERROR;
750
751 // if recording has been enabled, nothing needs to be done
752 if (mHardware->recordingEnabled()) {
753 return NO_ERROR;
754 }
755
756 // if preview has not been started, start preview first
757 if (!mHardware->previewEnabled()) {
758 result = startPreviewMode();
759 if (result != NO_ERROR) {
760 return result;
761 }
762 }
763
764 // start recording mode
765 enableMsgType(CAMERA_MSG_VIDEO_FRAME);
766 mCameraService->playSound(SOUND_RECORDING);
767 result = mHardware->startRecording();
768 if (result != NO_ERROR) {
Steve Block29357bc2012-01-06 19:20:56 +0000769 ALOGE("mHardware->startRecording() failed with status %d", result);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700770 }
771 return result;
772}
773
774// stop preview mode
775void CameraService::Client::stopPreview() {
776 LOG1("stopPreview (pid %d)", getCallingPid());
777 Mutex::Autolock lock(mLock);
778 if (checkPidAndHardware() != NO_ERROR) return;
779
Jamie Gennis4b791682010-08-10 16:37:53 -0700780
Mathias Agopian65ab4712010-07-14 17:59:35 -0700781 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
782 mHardware->stopPreview();
783
Mathias Agopian65ab4712010-07-14 17:59:35 -0700784 mPreviewBuffer.clear();
785}
786
787// stop recording mode
788void CameraService::Client::stopRecording() {
789 LOG1("stopRecording (pid %d)", getCallingPid());
790 Mutex::Autolock lock(mLock);
791 if (checkPidAndHardware() != NO_ERROR) return;
792
793 mCameraService->playSound(SOUND_RECORDING);
794 disableMsgType(CAMERA_MSG_VIDEO_FRAME);
795 mHardware->stopRecording();
796
797 mPreviewBuffer.clear();
798}
799
800// release a recording frame
801void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
802 Mutex::Autolock lock(mLock);
803 if (checkPidAndHardware() != NO_ERROR) return;
804 mHardware->releaseRecordingFrame(mem);
805}
806
James Donge2ad6732010-10-18 20:42:51 -0700807status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
808{
809 LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
810 Mutex::Autolock lock(mLock);
811 if (checkPidAndHardware() != NO_ERROR) {
812 return UNKNOWN_ERROR;
813 }
814 return mHardware->storeMetaDataInBuffers(enabled);
815}
816
Mathias Agopian65ab4712010-07-14 17:59:35 -0700817bool CameraService::Client::previewEnabled() {
818 LOG1("previewEnabled (pid %d)", getCallingPid());
819
820 Mutex::Autolock lock(mLock);
821 if (checkPidAndHardware() != NO_ERROR) return false;
822 return mHardware->previewEnabled();
823}
824
825bool CameraService::Client::recordingEnabled() {
826 LOG1("recordingEnabled (pid %d)", getCallingPid());
827
828 Mutex::Autolock lock(mLock);
829 if (checkPidAndHardware() != NO_ERROR) return false;
830 return mHardware->recordingEnabled();
831}
832
833status_t CameraService::Client::autoFocus() {
834 LOG1("autoFocus (pid %d)", getCallingPid());
835
836 Mutex::Autolock lock(mLock);
837 status_t result = checkPidAndHardware();
838 if (result != NO_ERROR) return result;
839
840 return mHardware->autoFocus();
841}
842
843status_t CameraService::Client::cancelAutoFocus() {
844 LOG1("cancelAutoFocus (pid %d)", getCallingPid());
845
846 Mutex::Autolock lock(mLock);
847 status_t result = checkPidAndHardware();
848 if (result != NO_ERROR) return result;
849
850 return mHardware->cancelAutoFocus();
851}
852
853// take a picture - image is returned in callback
James Donge468ac52011-02-17 16:38:06 -0800854status_t CameraService::Client::takePicture(int msgType) {
855 LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700856
857 Mutex::Autolock lock(mLock);
858 status_t result = checkPidAndHardware();
859 if (result != NO_ERROR) return result;
860
James Donge468ac52011-02-17 16:38:06 -0800861 if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
862 (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
Steve Block29357bc2012-01-06 19:20:56 +0000863 ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
James Donge468ac52011-02-17 16:38:06 -0800864 " cannot be both enabled");
865 return BAD_VALUE;
866 }
867
868 // We only accept picture related message types
869 // and ignore other types of messages for takePicture().
870 int picMsgType = msgType
871 & (CAMERA_MSG_SHUTTER |
872 CAMERA_MSG_POSTVIEW_FRAME |
873 CAMERA_MSG_RAW_IMAGE |
874 CAMERA_MSG_RAW_IMAGE_NOTIFY |
875 CAMERA_MSG_COMPRESSED_IMAGE);
876
877 enableMsgType(picMsgType);
Mathias Agopian65ab4712010-07-14 17:59:35 -0700878
879 return mHardware->takePicture();
880}
881
882// set preview/capture parameters - key/value pairs
883status_t CameraService::Client::setParameters(const String8& params) {
884 LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
885
886 Mutex::Autolock lock(mLock);
887 status_t result = checkPidAndHardware();
888 if (result != NO_ERROR) return result;
889
890 CameraParameters p(params);
891 return mHardware->setParameters(p);
892}
893
894// get preview/capture parameters - key/value pairs
895String8 CameraService::Client::getParameters() const {
896 Mutex::Autolock lock(mLock);
897 if (checkPidAndHardware() != NO_ERROR) return String8();
898
899 String8 params(mHardware->getParameters().flatten());
900 LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
901 return params;
902}
903
Nipun Kwatrab5ca4612010-09-11 19:31:10 -0700904// enable shutter sound
905status_t CameraService::Client::enableShutterSound(bool enable) {
906 LOG1("enableShutterSound (pid %d)", getCallingPid());
907
908 status_t result = checkPidAndHardware();
909 if (result != NO_ERROR) return result;
910
911 if (enable) {
912 mPlayShutterSound = true;
913 return OK;
914 }
915
916 // Disabling shutter sound may not be allowed. In that case only
917 // allow the mediaserver process to disable the sound.
918 char value[PROPERTY_VALUE_MAX];
919 property_get("ro.camera.sound.forced", value, "0");
920 if (strcmp(value, "0") != 0) {
921 // Disabling shutter sound is not allowed. Deny if the current
922 // process is not mediaserver.
923 if (getCallingPid() != getpid()) {
Steve Block29357bc2012-01-06 19:20:56 +0000924 ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
Nipun Kwatrab5ca4612010-09-11 19:31:10 -0700925 return PERMISSION_DENIED;
926 }
927 }
928
929 mPlayShutterSound = false;
930 return OK;
931}
932
Mathias Agopian65ab4712010-07-14 17:59:35 -0700933status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
934 LOG1("sendCommand (pid %d)", getCallingPid());
Wu-cheng Li4a73f3d2010-09-23 17:17:43 -0700935 int orientation;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700936 Mutex::Autolock lock(mLock);
937 status_t result = checkPidAndHardware();
938 if (result != NO_ERROR) return result;
939
940 if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
Wu-cheng Lie09591e2010-10-14 20:17:44 +0800941 // Mirror the preview if the camera is front-facing.
942 orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
943 if (orientation == -1) return BAD_VALUE;
944
Wu-cheng Li4a73f3d2010-09-23 17:17:43 -0700945 if (mOrientation != orientation) {
946 mOrientation = orientation;
Wu-cheng Lib9f58862011-10-07 13:13:54 +0800947 if (mPreviewWindow != 0) {
948 native_window_set_buffers_transform(mPreviewWindow.get(),
949 mOrientation);
950 }
Wu-cheng Li4a73f3d2010-09-23 17:17:43 -0700951 }
Mathias Agopian65ab4712010-07-14 17:59:35 -0700952 return OK;
Nipun Kwatrab5ca4612010-09-11 19:31:10 -0700953 } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
954 switch (arg1) {
955 case 0:
956 enableShutterSound(false);
957 break;
958 case 1:
959 enableShutterSound(true);
960 break;
961 default:
962 return BAD_VALUE;
963 }
964 return OK;
Nipun Kwatra3b7b3582010-09-14 16:49:08 -0700965 } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
966 mCameraService->playSound(SOUND_RECORDING);
Wu-cheng Li2fd24402012-02-23 19:01:00 -0800967 } else if (cmd == CAMERA_CMD_PING) {
968 // If mHardware is 0, checkPidAndHardware will return error.
969 return OK;
Mathias Agopian65ab4712010-07-14 17:59:35 -0700970 }
971
972 return mHardware->sendCommand(cmd, arg1, arg2);
973}
974
975// ----------------------------------------------------------------------------
976
977void CameraService::Client::enableMsgType(int32_t msgType) {
978 android_atomic_or(msgType, &mMsgEnabled);
979 mHardware->enableMsgType(msgType);
980}
981
982void CameraService::Client::disableMsgType(int32_t msgType) {
983 android_atomic_and(~msgType, &mMsgEnabled);
984 mHardware->disableMsgType(msgType);
985}
986
987#define CHECK_MESSAGE_INTERVAL 10 // 10ms
988bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
989 int sleepCount = 0;
990 while (mMsgEnabled & msgType) {
991 if (mLock.tryLock() == NO_ERROR) {
992 if (sleepCount > 0) {
993 LOG1("lockIfMessageWanted(%d): waited for %d ms",
994 msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
995 }
996 return true;
997 }
998 if (sleepCount++ == 0) {
999 LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
1000 }
1001 usleep(CHECK_MESSAGE_INTERVAL * 1000);
1002 }
Steve Block5ff1dd52012-01-05 23:22:43 +00001003 ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001004 return false;
1005}
1006
1007// ----------------------------------------------------------------------------
1008
Keun young Parkd8973a72012-03-28 14:13:09 -07001009Mutex* CameraService::Client::getClientLockFromCookie(void* user) {
1010 return gCameraService->getClientLockById((int) user);
1011}
1012
1013// Provide client pointer for callbacks. Client lock returned from getClientLockFromCookie should
1014// be acquired for this to be safe
1015CameraService::Client* CameraService::Client::getClientFromCookie(void* user) {
1016 Client* client = gCameraService->getClientByIdUnsafe((int) user);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001017
1018 // This could happen if the Client is in the process of shutting down (the
1019 // last strong reference is gone, but the destructor hasn't finished
1020 // stopping the hardware).
Keun young Parkd8973a72012-03-28 14:13:09 -07001021 if (client == NULL) return NULL;
1022
1023 // destruction already started, so should not be accessed
1024 if (client->mDestructionStarted) return NULL;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001025
1026 // The checks below are not necessary and are for debugging only.
1027 if (client->mCameraService.get() != gCameraService) {
Steve Block29357bc2012-01-06 19:20:56 +00001028 ALOGE("mismatch service!");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001029 return NULL;
1030 }
1031
1032 if (client->mHardware == 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001033 ALOGE("mHardware == 0: callback after disconnect()?");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001034 return NULL;
1035 }
1036
1037 return client;
1038}
1039
1040// Callback messages can be dispatched to internal handlers or pass to our
1041// client's callback functions, depending on the message type.
1042//
1043// notifyCallback:
1044// CAMERA_MSG_SHUTTER handleShutter
1045// (others) c->notifyCallback
1046// dataCallback:
1047// CAMERA_MSG_PREVIEW_FRAME handlePreviewData
1048// CAMERA_MSG_POSTVIEW_FRAME handlePostview
1049// CAMERA_MSG_RAW_IMAGE handleRawPicture
1050// CAMERA_MSG_COMPRESSED_IMAGE handleCompressedPicture
1051// (others) c->dataCallback
1052// dataCallbackTimestamp
1053// (others) c->dataCallbackTimestamp
1054//
1055// NOTE: the *Callback functions grab mLock of the client before passing
1056// control to handle* functions. So the handle* functions must release the
1057// lock before calling the ICameraClient's callbacks, so those callbacks can
1058// invoke methods in the Client class again (For example, the preview frame
1059// callback may want to releaseRecordingFrame). The handle* functions must
1060// release the lock after all accesses to member variables, so it must be
1061// handled very carefully.
1062
1063void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
1064 int32_t ext2, void* user) {
1065 LOG2("notifyCallback(%d)", msgType);
1066
Keun young Parkd8973a72012-03-28 14:13:09 -07001067 Mutex* lock = getClientLockFromCookie(user);
1068 if (lock == NULL) return;
1069 Mutex::Autolock alock(*lock);
1070
1071 Client* client = getClientFromCookie(user);
1072 if (client == NULL) return;
1073
Mathias Agopian65ab4712010-07-14 17:59:35 -07001074 if (!client->lockIfMessageWanted(msgType)) return;
1075
1076 switch (msgType) {
1077 case CAMERA_MSG_SHUTTER:
1078 // ext1 is the dimension of the yuv picture.
Iliyan Malchev108dddf2011-03-28 16:10:12 -07001079 client->handleShutter();
Mathias Agopian65ab4712010-07-14 17:59:35 -07001080 break;
1081 default:
1082 client->handleGenericNotify(msgType, ext1, ext2);
1083 break;
1084 }
1085}
1086
1087void CameraService::Client::dataCallback(int32_t msgType,
Wu-cheng Liff09ef82011-07-28 05:30:59 +08001088 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001089 LOG2("dataCallback(%d)", msgType);
1090
Keun young Parkd8973a72012-03-28 14:13:09 -07001091 Mutex* lock = getClientLockFromCookie(user);
1092 if (lock == NULL) return;
1093 Mutex::Autolock alock(*lock);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001094
Keun young Parkd8973a72012-03-28 14:13:09 -07001095 Client* client = getClientFromCookie(user);
1096 if (client == NULL) return;
1097
1098 if (!client->lockIfMessageWanted(msgType)) return;
Wu-cheng Li57c86182011-07-30 05:00:37 +08001099 if (dataPtr == 0 && metadata == NULL) {
Steve Block29357bc2012-01-06 19:20:56 +00001100 ALOGE("Null data returned in data callback");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001101 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1102 return;
1103 }
1104
Wu-cheng Li57c86182011-07-30 05:00:37 +08001105 switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001106 case CAMERA_MSG_PREVIEW_FRAME:
Wu-cheng Li57c86182011-07-30 05:00:37 +08001107 client->handlePreviewData(msgType, dataPtr, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001108 break;
1109 case CAMERA_MSG_POSTVIEW_FRAME:
1110 client->handlePostview(dataPtr);
1111 break;
1112 case CAMERA_MSG_RAW_IMAGE:
1113 client->handleRawPicture(dataPtr);
1114 break;
1115 case CAMERA_MSG_COMPRESSED_IMAGE:
1116 client->handleCompressedPicture(dataPtr);
1117 break;
1118 default:
Wu-cheng Li57c86182011-07-30 05:00:37 +08001119 client->handleGenericData(msgType, dataPtr, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001120 break;
1121 }
1122}
1123
1124void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
1125 int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
1126 LOG2("dataCallbackTimestamp(%d)", msgType);
1127
Keun young Parkd8973a72012-03-28 14:13:09 -07001128 Mutex* lock = getClientLockFromCookie(user);
1129 if (lock == NULL) return;
1130 Mutex::Autolock alock(*lock);
1131
1132 Client* client = getClientFromCookie(user);
1133 if (client == NULL) return;
1134
James Dong986ef2a2010-12-09 11:08:14 -08001135 if (!client->lockIfMessageWanted(msgType)) return;
Mathias Agopian65ab4712010-07-14 17:59:35 -07001136
1137 if (dataPtr == 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001138 ALOGE("Null data returned in data with timestamp callback");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001139 client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
1140 return;
1141 }
1142
1143 client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
1144}
1145
1146// snapshot taken callback
Iliyan Malchev108dddf2011-03-28 16:10:12 -07001147void CameraService::Client::handleShutter(void) {
Nipun Kwatrab5ca4612010-09-11 19:31:10 -07001148 if (mPlayShutterSound) {
1149 mCameraService->playSound(SOUND_SHUTTER);
1150 }
Mathias Agopian65ab4712010-07-14 17:59:35 -07001151
Mathias Agopian65ab4712010-07-14 17:59:35 -07001152 sp<ICameraClient> c = mCameraClient;
1153 if (c != 0) {
1154 mLock.unlock();
1155 c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
1156 if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
1157 }
1158 disableMsgType(CAMERA_MSG_SHUTTER);
1159
Mathias Agopian65ab4712010-07-14 17:59:35 -07001160 mLock.unlock();
1161}
1162
1163// preview callback - frame buffer update
Wu-cheng Li57c86182011-07-30 05:00:37 +08001164void CameraService::Client::handlePreviewData(int32_t msgType,
1165 const sp<IMemory>& mem,
1166 camera_frame_metadata_t *metadata) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001167 ssize_t offset;
1168 size_t size;
1169 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1170
Mathias Agopian65ab4712010-07-14 17:59:35 -07001171 // local copy of the callback flags
1172 int flags = mPreviewCallbackFlag;
1173
1174 // is callback enabled?
Iliyan Malchev9e626522011-04-14 16:51:21 -07001175 if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001176 // If the enable bit is off, the copy-out and one-shot bits are ignored
1177 LOG2("frame callback is disabled");
1178 mLock.unlock();
1179 return;
1180 }
1181
1182 // hold a strong pointer to the client
1183 sp<ICameraClient> c = mCameraClient;
1184
1185 // clear callback flags if no client or one-shot mode
Iliyan Malchev9e626522011-04-14 16:51:21 -07001186 if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001187 LOG2("Disable preview callback");
Iliyan Malchev9e626522011-04-14 16:51:21 -07001188 mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
1189 CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
1190 CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
Wu-cheng Li0667de72010-09-03 16:40:32 -07001191 disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001192 }
1193
1194 if (c != 0) {
1195 // Is the received frame copied out or not?
Iliyan Malchev9e626522011-04-14 16:51:21 -07001196 if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001197 LOG2("frame is copied");
Wu-cheng Li57c86182011-07-30 05:00:37 +08001198 copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001199 } else {
1200 LOG2("frame is forwarded");
1201 mLock.unlock();
Wu-cheng Li57c86182011-07-30 05:00:37 +08001202 c->dataCallback(msgType, mem, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001203 }
1204 } else {
1205 mLock.unlock();
1206 }
1207}
1208
1209// picture callback - postview image ready
1210void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
1211 disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
1212
1213 sp<ICameraClient> c = mCameraClient;
1214 mLock.unlock();
1215 if (c != 0) {
Wu-cheng Li57c86182011-07-30 05:00:37 +08001216 c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001217 }
1218}
1219
1220// picture callback - raw image ready
1221void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
1222 disableMsgType(CAMERA_MSG_RAW_IMAGE);
1223
1224 ssize_t offset;
1225 size_t size;
1226 sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
1227
Mathias Agopian65ab4712010-07-14 17:59:35 -07001228 sp<ICameraClient> c = mCameraClient;
1229 mLock.unlock();
1230 if (c != 0) {
Wu-cheng Li57c86182011-07-30 05:00:37 +08001231 c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001232 }
1233}
1234
1235// picture callback - compressed picture ready
1236void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
1237 disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
1238
1239 sp<ICameraClient> c = mCameraClient;
1240 mLock.unlock();
1241 if (c != 0) {
Wu-cheng Li57c86182011-07-30 05:00:37 +08001242 c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001243 }
1244}
1245
1246
1247void CameraService::Client::handleGenericNotify(int32_t msgType,
1248 int32_t ext1, int32_t ext2) {
1249 sp<ICameraClient> c = mCameraClient;
1250 mLock.unlock();
1251 if (c != 0) {
1252 c->notifyCallback(msgType, ext1, ext2);
1253 }
1254}
1255
1256void CameraService::Client::handleGenericData(int32_t msgType,
Wu-cheng Li57c86182011-07-30 05:00:37 +08001257 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001258 sp<ICameraClient> c = mCameraClient;
1259 mLock.unlock();
1260 if (c != 0) {
Wu-cheng Li57c86182011-07-30 05:00:37 +08001261 c->dataCallback(msgType, dataPtr, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001262 }
1263}
1264
1265void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
1266 int32_t msgType, const sp<IMemory>& dataPtr) {
1267 sp<ICameraClient> c = mCameraClient;
1268 mLock.unlock();
1269 if (c != 0) {
1270 c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
1271 }
1272}
1273
1274void CameraService::Client::copyFrameAndPostCopiedFrame(
Wu-cheng Li57c86182011-07-30 05:00:37 +08001275 int32_t msgType, const sp<ICameraClient>& client,
1276 const sp<IMemoryHeap>& heap, size_t offset, size_t size,
1277 camera_frame_metadata_t *metadata) {
Mathias Agopian65ab4712010-07-14 17:59:35 -07001278 LOG2("copyFrameAndPostCopiedFrame");
1279 // It is necessary to copy out of pmem before sending this to
1280 // the callback. For efficiency, reuse the same MemoryHeapBase
1281 // provided it's big enough. Don't allocate the memory or
1282 // perform the copy if there's no callback.
1283 // hold the preview lock while we grab a reference to the preview buffer
1284 sp<MemoryHeapBase> previewBuffer;
1285
1286 if (mPreviewBuffer == 0) {
1287 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1288 } else if (size > mPreviewBuffer->virtualSize()) {
1289 mPreviewBuffer.clear();
1290 mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
1291 }
1292 if (mPreviewBuffer == 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001293 ALOGE("failed to allocate space for preview buffer");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001294 mLock.unlock();
1295 return;
1296 }
1297 previewBuffer = mPreviewBuffer;
1298
1299 memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
1300
1301 sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
1302 if (frame == 0) {
Steve Block29357bc2012-01-06 19:20:56 +00001303 ALOGE("failed to allocate space for frame callback");
Mathias Agopian65ab4712010-07-14 17:59:35 -07001304 mLock.unlock();
1305 return;
1306 }
1307
1308 mLock.unlock();
Wu-cheng Li57c86182011-07-30 05:00:37 +08001309 client->dataCallback(msgType, frame, metadata);
Mathias Agopian65ab4712010-07-14 17:59:35 -07001310}
1311
Wu-cheng Lie09591e2010-10-14 20:17:44 +08001312int CameraService::Client::getOrientation(int degrees, bool mirror) {
1313 if (!mirror) {
1314 if (degrees == 0) return 0;
1315 else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
1316 else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
1317 else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
1318 } else { // Do mirror (horizontal flip)
1319 if (degrees == 0) { // FLIP_H and ROT_0
1320 return HAL_TRANSFORM_FLIP_H;
1321 } else if (degrees == 90) { // FLIP_H and ROT_90
1322 return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
1323 } else if (degrees == 180) { // FLIP_H and ROT_180
1324 return HAL_TRANSFORM_FLIP_V;
1325 } else if (degrees == 270) { // FLIP_H and ROT_270
1326 return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
1327 }
1328 }
Steve Block29357bc2012-01-06 19:20:56 +00001329 ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
Wu-cheng Lie09591e2010-10-14 20:17:44 +08001330 return -1;
1331}
1332
Wu-cheng Li2fd24402012-02-23 19:01:00 -08001333// Whether the client wants to keep the camera from taking
1334bool CameraService::Client::keep() const {
1335 return mKeep;
1336}
Wu-cheng Lie09591e2010-10-14 20:17:44 +08001337
Mathias Agopian65ab4712010-07-14 17:59:35 -07001338// ----------------------------------------------------------------------------
1339
1340static const int kDumpLockRetries = 50;
1341static const int kDumpLockSleep = 60000;
1342
1343static bool tryLock(Mutex& mutex)
1344{
1345 bool locked = false;
1346 for (int i = 0; i < kDumpLockRetries; ++i) {
1347 if (mutex.tryLock() == NO_ERROR) {
1348 locked = true;
1349 break;
1350 }
1351 usleep(kDumpLockSleep);
1352 }
1353 return locked;
1354}
1355
1356status_t CameraService::dump(int fd, const Vector<String16>& args) {
1357 static const char* kDeadlockedString = "CameraService may be deadlocked\n";
1358
1359 const size_t SIZE = 256;
1360 char buffer[SIZE];
1361 String8 result;
1362 if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
1363 snprintf(buffer, SIZE, "Permission Denial: "
1364 "can't dump CameraService from pid=%d, uid=%d\n",
1365 getCallingPid(),
1366 getCallingUid());
1367 result.append(buffer);
1368 write(fd, result.string(), result.size());
1369 } else {
1370 bool locked = tryLock(mServiceLock);
1371 // failed to lock - CameraService is probably deadlocked
1372 if (!locked) {
1373 String8 result(kDeadlockedString);
1374 write(fd, result.string(), result.size());
1375 }
1376
1377 bool hasClient = false;
1378 for (int i = 0; i < mNumberOfCameras; i++) {
1379 sp<Client> client = mClient[i].promote();
1380 if (client == 0) continue;
1381 hasClient = true;
1382 sprintf(buffer, "Client[%d] (%p) PID: %d\n",
1383 i,
1384 client->getCameraClient()->asBinder().get(),
1385 client->mClientPid);
1386 result.append(buffer);
1387 write(fd, result.string(), result.size());
1388 client->mHardware->dump(fd, args);
1389 }
1390 if (!hasClient) {
1391 result.append("No camera client yet.\n");
1392 write(fd, result.string(), result.size());
1393 }
1394
1395 if (locked) mServiceLock.unlock();
1396
1397 // change logging level
1398 int n = args.size();
1399 for (int i = 0; i + 1 < n; i++) {
1400 if (args[i] == String16("-v")) {
1401 String8 levelStr(args[i+1]);
1402 int level = atoi(levelStr.string());
1403 sprintf(buffer, "Set Log Level to %d", level);
1404 result.append(buffer);
1405 setLogLevel(level);
1406 }
1407 }
1408 }
1409 return NO_ERROR;
1410}
1411
Mathias Agopian65ab4712010-07-14 17:59:35 -07001412}; // namespace android