summaryrefslogtreecommitdiffstats
path: root/services/camera/libcameraservice/CameraService.cpp
diff options
context:
space:
mode:
authorIgor Murashkin <iam@google.com>2013-02-27 12:55:20 -0800
committerIgor Murashkin <iam@google.com>2013-02-28 15:55:15 -0800
commitbfc9915f482520eb9676c6d2dbf7f1ac078d937d (patch)
tree1353c3f2f63777397770edfd1f146c691e5684e2 /services/camera/libcameraservice/CameraService.cpp
parent3fa4891f54bbfdbe8ee652930d22c96639964eff (diff)
downloadframeworks_av-bfc9915f482520eb9676c6d2dbf7f1ac078d937d.zip
frameworks_av-bfc9915f482520eb9676c6d2dbf7f1ac078d937d.tar.gz
frameworks_av-bfc9915f482520eb9676c6d2dbf7f1ac078d937d.tar.bz2
Camera: Drop ProCamera connections when a Camera connection happens
* Also adds an ICameraServiceListener with available/not available statuses Bug: 8291653 Change-Id: I24680f1a2dc109510caf451cf7c7bd180b670d84
Diffstat (limited to 'services/camera/libcameraservice/CameraService.cpp')
-rw-r--r--services/camera/libcameraservice/CameraService.cpp126
1 files changed, 125 insertions, 1 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index d7c8807..8c4f619 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -77,6 +77,10 @@ CameraService::CameraService()
{
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
+
+ for (size_t i = 0; i < MAX_CAMERAS; ++i) {
+ mStatusList[i] = ICameraServiceListener::STATUS_AVAILABLE;
+ }
}
void CameraService::onFirstRef()
@@ -155,6 +159,23 @@ int CameraService::getDeviceVersion(int cameraId, int* facing) {
return deviceVersion;
}
+bool CameraService::isValidCameraId(int cameraId) {
+ int facing;
+ int deviceVersion = getDeviceVersion(cameraId, &facing);
+
+ switch(deviceVersion) {
+ case CAMERA_DEVICE_API_VERSION_1_0:
+ case CAMERA_DEVICE_API_VERSION_2_0:
+ case CAMERA_DEVICE_API_VERSION_2_1:
+ case CAMERA_DEVICE_API_VERSION_3_0:
+ return true;
+ default:
+ return false;
+ }
+
+ return false;
+}
+
sp<ICamera> CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
@@ -236,6 +257,10 @@ sp<ICamera> CameraService::connect(
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
+ if (isValidCameraId(cameraId)) {
+ updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE, cameraId);
+ }
+
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this, cameraClient,
@@ -259,6 +284,9 @@ sp<ICamera> CameraService::connect(
}
if (client->initialize(mModule) != OK) {
+ // this is probably not recoverable.. but maybe the client can try again
+ updateStatus(ICameraServiceListener::STATUS_AVAILABLE, cameraId);
+
return NULL;
}
@@ -266,6 +294,7 @@ sp<ICamera> CameraService::connect(
mClient[cameraId] = client;
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
+
return client;
}
@@ -275,6 +304,7 @@ sp<IProCameraUser> CameraService::connect(
const String16& clientPackageName,
int clientUid)
{
+ String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
// TODO: use clientPackageName and clientUid with appOpsMangr
@@ -301,6 +331,15 @@ sp<IProCameraUser> CameraService::connect(
return NULL;
}
+ // TODO: allow concurrent connections with a ProCamera
+ if (mBusy[cameraId]) {
+
+ ALOGW("CameraService::connectPro X (pid %d, \"%s\") rejected"
+ " (camera %d is still busy).", callingPid,
+ clientName8.string(), cameraId);
+ return NULL;
+ }
+
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
@@ -333,9 +372,45 @@ sp<IProCameraUser> CameraService::connect(
LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId,
getpid());
return client;
+}
+status_t CameraService::addListener(
+ const sp<ICameraServiceListener>& listener) {
+ ALOGV("%s: Add listener %p", __FUNCTION__, listener.get());
- return NULL;
+ Mutex::Autolock lock(mServiceLock);
+
+ Vector<sp<ICameraServiceListener> >::iterator it, end;
+ for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
+ if ((*it)->asBinder() == listener->asBinder()) {
+ ALOGW("%s: Tried to add listener %p which was already subscribed",
+ __FUNCTION__, listener.get());
+ return ALREADY_EXISTS;
+ }
+ }
+
+ mListenerList.push_back(listener);
+
+ return OK;
+}
+status_t CameraService::removeListener(
+ const sp<ICameraServiceListener>& listener) {
+ ALOGV("%s: Remove listener %p", __FUNCTION__, listener.get());
+
+ Mutex::Autolock lock(mServiceLock);
+
+ Vector<sp<ICameraServiceListener> >::iterator it;
+ for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
+ if ((*it)->asBinder() == listener->asBinder()) {
+ mListenerList.erase(it);
+ return OK;
+ }
+ }
+
+ ALOGW("%s: Tried to remove a listener %p which was not subscribed",
+ __FUNCTION__, listener.get());
+
+ return BAD_VALUE;
}
void CameraService::removeClientByRemote(const wp<IBinder>& remoteBinder) {
@@ -699,6 +774,8 @@ void CameraService::Client::notifyError() {
void CameraService::Client::disconnect() {
BasicClient::disconnect();
mCameraService->setCameraFree(mCameraId);
+ mCameraService->updateStatus(ICameraServiceListener::STATUS_AVAILABLE,
+ mCameraId);
}
CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client):
@@ -774,6 +851,10 @@ bool CameraService::ProClient::hasExclusiveLock() {
return false;
}
+void CameraService::ProClient::onExclusiveLockStolen() {
+ ALOGE("%s: not implemented yet", __FUNCTION__);
+}
+
status_t CameraService::ProClient::submitRequest(camera_metadata_t* request, bool streaming) {
ALOGE("%s: not implemented yet", __FUNCTION__);
@@ -944,4 +1025,47 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
}
+void CameraService::updateStatus(ICameraServiceListener::Status status,
+ int32_t cameraId) {
+ // do not lock mServiceLock here or can get into a deadlock from
+ // connect() -> ProClient::disconnect -> updateStatus
+ Mutex::Autolock lock(mStatusMutex);
+ updateStatusUnsafe(status, cameraId);
+}
+
+void CameraService::updateStatusUnsafe(ICameraServiceListener::Status status,
+ int32_t cameraId) {
+
+ ICameraServiceListener::Status oldStatus = mStatusList[cameraId];
+
+ mStatusList[cameraId] = status;
+
+ if (oldStatus != status) {
+ ALOGV("%s: Status has changed for camera ID %d from 0x%x to 0x%x",
+ __FUNCTION__, cameraId, (uint32_t)oldStatus, (uint32_t)status);
+
+ /**
+ * ProClients lose their exclusive lock.
+ * - Done before the CameraClient can initialize the HAL device,
+ * since we want to be able to close it before they get to initialize
+ */
+ if (status == ICameraServiceListener::STATUS_NOT_AVAILABLE) {
+ Vector<wp<ProClient> > proClients(mProClientList[cameraId]);
+ Vector<wp<ProClient> >::const_iterator it;
+
+ for (it = proClients.begin(); it != proClients.end(); ++it) {
+ sp<ProClient> proCl = it->promote();
+ if (proCl.get() != NULL) {
+ proCl->onExclusiveLockStolen();
+ }
+ }
+ }
+
+ Vector<sp<ICameraServiceListener> >::const_iterator it;
+ for (it = mListenerList.begin(); it != mListenerList.end(); ++it) {
+ (*it)->onStatusChanged(status, cameraId);
+ }
+ }
+}
+
}; // namespace android