diff options
Diffstat (limited to 'camera/libcameraservice/CameraService.cpp')
-rw-r--r-- | camera/libcameraservice/CameraService.cpp | 195 |
1 files changed, 121 insertions, 74 deletions
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp index 6419a5c..00bd54e 100644 --- a/camera/libcameraservice/CameraService.cpp +++ b/camera/libcameraservice/CameraService.cpp @@ -16,7 +16,6 @@ ** limitations under the License. */ -//#define LOG_NDEBUG 0 #define LOG_TAG "CameraService" #include <utils/Log.h> @@ -26,7 +25,11 @@ #include <utils/Errors.h> #include <binder/MemoryBase.h> #include <binder/MemoryHeapBase.h> -#include <ui/ICameraService.h> +#include <camera/ICameraService.h> +#include <surfaceflinger/ISurface.h> +#include <ui/Overlay.h> + +#include <hardware/hardware.h> #include <media/mediaplayer.h> #include <media/AudioSystem.h> @@ -95,7 +98,7 @@ CameraService::~CameraService() sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) { int callingPid = getCallingPid(); - LOGD("CameraService::connect E (pid %d, client %p)", callingPid, + LOGV("CameraService::connect E (pid %d, client %p)", callingPid, cameraClient->asBinder().get()); Mutex::Autolock lock(mServiceLock); @@ -106,30 +109,30 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) sp<ICameraClient> currentCameraClient(currentClient->getCameraClient()); if (cameraClient->asBinder() == currentCameraClient->asBinder()) { // This is the same client reconnecting... - LOGD("CameraService::connect X (pid %d, same client %p) is reconnecting...", + LOGV("CameraService::connect X (pid %d, same client %p) is reconnecting...", callingPid, cameraClient->asBinder().get()); return currentClient; } else { // It's another client... reject it - LOGD("CameraService::connect X (pid %d, new client %p) rejected. " + LOGV("CameraService::connect X (pid %d, new client %p) rejected. " "(old pid %d, old client %p)", callingPid, cameraClient->asBinder().get(), currentClient->mClientPid, currentCameraClient->asBinder().get()); if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) { - LOGD("The old client is dead!"); + LOGV("The old client is dead!"); } return client; } } else { // can't promote, the previous client has died... - LOGD("New client (pid %d) connecting, old reference was dangling...", + LOGV("New client (pid %d) connecting, old reference was dangling...", callingPid); mClient.clear(); } } if (mUsers > 0) { - LOGD("Still have client, rejected"); + LOGV("Still have client, rejected"); return client; } @@ -141,7 +144,7 @@ sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient) // the refcount. client->trackMe(true, true); #endif - LOGD("CameraService::connect X"); + LOGV("CameraService::connect X"); return client; } @@ -157,7 +160,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) if (mClient == 0) { // This happens when we have already disconnected. - LOGD("removeClient (pid %d): already disconnected", callingPid); + LOGV("removeClient (pid %d): already disconnected", callingPid); return; } @@ -165,7 +168,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) // Client::~Client() -> disconnect() -> removeClient(). client = mClient.promote(); if (client == 0) { - LOGD("removeClient (pid %d): no more strong reference", callingPid); + LOGV("removeClient (pid %d): no more strong reference", callingPid); mClient.clear(); return; } @@ -178,7 +181,7 @@ void CameraService::removeClient(const sp<ICameraClient>& cameraClient) mClient.clear(); } - LOGD("removeClient (pid %d) done", callingPid); + LOGV("removeClient (pid %d) done", callingPid); } // The reason we need this count is a new CameraService::connect() request may @@ -198,7 +201,7 @@ void CameraService::decUsers() { static sp<MediaPlayer> newMediaPlayer(const char *file) { sp<MediaPlayer> mp = new MediaPlayer(); - if (mp->setDataSource(file) == NO_ERROR) { + if (mp->setDataSource(file, NULL /* headers */) == NO_ERROR) { mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE); mp->prepare(); } else { @@ -212,7 +215,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, pid_t clientPid) { int callingPid = getCallingPid(); - LOGD("Client::Client E (pid %d)", callingPid); + LOGV("Client::Client E (pid %d)", callingPid); mCameraService = cameraService; mCameraClient = cameraClient; mClientPid = clientPid; @@ -236,8 +239,9 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, // Callback is disabled by default mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; + mOrientation = 0; cameraService->incUsers(); - LOGD("Client::Client X (pid %d)", callingPid); + LOGV("Client::Client X (pid %d)", callingPid); } status_t CameraService::Client::checkPid() @@ -253,7 +257,7 @@ status_t CameraService::Client::checkPid() status_t CameraService::Client::lock() { int callingPid = getCallingPid(); - LOGD("lock from pid %d (mClientPid %d)", callingPid, mClientPid); + LOGV("lock from pid %d (mClientPid %d)", callingPid, mClientPid); Mutex::Autolock _l(mLock); // lock camera to this client if the the camera is unlocked if (mClientPid == 0) { @@ -267,13 +271,13 @@ status_t CameraService::Client::lock() status_t CameraService::Client::unlock() { int callingPid = getCallingPid(); - LOGD("unlock from pid %d (mClientPid %d)", callingPid, mClientPid); + LOGV("unlock from pid %d (mClientPid %d)", callingPid, mClientPid); Mutex::Autolock _l(mLock); // allow anyone to use camera status_t result = checkPid(); if (result == NO_ERROR) { mClientPid = 0; - LOGD("clear mCameraClient (pid %d)", callingPid); + LOGV("clear mCameraClient (pid %d)", callingPid); // we need to remove the reference so that when app goes // away, the reference count goes to 0. mCameraClient.clear(); @@ -286,7 +290,7 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) int callingPid = getCallingPid(); // connect a new process to the camera - LOGD("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get()); + LOGV("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get()); // I hate this hack, but things get really ugly when the media recorder // service is handing back the camera to the app. The ICameraClient @@ -310,14 +314,14 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) // did the client actually change? if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) { - LOGD("Connect to the same client"); + LOGV("Connect to the same client"); return NO_ERROR; } mCameraClient = client; mClientPid = -1; mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP; - LOGD("Connect to the new client (pid %d, client %p)", + LOGV("Connect to the new client (pid %d, client %p)", callingPid, mCameraClient->asBinder().get()); } @@ -344,7 +348,7 @@ CameraService::Client::~Client() int callingPid = getCallingPid(); // tear down client - LOGD("Client::~Client E (pid %d, client %p)", + LOGV("Client::~Client E (pid %d, client %p)", callingPid, getCameraClient()->asBinder().get()); if (mSurface != 0 && !mUseOverlay) { #if HAVE_ANDROID_OS @@ -373,23 +377,23 @@ CameraService::Client::~Client() // make sure we tear down the hardware mClientPid = callingPid; disconnect(); - LOGD("Client::~Client X (pid %d)", mClientPid); + LOGV("Client::~Client X (pid %d)", mClientPid); } void CameraService::Client::disconnect() { int callingPid = getCallingPid(); - LOGD("Client::disconnect() E (pid %d client %p)", + LOGV("Client::disconnect() E (pid %d client %p)", callingPid, getCameraClient()->asBinder().get()); Mutex::Autolock lock(mLock); if (mClientPid <= 0) { - LOGD("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid); + LOGV("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid); return; } if (checkPid() != NO_ERROR) { - LOGD("Different client - don't disconnect"); + LOGV("Different client - don't disconnect"); return; } @@ -397,7 +401,7 @@ void CameraService::Client::disconnect() // from the user directly, or called by the destructor. if (mHardware == 0) return; - LOGD("hardware teardown"); + LOGV("hardware teardown"); // Before destroying mHardware, we must make sure it's in the // idle state. mHardware->stopPreview(); @@ -421,13 +425,13 @@ void CameraService::Client::disconnect() mCameraService->removeClient(mCameraClient); mCameraService->decUsers(); - LOGD("Client::disconnect() X (pid %d)", callingPid); + LOGV("Client::disconnect() X (pid %d)", callingPid); } // pass the buffered ISurface to the camera service status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) { - LOGD("setPreviewDisplay(%p) (pid %d)", + LOGV("setPreviewDisplay(%p) (pid %d)", ((surface == NULL) ? NULL : surface.get()), getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); @@ -438,7 +442,7 @@ status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface) // asBinder() is safe on NULL (returns NULL) if (surface->asBinder() != mSurface->asBinder()) { if (mSurface != 0) { - LOGD("clearing old preview surface %p", mSurface.get()); + LOGV("clearing old preview surface %p", mSurface.get()); if ( !mUseOverlay) { mSurface->unregisterBuffers(); @@ -487,7 +491,7 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) { int callingPid = getCallingPid(); - LOGD("startCameraMode(%d) (pid %d)", mode, callingPid); + LOGV("startCameraMode(%d) (pid %d)", mode, callingPid); /* we cannot call into mHardware with mLock held because * mHardware has callbacks onto us which acquire this lock @@ -512,7 +516,7 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) default: // CAMERA_PREVIEW_MODE if (mSurface == 0) { - LOGD("mSurface is not set yet."); + LOGV("mSurface is not set yet."); } return startPreviewMode(); } @@ -520,7 +524,7 @@ status_t CameraService::Client::startCameraMode(camera_mode mode) status_t CameraService::Client::startRecordingMode() { - LOGD("startRecordingMode (pid %d)", getCallingPid()); + LOGV("startRecordingMode (pid %d)", getCallingPid()); status_t ret = UNKNOWN_ERROR; @@ -547,7 +551,7 @@ status_t CameraService::Client::startRecordingMode() status_t CameraService::Client::setOverlay() { - LOGD("setOverlay"); + LOGV("setOverlay"); int w, h; CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&w, &h); @@ -571,9 +575,10 @@ status_t CameraService::Client::setOverlay() // wait in the createOverlay call if the previous overlay is in the // process of being destroyed. for (int retry = 0; retry < 50; ++retry) { - mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT); + mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT, + mOrientation); if (mOverlayRef != NULL) break; - LOGD("Overlay create failed - retrying"); + LOGW("Overlay create failed - retrying"); usleep(20000); } if ( mOverlayRef.get() == NULL ) @@ -602,15 +607,10 @@ status_t CameraService::Client::registerPreviewBuffers() CameraParameters params(mHardware->getParameters()); params.getPreviewSize(&w, &h); - uint32_t transform = 0; - if (params.getOrientation() == - CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { - LOGV("portrait mode"); - transform = ISurface::BufferHeap::ROT_90; - } + // don't use a hardcoded format here ISurface::BufferHeap buffers(w, h, w, h, - PIXEL_FORMAT_YCbCr_420_SP, - transform, + HAL_PIXEL_FORMAT_YCrCb_420_SP, + mOrientation, 0, mHardware->getPreviewHeap()); @@ -623,7 +623,7 @@ status_t CameraService::Client::registerPreviewBuffers() status_t CameraService::Client::startPreviewMode() { - LOGD("startPreviewMode (pid %d)", getCallingPid()); + LOGV("startPreviewMode (pid %d)", getCallingPid()); // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) { @@ -659,14 +659,14 @@ status_t CameraService::Client::startPreviewMode() status_t CameraService::Client::startPreview() { - LOGD("startPreview (pid %d)", getCallingPid()); + LOGV("startPreview (pid %d)", getCallingPid()); return startCameraMode(CAMERA_PREVIEW_MODE); } status_t CameraService::Client::startRecording() { - LOGD("startRecording (pid %d)", getCallingPid()); + LOGV("startRecording (pid %d)", getCallingPid()); if (mMediaPlayerBeep.get() != NULL) { // do not play record jingle if stream volume is 0 @@ -687,7 +687,7 @@ status_t CameraService::Client::startRecording() // stop preview mode void CameraService::Client::stopPreview() { - LOGD("stopPreview (pid %d)", getCallingPid()); + LOGV("stopPreview (pid %d)", getCallingPid()); // hold main lock during state transition { @@ -701,7 +701,7 @@ void CameraService::Client::stopPreview() mHardware->stopPreview(); mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME); - LOGD("stopPreview(), hardware stopped OK"); + LOGV("stopPreview(), hardware stopped OK"); if (mSurface != 0 && !mUseOverlay) { mSurface->unregisterBuffers(); @@ -718,7 +718,7 @@ void CameraService::Client::stopPreview() // stop recording mode void CameraService::Client::stopRecording() { - LOGD("stopRecording (pid %d)", getCallingPid()); + LOGV("stopRecording (pid %d)", getCallingPid()); // hold main lock during state transition { @@ -737,7 +737,7 @@ void CameraService::Client::stopRecording() mHardware->stopRecording(); mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME); - LOGD("stopRecording(), hardware stopped OK"); + LOGV("stopRecording(), hardware stopped OK"); } // hold preview buffer lock @@ -805,14 +805,14 @@ static void dump_to_file(const char *fname, int nw, cnt = 0; uint32_t written = 0; - LOGD("opening file [%s]\n", fname); + LOGV("opening file [%s]\n", fname); int fd = open(fname, O_RDWR | O_CREAT); if (fd < 0) { LOGE("failed to create file [%s]: %s", fname, strerror(errno)); return; } - LOGD("writing %d bytes to file [%s]\n", size, fname); + LOGV("writing %d bytes to file [%s]\n", size, fname); while (written < size) { nw = ::write(fd, buf + written, @@ -825,7 +825,7 @@ static void dump_to_file(const char *fname, written += nw; cnt++; } - LOGD("done writing %d bytes to file [%s] in %d passes\n", + LOGV("done writing %d bytes to file [%s] in %d passes\n", size, fname, cnt); ::close(fd); } @@ -833,7 +833,7 @@ static void dump_to_file(const char *fname, status_t CameraService::Client::autoFocus() { - LOGD("autoFocus (pid %d)", getCallingPid()); + LOGV("autoFocus (pid %d)", getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); @@ -849,7 +849,7 @@ status_t CameraService::Client::autoFocus() status_t CameraService::Client::cancelAutoFocus() { - LOGD("cancelAutoFocus (pid %d)", getCallingPid()); + LOGV("cancelAutoFocus (pid %d)", getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); @@ -866,7 +866,7 @@ status_t CameraService::Client::cancelAutoFocus() // take a picture - image is returned in callback status_t CameraService::Client::takePicture() { - LOGD("takePicture (pid %d)", getCallingPid()); + LOGV("takePicture (pid %d)", getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); @@ -920,12 +920,6 @@ void CameraService::Client::handleShutter( if (mSurface != 0 && !mUseOverlay) { int w, h; CameraParameters params(mHardware->getParameters()); - uint32_t transform = 0; - if (params.getOrientation() == CameraParameters::CAMERA_ORIENTATION_PORTRAIT) { - LOGV("portrait mode"); - transform = ISurface::BufferHeap::ROT_90; - } - if (size == NULL) { params.getPictureSize(&w, &h); } else { @@ -933,10 +927,12 @@ void CameraService::Client::handleShutter( h = size->height; w &= ~1; h &= ~1; - LOGD("Snapshot image width=%d, height=%d", w, h); + LOGV("Snapshot image width=%d, height=%d", w, h); } + // FIXME: don't use hardcoded format constants here ISurface::BufferHeap buffers(w, h, w, h, - PIXEL_FORMAT_YCbCr_420_SP, transform, 0, mHardware->getRawHeap()); + HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0, + mHardware->getRawHeap()); mSurface->registerBuffers(buffers); } @@ -952,7 +948,7 @@ void CameraService::Client::handlePreviewData(const sp<IMemory>& mem) #if DEBUG_HEAP_LEAKS && 0 // debugging if (gWeakHeap == NULL) { if (gWeakHeap != heap) { - LOGD("SETTING PREVIEW HEAP"); + LOGV("SETTING PREVIEW HEAP"); heap->trackMe(true, true); gWeakHeap = heap; } @@ -1189,7 +1185,7 @@ void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msg // set preview/capture parameters - key/value pairs status_t CameraService::Client::setParameters(const String8& params) { - LOGD("setParameters(%s)", params.string()); + LOGV("setParameters(%s)", params.string()); Mutex::Autolock lock(mLock); status_t result = checkPid(); @@ -1201,6 +1197,7 @@ status_t CameraService::Client::setParameters(const String8& params) } CameraParameters p(params); + return mHardware->setParameters(p); } @@ -1215,17 +1212,41 @@ String8 CameraService::Client::getParameters() const } String8 params(mHardware->getParameters().flatten()); - LOGD("getParameters(%s)", params.string()); + LOGV("getParameters(%s)", params.string()); return params; } status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) { - LOGD("sendCommand (pid %d)", getCallingPid()); + LOGV("sendCommand (pid %d)", getCallingPid()); Mutex::Autolock lock(mLock); status_t result = checkPid(); if (result != NO_ERROR) return result; + if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) { + // The orientation cannot be set during preview. + if (mHardware->previewEnabled()) { + return INVALID_OPERATION; + } + switch (arg1) { + case 0: + mOrientation = ISurface::BufferHeap::ROT_0; + break; + case 90: + mOrientation = ISurface::BufferHeap::ROT_90; + break; + case 180: + mOrientation = ISurface::BufferHeap::ROT_180; + break; + case 270: + mOrientation = ISurface::BufferHeap::ROT_270; + break; + default: + return BAD_VALUE; + } + return OK; + } + if (mHardware == 0) { LOGE("mHardware is NULL, returning."); return INVALID_OPERATION; @@ -1270,8 +1291,26 @@ void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame); } +static const int kDumpLockRetries = 50; +static const int kDumpLockSleep = 60000; + +static bool tryLock(Mutex& mutex) +{ + bool locked = false; + for (int i = 0; i < kDumpLockRetries; ++i) { + if (mutex.tryLock() == NO_ERROR) { + locked = true; + break; + } + usleep(kDumpLockSleep); + } + return locked; +} + status_t CameraService::dump(int fd, const Vector<String16>& args) { + static const char* kDeadlockedString = "CameraService may be deadlocked\n"; + const size_t SIZE = 256; char buffer[SIZE]; String8 result; @@ -1283,7 +1322,13 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) result.append(buffer); write(fd, result.string(), result.size()); } else { - AutoMutex lock(&mServiceLock); + bool locked = tryLock(mServiceLock); + // failed to lock - CameraService is probably deadlocked + if (!locked) { + String8 result(kDeadlockedString); + write(fd, result.string(), result.size()); + } + if (mClient != 0) { sp<Client> currentClient = mClient.promote(); sprintf(buffer, "Client (%p) PID: %d\n", @@ -1296,6 +1341,8 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) result.append("No camera client yet.\n"); write(fd, result.string(), result.size()); } + + if (locked) mServiceLock.unlock(); } return NO_ERROR; } @@ -1327,7 +1374,7 @@ status_t CameraService::onTransact( status_t err = BnCameraService::onTransact(code, data, reply, flags); #if DEBUG_HEAP_LEAKS - LOGD("+++ onTransact err %d code %d", err, code); + LOGV("+++ onTransact err %d code %d", err, code); if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) { // the 'service' command interrogates this binder for its name, and then supplies it @@ -1335,7 +1382,7 @@ status_t CameraService::onTransact( // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to // BnSurfaceComposer before falling through to this code). - LOGD("+++ onTransact code %d", code); + LOGV("+++ onTransact code %d", code); CHECK_INTERFACE(ICameraService, data, reply); @@ -1345,13 +1392,13 @@ status_t CameraService::onTransact( if (gWeakHeap != 0) { sp<IMemoryHeap> h = gWeakHeap.promote(); IMemoryHeap *p = gWeakHeap.unsafe_get(); - LOGD("CHECKING WEAK REFERENCE %p (%p)", h.get(), p); + LOGV("CHECKING WEAK REFERENCE %p (%p)", h.get(), p); if (h != 0) h->printRefs(); bool attempt_to_delete = data.readInt32() == 1; if (attempt_to_delete) { // NOT SAFE! - LOGD("DELETING WEAK REFERENCE %p (%p)", h.get(), p); + LOGV("DELETING WEAK REFERENCE %p (%p)", h.get(), p); if (p) delete p; } return NO_ERROR; |