Merge "Enable hdcp for WiFi display" into jb-mr1-dev
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 8c612d4..cacfa54 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -108,6 +108,11 @@
status_t requestIDRFrame();
+ // Notification will be posted once there "is something to do", i.e.
+ // an input/output buffer has become available, a format change is
+ // pending, an error is pending.
+ void requestActivityNotification(const sp<AMessage> ¬ify);
+
protected:
virtual ~MediaCodec();
virtual void onMessageReceived(const sp<AMessage> &msg);
@@ -132,22 +137,23 @@
};
enum {
- kWhatInit = 'init',
- kWhatConfigure = 'conf',
- kWhatStart = 'strt',
- kWhatStop = 'stop',
- kWhatRelease = 'rele',
- kWhatDequeueInputBuffer = 'deqI',
- kWhatQueueInputBuffer = 'queI',
- kWhatDequeueOutputBuffer = 'deqO',
- kWhatReleaseOutputBuffer = 'relO',
- kWhatGetBuffers = 'getB',
- kWhatFlush = 'flus',
- kWhatGetOutputFormat = 'getO',
- kWhatDequeueInputTimedOut = 'dITO',
- kWhatDequeueOutputTimedOut = 'dOTO',
- kWhatCodecNotify = 'codc',
- kWhatRequestIDRFrame = 'ridr',
+ kWhatInit = 'init',
+ kWhatConfigure = 'conf',
+ kWhatStart = 'strt',
+ kWhatStop = 'stop',
+ kWhatRelease = 'rele',
+ kWhatDequeueInputBuffer = 'deqI',
+ kWhatQueueInputBuffer = 'queI',
+ kWhatDequeueOutputBuffer = 'deqO',
+ kWhatReleaseOutputBuffer = 'relO',
+ kWhatGetBuffers = 'getB',
+ kWhatFlush = 'flus',
+ kWhatGetOutputFormat = 'getO',
+ kWhatDequeueInputTimedOut = 'dITO',
+ kWhatDequeueOutputTimedOut = 'dOTO',
+ kWhatCodecNotify = 'codc',
+ kWhatRequestIDRFrame = 'ridr',
+ kWhatRequestActivityNotification = 'racN',
};
enum {
@@ -191,6 +197,8 @@
List<sp<ABuffer> > mCSD;
+ sp<AMessage> mActivityNotify;
+
MediaCodec(const sp<ALooper> &looper);
static status_t PostAndAwaitResponse(
@@ -216,6 +224,8 @@
status_t setNativeWindow(
const sp<SurfaceTextureClient> &surfaceTextureClient);
+ void postActivityNotificationIfPossible();
+
DISALLOW_EVIL_CONSTRUCTORS(MediaCodec);
};
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 7f97430..56e6df0 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -333,6 +333,12 @@
return OK;
}
+void MediaCodec::requestActivityNotification(const sp<AMessage> ¬ify) {
+ sp<AMessage> msg = new AMessage(kWhatRequestActivityNotification, id());
+ msg->setMessage("notify", notify);
+ msg->post();
+}
+
////////////////////////////////////////////////////////////////////////////////
void MediaCodec::cancelPendingDequeueOperations() {
@@ -498,6 +504,7 @@
sendErrorReponse = false;
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
cancelPendingDequeueOperations();
break;
@@ -508,6 +515,7 @@
sendErrorReponse = false;
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
break;
}
}
@@ -600,6 +608,7 @@
(new AMessage)->postReply(mReplyID);
} else {
mFlags |= kFlagOutputBuffersChanged;
+ postActivityNotificationIfPossible();
}
}
break;
@@ -638,6 +647,7 @@
mOutputFormat = msg;
mFlags |= kFlagOutputFormatChanged;
+ postActivityNotificationIfPossible();
break;
}
@@ -669,6 +679,8 @@
err);
mFlags |= kFlagStickyError;
+ postActivityNotificationIfPossible();
+
cancelPendingDequeueOperations();
}
break;
@@ -680,6 +692,8 @@
++mDequeueInputTimeoutGeneration;
mFlags &= ~kFlagDequeueInputPending;
mDequeueInputReplyID = 0;
+ } else {
+ postActivityNotificationIfPossible();
}
break;
}
@@ -709,7 +723,10 @@
++mDequeueOutputTimeoutGeneration;
mFlags &= ~kFlagDequeueOutputPending;
mDequeueOutputReplyID = 0;
+ } else {
+ postActivityNotificationIfPossible();
}
+
break;
}
@@ -1145,6 +1162,15 @@
break;
}
+ case kWhatRequestActivityNotification:
+ {
+ CHECK(mActivityNotify == NULL);
+ CHECK(msg->findMessage("notify", &mActivityNotify));
+
+ postActivityNotificationIfPossible();
+ break;
+ }
+
default:
TRESPASS();
}
@@ -1210,6 +1236,8 @@
mFlags &= ~kFlagOutputFormatChanged;
mFlags &= ~kFlagOutputBuffersChanged;
mFlags &= ~kFlagStickyError;
+
+ mActivityNotify.clear();
}
mState = newState;
@@ -1477,4 +1505,19 @@
return OK;
}
+void MediaCodec::postActivityNotificationIfPossible() {
+ if (mActivityNotify == NULL) {
+ return;
+ }
+
+ if ((mFlags & (kFlagStickyError
+ | kFlagOutputBuffersChanged
+ | kFlagOutputFormatChanged))
+ || !mAvailPortBuffers[kPortIndexInput].empty()
+ || !mAvailPortBuffers[kPortIndexOutput].empty()) {
+ mActivityNotify->post();
+ mActivityNotify.clear();
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 6f336c7..0e8c9af 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -128,7 +128,7 @@
mOutputFormat->setString("mime", outputMIME.c_str());
int32_t audioBitrate = getBitrate("media.wfd.audio-bitrate", 128000);
- int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 5000000);
+ int32_t videoBitrate = getBitrate("media.wfd.video-bitrate", 2500000);
ALOGI("using audio bitrate of %d bps, video bitrate of %d bps",
audioBitrate, videoBitrate);
@@ -242,16 +242,18 @@
#if ENABLE_SILENCE_DETECTION
if (!mIsVideo) {
if (IsSilence(accessUnit)) {
- if (!mInSilentMode) {
- int64_t nowUs = ALooper::GetNowUs();
+ if (mInSilentMode) {
+ break;
+ }
- if (mFirstSilentFrameUs < 0ll) {
- mFirstSilentFrameUs = nowUs;
- } else if (nowUs >= mFirstSilentFrameUs + 1000000ll) {
- mInSilentMode = true;
- ALOGI("audio in silent mode now.");
- break;
- }
+ int64_t nowUs = ALooper::GetNowUs();
+
+ if (mFirstSilentFrameUs < 0ll) {
+ mFirstSilentFrameUs = nowUs;
+ } else if (nowUs >= mFirstSilentFrameUs + 10000000ll) {
+ mInSilentMode = true;
+ ALOGI("audio in silent mode now.");
+ break;
}
} else {
if (mInSilentMode) {
@@ -272,8 +274,17 @@
break;
}
- case kWhatDoMoreWork:
+ case kWhatEncoderActivity:
{
+#if 0
+ int64_t whenUs;
+ if (msg->findInt64("whenUs", &whenUs)) {
+ int64_t nowUs = ALooper::GetNowUs();
+ ALOGI("[%s] kWhatEncoderActivity after %lld us",
+ mIsVideo ? "video" : "audio", nowUs - whenUs);
+ }
+#endif
+
mDoMoreWorkPending = false;
if (mEncoder == NULL) {
@@ -326,7 +337,17 @@
}
mDoMoreWorkPending = true;
- (new AMessage(kWhatDoMoreWork, id()))->post(mIsVideo ? 10000ll : 5000ll);
+
+#if 1
+ if (mEncoderActivityNotify == NULL) {
+ mEncoderActivityNotify = new AMessage(kWhatEncoderActivity, id());
+ }
+ mEncoder->requestActivityNotification(mEncoderActivityNotify->dup());
+#else
+ sp<AMessage> notify = new AMessage(kWhatEncoderActivity, id());
+ notify->setInt64("whenUs", ALooper::GetNowUs());
+ mEncoder->requestActivityNotification(notify);
+#endif
}
status_t Converter::feedEncoderInputBuffers() {
@@ -373,15 +394,23 @@
}
status_t Converter::doMoreWork() {
- size_t bufferIndex;
- status_t err = mEncoder->dequeueInputBuffer(&bufferIndex);
-
- if (err == OK) {
- mAvailEncoderInputIndices.push_back(bufferIndex);
- feedEncoderInputBuffers();
- }
+ status_t err;
for (;;) {
+ size_t bufferIndex;
+ err = mEncoder->dequeueInputBuffer(&bufferIndex);
+
+ if (err != OK) {
+ break;
+ }
+
+ mAvailEncoderInputIndices.push_back(bufferIndex);
+ }
+
+ feedEncoderInputBuffers();
+
+ for (;;) {
+ size_t bufferIndex;
size_t offset;
size_t size;
int64_t timeUs;
@@ -404,9 +433,8 @@
sp<ABuffer> buffer = new ABuffer(size);
buffer->meta()->setInt64("timeUs", timeUs);
- if (!mIsVideo) {
- ALOGV("audio time %lld us (%.2f secs)", timeUs, timeUs / 1E6);
- }
+ ALOGV("[%s] time %lld us (%.2f secs)",
+ mIsVideo ? "video" : "audio", timeUs, timeUs / 1E6);
memcpy(buffer->data(),
mEncoderOutputBuffers.itemAt(bufferIndex)->base() + offset,
diff --git a/media/libstagefright/wifi-display/source/Converter.h b/media/libstagefright/wifi-display/source/Converter.h
index 93ff72f..8d45395 100644
--- a/media/libstagefright/wifi-display/source/Converter.h
+++ b/media/libstagefright/wifi-display/source/Converter.h
@@ -58,6 +58,7 @@
kWhatRequestIDRFrame,
kWhatShutdown,
kWhatMediaPullerNotify,
+ kWhatEncoderActivity,
};
void shutdownAsync();
@@ -75,6 +76,7 @@
sp<AMessage> mOutputFormat;
sp<MediaCodec> mEncoder;
+ sp<AMessage> mEncoderActivityNotify;
Vector<sp<ABuffer> > mEncoderInputBuffers;
Vector<sp<ABuffer> > mEncoderOutputBuffers;
diff --git a/media/libstagefright/wifi-display/source/PlaybackSession.cpp b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
index c91b4c8..ffdafed 100644
--- a/media/libstagefright/wifi-display/source/PlaybackSession.cpp
+++ b/media/libstagefright/wifi-display/source/PlaybackSession.cpp
@@ -919,13 +919,22 @@
source->setUseAbsoluteTimestamps();
+#if 1
sp<RepeaterSource> videoSource =
new RepeaterSource(source, 30.0 /* rateHz */);
+#endif
+#if 1
size_t numInputBuffers;
status_t err = addSource(
true /* isVideo */, videoSource, true /* isRepeaterSource */,
&numInputBuffers);
+#else
+ size_t numInputBuffers;
+ status_t err = addSource(
+ true /* isVideo */, source, false /* isRepeaterSource */,
+ &numInputBuffers);
+#endif
if (err != OK) {
return err;
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 1c650f6..948b59f 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -47,9 +47,10 @@
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
- int clientPid):
+ int clientPid,
+ int servicePid):
Client(cameraService, cameraClient,
- cameraId, cameraFacing, clientPid),
+ cameraId, cameraFacing, clientPid, servicePid),
mSharedCameraClient(cameraClient),
mParameters(cameraId, cameraFacing)
{
@@ -64,10 +65,10 @@
status_t Camera2Client::checkPid(const char* checkLocation) const {
int callingPid = getCallingPid();
- if (callingPid == mClientPid) return NO_ERROR;
+ if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
ALOGE("%s: attempt to use a locked camera from a different process"
- " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
+ " (old pid %d, new pid %d, servicePid %d)", checkLocation, mClientPid, callingPid, mServicePid);
return PERMISSION_DENIED;
}
@@ -138,8 +139,15 @@
mDestructionStarted = true;
- SharedParameters::Lock l(mParameters);
- if (l.mParameters.state != Parameters::DISCONNECTED) {
+ Parameters::State state;
+ // warning:
+ // holding on to locks more than necessary may be hazardous to your health
+ {
+ SharedParameters::Lock l(mParameters);
+ state = l.mParameters.state;
+ }
+
+ if (state != Parameters::DISCONNECTED) {
// Rewrite mClientPid to allow shutdown by CameraService
mClientPid = getCallingPid();
disconnect();
@@ -315,6 +323,21 @@
getCaptureStreamId());
result.appendFormat(" Recording stream ID: %d\n",
getRecordingStreamId());
+
+ result.append(" Quirks for this camera:\n");
+ bool haveQuirk = false;
+ if (p.quirks.triggerAfWithAuto) {
+ result.appendFormat(" triggerAfWithAuto\n");
+ haveQuirk = true;
+ }
+ if (p.quirks.useZslFormat) {
+ result.appendFormat(" useZslFormat\n");
+ haveQuirk = true;
+ }
+ if (!haveQuirk) {
+ result.appendFormat(" none\n");
+ }
+
write(fd, result.string(), result.size());
mStreamingProcessor->dump(fd, args);
@@ -404,9 +427,6 @@
mCameraClient = client;
mSharedCameraClient = client;
- SharedParameters::Lock l(mParameters);
- l.mParameters.state = Parameters::STOPPED;
-
return OK;
}
@@ -588,6 +608,9 @@
status_t Camera2Client::startPreviewL(Parameters ¶ms, bool restart) {
ATRACE_CALL();
status_t res;
+
+ ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
+
if (params.state == Parameters::PREVIEW && !restart) {
// Succeed attempt to re-enter preview state
ALOGI("%s: Not starting preview; already in preview state.",
@@ -777,6 +800,9 @@
status_t Camera2Client::startRecordingL(Parameters ¶ms, bool restart) {
status_t res;
+
+ ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
+
switch (params.state) {
case Parameters::STOPPED:
res = startPreviewL(params, false);
@@ -1415,6 +1441,8 @@
status_t Camera2Client::updateRequests(Parameters ¶ms) {
status_t res;
+ ALOGV("%s: Camera %d: state = %d", __FUNCTION__, getCameraId(), params.state);
+
res = mStreamingProcessor->updatePreviewRequest(params);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index 3a9d307..fb1dcde 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -74,7 +74,8 @@
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
- int clientPid);
+ int clientPid,
+ int servicePid);
virtual ~Camera2Client();
status_t initialize(camera_module_t *module);
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 2e4098e..25b7a58 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -42,6 +42,7 @@
Camera2Device::~Camera2Device()
{
ATRACE_CALL();
+ ALOGV("%s: Tearing down for camera id %d", __FUNCTION__, mId);
disconnect();
}
@@ -1114,9 +1115,17 @@
if (mState >= CONNECTED) {
res = native_window_api_disconnect(mConsumerInterface.get(),
NATIVE_WINDOW_API_CAMERA);
- if (res != OK) {
- ALOGE("%s: Unable to disconnect stream %d from native window",
- __FUNCTION__, mId);
+
+ /* this is not an error. if client calling process dies,
+ the window will also die and all calls to it will return
+ DEAD_OBJECT, thus it's already "disconnected" */
+ if (res == DEAD_OBJECT) {
+ ALOGW("%s: While disconnecting stream %d from native window, the"
+ " native window died from under us", __FUNCTION__, mId);
+ }
+ else if (res != OK) {
+ ALOGE("%s: Unable to disconnect stream %d from native window (error %d %s)",
+ __FUNCTION__, mId, res, strerror(-res));
return res;
}
}
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index c9c816a..5b59ef9 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -40,9 +40,9 @@
CameraClient::CameraClient(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- int cameraId, int cameraFacing, int clientPid):
+ int cameraId, int cameraFacing, int clientPid, int servicePid):
Client(cameraService, cameraClient,
- cameraId, cameraFacing, clientPid)
+ cameraId, cameraFacing, clientPid, servicePid)
{
int callingPid = getCallingPid();
LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
@@ -124,7 +124,7 @@
status_t CameraClient::checkPid() const {
int callingPid = getCallingPid();
- if (callingPid == mClientPid) return NO_ERROR;
+ if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
ALOGW("attempt to use a locked camera from a different process"
" (old pid %d, new pid %d)", mClientPid, callingPid);
diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h
index 256298d..2f31c4e 100644
--- a/services/camera/libcameraservice/CameraClient.h
+++ b/services/camera/libcameraservice/CameraClient.h
@@ -55,7 +55,8 @@
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
- int clientPid);
+ int clientPid,
+ int servicePid);
~CameraClient();
status_t initialize(camera_module_t *module);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 878afde..4d48d8d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -196,11 +196,11 @@
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
client = new CameraClient(this, cameraClient, cameraId,
- info.facing, callingPid);
+ info.facing, callingPid, getpid());
break;
case CAMERA_DEVICE_API_VERSION_2_0:
client = new Camera2Client(this, cameraClient, cameraId,
- info.facing, callingPid);
+ info.facing, callingPid, getpid());
break;
default:
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
@@ -211,8 +211,10 @@
return NULL;
}
+ cameraClient->asBinder()->linkToDeath(this);
+
mClient[cameraId] = client;
- LOG1("CameraService::connect X (id %d)", cameraId);
+ LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
return client;
}
@@ -220,12 +222,29 @@
int callingPid = getCallingPid();
LOG1("CameraService::removeClient E (pid %d)", callingPid);
- for (int i = 0; i < mNumberOfCameras; i++) {
- // Declare this before the lock to make absolutely sure the
- // destructor won't be called with the lock held.
- sp<Client> client;
+ // Declare this before the lock to make absolutely sure the
+ // destructor won't be called with the lock held.
+ Mutex::Autolock lock(mServiceLock);
- Mutex::Autolock lock(mServiceLock);
+ int outIndex;
+ sp<Client> client = findClientUnsafe(cameraClient, outIndex);
+
+ if (client != 0) {
+ // Found our camera, clear and leave.
+ LOG1("removeClient: clear camera %d", outIndex);
+ mClient[outIndex].clear();
+
+ client->unlinkToDeath(this);
+ }
+
+ LOG1("CameraService::removeClient X (pid %d)", callingPid);
+}
+
+sp<CameraService::Client> CameraService::findClientUnsafe(
+ const sp<ICameraClient>& cameraClient, int& outIndex) {
+ sp<Client> client;
+
+ for (int i = 0; i < mNumberOfCameras; i++) {
// This happens when we have already disconnected (or this is
// just another unused camera).
@@ -235,20 +254,21 @@
// Client::~Client() -> disconnect() -> removeClient().
client = mClient[i].promote();
- if (client == 0) {
+ // Clean up stale client entry
+ if (client == NULL) {
mClient[i].clear();
continue;
}
if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
- // Found our camera, clear and leave.
- LOG1("removeClient: clear camera %d", i);
- mClient[i].clear();
- break;
+ // Found our camera
+ outIndex = i;
+ return client;
}
}
- LOG1("CameraService::removeClient X (pid %d)", callingPid);
+ outIndex = -1;
+ return NULL;
}
CameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
@@ -261,6 +281,21 @@
return &mClientLock[cameraId];
}
+/*virtual*/sp<CameraService::Client> CameraService::getClientByRemote(
+ const sp<ICameraClient>& cameraClient) {
+
+ // Declare this before the lock to make absolutely sure the
+ // destructor won't be called with the lock held.
+ sp<Client> client;
+
+ Mutex::Autolock lock(mServiceLock);
+
+ int outIndex;
+ client = findClientUnsafe(cameraClient, outIndex);
+
+ return client;
+}
+
status_t CameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
// Permission checks
@@ -292,10 +327,14 @@
// the hardware first.
void CameraService::setCameraBusy(int cameraId) {
android_atomic_write(1, &mBusy[cameraId]);
+
+ ALOGV("setCameraBusy cameraId=%d", cameraId);
}
void CameraService::setCameraFree(int cameraId) {
android_atomic_write(0, &mBusy[cameraId]);
+
+ ALOGV("setCameraFree cameraId=%d", cameraId);
}
// We share the media players for shutter and recording sound for all clients.
@@ -350,7 +389,7 @@
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- int cameraId, int cameraFacing, int clientPid) {
+ int cameraId, int cameraFacing, int clientPid, int servicePid) {
int callingPid = getCallingPid();
LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
@@ -359,6 +398,7 @@
mCameraId = cameraId;
mCameraFacing = cameraFacing;
mClientPid = clientPid;
+ mServicePid = servicePid;
mDestructionStarted = false;
cameraService->setCameraBusy(cameraId);
@@ -514,4 +554,26 @@
return NO_ERROR;
}
+/*virtual*/void CameraService::binderDied(
+ const wp<IBinder> &who) {
+
+ ALOGV("java clients' binder died");
+
+ sp<IBinder> whoStrong = who.promote();
+
+ if (whoStrong == 0) {
+ ALOGV("java clients' binder death already cleaned up (normal case)");
+ return;
+ }
+
+ sp<ICameraClient> iCamClient = interface_cast<ICameraClient>(whoStrong);
+
+ sp<Client> cameraClient = getClientByRemote(iCamClient);
+ ALOGW("Disconnecting camera client %p since the binder for it "
+ "died (this pid %d)", cameraClient.get(), getCallingPid());
+
+ cameraClient->disconnect();
+
+}
+
}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 630fca7..f1e7df6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -34,7 +34,8 @@
class CameraService :
public BinderService<CameraService>,
- public BnCameraService
+ public BnCameraService,
+ public IBinder::DeathRecipient
{
friend class BinderService<CameraService>;
public:
@@ -54,6 +55,8 @@
virtual Client* getClientByIdUnsafe(int cameraId);
virtual Mutex* getClientLockById(int cameraId);
+ virtual sp<Client> getClientByRemote(const sp<ICameraClient>& cameraClient);
+
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
@@ -100,7 +103,8 @@
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
- int clientPid);
+ int clientPid,
+ int servicePid);
~Client();
// return our camera client
@@ -128,6 +132,7 @@
int mCameraId; // immutable after constructor
int mCameraFacing; // immutable after constructor
pid_t mClientPid;
+ pid_t mServicePid; // immutable after constructor
};
@@ -137,6 +142,9 @@
Mutex mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
int mNumberOfCameras;
+ // needs to be called with mServiceLock held
+ sp<Client> findClientUnsafe(const sp<ICameraClient>& cameraClient, int& outIndex);
+
// atomics to record whether the hardware is allocated to some client.
volatile int32_t mBusy[MAX_CAMERAS];
void setCameraBusy(int cameraId);
@@ -150,6 +158,9 @@
int mSoundRef; // reference count (release all MediaPlayer when 0)
camera_module_t *mModule;
+
+ // IBinder::DeathRecipient implementation
+ virtual void binderDied(const wp<IBinder> &who);
};
} // namespace android
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index ede97a6..3e9c255 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -86,6 +86,8 @@
// Since size should only change while preview is not running,
// assuming that all existing use of old callback stream is
// completed.
+ ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+ __FUNCTION__, client->getCameraId(), mCallbackStreamId);
res = device->deleteStream(mCallbackStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index c9498c2..98aa380 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -289,13 +289,6 @@
client->registerFrameListener(mCaptureId,
this);
- res = client->getCameraDevice()->clearStreamingRequest();
- if (res != OK) {
- ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
- "%s (%d)",
- __FUNCTION__, client->getCameraId(), strerror(-res), res);
- return DONE;
- }
// TODO: Actually select the right thing here.
res = processor->pushToReprocess(mCaptureId);
if (res != OK) {
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 7b368fa..a353679 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -107,6 +107,8 @@
}
if (currentWidth != (uint32_t)params.pictureWidth ||
currentHeight != (uint32_t)params.pictureHeight) {
+ ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+ __FUNCTION__, client->getCameraId(), mCaptureStreamId);
res = device->deleteStream(mCaptureStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index fd44a3e..74f4a7e 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -53,6 +53,9 @@
res = buildFastInfo();
if (res != OK) return res;
+ res = buildQuirks();
+ if (res != OK) return res;
+
camera_metadata_ro_entry_t availableProcessedSizes =
staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, 2);
if (!availableProcessedSizes.count) return NO_INIT;
@@ -891,6 +894,21 @@
return OK;
}
+status_t Parameters::buildQuirks() {
+ camera_metadata_ro_entry_t entry;
+ entry = info->find(ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO);
+ quirks.triggerAfWithAuto = (entry.count != 0 && entry.data.u8[0] == 1);
+ ALOGV_IF(quirks.triggerAfWithAuto, "Camera %d: Quirk triggerAfWithAuto enabled",
+ cameraId);
+
+ entry = info->find(ANDROID_QUIRKS_USE_ZSL_FORMAT);
+ quirks.useZslFormat = (entry.count != 0 && entry.data.u8[0] == 1);
+ ALOGV_IF(quirks.useZslFormat, "Camera %d: Quirk useZslFormat enabled",
+ cameraId);
+
+ return OK;
+}
+
camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag,
size_t minCount, size_t maxCount) const {
status_t res;
@@ -1039,6 +1057,10 @@
validatedParams.previewFpsRange[1] =
availableFrameRates.data.i32[i+1];
}
+ newParams.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+ String8::format("%d,%d",
+ validatedParams.previewFpsRange[0] * kFpsToApiScale,
+ validatedParams.previewFpsRange[1] * kFpsToApiScale));
}
// PICTURE_SIZE
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index c587ca5..47eb993 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -195,8 +195,10 @@
// Sets up default parameters
status_t initialize(const CameraMetadata *info);
- // Build fast device info
+ // Build fast-access device static info from static info
status_t buildFastInfo();
+ // Query for quirks from static info
+ status_t buildQuirks();
// Get entry from camera static characteristics information. min/maxCount
// are used for error checking the number of values in the entry. 0 for
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index 140138d..744b7ed 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -170,6 +170,9 @@
if (client == 0) return INVALID_OPERATION;
sp<Camera2Device> device = client->getCameraDevice();
+ ALOGV("%s: for cameraId %d on streamId %d",
+ __FUNCTION__, client->getCameraId(), mPreviewStreamId);
+
res = device->waitUntilDrained();
if (res != OK) {
ALOGE("%s: Error waiting for preview to drain: %s (%d)",
@@ -351,6 +354,8 @@
sp<Camera2Client> client = mClient.promote();
if (client == 0) return INVALID_OPERATION;
+ ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type);
+
Mutex::Autolock m(mMutex);
CameraMetadata &request = (type == PREVIEW) ?
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 9516f97..7977f9d 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -147,6 +147,8 @@
client->getCameraId(), strerror(-res), res);
return res;
}
+ ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+ __FUNCTION__, client->getCameraId(), mZslStreamId);
res = device->deleteStream(mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to delete old output stream "
@@ -161,9 +163,12 @@
if (mZslStreamId == NO_STREAM) {
// Create stream for HAL production
// TODO: Sort out better way to select resolution for ZSL
+ int streamType = params.quirks.useZslFormat ?
+ (int)CAMERA2_HAL_PIXEL_FORMAT_ZSL :
+ (int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
res = device->createStream(mZslWindow,
params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
- CAMERA2_HAL_PIXEL_FORMAT_ZSL, 0,
+ streamType, 0,
&mZslStreamId);
if (res != OK) {
ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
@@ -292,6 +297,14 @@
return INVALID_OPERATION;
}
+ res = client->getCameraDevice()->clearStreamingRequest();
+ if (res != OK) {
+ ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
+ "%s (%d)",
+ __FUNCTION__, client->getCameraId(), strerror(-res), res);
+ return INVALID_OPERATION;
+ }
+ // TODO: have push-and-clear be atomic
res = client->getCameraDevice()->pushReprocessBuffer(mZslReprocessStreamId,
handle, this);
if (res != OK) {