merge in lmp-release history after reset to d0fded31e473e909c018f534d3019fb5168bdcd6
diff --git a/drm/mediadrm/plugins/clearkey/DrmPlugin.h b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
index bfbc6bf..27df9cd 100644
--- a/drm/mediadrm/plugins/clearkey/DrmPlugin.h
+++ b/drm/mediadrm/plugins/clearkey/DrmPlugin.h
@@ -104,6 +104,10 @@
return android::ERROR_DRM_CANNOT_HANDLE;
}
+ virtual status_t unprovisionDevice() {
+ return android::ERROR_DRM_CANNOT_HANDLE;
+ }
+
virtual status_t getSecureStops(List<Vector<uint8_t> >& secureStops) {
UNUSED(secureStops);
return android::ERROR_DRM_CANNOT_HANDLE;
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
index 6efc712..2ea554b 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.cpp
@@ -299,6 +299,12 @@
return OK;
}
+ status_t MockDrmPlugin::unprovisionDevice()
+ {
+ ALOGD("MockDrmPlugin::unprovisionDevice()");
+ return OK;
+ }
+
status_t MockDrmPlugin::getSecureStops(List<Vector<uint8_t> > &secureStops)
{
Mutex::Autolock lock(mLock);
diff --git a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
index 97d7052..4b63299 100644
--- a/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
+++ b/drm/mediadrm/plugins/mock/MockDrmCryptoPlugin.h
@@ -85,6 +85,8 @@
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey);
+ status_t unprovisionDevice();
+
status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
diff --git a/include/media/IDrm.h b/include/media/IDrm.h
index 32ae28e..68de87a 100644
--- a/include/media/IDrm.h
+++ b/include/media/IDrm.h
@@ -70,6 +70,8 @@
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey) = 0;
+ virtual status_t unprovisionDevice() = 0;
+
virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) = 0;
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease) = 0;
diff --git a/include/media/stagefright/MediaCodecSource.h b/include/media/stagefright/MediaCodecSource.h
index 4b18a0b..e1b2830 100644
--- a/include/media/stagefright/MediaCodecSource.h
+++ b/include/media/stagefright/MediaCodecSource.h
@@ -106,7 +106,6 @@
bool mStarted;
bool mStopping;
bool mDoMoreWorkPending;
- bool mPullerReachedEOS;
sp<AMessage> mEncoderActivityNotify;
sp<IGraphicBufferProducer> mGraphicBufferProducer;
Vector<sp<ABuffer> > mEncoderInputBuffers;
@@ -123,7 +122,7 @@
Mutex mOutputBufferLock;
Condition mOutputBufferCond;
List<MediaBuffer*> mOutputBufferQueue;
- bool mEncodedReachedEOS;
+ bool mEncoderReachedEOS;
status_t mErrorCode;
DISALLOW_EVIL_CONSTRUCTORS(MediaCodecSource);
diff --git a/media/libmedia/IDrm.cpp b/media/libmedia/IDrm.cpp
index f1a6a9f..1904839 100644
--- a/media/libmedia/IDrm.cpp
+++ b/media/libmedia/IDrm.cpp
@@ -53,7 +53,8 @@
SIGN,
SIGN_RSA,
VERIFY,
- SET_LISTENER
+ SET_LISTENER,
+ UNPROVISION_DEVICE
};
struct BpDrm : public BpInterface<IDrm> {
@@ -229,6 +230,15 @@
return reply.readInt32();
}
+ virtual status_t unprovisionDevice() {
+ Parcel data, reply;
+ data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
+
+ remote()->transact(UNPROVISION_DEVICE, data, &reply);
+
+ return reply.readInt32();
+ }
+
virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops) {
Parcel data, reply;
data.writeInterfaceToken(IDrm::getInterfaceDescriptor());
@@ -619,6 +629,14 @@
return OK;
}
+ case UNPROVISION_DEVICE:
+ {
+ CHECK_INTERFACE(IDrm, data, reply);
+ status_t result = unprovisionDevice();
+ reply->writeInt32(result);
+ return OK;
+ }
+
case GET_SECURE_STOPS:
{
CHECK_INTERFACE(IDrm, data, reply);
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index d50037f..d222316 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -417,6 +417,23 @@
return mPlugin->provideProvisionResponse(response, certificate, wrappedKey);
}
+status_t Drm::unprovisionDevice() {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
+
+ if (!checkPermission("android.permission.REMOVE_DRM_CERTIFICATES")) {
+ return -EPERM;
+ }
+
+ return mPlugin->unprovisionDevice();
+}
status_t Drm::getSecureStops(List<Vector<uint8_t> > &secureStops) {
Mutex::Autolock autoLock(mLock);
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 3d4b0fc..9e23e2e 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -75,6 +75,8 @@
Vector<uint8_t> &certificate,
Vector<uint8_t> &wrappedKey);
+ virtual status_t unprovisionDevice();
+
virtual status_t getSecureStops(List<Vector<uint8_t> > &secureStops);
virtual status_t releaseSecureStops(Vector<uint8_t> const &ssRelease);
diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp
index a67fabe..804f131 100644
--- a/media/libstagefright/AudioSource.cpp
+++ b/media/libstagefright/AudioSource.cpp
@@ -155,12 +155,12 @@
}
mStarted = false;
+ mFrameAvailableCondition.signal();
+
mRecord->stop();
waitOutstandingEncodingFrames_l();
releaseQueuedFrames_l();
- mFrameAvailableCondition.signal();
-
return OK;
}
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 9868ecf..1a80dcc 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -54,7 +54,7 @@
Puller(const sp<MediaSource> &source);
status_t start(const sp<MetaData> &meta, const sp<AMessage> ¬ify);
- void stopAsync();
+ void stop();
void pause();
void resume();
@@ -139,8 +139,17 @@
return postSynchronouslyAndReturnError(msg);
}
-void MediaCodecSource::Puller::stopAsync() {
- ALOGV("puller (%s) stopAsync", mIsAudio ? "audio" : "video");
+void MediaCodecSource::Puller::stop() {
+ // Stop source from caller's thread instead of puller's looper.
+ // mSource->stop() is thread-safe, doing it outside the puller's
+ // looper allows us to at least stop if source gets stuck.
+ // If source gets stuck in read(), the looper would never
+ // be able to process the stop(), which could lead to ANR.
+
+ ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
+ mSource->stop();
+ ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
+
(new AMessage(kWhatStop, id()))->post();
}
@@ -194,9 +203,6 @@
case kWhatStop:
{
- ALOGV("source (%s) stopping", mIsAudio ? "audio" : "video");
- mSource->stop();
- ALOGV("source (%s) stopped", mIsAudio ? "audio" : "video");
++mPullGeneration;
handleEOS();
@@ -283,7 +289,21 @@
status_t MediaCodecSource::stop() {
sp<AMessage> msg = new AMessage(kWhatStop, mReflector->id());
- return postSynchronouslyAndReturnError(msg);
+ status_t err = postSynchronouslyAndReturnError(msg);
+
+ // mPuller->stop() needs to be done outside MediaCodecSource's looper,
+ // as it contains a synchronous call to stop the underlying MediaSource,
+ // which often waits for all outstanding MediaBuffers to return, but
+ // MediaBuffers are only returned when MediaCodecSource looper gets
+ // to process them.
+
+ if (mPuller != NULL) {
+ ALOGI("puller (%s) stopping", mIsVideo ? "video" : "audio");
+ mPuller->stop();
+ ALOGI("puller (%s) stopped", mIsVideo ? "video" : "audio");
+ }
+
+ return err;
}
status_t MediaCodecSource::pause() {
@@ -301,10 +321,10 @@
Mutex::Autolock autolock(mOutputBufferLock);
*buffer = NULL;
- while (mOutputBufferQueue.size() == 0 && !mEncodedReachedEOS) {
+ while (mOutputBufferQueue.size() == 0 && !mEncoderReachedEOS) {
mOutputBufferCond.wait(mOutputBufferLock);
}
- if (!mEncodedReachedEOS) {
+ if (!mEncoderReachedEOS) {
*buffer = *mOutputBufferQueue.begin();
mOutputBufferQueue.erase(mOutputBufferQueue.begin());
return OK;
@@ -330,9 +350,8 @@
mStarted(false),
mStopping(false),
mDoMoreWorkPending(false),
- mPullerReachedEOS(false),
mFirstSampleTimeUs(-1ll),
- mEncodedReachedEOS(false),
+ mEncoderReachedEOS(false),
mErrorCode(OK) {
CHECK(mLooper != NULL);
@@ -434,7 +453,7 @@
return err;
}
- mEncodedReachedEOS = false;
+ mEncoderReachedEOS = false;
mErrorCode = OK;
return OK;
@@ -465,10 +484,6 @@
mEncoderOutputBuffers.clear();
}
-bool MediaCodecSource::reachedEOS() {
- return mEncodedReachedEOS && ((mPuller == NULL) || mPullerReachedEOS);
-}
-
status_t MediaCodecSource::postSynchronouslyAndReturnError(
const sp<AMessage> &msg) {
sp<AMessage> response;
@@ -486,8 +501,8 @@
}
void MediaCodecSource::signalEOS(status_t err) {
- if (!mEncodedReachedEOS) {
- ALOGI("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
+ if (!mEncoderReachedEOS) {
+ ALOGV("encoder (%s) reached EOS", mIsVideo ? "video" : "audio");
{
Mutex::Autolock autoLock(mOutputBufferLock);
// release all unread media buffers
@@ -496,16 +511,15 @@
(*it)->release();
}
mOutputBufferQueue.clear();
- mEncodedReachedEOS = true;
+ mEncoderReachedEOS = true;
mErrorCode = err;
mOutputBufferCond.signal();
}
releaseEncoder();
}
- if (mStopping && reachedEOS()) {
- ALOGI("MediaCodecSource (%s) fully stopped",
- mIsVideo ? "video" : "audio");
+ if (mStopping && mEncoderReachedEOS) {
+ ALOGI("encoder (%s) stopped", mIsVideo ? "video" : "audio");
// posting reply to everyone that's waiting
List<uint32_t>::iterator it;
for (it = mStopReplyIDQueue.begin();
@@ -755,7 +769,6 @@
kWhatPullerNotify, mReflector->id());
err = mPuller->start(params, notify);
if (err != OK) {
- mPullerReachedEOS = true;
return err;
}
}
@@ -774,9 +787,9 @@
CHECK(msg->findPointer("accessUnit", (void**)&mbuf));
if (mbuf == NULL) {
- ALOGI("puller (%s) reached EOS",
+ ALOGV("puller (%s) reached EOS",
mIsVideo ? "video" : "audio");
- mPullerReachedEOS = true;
+ signalEOS();
}
if (mEncoder == NULL) {
@@ -785,9 +798,8 @@
if (mbuf != NULL) {
mbuf->release();
- } else {
- signalEOS();
}
+
break;
}
@@ -833,14 +845,14 @@
}
case kWhatStop:
{
- ALOGI("MediaCodecSource (%s) stopping", mIsVideo ? "video" : "audio");
+ ALOGI("encoder (%s) stopping", mIsVideo ? "video" : "audio");
uint32_t replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
- if (reachedEOS()) {
+ if (mEncoderReachedEOS) {
// if we already reached EOS, reply and return now
- ALOGI("MediaCodecSource (%s) already stopped",
+ ALOGI("encoder (%s) already stopped",
mIsVideo ? "video" : "audio");
(new AMessage)->postReply(replyID);
break;
@@ -860,8 +872,6 @@
if (mFlags & FLAG_USE_SURFACE_INPUT) {
mEncoder->signalEndOfInputStream();
} else {
- CHECK(mPuller != NULL);
- mPuller->stopAsync();
signalEOS();
}
break;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index bd7121e..b8cc33a 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1159,6 +1159,9 @@
void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)
{
Mutex::Autolock _l(mLock);
+ if (client == 0) {
+ return;
+ }
bool clientAdded = false;
{
Mutex::Autolock _cl(mClientLock);
@@ -1453,6 +1456,9 @@
audio_module_handle_t AudioFlinger::loadHwModule(const char *name)
{
+ if (name == NULL) {
+ return 0;
+ }
if (!settingsAllowed()) {
return 0;
}
diff --git a/services/audiopolicy/AudioPolicyManager.cpp b/services/audiopolicy/AudioPolicyManager.cpp
index 09595ff..440f5d0 100644
--- a/services/audiopolicy/AudioPolicyManager.cpp
+++ b/services/audiopolicy/AudioPolicyManager.cpp
@@ -709,7 +709,9 @@
config.sample_rate = mTestSamplingRate;
config.channel_mask = mTestChannels;
config.format = mTestFormat;
- config.offload_info = *offloadInfo;
+ if (offloadInfo != NULL) {
+ config.offload_info = *offloadInfo;
+ }
status = mpClientInterface->openOutput(0,
&mTestOutputs[mCurOutput],
&config,
@@ -784,7 +786,9 @@
config.sample_rate = samplingRate;
config.channel_mask = channelMask;
config.format = format;
- config.offload_info = *offloadInfo;
+ if (offloadInfo != NULL) {
+ config.offload_info = *offloadInfo;
+ }
status = mpClientInterface->openOutput(profile->mModule->mHandle,
&output,
&config,