Merge changes Ia529bf53,I10888d0b into mnc-dev
* changes:
Enable building with clang/llvm.
Enable clang compilation.
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 51a775b..a02dbe2 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -20,6 +20,7 @@
#include <utils/Errors.h>
#include <utils/String16.h>
+#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
@@ -303,10 +304,10 @@
return res;
}
- virtual void notifySystemEvent(int eventId, int arg0) {
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t len) {
Parcel data, reply;
data.writeInt32(eventId);
- data.writeInt32(arg0);
+ data.writeInt32Array(len, args);
remote()->transact(BnCameraService::NOTIFY_SYSTEM_EVENT, data, &reply,
IBinder::FLAG_ONEWAY);
}
@@ -481,9 +482,26 @@
} break;
case NOTIFY_SYSTEM_EVENT: {
CHECK_INTERFACE(ICameraService, data, reply);
- int eventId = data.readInt32();
- int arg0 = data.readInt32();
- notifySystemEvent(eventId, arg0);
+ int32_t eventId = data.readInt32();
+ int32_t len = data.readInt32();
+ if (len < 0) {
+ ALOGE("%s: Received poorly formatted length in binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ if (len > 512) {
+ ALOGE("%s: Length %" PRIi32 " too long in binder request: notifySystemEvent.",
+ __FUNCTION__, len);
+ return FAILED_TRANSACTION;
+ }
+ int32_t events[len] = {};
+ status_t status = data.read(events, sizeof(int32_t) * len);
+ if (status != NO_ERROR) {
+ ALOGE("%s: Received poorly formatted binder request: notifySystemEvent.",
+ __FUNCTION__);
+ return FAILED_TRANSACTION;
+ }
+ notifySystemEvent(eventId, events, len);
return NO_ERROR;
} break;
default:
diff --git a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
index 9d15835..6a0b3c0 100644
--- a/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
+++ b/drm/libdrmframework/plugins/forward-lock/internal-format/converter/FwdLockConv.c
@@ -19,6 +19,7 @@
#include <fcntl.h>
#include <limits.h>
#include <pthread.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index cad275e..5f85635 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -164,7 +164,7 @@
/**
* Notify the camera service of a system event. Should only be called from system_server.
*/
- virtual void notifySystemEvent(int eventId, int arg0) = 0;
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) = 0;
};
// ----------------------------------------------------------------------------
diff --git a/include/media/IMediaRecorder.h b/include/media/IMediaRecorder.h
index 47de0ca..77ed5d3 100644
--- a/include/media/IMediaRecorder.h
+++ b/include/media/IMediaRecorder.h
@@ -56,7 +56,7 @@
virtual status_t init() = 0;
virtual status_t close() = 0;
virtual status_t release() = 0;
- virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() = 0;
};
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index df3aeca..d33d142 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -118,7 +118,7 @@
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer) = 0;
- virtual status_t usePersistentInputSurface(
+ virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer) = 0;
diff --git a/include/media/MediaRecorderBase.h b/include/media/MediaRecorderBase.h
index 9947309..d6cc4bb 100644
--- a/include/media/MediaRecorderBase.h
+++ b/include/media/MediaRecorderBase.h
@@ -57,7 +57,7 @@
virtual status_t reset() = 0;
virtual status_t getMaxAmplitude(int *max) = 0;
virtual status_t dump(int fd, const Vector<String16>& args) const = 0;
- virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
+ virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface) = 0;
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource() const = 0;
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 9210feb..15ff82d 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -237,7 +237,7 @@
status_t close();
status_t release();
void notify(int msg, int ext1, int ext2);
- status_t usePersistentSurface(const sp<PersistentSurface>& surface);
+ status_t setInputSurface(const sp<PersistentSurface>& surface);
sp<IGraphicBufferProducer> querySurfaceMediaSourceFromMediaServer();
private:
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index b8327a3..4ed97e5 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -44,8 +44,7 @@
virtual void initiateAllocateComponent(const sp<AMessage> &msg);
virtual void initiateConfigureComponent(const sp<AMessage> &msg);
virtual void initiateCreateInputSurface();
- virtual void initiateUsePersistentInputSurface(
- const sp<PersistentSurface> &surface);
+ virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
virtual void initiateStart();
virtual void initiateShutdown(bool keepComponentAllocated = false);
@@ -119,7 +118,7 @@
kWhatConfigureComponent = 'conf',
kWhatSetSurface = 'setS',
kWhatCreateInputSurface = 'cisf',
- kWhatUsePersistentInputSurface = 'pisf',
+ kWhatSetInputSurface = 'sisf',
kWhatSignalEndOfInputStream = 'eois',
kWhatStart = 'star',
kWhatRequestIDRFrame = 'ridr',
@@ -147,8 +146,13 @@
OWNED_BY_UPSTREAM,
OWNED_BY_DOWNSTREAM,
OWNED_BY_NATIVE_WINDOW,
+ UNRECOGNIZED, // not a tracked buffer
};
+ static inline Status getSafeStatus(BufferInfo *info) {
+ return info == NULL ? UNRECOGNIZED : info->mStatus;
+ }
+
IOMX::buffer_id mBufferID;
Status mStatus;
unsigned mDequeuedAt;
@@ -157,6 +161,9 @@
sp<GraphicBuffer> mGraphicBuffer;
};
+ static const char *_asString(BufferInfo::Status s);
+ void dumpBuffers(OMX_U32 portIndex);
+
#if TRACK_BUFFER_TIMING
struct BufferStats {
int64_t mEmptyBufferTimeUs;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index 51213b6..989df4f 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -50,7 +50,7 @@
virtual void initiateAllocateComponent(const sp<AMessage> &msg) = 0;
virtual void initiateConfigureComponent(const sp<AMessage> &msg) = 0;
virtual void initiateCreateInputSurface() = 0;
- virtual void initiateUsePersistentInputSurface(
+ virtual void initiateSetInputSurface(
const sp<PersistentSurface> &surface) = 0;
virtual void initiateStart() = 0;
virtual void initiateShutdown(bool keepComponentAllocated = false) = 0;
diff --git a/include/media/stagefright/MediaCodec.h b/include/media/stagefright/MediaCodec.h
index 82c768d..6e14fc5 100644
--- a/include/media/stagefright/MediaCodec.h
+++ b/include/media/stagefright/MediaCodec.h
@@ -80,7 +80,7 @@
status_t createInputSurface(sp<IGraphicBufferProducer>* bufferProducer);
- status_t usePersistentInputSurface(const sp<PersistentSurface> &surface);
+ status_t setInputSurface(const sp<PersistentSurface> &surface);
status_t start();
@@ -193,7 +193,7 @@
kWhatConfigure = 'conf',
kWhatSetSurface = 'sSur',
kWhatCreateInputSurface = 'cisf',
- kWhatUsePersistentInputSurface = 'pisf',
+ kWhatSetInputSurface = 'sisf',
kWhatStart = 'strt',
kWhatStop = 'stop',
kWhatRelease = 'rele',
diff --git a/include/media/stagefright/MediaDefs.h b/include/media/stagefright/MediaDefs.h
index 3b58122..21eb04a 100644
--- a/include/media/stagefright/MediaDefs.h
+++ b/include/media/stagefright/MediaDefs.h
@@ -64,7 +64,7 @@
extern const char *MEDIA_MIMETYPE_TEXT_SUBRIP;
extern const char *MEDIA_MIMETYPE_TEXT_VTT;
extern const char *MEDIA_MIMETYPE_TEXT_CEA_608;
-extern const char *MEDIA_MIMETYPE_DATA_METADATA;
+extern const char *MEDIA_MIMETYPE_DATA_TIMED_ID3;
} // namespace android
diff --git a/include/media/stagefright/MediaFilter.h b/include/media/stagefright/MediaFilter.h
index fdd2a34..d0a572c 100644
--- a/include/media/stagefright/MediaFilter.h
+++ b/include/media/stagefright/MediaFilter.h
@@ -34,8 +34,7 @@
virtual void initiateAllocateComponent(const sp<AMessage> &msg);
virtual void initiateConfigureComponent(const sp<AMessage> &msg);
virtual void initiateCreateInputSurface();
- virtual void initiateUsePersistentInputSurface(
- const sp<PersistentSurface> &surface);
+ virtual void initiateSetInputSurface(const sp<PersistentSurface> &surface);
virtual void initiateStart();
virtual void initiateShutdown(bool keepComponentAllocated = false);
diff --git a/include/media/stagefright/MediaSync.h b/include/media/stagefright/MediaSync.h
index d1d634d..1eef211 100644
--- a/include/media/stagefright/MediaSync.h
+++ b/include/media/stagefright/MediaSync.h
@@ -169,7 +169,7 @@
class OutputListener : public BnProducerListener,
public IBinder::DeathRecipient {
public:
- OutputListener(const sp<MediaSync> &sync);
+ OutputListener(const sp<MediaSync> &sync, const sp<IGraphicBufferProducer> &output);
virtual ~OutputListener();
// From IProducerListener
@@ -180,6 +180,7 @@
private:
sp<MediaSync> mSync;
+ sp<IGraphicBufferProducer> mOutput;
};
// mIsAbandoned is set to true when the input or output dies.
@@ -192,6 +193,7 @@
size_t mNumOutstandingBuffers;
sp<IGraphicBufferConsumer> mInput;
sp<IGraphicBufferProducer> mOutput;
+ int mUsageFlagsFromOutput;
sp<AudioTrack> mAudioTrack;
uint32_t mNativeSampleRateInHz;
@@ -207,6 +209,12 @@
// and that could cause problem if the producer of |mInput| only
// supports pre-registered buffers.
KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersFromInput;
+
+ // Keep track of buffers sent to |mOutput|. When a new output surface comes
+ // in, those buffers will be returned to input and old output surface will
+ // be disconnected immediately.
+ KeyedVector<uint64_t, sp<GraphicBuffer> > mBuffersSentToOutput;
+
sp<ALooper> mLooper;
float mPlaybackRate;
@@ -241,7 +249,7 @@
// It gets called from an OutputListener.
// During this callback, we detach the buffer from the output, and release
// it to the input. A blocked onFrameAvailable call will be allowed to proceed.
- void onBufferReleasedByOutput();
+ void onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output);
// Return |buffer| back to the input.
void returnBufferToInput_l(const sp<GraphicBuffer> &buffer, const sp<Fence> &fence);
diff --git a/include/media/stagefright/foundation/AUtils.h b/include/media/stagefright/foundation/AUtils.h
index d7ecf50..47444c1 100644
--- a/include/media/stagefright/foundation/AUtils.h
+++ b/include/media/stagefright/foundation/AUtils.h
@@ -61,6 +61,28 @@
return a > b ? a : b;
}
+template<class T>
+void ENSURE_UNSIGNED_TYPE() {
+ T TYPE_MUST_BE_UNSIGNED[(T)-1 < 0 ? -1 : 0] __unused;
+}
+
+// needle is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(const T &hayStart, const U &haySize, const T &needle) {
+ ENSURE_UNSIGNED_TYPE<U>();
+ return (T)(hayStart + haySize) >= hayStart && needle >= hayStart && (U)(needle - hayStart) < haySize;
+}
+
+// [needleStart, needleStart + needleSize) is in range [hayStart, hayStart + haySize)
+template<class T, class U>
+inline static bool isInRange(
+ const T &hayStart, const U &haySize, const T &needleStart, const U &needleSize) {
+ ENSURE_UNSIGNED_TYPE<U>();
+ return isInRange(hayStart, haySize, needleStart)
+ && (T)(needleStart + needleSize) >= needleStart
+ && (U)(needleStart + needleSize - hayStart) <= haySize;
+}
+
/* T must be integer type, period must be positive */
template<class T>
inline static T periodicError(const T &val, const T &period) {
diff --git a/media/libmedia/IMediaRecorder.cpp b/media/libmedia/IMediaRecorder.cpp
index c7a1394..ee3b584 100644
--- a/media/libmedia/IMediaRecorder.cpp
+++ b/media/libmedia/IMediaRecorder.cpp
@@ -35,7 +35,7 @@
RELEASE = IBinder::FIRST_CALL_TRANSACTION,
INIT,
CLOSE,
- USE_PERSISTENT_SURFACE,
+ SET_INPUT_SURFACE,
QUERY_SURFACE_MEDIASOURCE,
RESET,
STOP,
@@ -76,13 +76,13 @@
return reply.readInt32();
}
- status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface)
+ status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface)
{
- ALOGV("usePersistentSurface(%p)", surface.get());
+ ALOGV("setInputSurface(%p)", surface.get());
Parcel data, reply;
data.writeInterfaceToken(IMediaRecorder::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(surface));
- remote()->transact(USE_PERSISTENT_SURFACE, data, &reply);
+ remote()->transact(SET_INPUT_SURFACE, data, &reply);
return reply.readInt32();
}
@@ -453,12 +453,12 @@
reply->writeInt32(setCamera(camera, proxy));
return NO_ERROR;
} break;
- case USE_PERSISTENT_SURFACE: {
- ALOGV("USE_PERSISTENT_SURFACE");
+ case SET_INPUT_SURFACE: {
+ ALOGV("SET_INPUT_SURFACE");
CHECK_INTERFACE(IMediaRecorder, data, reply);
sp<IGraphicBufferConsumer> surface = interface_cast<IGraphicBufferConsumer>(
data.readStrongBinder());
- reply->writeInt32(usePersistentSurface(surface));
+ reply->writeInt32(setInputSurface(surface));
return NO_ERROR;
} break;
case QUERY_SURFACE_MEDIASOURCE: {
diff --git a/media/libmedia/IOMX.cpp b/media/libmedia/IOMX.cpp
index 39b135b..c14debf 100644
--- a/media/libmedia/IOMX.cpp
+++ b/media/libmedia/IOMX.cpp
@@ -42,7 +42,7 @@
USE_GRAPHIC_BUFFER,
CREATE_INPUT_SURFACE,
CREATE_PERSISTENT_INPUT_SURFACE,
- USE_PERSISTENT_INPUT_SURFACE,
+ SET_INPUT_SURFACE,
SIGNAL_END_OF_INPUT_STREAM,
STORE_META_DATA_IN_BUFFERS,
PREPARE_FOR_ADAPTIVE_PLAYBACK,
@@ -353,7 +353,7 @@
return err;
}
- virtual status_t usePersistentInputSurface(
+ virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer) {
Parcel data, reply;
@@ -363,7 +363,7 @@
data.writeInt32(port_index);
data.writeStrongBinder(IInterface::asBinder(bufferConsumer));
- err = remote()->transact(USE_PERSISTENT_INPUT_SURFACE, data, &reply);
+ err = remote()->transact(SET_INPUT_SURFACE, data, &reply);
if (err != OK) {
ALOGW("binder transaction failed: %d", err);
@@ -372,7 +372,6 @@
return reply.readInt32();
}
-
virtual status_t signalEndOfInputStream(node_id node) {
Parcel data, reply;
status_t err;
@@ -847,7 +846,7 @@
return NO_ERROR;
}
- case USE_PERSISTENT_INPUT_SURFACE:
+ case SET_INPUT_SURFACE:
{
CHECK_OMX_INTERFACE(IOMX, data, reply);
@@ -857,8 +856,7 @@
sp<IGraphicBufferConsumer> bufferConsumer =
interface_cast<IGraphicBufferConsumer>(data.readStrongBinder());
- status_t err = usePersistentInputSurface(
- node, port_index, bufferConsumer);
+ status_t err = setInputSurface(node, port_index, bufferConsumer);
reply->writeInt32(err);
return NO_ERROR;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 1f8b1d3..8bbd8f1 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -345,9 +345,9 @@
-status_t MediaRecorder::usePersistentSurface(const sp<PersistentSurface>& surface)
+status_t MediaRecorder::setInputSurface(const sp<PersistentSurface>& surface)
{
- ALOGV("usePersistentSurface");
+ ALOGV("setInputSurface");
if (mMediaRecorder == NULL) {
ALOGE("media recorder is not initialized yet");
return INVALID_OPERATION;
@@ -356,11 +356,11 @@
(MEDIA_RECORDER_PREPARED |
MEDIA_RECORDER_RECORDING));
if (isInvalidState) {
- ALOGE("usePersistentSurface is called in an invalid state: %d", mCurrentState);
+ ALOGE("setInputSurface is called in an invalid state: %d", mCurrentState);
return INVALID_OPERATION;
}
- return mMediaRecorder->usePersistentSurface(surface->getBufferConsumer());
+ return mMediaRecorder->setInputSurface(surface->getBufferConsumer());
}
status_t MediaRecorder::setVideoFrameRate(int frames_per_second)
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index d55482d..a7f6f8b 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -358,7 +358,18 @@
status_t err = mPlugin->openSession(sessionId);
if (err == ERROR_DRM_RESOURCE_BUSY) {
bool retry = false;
+ mLock.unlock();
+ // reclaimSession may call back to closeSession, since mLock is shared between Drm
+ // instances, we should unlock here to avoid deadlock.
retry = DrmSessionManager::Instance()->reclaimSession(getCallingPid());
+ mLock.lock();
+ if (mInitCheck != OK) {
+ return mInitCheck;
+ }
+
+ if (mPlugin == NULL) {
+ return -EINVAL;
+ }
if (retry) {
err = mPlugin->openSession(sessionId);
}
diff --git a/media/libmediaplayerservice/MediaRecorderClient.cpp b/media/libmediaplayerservice/MediaRecorderClient.cpp
index ed442e3..f761dec 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.cpp
+++ b/media/libmediaplayerservice/MediaRecorderClient.cpp
@@ -55,15 +55,15 @@
return ok;
}
-status_t MediaRecorderClient::usePersistentSurface(const sp<IGraphicBufferConsumer>& surface)
+status_t MediaRecorderClient::setInputSurface(const sp<IGraphicBufferConsumer>& surface)
{
- ALOGV("usePersistentSurface");
+ ALOGV("setInputSurface");
Mutex::Autolock lock(mLock);
if (mRecorder == NULL) {
ALOGE("recorder is not initialized");
return NO_INIT;
}
- return mRecorder->usePersistentSurface(surface);
+ return mRecorder->setInputSurface(surface);
}
sp<IGraphicBufferProducer> MediaRecorderClient::querySurfaceMediaSource()
diff --git a/media/libmediaplayerservice/MediaRecorderClient.h b/media/libmediaplayerservice/MediaRecorderClient.h
index 7ac88cb..05130d4 100644
--- a/media/libmediaplayerservice/MediaRecorderClient.h
+++ b/media/libmediaplayerservice/MediaRecorderClient.h
@@ -55,7 +55,7 @@
virtual status_t close();
virtual status_t release();
virtual status_t dump(int fd, const Vector<String16>& args);
- virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
virtual sp<IGraphicBufferProducer> querySurfaceMediaSource();
private:
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 509a592..e16a4b5 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -243,7 +243,7 @@
return OK;
}
-status_t StagefrightRecorder::usePersistentSurface(
+status_t StagefrightRecorder::setInputSurface(
const sp<IGraphicBufferConsumer>& surface) {
mPersistentSurface = surface;
@@ -1752,6 +1752,7 @@
}
mGraphicBufferProducer.clear();
+ mPersistentSurface.clear();
if (mOutputFd >= 0) {
::close(mOutputFd);
diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h
index 1a7b720..7473f42 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.h
+++ b/media/libmediaplayerservice/StagefrightRecorder.h
@@ -54,7 +54,7 @@
virtual status_t setVideoFrameRate(int frames_per_second);
virtual status_t setCamera(const sp<ICamera>& camera, const sp<ICameraRecordingProxy>& proxy);
virtual status_t setPreviewSurface(const sp<IGraphicBufferProducer>& surface);
- virtual status_t usePersistentSurface(const sp<IGraphicBufferConsumer>& surface);
+ virtual status_t setInputSurface(const sp<IGraphicBufferConsumer>& surface);
virtual status_t setOutputFile(int fd, int64_t offset, int64_t length);
virtual status_t setParameters(const String8& params);
virtual status_t setListener(const sp<IMediaRecorderClient>& listener);
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
index 39b8d09..126625a 100644
--- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -161,24 +161,22 @@
status_t err = INVALID_OPERATION;
bool postFetchMsg = false, isSub = false;
- if (trackIndex != mLiveSession->getTrackCount() - 1) {
+ if (!mHasMetadata || trackIndex != mLiveSession->getTrackCount() - 1) {
err = mLiveSession->selectTrack(trackIndex, select);
postFetchMsg = select;
isSub = true;
} else {
- // metadata track
- if (mHasMetadata) {
- if (mMetadataSelected && !select) {
- err = OK;
- } else if (!mMetadataSelected && select) {
- postFetchMsg = true;
- err = OK;
- } else {
- err = BAD_VALUE; // behave as LiveSession::selectTrack
- }
-
- mMetadataSelected = select;
+ // metadata track; i.e. (mHasMetadata && trackIndex == mLiveSession->getTrackCount() - 1)
+ if (mMetadataSelected && !select) {
+ err = OK;
+ } else if (!mMetadataSelected && select) {
+ postFetchMsg = true;
+ err = OK;
+ } else {
+ err = BAD_VALUE; // behave as LiveSession::selectTrack
}
+
+ mMetadataSelected = select;
}
if (err == OK) {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 6b8f99c..007a335 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -146,7 +146,7 @@
return OK;
}
- if (mAudioSink != NULL) {
+ if (mAudioSink != NULL && mAudioSink->ready()) {
status_t err = mAudioSink->setPlaybackRate(rate);
if (err != OK) {
return err;
@@ -172,7 +172,7 @@
}
status_t NuPlayer::Renderer::onGetPlaybackSettings(AudioPlaybackRate *rate /* nonnull */) {
- if (mAudioSink != NULL) {
+ if (mAudioSink != NULL && mAudioSink->ready()) {
status_t err = mAudioSink->getPlaybackRate(rate);
if (err == OK) {
if (!isAudioPlaybackRateEqual(*rate, mPlaybackSettings)) {
@@ -1378,7 +1378,7 @@
mPaused = false;
// configure audiosink as we did not do it when pausing
- if (mAudioSink != NULL) {
+ if (mAudioSink != NULL && mAudioSink->ready()) {
mAudioSink->setPlaybackRate(mPlaybackSettings);
}
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index b9ae125..34bd4c7 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -49,6 +49,7 @@
#include <OMX_VideoExt.h>
#include <OMX_Component.h>
#include <OMX_IndexExt.h>
+#include <OMX_AsString.h>
#include "include/avc_utils.h"
@@ -154,7 +155,7 @@
}
default:
- TRESPASS();
+ ALOGE("Unrecognized message type: %d", omx_msg.type);
break;
}
@@ -261,7 +262,7 @@
bool onConfigureComponent(const sp<AMessage> &msg);
void onCreateInputSurface(const sp<AMessage> &msg);
- void onUsePersistentInputSurface(const sp<AMessage> &msg);
+ void onSetInputSurface(const sp<AMessage> &msg);
void onStart();
void onShutdown(bool keepComponentAllocated);
@@ -498,9 +499,9 @@
(new AMessage(kWhatCreateInputSurface, this))->post();
}
-void ACodec::initiateUsePersistentInputSurface(
+void ACodec::initiateSetInputSurface(
const sp<PersistentSurface> &surface) {
- sp<AMessage> msg = new AMessage(kWhatUsePersistentInputSurface, this);
+ sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
msg->setObject("input-surface", surface);
msg->post();
}
@@ -697,7 +698,9 @@
for (OMX_U32 i = 0; i < def.nBufferCountActual; ++i) {
sp<IMemory> mem = mDealer[portIndex]->allocate(def.nBufferSize);
- CHECK(mem.get() != NULL);
+ if (mem == NULL || mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
BufferInfo info;
info.mStatus = BufferInfo::OWNED_BY_US;
@@ -987,7 +990,9 @@
sp<IMemory> mem = mDealer[kPortIndexOutput]->allocate(
sizeof(struct VideoDecoderOutputMetaData));
- CHECK(mem.get() != NULL);
+ if (mem == NULL || mem->pointer() == NULL) {
+ return NO_MEMORY;
+ }
info.mData = new ABuffer(mem->pointer(), mem->size());
// we use useBuffer for metadata regardless of quirks
@@ -1049,18 +1054,46 @@
return OK;
BufferInfo *info = dequeueBufferFromNativeWindow();
- if (info == NULL)
+ if (info == NULL) {
return ERROR_IO;
+ }
ALOGV("[%s] submitting output meta buffer ID %u for graphic buffer %p",
mComponentName.c_str(), info->mBufferID, info->mGraphicBuffer.get());
--mMetaDataBuffersToSubmit;
- CHECK_EQ(mOMX->fillBuffer(mNode, info->mBufferID),
- (status_t)OK);
+ status_t err = mOMX->fillBuffer(mNode, info->mBufferID);
+ if (err == OK) {
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ }
- info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
- return OK;
+ return err;
+}
+
+// static
+const char *ACodec::_asString(BufferInfo::Status s) {
+ switch (s) {
+ case BufferInfo::OWNED_BY_US: return "OUR";
+ case BufferInfo::OWNED_BY_COMPONENT: return "COMPONENT";
+ case BufferInfo::OWNED_BY_UPSTREAM: return "UPSTREAM";
+ case BufferInfo::OWNED_BY_DOWNSTREAM: return "DOWNSTREAM";
+ case BufferInfo::OWNED_BY_NATIVE_WINDOW: return "SURFACE";
+ case BufferInfo::UNRECOGNIZED: return "UNRECOGNIZED";
+ default: return "?";
+ }
+}
+
+void ACodec::dumpBuffers(OMX_U32 portIndex) {
+ CHECK(portIndex == kPortIndexInput || portIndex == kPortIndexOutput);
+ ALOGI("[%s] %s port has %zu buffers:", mComponentName.c_str(),
+ portIndex == kPortIndexInput ? "input" : "output", mBuffers[portIndex].size());
+ for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
+ const BufferInfo &info = mBuffers[portIndex][i];
+ ALOGI(" slot %2zu: #%8u %p/%p %s(%d) dequeued:%u",
+ i, info.mBufferID, info.mGraphicBuffer.get(),
+ info.mGraphicBuffer == NULL ? NULL : info.mGraphicBuffer->getNativeBuffer(),
+ _asString(info.mStatus), info.mStatus, info.mDequeuedAt);
+ }
}
status_t ACodec::cancelBufferToNativeWindow(BufferInfo *info) {
@@ -1074,7 +1107,7 @@
ALOGW_IF(err != 0, "[%s] can not return buffer %u to native window",
mComponentName.c_str(), info->mBufferID);
-
+ // change ownership even if cancelBuffer fails
info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
return err;
@@ -1150,47 +1183,50 @@
}
}
- if (oldest) {
- CHECK(mStoreMetaDataInOutputBuffers);
+ // it is impossible dequeue a buffer when there are no buffers with ANW
+ CHECK(oldest != NULL);
+ // it is impossible to dequeue an unknown buffer in non-meta mode, as the
+ // while loop above does not complete
+ CHECK(mStoreMetaDataInOutputBuffers);
- // discard buffer in LRU info and replace with new buffer
- oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
- oldest->mStatus = BufferInfo::OWNED_BY_US;
+ // discard buffer in LRU info and replace with new buffer
+ oldest->mGraphicBuffer = new GraphicBuffer(buf, false);
+ oldest->mStatus = BufferInfo::OWNED_BY_US;
- mOMX->updateGraphicBufferInMeta(
- mNode, kPortIndexOutput, oldest->mGraphicBuffer,
- oldest->mBufferID);
+ mOMX->updateGraphicBufferInMeta(
+ mNode, kPortIndexOutput, oldest->mGraphicBuffer,
+ oldest->mBufferID);
- VideoDecoderOutputMetaData *metaData =
- reinterpret_cast<VideoDecoderOutputMetaData *>(
- oldest->mData->base());
- CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
+ VideoDecoderOutputMetaData *metaData =
+ reinterpret_cast<VideoDecoderOutputMetaData *>(
+ oldest->mData->base());
+ CHECK_EQ(metaData->eType, kMetadataBufferTypeGrallocSource);
- ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
- (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
- mDequeueCounter - oldest->mDequeuedAt,
- metaData->pHandle,
- oldest->mGraphicBuffer->handle, oldest->mData->base());
+ ALOGV("replaced oldest buffer #%u with age %u (%p/%p stored in %p)",
+ (unsigned)(oldest - &mBuffers[kPortIndexOutput][0]),
+ mDequeueCounter - oldest->mDequeuedAt,
+ metaData->pHandle,
+ oldest->mGraphicBuffer->handle, oldest->mData->base());
- return oldest;
- }
-
- TRESPASS();
-
- return NULL;
+ return oldest;
}
status_t ACodec::freeBuffersOnPort(OMX_U32 portIndex) {
+ status_t err = OK;
for (size_t i = mBuffers[portIndex].size(); i-- > 0;) {
- CHECK_EQ((status_t)OK, freeBuffer(portIndex, i));
+ status_t err2 = freeBuffer(portIndex, i);
+ if (err == OK) {
+ err = err2;
+ }
}
+ // clear mDealer even on an error
mDealer[portIndex].clear();
-
- return OK;
+ return err;
}
status_t ACodec::freeOutputBuffersNotOwnedByComponent() {
+ status_t err = OK;
for (size_t i = mBuffers[kPortIndexOutput].size(); i-- > 0;) {
BufferInfo *info =
&mBuffers[kPortIndexOutput].editItemAt(i);
@@ -1199,36 +1235,45 @@
// or being drained.
if (info->mStatus != BufferInfo::OWNED_BY_COMPONENT &&
info->mStatus != BufferInfo::OWNED_BY_DOWNSTREAM) {
- CHECK_EQ((status_t)OK, freeBuffer(kPortIndexOutput, i));
+ status_t err2 = freeBuffer(kPortIndexOutput, i);
+ if (err == OK) {
+ err = err2;
+ }
}
}
- return OK;
+ return err;
}
status_t ACodec::freeBuffer(OMX_U32 portIndex, size_t i) {
BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
+ status_t err = OK;
- CHECK(info->mStatus == BufferInfo::OWNED_BY_US
- || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+ switch (info->mStatus) {
+ case BufferInfo::OWNED_BY_US:
+ if (portIndex == kPortIndexOutput && mNativeWindow != NULL) {
+ (void)cancelBufferToNativeWindow(info);
+ }
+ // fall through
- if (portIndex == kPortIndexOutput && mNativeWindow != NULL
- && info->mStatus == BufferInfo::OWNED_BY_US) {
- cancelBufferToNativeWindow(info);
+ case BufferInfo::OWNED_BY_NATIVE_WINDOW:
+ err = mOMX->freeBuffer(mNode, portIndex, info->mBufferID);
+ break;
+
+ default:
+ ALOGE("trying to free buffer not owned by us or ANW (%d)", info->mStatus);
+ err = FAILED_TRANSACTION;
+ break;
}
- CHECK_EQ(mOMX->freeBuffer(
- mNode, portIndex, info->mBufferID),
- (status_t)OK);
-
+ // remove buffer even if mOMX->freeBuffer fails
mBuffers[portIndex].removeAt(i);
- return OK;
+ return err;
}
ACodec::BufferInfo *ACodec::findBufferByID(
- uint32_t portIndex, IOMX::buffer_id bufferID,
- ssize_t *index) {
+ uint32_t portIndex, IOMX::buffer_id bufferID, ssize_t *index) {
for (size_t i = 0; i < mBuffers[portIndex].size(); ++i) {
BufferInfo *info = &mBuffers[portIndex].editItemAt(i);
@@ -1240,8 +1285,7 @@
}
}
- TRESPASS();
-
+ ALOGE("Could not find buffer with ID %u", bufferID);
return NULL;
}
@@ -1638,22 +1682,30 @@
if (haveNativeWindow) {
mNativeWindow = static_cast<Surface *>(obj.get());
- CHECK(mNativeWindow != NULL);
}
// initialize native window now to get actual output format
// TODO: this is needed for some encoders even though they don't use native window
- CHECK_EQ((status_t)OK, initNativeWindow());
+ err = initNativeWindow();
+ if (err != OK) {
+ return err;
+ }
// fallback for devices that do not handle flex-YUV for native buffers
if (haveNativeWindow) {
int32_t requestedColorFormat = OMX_COLOR_FormatUnused;
if (msg->findInt32("color-format", &requestedColorFormat) &&
requestedColorFormat == OMX_COLOR_FormatYUV420Flexible) {
- CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
+ status_t err = getPortFormat(kPortIndexOutput, outputFormat);
+ if (err != OK) {
+ return err;
+ }
int32_t colorFormat = OMX_COLOR_FormatUnused;
OMX_U32 flexibleEquivalent = OMX_COLOR_FormatUnused;
- CHECK(outputFormat->findInt32("color-format", &colorFormat));
+ if (!outputFormat->findInt32("color-format", &colorFormat)) {
+ ALOGE("ouptut port did not have a color format (wrong domain?)");
+ return BAD_VALUE;
+ }
ALOGD("[%s] Requested output format %#x and got %#x.",
mComponentName.c_str(), requestedColorFormat, colorFormat);
if (!isFlexibleColorFormat(
@@ -1874,11 +1926,14 @@
mBaseOutputFormat = outputFormat;
- CHECK_EQ(getPortFormat(kPortIndexInput, inputFormat), (status_t)OK);
- CHECK_EQ(getPortFormat(kPortIndexOutput, outputFormat), (status_t)OK);
- mInputFormat = inputFormat;
- mOutputFormat = outputFormat;
-
+ err = getPortFormat(kPortIndexInput, inputFormat);
+ if (err == OK) {
+ err = getPortFormat(kPortIndexOutput, outputFormat);
+ if (err == OK) {
+ mInputFormat = inputFormat;
+ mOutputFormat = outputFormat;
+ }
+ }
return err;
}
@@ -1958,7 +2013,10 @@
return err;
}
- CHECK(def.nBufferSize >= size);
+ if (def.nBufferSize < size) {
+ ALOGE("failed to set min buffer size to %zu (is still %u)", size, def.nBufferSize);
+ return FAILED_TRANSACTION;
+ }
return OK;
}
@@ -2286,7 +2344,9 @@
}
status_t ACodec::setupG711Codec(bool encoder, int32_t sampleRate, int32_t numChannels) {
- CHECK(!encoder); // XXX TODO
+ if (encoder) {
+ return INVALID_OPERATION;
+ }
return setupRawAudioFormat(
kPortIndexInput, sampleRate, numChannels);
@@ -3395,8 +3455,9 @@
status_t err = mOMX->getParameter(
mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
-
- CHECK_EQ(err, (status_t)OK);
+ if (err != OK) {
+ return err;
+ }
if (portIndex == kPortIndexInput) {
// XXX Need a (much) better heuristic to compute input buffer sizes.
@@ -3406,7 +3467,10 @@
}
}
- CHECK_EQ((int)def.eDomain, (int)OMX_PortDomainVideo);
+ if (def.eDomain != OMX_PortDomainVideo) {
+ ALOGE("expected video port, got %s(%d)", asString(def.eDomain), def.eDomain);
+ return FAILED_TRANSACTION;
+ }
video_def->nFrameWidth = width;
video_def->nFrameHeight = height;
@@ -3683,17 +3747,20 @@
}
status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> ¬ify) {
- // TODO: catch errors an return them instead of using CHECK
+ const char *niceIndex = portIndex == kPortIndexInput ? "input" : "output";
OMX_PARAM_PORTDEFINITIONTYPE def;
InitOMXParams(&def);
def.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamPortDefinition, &def, sizeof(def)),
- (status_t)OK);
+ status_t err = mOMX->getParameter(mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
+ if (err != OK) {
+ return err;
+ }
- CHECK_EQ((int)def.eDir,
- (int)(portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput));
+ if (def.eDir != (portIndex == kPortIndexOutput ? OMX_DirOutput : OMX_DirInput)) {
+ ALOGE("unexpected dir: %s(%d) on %s port", asString(def.eDir), def.eDir, niceIndex);
+ return BAD_VALUE;
+ }
switch (def.eDomain) {
case OMX_PortDomainVideo:
@@ -3756,12 +3823,16 @@
rect.nHeight = videoDef->nFrameHeight;
}
- CHECK_GE(rect.nLeft, 0);
- CHECK_GE(rect.nTop, 0);
- CHECK_GE(rect.nWidth, 0u);
- CHECK_GE(rect.nHeight, 0u);
- CHECK_LE(rect.nLeft + rect.nWidth - 1, videoDef->nFrameWidth);
- CHECK_LE(rect.nTop + rect.nHeight - 1, videoDef->nFrameHeight);
+ if (rect.nLeft < 0 ||
+ rect.nTop < 0 ||
+ rect.nLeft + rect.nWidth > videoDef->nFrameWidth ||
+ rect.nTop + rect.nHeight > videoDef->nFrameHeight) {
+ ALOGE("Wrong cropped rect (%d, %d) - (%u, %u) vs. frame (%u, %u)",
+ rect.nLeft, rect.nTop,
+ rect.nLeft + rect.nWidth, rect.nTop + rect.nHeight,
+ videoDef->nFrameWidth, videoDef->nFrameHeight);
+ return BAD_VALUE;
+ }
notify->setRect(
"crop",
@@ -3818,7 +3889,13 @@
default:
{
- CHECK(mIsEncoder ^ (portIndex == kPortIndexInput));
+ if (mIsEncoder ^ (portIndex == kPortIndexOutput)) {
+ // should be CodingUnused
+ ALOGE("Raw port video compression format is %s(%d)",
+ asString(videoDef->eCompressionFormat),
+ videoDef->eCompressionFormat);
+ return BAD_VALUE;
+ }
AString mime;
if (GetMimeTypeForVideoCoding(
videoDef->eCompressionFormat, &mime) != OK) {
@@ -3849,20 +3926,25 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
- CHECK_GT(params.nChannels, 0);
- CHECK(params.nChannels == 1 || params.bInterleaved);
- CHECK_EQ(params.nBitPerSample, 16u);
-
- CHECK_EQ((int)params.eNumData,
- (int)OMX_NumericalDataSigned);
-
- CHECK_EQ((int)params.ePCMMode,
- (int)OMX_AUDIO_PCMModeLinear);
+ if (params.nChannels <= 0
+ || (params.nChannels != 1 && !params.bInterleaved)
+ || params.nBitPerSample != 16u
+ || params.eNumData != OMX_NumericalDataSigned
+ || params.ePCMMode != OMX_AUDIO_PCMModeLinear) {
+ ALOGE("unsupported PCM port: %u channels%s, %u-bit, %s(%d), %s(%d) mode ",
+ params.nChannels,
+ params.bInterleaved ? " interleaved" : "",
+ params.nBitPerSample,
+ asString(params.eNumData), params.eNumData,
+ asString(params.ePCMMode), params.ePCMMode);
+ return FAILED_TRANSACTION;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_RAW);
notify->setInt32("channel-count", params.nChannels);
@@ -3880,10 +3962,11 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioAac,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAac, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC);
notify->setInt32("channel-count", params.nChannels);
@@ -3897,21 +3980,18 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioAmr,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioAmr, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setInt32("channel-count", 1);
if (params.eAMRBandMode >= OMX_AUDIO_AMRBandModeWB0) {
- notify->setString(
- "mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
-
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB);
notify->setInt32("sample-rate", 16000);
} else {
- notify->setString(
- "mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
-
+ notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB);
notify->setInt32("sample-rate", 8000);
}
break;
@@ -3923,10 +4003,11 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioFlac,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioFlac, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_FLAC);
notify->setInt32("channel-count", params.nChannels);
@@ -3940,10 +4021,11 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioMp3,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioMp3, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MPEG);
notify->setInt32("channel-count", params.nChannels);
@@ -3957,10 +4039,11 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioVorbis,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioVorbis, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_VORBIS);
notify->setInt32("channel-count", params.nChannels);
@@ -3974,11 +4057,12 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ((status_t)OK, mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
- ¶ms,
- sizeof(params)));
+ err = mOMX->getParameter(
+ mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidAc3,
+ ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_AC3);
notify->setInt32("channel-count", params.nChannels);
@@ -3992,11 +4076,12 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ((status_t)OK, mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
- ¶ms,
- sizeof(params)));
+ err = mOMX->getParameter(
+ mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidEac3,
+ ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_EAC3);
notify->setInt32("channel-count", params.nChannels);
@@ -4010,11 +4095,12 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ((status_t)OK, mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
- ¶ms,
- sizeof(params)));
+ err = mOMX->getParameter(
+ mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioAndroidOpus,
+ ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_OPUS);
notify->setInt32("channel-count", params.nChannels);
@@ -4028,11 +4114,11 @@
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ((status_t)OK, mOMX->getParameter(
- mNode,
- (OMX_INDEXTYPE)OMX_IndexParamAudioPcm,
- ¶ms,
- sizeof(params)));
+ err = mOMX->getParameter(
+ mNode, (OMX_INDEXTYPE)OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
const char *mime = NULL;
if (params.ePCMMode == OMX_AUDIO_PCMModeMULaw) {
@@ -4050,30 +4136,33 @@
case OMX_AUDIO_CodingGSMFR:
{
- OMX_AUDIO_PARAM_MP3TYPE params;
+ OMX_AUDIO_PARAM_PCMMODETYPE params;
InitOMXParams(¶ms);
params.nPortIndex = portIndex;
- CHECK_EQ(mOMX->getParameter(
- mNode, OMX_IndexParamAudioPcm,
- ¶ms, sizeof(params)),
- (status_t)OK);
+ err = mOMX->getParameter(
+ mNode, OMX_IndexParamAudioPcm, ¶ms, sizeof(params));
+ if (err != OK) {
+ return err;
+ }
notify->setString("mime", MEDIA_MIMETYPE_AUDIO_MSGSM);
notify->setInt32("channel-count", params.nChannels);
- notify->setInt32("sample-rate", params.nSampleRate);
+ notify->setInt32("sample-rate", params.nSamplingRate);
break;
}
default:
- ALOGE("UNKNOWN AUDIO CODING: %d\n", audioDef->eEncoding);
- TRESPASS();
+ ALOGE("Unsupported audio coding: %s(%d)\n",
+ asString(audioDef->eEncoding), audioDef->eEncoding);
+ return BAD_TYPE;
}
break;
}
default:
- TRESPASS();
+ ALOGE("Unsupported domain: %s(%d)", asString(def.eDomain), def.eDomain);
+ return BAD_TYPE;
}
return OK;
@@ -4083,7 +4172,10 @@
sp<AMessage> notify = mBaseOutputFormat->dup();
notify->setInt32("what", kWhatOutputFormatChanged);
- CHECK_EQ(getPortFormat(kPortIndexOutput, notify), (status_t)OK);
+ if (getPortFormat(kPortIndexOutput, notify) != OK) {
+ ALOGE("[%s] Failed to get port format to send format change", mComponentName.c_str());
+ return;
+ }
AString mime;
CHECK(notify->findString("mime", &mime));
@@ -4225,7 +4317,7 @@
}
case ACodec::kWhatCreateInputSurface:
- case ACodec::kWhatUsePersistentInputSurface:
+ case ACodec::kWhatSetInputSurface:
case ACodec::kWhatSignalEndOfInputStream:
{
// This may result in an app illegal state exception.
@@ -4276,7 +4368,10 @@
IOMX::node_id nodeID;
CHECK(msg->findInt32("node", (int32_t*)&nodeID));
- CHECK_EQ(nodeID, mCodec->mNode);
+ if (nodeID != mCodec->mNode) {
+ ALOGE("Unexpected message for nodeID: %u, should have been %u", nodeID, mCodec->mNode);
+ return false;
+ }
switch (type) {
case omx_message::EVENT:
@@ -4332,8 +4427,8 @@
}
default:
- TRESPASS();
- break;
+ ALOGE("Unexpected message type: %d", type);
+ return false;
}
}
@@ -4363,10 +4458,13 @@
ALOGV("[%s] onOMXEmptyBufferDone %u",
mCodec->mComponentName.c_str(), bufferID);
- BufferInfo *info =
- mCodec->findBufferByID(kPortIndexInput, bufferID);
-
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+ BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
+ BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+ if (status != BufferInfo::OWNED_BY_COMPONENT) {
+ ALOGE("Wrong ownership in EBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+ mCodec->dumpBuffers(kPortIndexInput);
+ return false;
+ }
info->mStatus = BufferInfo::OWNED_BY_US;
// We're in "store-metadata-in-buffers" mode, the underlying
@@ -4386,12 +4484,10 @@
postFillThisBuffer(info);
break;
+ case FREE_BUFFERS:
default:
- {
- CHECK_EQ((int)mode, (int)FREE_BUFFERS);
- TRESPASS(); // Not currently used
- break;
- }
+ ALOGE("SHOULD NOT REACH HERE: cannot free empty output buffers");
+ return false;
}
return true;
@@ -4452,7 +4548,13 @@
}
BufferInfo *info = mCodec->findBufferByID(kPortIndexInput, bufferID);
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_UPSTREAM);
+ BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+ if (status != BufferInfo::OWNED_BY_UPSTREAM) {
+ ALOGE("Wrong ownership in IBF: %s(%d) buffer #%u", _asString(status), status, bufferID);
+ mCodec->dumpBuffers(kPortIndexInput);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return;
+ }
info->mStatus = BufferInfo::OWNED_BY_US;
@@ -4491,7 +4593,13 @@
bufferID,
buffer.get(), info->mData.get());
- CHECK_LE(buffer->size(), info->mData->capacity());
+ if (buffer->size() > info->mData->capacity()) {
+ ALOGE("data size (%zu) is greated than buffer capacity (%zu)",
+ buffer->size(), // this is the data received
+ info->mData->capacity()); // this is out buffer size
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return;
+ }
memcpy(info->mData->data(), buffer->data(), buffer->size());
}
@@ -4530,31 +4638,31 @@
mCodec->submitOutputMetaDataBuffer();
}
}
-
- CHECK_EQ(mCodec->mOMX->emptyBuffer(
- mCodec->mNode,
- bufferID,
- 0,
- buffer->size(),
- flags,
- timeUs),
- (status_t)OK);
-
+ status_t err2 = mCodec->mOMX->emptyBuffer(
+ mCodec->mNode,
+ bufferID,
+ 0,
+ buffer->size(),
+ flags,
+ timeUs);
+ if (err2 != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
+ return;
+ }
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
- if (!eos) {
+ if (!eos && err == OK) {
getMoreInputDataIfPossible();
} else {
- ALOGV("[%s] Signalled EOS on the input port",
- mCodec->mComponentName.c_str());
+ ALOGV("[%s] Signalled EOS (%d) on the input port",
+ mCodec->mComponentName.c_str(), err);
mCodec->mPortEOS[kPortIndexInput] = true;
mCodec->mInputEOSResult = err;
}
} else if (!mCodec->mPortEOS[kPortIndexInput]) {
- if (err != ERROR_END_OF_STREAM) {
- ALOGV("[%s] Signalling EOS on the input port "
- "due to error %d",
+ if (err != OK && err != ERROR_END_OF_STREAM) {
+ ALOGV("[%s] Signalling EOS on the input port due to error %d",
mCodec->mComponentName.c_str(), err);
} else {
ALOGV("[%s] Signalling EOS on the input port",
@@ -4564,15 +4672,17 @@
ALOGV("[%s] calling emptyBuffer %u signalling EOS",
mCodec->mComponentName.c_str(), bufferID);
- CHECK_EQ(mCodec->mOMX->emptyBuffer(
- mCodec->mNode,
- bufferID,
- 0,
- 0,
- OMX_BUFFERFLAG_EOS,
- 0),
- (status_t)OK);
-
+ status_t err2 = mCodec->mOMX->emptyBuffer(
+ mCodec->mNode,
+ bufferID,
+ 0,
+ 0,
+ OMX_BUFFERFLAG_EOS,
+ 0);
+ if (err2 != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
+ return;
+ }
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
mCodec->mPortEOS[kPortIndexInput] = true;
@@ -4581,8 +4691,11 @@
break;
}
+ case FREE_BUFFERS:
+ break;
+
default:
- CHECK_EQ((int)mode, (int)FREE_BUFFERS);
+ ALOGE("invalid port mode: %d", mode);
break;
}
}
@@ -4625,6 +4738,7 @@
mCodec->mComponentName.c_str(), bufferID, timeUs, flags);
ssize_t index;
+ status_t err= OK;
#if TRACK_BUFFER_TIMING
index = mCodec->mBufferStats.indexOfKey(timeUs);
@@ -4643,8 +4757,13 @@
BufferInfo *info =
mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
-
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_COMPONENT);
+ BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+ if (status != BufferInfo::OWNED_BY_COMPONENT) {
+ ALOGE("Wrong ownership in FBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+ mCodec->dumpBuffers(kPortIndexOutput);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return true;
+ }
info->mDequeuedAt = ++mCodec->mDequeueCounter;
info->mStatus = BufferInfo::OWNED_BY_US;
@@ -4662,9 +4781,11 @@
ALOGV("[%s] calling fillBuffer %u",
mCodec->mComponentName.c_str(), info->mBufferID);
- CHECK_EQ(mCodec->mOMX->fillBuffer(
- mCodec->mNode, info->mBufferID),
- (status_t)OK);
+ err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ return true;
+ }
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
break;
@@ -4726,14 +4847,17 @@
break;
}
- default:
- {
- CHECK_EQ((int)mode, (int)FREE_BUFFERS);
-
- CHECK_EQ((status_t)OK,
- mCodec->freeBuffer(kPortIndexOutput, index));
+ case FREE_BUFFERS:
+ err = mCodec->freeBuffer(kPortIndexOutput, index);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ return true;
+ }
break;
- }
+
+ default:
+ ALOGE("Invalid port mode: %d", mode);
+ return false;
}
return true;
@@ -4743,15 +4867,19 @@
IOMX::buffer_id bufferID;
CHECK(msg->findInt32("buffer-id", (int32_t*)&bufferID));
ssize_t index;
- BufferInfo *info =
- mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_DOWNSTREAM);
+ BufferInfo *info = mCodec->findBufferByID(kPortIndexOutput, bufferID, &index);
+ BufferInfo::Status status = BufferInfo::getSafeStatus(info);
+ if (status != BufferInfo::OWNED_BY_DOWNSTREAM) {
+ ALOGE("Wrong ownership in OBD: %s(%d) buffer #%u", _asString(status), status, bufferID);
+ mCodec->dumpBuffers(kPortIndexOutput);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return;
+ }
android_native_rect_t crop;
- if (msg->findRect("crop",
- &crop.left, &crop.top, &crop.right, &crop.bottom)) {
- CHECK_EQ(0, native_window_set_crop(
- mCodec->mNativeWindow.get(), &crop));
+ if (msg->findRect("crop", &crop.left, &crop.top, &crop.right, &crop.bottom)) {
+ status_t err = native_window_set_crop(mCodec->mNativeWindow.get(), &crop);
+ ALOGW_IF(err != NO_ERROR, "failed to set crop: %d", err);
}
int32_t render;
@@ -4777,13 +4905,11 @@
status_t err;
err = native_window_set_buffers_timestamp(mCodec->mNativeWindow.get(), timestampNs);
- if (err != OK) {
- ALOGW("failed to set buffer timestamp: %d", err);
- }
+ ALOGW_IF(err != NO_ERROR, "failed to set buffer timestamp: %d", err);
- if ((err = mCodec->mNativeWindow->queueBuffer(
- mCodec->mNativeWindow.get(),
- info->mGraphicBuffer.get(), -1)) == OK) {
+ err = mCodec->mNativeWindow->queueBuffer(
+ mCodec->mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
+ if (err == OK) {
info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
} else {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
@@ -4826,24 +4952,29 @@
if (info != NULL) {
ALOGV("[%s] calling fillBuffer %u",
mCodec->mComponentName.c_str(), info->mBufferID);
-
- CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
- (status_t)OK);
-
- info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+ if (err == OK) {
+ info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
+ } else {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ }
}
}
break;
}
- default:
+ case FREE_BUFFERS:
{
- CHECK_EQ((int)mode, (int)FREE_BUFFERS);
-
- CHECK_EQ((status_t)OK,
- mCodec->freeBuffer(kPortIndexOutput, index));
+ status_t err = mCodec->freeBuffer(kPortIndexOutput, index);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ }
break;
}
+
+ default:
+ ALOGE("Invalid port mode: %d", mode);
+ return;
}
}
@@ -5090,7 +5221,7 @@
void ACodec::LoadedState::onShutdown(bool keepComponentAllocated) {
if (!keepComponentAllocated) {
- CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
+ (void)mCodec->mOMX->freeNode(mCodec->mNode);
mCodec->changeState(mCodec->mUninitializedState);
}
@@ -5121,9 +5252,9 @@
break;
}
- case ACodec::kWhatUsePersistentInputSurface:
+ case ACodec::kWhatSetInputSurface:
{
- onUsePersistentInputSurface(msg);
+ onSetInputSurface(msg);
handled = true;
break;
}
@@ -5171,11 +5302,13 @@
CHECK(mCodec->mNode != 0);
+ status_t err = OK;
AString mime;
- CHECK(msg->findString("mime", &mime));
-
- status_t err = mCodec->configureCodec(mime.c_str(), msg);
-
+ if (!msg->findString("mime", &mime)) {
+ err = BAD_VALUE;
+ } else {
+ err = mCodec->configureCodec(mime.c_str(), msg);
+ }
if (err != OK) {
ALOGE("[%s] configureCodec returning error %d",
mCodec->mComponentName.c_str(), err);
@@ -5316,9 +5449,9 @@
notify->post();
}
-void ACodec::LoadedState::onUsePersistentInputSurface(
+void ACodec::LoadedState::onSetInputSurface(
const sp<AMessage> &msg) {
- ALOGV("onUsePersistentInputSurface");
+ ALOGV("onSetInputSurface");
sp<AMessage> notify = mCodec->mNotify->dup();
notify->setInt32("what", CodecBase::kWhatInputSurfaceAccepted);
@@ -5327,7 +5460,7 @@
CHECK(msg->findObject("input-surface", &obj));
sp<PersistentSurface> surface = static_cast<PersistentSurface *>(obj.get());
- status_t err = mCodec->mOMX->usePersistentInputSurface(
+ status_t err = mCodec->mOMX->setInputSurface(
mCodec->mNode, kPortIndexInput, surface->getBufferConsumer());
if (err == OK) {
@@ -5338,7 +5471,7 @@
// Can't use mCodec->signalError() here -- MediaCodec won't forward
// the error through because it's in the "configured" state. We
// send a kWhatInputSurfaceAccepted with an error value instead.
- ALOGE("[%s] onUsePersistentInputSurface returning error %d",
+ ALOGE("[%s] onSetInputSurface returning error %d",
mCodec->mComponentName.c_str(), err);
notify->setInt32("err", err);
}
@@ -5348,11 +5481,12 @@
void ACodec::LoadedState::onStart() {
ALOGV("onStart");
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
- (status_t)OK);
-
- mCodec->changeState(mCodec->mLoadedToIdleState);
+ status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ } else {
+ mCodec->changeState(mCodec->mLoadedToIdleState);
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -5426,14 +5560,25 @@
switch (event) {
case OMX_EventCmdComplete:
{
- CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
- CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+ status_t err = OK;
+ if (data1 != (OMX_U32)OMX_CommandStateSet
+ || data2 != (OMX_U32)OMX_StateIdle) {
+ ALOGE("Unexpected command completion in LoadedToIdleState: %s(%u) %s(%u)",
+ asString((OMX_COMMANDTYPE)data1), data1,
+ asString((OMX_STATETYPE)data2), data2);
+ err = FAILED_TRANSACTION;
+ }
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting),
- (status_t)OK);
+ if (err == OK) {
+ err = mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateExecuting);
+ }
- mCodec->changeState(mCodec->mIdleToExecutingState);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
+ } else {
+ mCodec->changeState(mCodec->mIdleToExecutingState);
+ }
return true;
}
@@ -5494,8 +5639,14 @@
switch (event) {
case OMX_EventCmdComplete:
{
- CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
- CHECK_EQ(data2, (OMX_U32)OMX_StateExecuting);
+ if (data1 != (OMX_U32)OMX_CommandStateSet
+ || data2 != (OMX_U32)OMX_StateExecuting) {
+ ALOGE("Unexpected command completion in IdleToExecutingState: %s(%u) %s(%u)",
+ asString((OMX_COMMANDTYPE)data1), data1,
+ asString((OMX_STATETYPE)data2), data2);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return true;
+ }
mCodec->mExecutingState->resume();
mCodec->changeState(mCodec->mExecutingState);
@@ -5537,28 +5688,43 @@
}
void ACodec::ExecutingState::submitRegularOutputBuffers() {
+ bool failed = false;
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexOutput].size(); ++i) {
BufferInfo *info = &mCodec->mBuffers[kPortIndexOutput].editItemAt(i);
if (mCodec->mNativeWindow != NULL) {
- CHECK(info->mStatus == BufferInfo::OWNED_BY_US
- || info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW);
+ if (info->mStatus != BufferInfo::OWNED_BY_US
+ && info->mStatus != BufferInfo::OWNED_BY_NATIVE_WINDOW) {
+ ALOGE("buffers should be owned by us or the surface");
+ failed = true;
+ break;
+ }
if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
continue;
}
} else {
- CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
+ if (info->mStatus != BufferInfo::OWNED_BY_US) {
+ ALOGE("buffers should be owned by us");
+ failed = true;
+ break;
+ }
}
- ALOGV("[%s] calling fillBuffer %u",
- mCodec->mComponentName.c_str(), info->mBufferID);
+ ALOGV("[%s] calling fillBuffer %u", mCodec->mComponentName.c_str(), info->mBufferID);
- CHECK_EQ(mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID),
- (status_t)OK);
+ status_t err = mCodec->mOMX->fillBuffer(mCodec->mNode, info->mBufferID);
+ if (err != OK) {
+ failed = true;
+ break;
+ }
info->mStatus = BufferInfo::OWNED_BY_COMPONENT;
}
+
+ if (failed) {
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ }
}
void ACodec::ExecutingState::submitOutputBuffers() {
@@ -5570,16 +5736,17 @@
void ACodec::ExecutingState::resume() {
if (mActive) {
- ALOGV("[%s] We're already active, no need to resume.",
- mCodec->mComponentName.c_str());
-
+ ALOGV("[%s] We're already active, no need to resume.", mCodec->mComponentName.c_str());
return;
}
submitOutputBuffers();
// Post all available input buffers
- CHECK_GT(mCodec->mBuffers[kPortIndexInput].size(), 0u);
+ if (mCodec->mBuffers[kPortIndexInput].size() == 0u) {
+ ALOGW("[%s] we don't have any input buffers to resume", mCodec->mComponentName.c_str());
+ }
+
for (size_t i = 0; i < mCodec->mBuffers[kPortIndexInput].size(); i++) {
BufferInfo *info = &mCodec->mBuffers[kPortIndexInput].editItemAt(i);
if (info->mStatus == BufferInfo::OWNED_BY_US) {
@@ -5612,11 +5779,16 @@
mActive = false;
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle),
- (status_t)OK);
-
- mCodec->changeState(mCodec->mExecutingToIdleState);
+ status_t err = mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateIdle);
+ if (err != OK) {
+ if (keepComponentAllocated) {
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ }
+ // TODO: do some recovery here.
+ } else {
+ mCodec->changeState(mCodec->mExecutingToIdleState);
+ }
handled = true;
break;
@@ -5634,11 +5806,13 @@
mActive = false;
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandFlush, OMX_ALL),
- (status_t)OK);
+ status_t err = mCodec->mOMX->sendCommand(mCodec->mNode, OMX_CommandFlush, OMX_ALL);
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ } else {
+ mCodec->changeState(mCodec->mFlushingState);
+ }
- mCodec->changeState(mCodec->mFlushingState);
handled = true;
break;
}
@@ -5889,25 +6063,34 @@
case OMX_EventCmdComplete:
{
if (data1 == (OMX_U32)OMX_CommandPortDisable) {
- CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+ if (data2 != (OMX_U32)kPortIndexOutput) {
+ ALOGW("ignoring EventCmdComplete CommandPortDisable for port %u", data2);
+ return false;
+ }
- ALOGV("[%s] Output port now disabled.",
- mCodec->mComponentName.c_str());
+ ALOGV("[%s] Output port now disabled.", mCodec->mComponentName.c_str());
- CHECK(mCodec->mBuffers[kPortIndexOutput].isEmpty());
- mCodec->mDealer[kPortIndexOutput].clear();
+ status_t err = OK;
+ if (!mCodec->mBuffers[kPortIndexOutput].isEmpty()) {
+ ALOGE("disabled port should be empty, but has %zu buffers",
+ mCodec->mBuffers[kPortIndexOutput].size());
+ err = FAILED_TRANSACTION;
+ } else {
+ mCodec->mDealer[kPortIndexOutput].clear();
+ }
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput),
- (status_t)OK);
+ if (err == OK) {
+ err = mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandPortEnable, kPortIndexOutput);
+ }
- status_t err;
- if ((err = mCodec->allocateBuffersOnPort(
- kPortIndexOutput)) != OK) {
- ALOGE("Failed to allocate output port buffers after "
- "port reconfiguration (error 0x%08x)",
- err);
+ if (err == OK) {
+ err = mCodec->allocateBuffersOnPort(kPortIndexOutput);
+ ALOGE_IF(err != OK, "Failed to allocate output port buffers after port "
+ "reconfiguration: (%d)", err);
+ }
+ if (err != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err));
// This is technically not correct, but appears to be
@@ -5922,12 +6105,14 @@
return true;
} else if (data1 == (OMX_U32)OMX_CommandPortEnable) {
- CHECK_EQ(data2, (OMX_U32)kPortIndexOutput);
+ if (data2 != (OMX_U32)kPortIndexOutput) {
+ ALOGW("ignoring EventCmdComplete OMX_CommandPortEnable for port %u", data2);
+ return false;
+ }
mCodec->mSentFormat = false;
- ALOGV("[%s] Output port now reenabled.",
- mCodec->mComponentName.c_str());
+ ALOGV("[%s] Output port now reenabled.", mCodec->mComponentName.c_str());
if (mCodec->mExecutingState->active()) {
mCodec->mExecutingState->submitOutputBuffers();
@@ -5961,7 +6146,7 @@
{
// Don't send me a flush request if you previously wanted me
// to shutdown.
- TRESPASS();
+ ALOGW("Ignoring flush request in ExecutingToIdleState");
break;
}
@@ -5993,8 +6178,14 @@
switch (event) {
case OMX_EventCmdComplete:
{
- CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
- CHECK_EQ(data2, (OMX_U32)OMX_StateIdle);
+ if (data1 != (OMX_U32)OMX_CommandStateSet
+ || data2 != (OMX_U32)OMX_StateIdle) {
+ ALOGE("Unexpected command completion in ExecutingToIdleState: %s(%u) %s(%u)",
+ asString((OMX_COMMANDTYPE)data1), data1,
+ asString((OMX_STATETYPE)data2), data2);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return true;
+ }
mComponentNowIdle = true;
@@ -6017,12 +6208,15 @@
void ACodec::ExecutingToIdleState::changeStateIfWeOwnAllBuffers() {
if (mComponentNowIdle && mCodec->allYourBuffersAreBelongToUs()) {
- CHECK_EQ(mCodec->mOMX->sendCommand(
- mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded),
- (status_t)OK);
-
- CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexInput), (status_t)OK);
- CHECK_EQ(mCodec->freeBuffersOnPort(kPortIndexOutput), (status_t)OK);
+ status_t err = mCodec->mOMX->sendCommand(
+ mCodec->mNode, OMX_CommandStateSet, OMX_StateLoaded);
+ if (err == OK) {
+ err = mCodec->freeBuffersOnPort(kPortIndexInput);
+ status_t err2 = mCodec->freeBuffersOnPort(kPortIndexOutput);
+ if (err == OK) {
+ err = err2;
+ }
+ }
if ((mCodec->mFlags & kFlagPushBlankBuffersToNativeWindowOnShutdown)
&& mCodec->mNativeWindow != NULL) {
@@ -6033,6 +6227,11 @@
pushBlankBuffersToNativeWindow(mCodec->mNativeWindow.get());
}
+ if (err != OK) {
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return;
+ }
+
mCodec->changeState(mCodec->mIdleToLoadedState);
}
}
@@ -6073,7 +6272,7 @@
{
// Don't send me a flush request if you previously wanted me
// to shutdown.
- TRESPASS();
+ ALOGE("Got flush request in IdleToLoadedState");
break;
}
@@ -6094,8 +6293,14 @@
switch (event) {
case OMX_EventCmdComplete:
{
- CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
- CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
+ if (data1 != (OMX_U32)OMX_CommandStateSet
+ || data2 != (OMX_U32)OMX_StateLoaded) {
+ ALOGE("Unexpected command completion in IdleToLoadedState: %s(%u) %s(%u)",
+ asString((OMX_COMMANDTYPE)data1), data1,
+ asString((OMX_STATETYPE)data2), data2);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return true;
+ }
mCodec->changeState(mCodec->mLoadedState);
@@ -6152,22 +6357,35 @@
switch (event) {
case OMX_EventCmdComplete:
{
- CHECK_EQ(data1, (OMX_U32)OMX_CommandFlush);
+ if (data1 != (OMX_U32)OMX_CommandFlush) {
+ ALOGE("unexpected EventCmdComplete %s(%d) data2:%d in FlushingState",
+ asString((OMX_COMMANDTYPE)data1), data1, data2);
+ mCodec->signalError(OMX_ErrorUndefined, FAILED_TRANSACTION);
+ return true;
+ }
if (data2 == kPortIndexInput || data2 == kPortIndexOutput) {
- CHECK(!mFlushComplete[data2]);
+ if (mFlushComplete[data2]) {
+ ALOGW("Flush already completed for %s port",
+ data2 == kPortIndexInput ? "input" : "output");
+ return true;
+ }
mFlushComplete[data2] = true;
- if (mFlushComplete[kPortIndexInput]
- && mFlushComplete[kPortIndexOutput]) {
+ if (mFlushComplete[kPortIndexInput] && mFlushComplete[kPortIndexOutput]) {
changeStateIfWeOwnAllBuffers();
}
- } else {
- CHECK_EQ(data2, OMX_ALL);
- CHECK(mFlushComplete[kPortIndexInput]);
- CHECK(mFlushComplete[kPortIndexOutput]);
+ } else if (data2 == OMX_ALL) {
+ if (!mFlushComplete[kPortIndexInput] || !mFlushComplete[kPortIndexOutput]) {
+ ALOGW("received flush complete event for OMX_ALL before ports have been"
+ "flushed (%d/%d)",
+ mFlushComplete[kPortIndexInput], mFlushComplete[kPortIndexOutput]);
+ return false;
+ }
changeStateIfWeOwnAllBuffers();
+ } else {
+ ALOGW("data2 not OMX_ALL but %u in EventCmdComplete CommandFlush", data2);
}
return true;
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 5c0afa9..65d8a04 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -33,6 +33,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/foundation/AUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDefs.h>
@@ -221,8 +222,7 @@
ssize_t MPEG4DataSource::readAt(off64_t offset, void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
- if (offset >= mCachedOffset
- && offset + size <= mCachedOffset + mCachedSize) {
+ if (isInRange(mCachedOffset, mCachedSize, offset, size)) {
memcpy(data, &mCache[offset - mCachedOffset], size);
return size;
}
@@ -4120,12 +4120,12 @@
size_t dstOffset = 0;
while (srcOffset < size) {
- bool isMalFormed = (srcOffset + mNALLengthSize > size);
+ bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
size_t nalLength = 0;
if (!isMalFormed) {
nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
srcOffset += mNALLengthSize;
- isMalFormed = srcOffset + nalLength > size;
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
}
if (isMalFormed) {
@@ -4397,12 +4397,12 @@
size_t dstOffset = 0;
while (srcOffset < size) {
- bool isMalFormed = (srcOffset + mNALLengthSize > size);
+ bool isMalFormed = !isInRange((size_t)0u, size, srcOffset, mNALLengthSize);
size_t nalLength = 0;
if (!isMalFormed) {
nalLength = parseNALSize(&mSrcBuffer[srcOffset]);
srcOffset += mNALLengthSize;
- isMalFormed = srcOffset + nalLength > size;
+ isMalFormed = !isInRange((size_t)0u, size, srcOffset, nalLength);
}
if (isMalFormed) {
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 3bc22f2..95f361e 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -369,9 +369,16 @@
mWriterThreadStarted(false),
mOffset(0),
mMdatOffset(0),
+ mMoovBoxBuffer(NULL),
+ mMoovBoxBufferOffset(0),
+ mWriteMoovBoxToMemory(false),
+ mFreeBoxOffset(0),
+ mStreamableFile(false),
mEstimatedMoovBoxSize(0),
mMoovExtraSize(0),
mInterleaveDurationUs(1000000),
+ mTimeScale(-1),
+ mStartTimestampUs(-1ll),
mLatitudex10000(0),
mLongitudex10000(0),
mAreGeoTagsAvailable(false),
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 4080391..46c154d 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -554,9 +554,9 @@
return err;
}
-status_t MediaCodec::usePersistentInputSurface(
+status_t MediaCodec::setInputSurface(
const sp<PersistentSurface> &surface) {
- sp<AMessage> msg = new AMessage(kWhatUsePersistentInputSurface, this);
+ sp<AMessage> msg = new AMessage(kWhatSetInputSurface, this);
msg->setObject("input-surface", surface.get());
sp<AMessage> response;
@@ -1290,7 +1290,7 @@
case CodecBase::kWhatInputSurfaceAccepted:
{
- // response to initiateUsePersistentInputSurface()
+ // response to initiateSetInputSurface()
status_t err = NO_ERROR;
sp<AMessage> response = new AMessage();
if (!msg->findInt32("err", &err)) {
@@ -1776,7 +1776,7 @@
}
case kWhatCreateInputSurface:
- case kWhatUsePersistentInputSurface:
+ case kWhatSetInputSurface:
{
sp<AReplyToken> replyID;
CHECK(msg->senderAwaitsResponse(&replyID));
@@ -1794,7 +1794,7 @@
sp<RefBase> obj;
CHECK(msg->findObject("input-surface", &obj));
- mCodec->initiateUsePersistentInputSurface(
+ mCodec->initiateSetInputSurface(
static_cast<PersistentSurface *>(obj.get()));
}
break;
diff --git a/media/libstagefright/MediaCodecSource.cpp b/media/libstagefright/MediaCodecSource.cpp
index 9b57733..e089c46 100644
--- a/media/libstagefright/MediaCodecSource.cpp
+++ b/media/libstagefright/MediaCodecSource.cpp
@@ -427,7 +427,7 @@
// When using persistent surface, we are only interested in the
// consumer, but have to use PersistentSurface as a wrapper to
// pass consumer over messages (similar to BufferProducerWrapper)
- err = mEncoder->usePersistentInputSurface(
+ err = mEncoder->setInputSurface(
new PersistentSurface(NULL, mGraphicBufferConsumer));
} else {
err = mEncoder->createInputSurface(&mGraphicBufferProducer);
diff --git a/media/libstagefright/MediaDefs.cpp b/media/libstagefright/MediaDefs.cpp
index b0a65d2..2a50692 100644
--- a/media/libstagefright/MediaDefs.cpp
+++ b/media/libstagefright/MediaDefs.cpp
@@ -62,6 +62,6 @@
const char *MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
const char *MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
const char *MEDIA_MIMETYPE_TEXT_CEA_608 = "text/cea-608";
-const char *MEDIA_MIMETYPE_DATA_METADATA = "application/octet-stream";
+const char *MEDIA_MIMETYPE_DATA_TIMED_ID3 = "application/x-id3v4";
} // namespace android
diff --git a/media/libstagefright/MediaSync.cpp b/media/libstagefright/MediaSync.cpp
index 97264fb..b402e48 100644
--- a/media/libstagefright/MediaSync.cpp
+++ b/media/libstagefright/MediaSync.cpp
@@ -49,6 +49,7 @@
mMutex(),
mReleaseCondition(),
mNumOutstandingBuffers(0),
+ mUsageFlagsFromOutput(0),
mNativeSampleRateInHz(0),
mNumFramesWritten(0),
mHasAudio(false),
@@ -82,10 +83,8 @@
status_t MediaSync::setSurface(const sp<IGraphicBufferProducer> &output) {
Mutex::Autolock lock(mMutex);
- // TODO: support suface change.
- if (mOutput != NULL) {
- ALOGE("setSurface: output surface has already been configured.");
- return INVALID_OPERATION;
+ if (output == mOutput) {
+ return NO_ERROR; // same output surface.
}
if (output == NULL && mSyncSettings.mSource == AVSYNC_SOURCE_VSYNC) {
@@ -94,8 +93,24 @@
}
if (output != NULL) {
+ int newUsage = 0;
+ output->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &newUsage);
+
+ // Check usage flags only when current output surface has been used to create input surface.
+ if (mOutput != NULL && mInput != NULL) {
+ int ignoredFlags = (GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER
+ | GRALLOC_USAGE_EXTERNAL_DISP);
+ // New output surface is not allowed to add new usage flag except ignored ones.
+ if ((newUsage & ~(mUsageFlagsFromOutput | ignoredFlags)) != 0) {
+ ALOGE("setSurface: new output surface has new usage flag not used by current one.");
+ return BAD_VALUE;
+ }
+ }
+
+ // Try to connect to new output surface. If failed, current output surface will not
+ // be changed.
IGraphicBufferProducer::QueueBufferOutput queueBufferOutput;
- sp<OutputListener> listener(new OutputListener(this));
+ sp<OutputListener> listener(new OutputListener(this, output));
IInterface::asBinder(output)->linkToDeath(listener);
status_t status =
output->connect(listener,
@@ -106,10 +121,18 @@
ALOGE("setSurface: failed to connect (%d)", status);
return status;
}
-
- mOutput = output;
}
+ if (mOutput != NULL) {
+ mOutput->disconnect(NATIVE_WINDOW_API_MEDIA);
+ while (!mBuffersSentToOutput.isEmpty()) {
+ returnBufferToInput_l(mBuffersSentToOutput.valueAt(0), Fence::NO_FENCE);
+ mBuffersSentToOutput.removeItemsAt(0);
+ }
+ }
+
+ mOutput = output;
+
return NO_ERROR;
}
@@ -181,9 +204,9 @@
if (status == NO_ERROR) {
bufferConsumer->setConsumerName(String8("MediaSync"));
// propagate usage bits from output surface
- int usage = 0;
- mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &usage);
- bufferConsumer->setConsumerUsageBits(usage);
+ mUsageFlagsFromOutput = 0;
+ mOutput->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &mUsageFlagsFromOutput);
+ bufferConsumer->setConsumerUsageBits(mUsageFlagsFromOutput);
*outBufferProducer = bufferProducer;
mInput = bufferConsumer;
}
@@ -602,12 +625,24 @@
return;
}
+ if (mBuffersSentToOutput.indexOfKey(bufferItem.mGraphicBuffer->getId()) >= 0) {
+ // Something is wrong since this buffer should be held by output now, bail.
+ mInput->consumerDisconnect();
+ onAbandoned_l(true /* isInput */);
+ return;
+ }
+ mBuffersSentToOutput.add(bufferItem.mGraphicBuffer->getId(), bufferItem.mGraphicBuffer);
+
ALOGV("queued buffer %#llx to output", (long long)bufferItem.mGraphicBuffer->getId());
}
-void MediaSync::onBufferReleasedByOutput() {
+void MediaSync::onBufferReleasedByOutput(sp<IGraphicBufferProducer> &output) {
Mutex::Autolock lock(mMutex);
+ if (output != mOutput) {
+ return; // This is not the current output, ignore.
+ }
+
sp<GraphicBuffer> buffer;
sp<Fence> fence;
status_t status = mOutput->detachNextBuffer(&buffer, &fence);
@@ -628,6 +663,13 @@
return;
}
+ ssize_t ix = mBuffersSentToOutput.indexOfKey(buffer->getId());
+ if (ix < 0) {
+ // The buffer is unknown, maybe leftover, ignore.
+ return;
+ }
+ mBuffersSentToOutput.removeItemsAt(ix);
+
returnBufferToInput_l(buffer, fence);
}
@@ -727,13 +769,15 @@
mSync->onAbandoned_l(true /* isInput */);
}
-MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync)
- : mSync(sync) {}
+MediaSync::OutputListener::OutputListener(const sp<MediaSync> &sync,
+ const sp<IGraphicBufferProducer> &output)
+ : mSync(sync),
+ mOutput(output) {}
MediaSync::OutputListener::~OutputListener() {}
void MediaSync::OutputListener::onBufferReleased() {
- mSync->onBufferReleasedByOutput();
+ mSync->onBufferReleasedByOutput(mOutput);
}
void MediaSync::OutputListener::binderDied(const wp<IBinder> &/* who */) {
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 44695ce..f1ebea2 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -108,7 +108,7 @@
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer);
- virtual status_t usePersistentInputSurface(
+ virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer);
@@ -356,11 +356,10 @@
bufferProducer, bufferConsumer);
}
-status_t MuxOMX::usePersistentInputSurface(
+status_t MuxOMX::setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer) {
- return getOMX(node)->usePersistentInputSurface(
- node, port_index, bufferConsumer);
+ return getOMX(node)->setInputSurface(node, port_index, bufferConsumer);
}
status_t MuxOMX::signalEndOfInputStream(node_id node) {
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 10937ec..965c55e 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -75,7 +75,7 @@
SoftAAC2::~SoftAAC2() {
aacDecoder_Close(mAACDecoder);
- delete mOutputDelayRingBuffer;
+ delete[] mOutputDelayRingBuffer;
}
void SoftAAC2::initPorts() {
diff --git a/media/libstagefright/filters/MediaFilter.cpp b/media/libstagefright/filters/MediaFilter.cpp
index fa9d630..0cf6b06 100644
--- a/media/libstagefright/filters/MediaFilter.cpp
+++ b/media/libstagefright/filters/MediaFilter.cpp
@@ -76,9 +76,9 @@
(new AMessage(kWhatCreateInputSurface, this))->post();
}
-void MediaFilter::initiateUsePersistentInputSurface(
+void MediaFilter::initiateSetInputSurface(
const sp<PersistentSurface> & /* surface */) {
- ALOGW("initiateUsePersistentInputSurface() unsupported");
+ ALOGW("initiateSetInputSurface() unsupported");
}
void MediaFilter::initiateStart() {
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 64a8532..27509cb 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -1406,7 +1406,7 @@
sp<AMessage> format = new AMessage();
format->setInt32("type", MEDIA_TRACK_TYPE_METADATA);
format->setString("language", "und");
- format->setString("mime", MEDIA_MIMETYPE_DATA_METADATA);
+ format->setString("mime", MEDIA_MIMETYPE_DATA_TIMED_ID3);
return format;
}
return mPlaylist->getTrackInfo(trackIndex);
diff --git a/media/libstagefright/include/OMX.h b/media/libstagefright/include/OMX.h
index b1ee628..c183208 100644
--- a/media/libstagefright/include/OMX.h
+++ b/media/libstagefright/include/OMX.h
@@ -99,7 +99,7 @@
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer);
- virtual status_t usePersistentInputSurface(
+ virtual status_t setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer);
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 03c9a8a..ad1e181 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -87,7 +87,7 @@
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer);
- status_t usePersistentInputSurface(
+ status_t setInputSurface(
OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer);
status_t signalEndOfInputStream();
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index baf3b15..36ec367 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -1393,7 +1393,7 @@
if (mFormat == NULL) {
mFormat = new MetaData;
- mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_DATA_METADATA);
+ mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_DATA_TIMED_ID3);
}
return accessUnit;
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 876abb8..a1ceb2e 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -385,11 +385,10 @@
bufferProducer, bufferConsumer);
}
-status_t OMX::usePersistentInputSurface(
+status_t OMX::setInputSurface(
node_id node, OMX_U32 port_index,
const sp<IGraphicBufferConsumer> &bufferConsumer) {
- return findInstance(node)->usePersistentInputSurface(
- port_index, bufferConsumer);
+ return findInstance(node)->setInputSurface(port_index, bufferConsumer);
}
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 04293d6..91cee73 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -891,7 +891,7 @@
return OK;
}
-status_t OMXNodeInstance::usePersistentInputSurface(
+status_t OMXNodeInstance::setInputSurface(
OMX_U32 portIndex, const sp<IGraphicBufferConsumer> &bufferConsumer) {
Mutex::Autolock autolock(mLock);
return createGraphicBufferSource(portIndex, bufferConsumer);
diff --git a/media/libstagefright/tests/Utils_test.cpp b/media/libstagefright/tests/Utils_test.cpp
index 5c323c1..c1e663c 100644
--- a/media/libstagefright/tests/Utils_test.cpp
+++ b/media/libstagefright/tests/Utils_test.cpp
@@ -192,6 +192,87 @@
ASSERT_EQ(max(-4.3, 8.6), 8.6);
ASSERT_EQ(max(8.6, -4.3), 8.6);
+ ASSERT_FALSE(isInRange(-43, 86u, -44));
+ ASSERT_TRUE(isInRange(-43, 87u, -43));
+ ASSERT_TRUE(isInRange(-43, 88u, -1));
+ ASSERT_TRUE(isInRange(-43, 89u, 0));
+ ASSERT_TRUE(isInRange(-43, 90u, 46));
+ ASSERT_FALSE(isInRange(-43, 91u, 48));
+ ASSERT_FALSE(isInRange(-43, 92u, 50));
+
+ ASSERT_FALSE(isInRange(43, 86u, 42));
+ ASSERT_TRUE(isInRange(43, 87u, 43));
+ ASSERT_TRUE(isInRange(43, 88u, 44));
+ ASSERT_TRUE(isInRange(43, 89u, 131));
+ ASSERT_FALSE(isInRange(43, 90u, 133));
+ ASSERT_FALSE(isInRange(43, 91u, 135));
+
+ ASSERT_FALSE(isInRange(43u, 86u, 42u));
+ ASSERT_TRUE(isInRange(43u, 85u, 43u));
+ ASSERT_TRUE(isInRange(43u, 84u, 44u));
+ ASSERT_TRUE(isInRange(43u, 83u, 125u));
+ ASSERT_FALSE(isInRange(43u, 82u, 125u));
+ ASSERT_FALSE(isInRange(43u, 81u, 125u));
+
+ ASSERT_FALSE(isInRange(-43, ~0u, 43));
+ ASSERT_FALSE(isInRange(-43, ~0u, 44));
+ ASSERT_FALSE(isInRange(-43, ~0u, ~0));
+ ASSERT_FALSE(isInRange(-43, ~0u, 41));
+ ASSERT_FALSE(isInRange(-43, ~0u, 40));
+
+ ASSERT_FALSE(isInRange(43u, ~0u, 43u));
+ ASSERT_FALSE(isInRange(43u, ~0u, 41u));
+ ASSERT_FALSE(isInRange(43u, ~0u, 40u));
+ ASSERT_FALSE(isInRange(43u, ~0u, ~0u));
+
+ ASSERT_FALSE(isInRange(-43, 86u, -44, 0u));
+ ASSERT_FALSE(isInRange(-43, 86u, -44, 1u));
+ ASSERT_FALSE(isInRange(-43, 86u, -44, 2u));
+ ASSERT_FALSE(isInRange(-43, 86u, -44, ~0u));
+ ASSERT_TRUE(isInRange(-43, 87u, -43, 0u));
+ ASSERT_TRUE(isInRange(-43, 87u, -43, 1u));
+ ASSERT_TRUE(isInRange(-43, 87u, -43, 86u));
+ ASSERT_TRUE(isInRange(-43, 87u, -43, 87u));
+ ASSERT_FALSE(isInRange(-43, 87u, -43, 88u));
+ ASSERT_FALSE(isInRange(-43, 87u, -43, ~0u));
+ ASSERT_TRUE(isInRange(-43, 88u, -1, 0u));
+ ASSERT_TRUE(isInRange(-43, 88u, -1, 45u));
+ ASSERT_TRUE(isInRange(-43, 88u, -1, 46u));
+ ASSERT_FALSE(isInRange(-43, 88u, -1, 47u));
+ ASSERT_FALSE(isInRange(-43, 88u, -1, ~3u));
+ ASSERT_TRUE(isInRange(-43, 90u, 46, 0u));
+ ASSERT_TRUE(isInRange(-43, 90u, 46, 1u));
+ ASSERT_FALSE(isInRange(-43, 90u, 46, 2u));
+ ASSERT_FALSE(isInRange(-43, 91u, 48, 0u));
+ ASSERT_FALSE(isInRange(-43, 91u, 48, 2u));
+ ASSERT_FALSE(isInRange(-43, 91u, 48, ~6u));
+ ASSERT_FALSE(isInRange(-43, 92u, 50, 0u));
+ ASSERT_FALSE(isInRange(-43, 92u, 50, 1u));
+
+ ASSERT_FALSE(isInRange(43u, 86u, 42u, 0u));
+ ASSERT_FALSE(isInRange(43u, 86u, 42u, 1u));
+ ASSERT_FALSE(isInRange(43u, 86u, 42u, 2u));
+ ASSERT_FALSE(isInRange(43u, 86u, 42u, ~0u));
+ ASSERT_TRUE(isInRange(43u, 87u, 43u, 0u));
+ ASSERT_TRUE(isInRange(43u, 87u, 43u, 1u));
+ ASSERT_TRUE(isInRange(43u, 87u, 43u, 86u));
+ ASSERT_TRUE(isInRange(43u, 87u, 43u, 87u));
+ ASSERT_FALSE(isInRange(43u, 87u, 43u, 88u));
+ ASSERT_FALSE(isInRange(43u, 87u, 43u, ~0u));
+ ASSERT_TRUE(isInRange(43u, 88u, 60u, 0u));
+ ASSERT_TRUE(isInRange(43u, 88u, 60u, 70u));
+ ASSERT_TRUE(isInRange(43u, 88u, 60u, 71u));
+ ASSERT_FALSE(isInRange(43u, 88u, 60u, 72u));
+ ASSERT_FALSE(isInRange(43u, 88u, 60u, ~3u));
+ ASSERT_TRUE(isInRange(43u, 90u, 132u, 0u));
+ ASSERT_TRUE(isInRange(43u, 90u, 132u, 1u));
+ ASSERT_FALSE(isInRange(43u, 90u, 132u, 2u));
+ ASSERT_FALSE(isInRange(43u, 91u, 134u, 0u));
+ ASSERT_FALSE(isInRange(43u, 91u, 134u, 2u));
+ ASSERT_FALSE(isInRange(43u, 91u, 134u, ~6u));
+ ASSERT_FALSE(isInRange(43u, 92u, 136u, 0u));
+ ASSERT_FALSE(isInRange(43u, 92u, 136u, 1u));
+
ASSERT_EQ(periodicError(124, 100), 24);
ASSERT_EQ(periodicError(288, 100), 12);
ASSERT_EQ(periodicError(-345, 100), 45);
diff --git a/services/audioflinger/ServiceUtilities.cpp b/services/audioflinger/ServiceUtilities.cpp
index 0a718fb..33bd416 100644
--- a/services/audioflinger/ServiceUtilities.cpp
+++ b/services/audioflinger/ServiceUtilities.cpp
@@ -83,7 +83,7 @@
}
AppOpsManager appOps;
- if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, opPackageName)
+ if (appOps.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, checkedOpPackageName)
!= AppOpsManager::MODE_ALLOWED) {
ALOGE("Request denied by app op OP_RECORD_AUDIO");
return false;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 8de8930..fc9a332 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -122,8 +122,8 @@
// should be ok for now.
static CameraService *gCameraService;
-CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH),
- mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) {
+CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(),
+ mSoundRef(0), mModule(0), mFlashlight(0) {
ALOGI("CameraService started (pid=%d)", getpid());
gCameraService = this;
@@ -519,34 +519,12 @@
int CameraService::getCameraPriorityFromProcState(int procState) {
// Find the priority for the camera usage based on the process state. Higher priority clients
// win for evictions.
- // Note: Unlike the ordering for ActivityManager, persistent system processes will always lose
- // the camera to the top/foreground applications.
- switch(procState) {
- case PROCESS_STATE_TOP: // User visible
- return 100;
- case PROCESS_STATE_IMPORTANT_FOREGROUND: // Foreground
- return 90;
- case PROCESS_STATE_PERSISTENT: // Persistent system services
- case PROCESS_STATE_PERSISTENT_UI:
- return 80;
- case PROCESS_STATE_IMPORTANT_BACKGROUND: // "Important" background processes
- return 70;
- case PROCESS_STATE_BACKUP: // Everything else
- case PROCESS_STATE_HEAVY_WEIGHT:
- case PROCESS_STATE_SERVICE:
- case PROCESS_STATE_RECEIVER:
- case PROCESS_STATE_HOME:
- case PROCESS_STATE_LAST_ACTIVITY:
- case PROCESS_STATE_CACHED_ACTIVITY:
- case PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
- case PROCESS_STATE_CACHED_EMPTY:
- return 1;
- case PROCESS_STATE_NONEXISTENT:
- return -1;
- default:
- ALOGE("%s: Received unknown process state from ActivityManagerService!", __FUNCTION__);
- return -1;
+ if (procState < 0) {
+ ALOGE("%s: Received invalid process state %d from ActivityManagerService!", __FUNCTION__,
+ procState);
+ return -1;
}
+ return INT_MAX - procState;
}
status_t CameraService::getCameraVendorTagDescriptor(/*out*/sp<VendorTagDescriptor>& desc) {
@@ -698,6 +676,20 @@
return NO_ERROR;
}
+String8 CameraService::toString(std::set<userid_t> intSet) {
+ String8 s("");
+ bool first = true;
+ for (userid_t i : intSet) {
+ if (first) {
+ s.appendFormat("%d", i);
+ first = false;
+ } else {
+ s.appendFormat(", %d", i);
+ }
+ }
+ return s;
+}
+
status_t CameraService::initializeShimMetadata(int cameraId) {
int uid = getCallingUid();
@@ -805,7 +797,7 @@
// Check device policy for this camera
char value[PROPERTY_VALUE_MAX];
char key[PROPERTY_KEY_MAX];
- int clientUserId = multiuser_get_user_id(clientUid);
+ userid_t clientUserId = multiuser_get_user_id(clientUid);
snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);
property_get(key, value, "0");
if (strcmp(value, "1") == 0) {
@@ -817,10 +809,10 @@
// Only allow clients who are being used by the current foreground device user, unless calling
// from our own process.
- if (callingPid != getpid() &&
- (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID)) {
- ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from previous "
- "device user %d, current device user %d)", callingPid, clientUserId, mLastUserId);
+ if (callingPid != getpid() && (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) {
+ ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from "
+ "device user %d, currently allowed device users: %s)", callingPid, clientUserId,
+ toString(mAllowedUsers).string());
return PERMISSION_DENIED;
}
@@ -1219,10 +1211,10 @@
return OK;
}
-void CameraService::notifySystemEvent(int eventId, int arg0) {
+void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) {
switch(eventId) {
case ICameraService::USER_SWITCHED: {
- doUserSwitch(/*newUserId*/arg0);
+ doUserSwitch(/*newUserIds*/args, /*length*/length);
break;
}
case ICameraService::NO_EVENT:
@@ -1465,20 +1457,30 @@
return clientDescriptorPtr->getValue();
}
-void CameraService::doUserSwitch(int newUserId) {
+void CameraService::doUserSwitch(const int32_t* newUserId, size_t length) {
// Acquire mServiceLock and prevent other clients from connecting
std::unique_ptr<AutoConditionLock> lock =
AutoConditionLock::waitAndAcquire(mServiceLockWrapper);
- if (newUserId <= 0) {
- ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__,
- newUserId);
- newUserId = DEFAULT_LAST_USER_ID;
+ std::set<userid_t> newAllowedUsers;
+ for (size_t i = 0; i < length; i++) {
+ if (newUserId[i] < 0) {
+ ALOGE("%s: Bad user ID %d given during user switch, ignoring.",
+ __FUNCTION__, newUserId[i]);
+ return;
+ }
+ newAllowedUsers.insert(static_cast<userid_t>(newUserId[i]));
}
- logUserSwitch(mLastUserId, newUserId);
- mLastUserId = newUserId;
+ if (newAllowedUsers == mAllowedUsers) {
+ ALOGW("%s: Received notification of user switch with no updated user IDs.", __FUNCTION__);
+ return;
+ }
+
+ logUserSwitch(mAllowedUsers, newAllowedUsers);
+
+ mAllowedUsers = std::move(newAllowedUsers);
// Current user has switched, evict all current clients.
std::vector<sp<BasicClient>> evicted;
@@ -1490,6 +1492,13 @@
continue;
}
+ // Don't evict clients that are still allowed.
+ uid_t clientUid = clientSp->getClientUid();
+ userid_t clientUserId = multiuser_get_user_id(clientUid);
+ if (mAllowedUsers.find(clientUserId) != mAllowedUsers.end()) {
+ continue;
+ }
+
evicted.push_back(clientSp);
String8 curTime = getFormattedCurrentTime();
@@ -1549,10 +1558,13 @@
cameraId, clientPackage, clientPid, reason));
}
-void CameraService::logUserSwitch(int oldUserId, int newUserId) {
+void CameraService::logUserSwitch(const std::set<userid_t>& oldUserIds,
+ const std::set<userid_t>& newUserIds) {
+ String8 newUsers = toString(newUserIds);
+ String8 oldUsers = toString(oldUserIds);
// Log the new and old users
- logEvent(String8::format("USER_SWITCH from old user: %d , to new user: %d", oldUserId,
- newUserId));
+ logEvent(String8::format("USER_SWITCH previous allowed users: %s , current allowed users: %s",
+ oldUsers.string(), newUsers.string()));
}
void CameraService::logDeviceRemoved(const char* cameraId, const char* reason) {
@@ -1757,6 +1769,10 @@
return mClientPid;
}
+uid_t CameraService::BasicClient::getClientUid() const {
+ return mClientUid;
+}
+
bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const {
// Defaults to API2.
return level == API_2;
@@ -1959,12 +1975,18 @@
auto conflicting = i->getConflicting();
auto clientSp = i->getValue();
String8 packageName;
+ userid_t clientUserId;
if (clientSp.get() != nullptr) {
packageName = String8{clientSp->getPackageName()};
+ uid_t clientUid = clientSp->getClientUid();
+ clientUserId = multiuser_get_user_id(clientUid);
}
ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"
PRId32 ", ", key.string(), cost, pid, priority);
+ if (clientSp.get() != nullptr) {
+ ret.appendFormat("User Id: %d, ", clientUserId);
+ }
if (packageName.size() != 0) {
ret.appendFormat("Client Package Name: %s", packageName.string());
}
@@ -2047,6 +2069,7 @@
result.appendFormat("Number of camera devices: %d\n", mNumberOfCameras);
String8 activeClientString = mActiveClientManager.toString();
result.appendFormat("Active Camera Clients:\n%s", activeClientString.string());
+ result.appendFormat("Allowed users:\n%s\n", toString(mAllowedUsers).string());
sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();
if (desc == NULL) {
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 8df746a..9b7163a 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -71,22 +71,8 @@
API_2 = 2
};
- // Process States (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
+ // Process state (mirrors frameworks/base/core/java/android/app/ActivityManager.java)
static const int PROCESS_STATE_NONEXISTENT = -1;
- static const int PROCESS_STATE_PERSISTENT = 0;
- static const int PROCESS_STATE_PERSISTENT_UI = 1;
- static const int PROCESS_STATE_TOP = 2;
- static const int PROCESS_STATE_IMPORTANT_FOREGROUND = 3;
- static const int PROCESS_STATE_IMPORTANT_BACKGROUND = 4;
- static const int PROCESS_STATE_BACKUP = 5;
- static const int PROCESS_STATE_HEAVY_WEIGHT = 6;
- static const int PROCESS_STATE_SERVICE = 7;
- static const int PROCESS_STATE_RECEIVER = 8;
- static const int PROCESS_STATE_HOME = 9;
- static const int PROCESS_STATE_LAST_ACTIVITY = 10;
- static const int PROCESS_STATE_CACHED_ACTIVITY = 11;
- static const int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 12;
- static const int PROCESS_STATE_CACHED_EMPTY = 13;
// 3 second busy timeout when other clients are connecting
static const nsecs_t DEFAULT_CONNECT_TIMEOUT_NS = 3000000000;
@@ -97,11 +83,6 @@
// Default number of messages to store in eviction log
static const size_t DEFAULT_EVENT_LOG_LENGTH = 100;
- enum {
- // Default last user id
- DEFAULT_LAST_USER_ID = 0,
- };
-
// Implementation of BinderService<T>
static char const* getServiceName() { return "media.camera"; }
@@ -155,7 +136,7 @@
virtual status_t setTorchMode(const String16& cameraId, bool enabled,
const sp<IBinder>& clientBinder);
- virtual void notifySystemEvent(int eventId, int arg0);
+ virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length);
// OK = supports api of that version, -EOPNOTSUPP = does not support
virtual status_t supportsCameraApi(
@@ -214,6 +195,9 @@
virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,
const CaptureResultExtras& resultExtras) = 0;
+ // Get the UID of the application client using this
+ virtual uid_t getClientUid() const;
+
// Get the PID of the application client using this
virtual int getClientPid() const;
@@ -483,7 +467,6 @@
const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
-
// Lock guarding camera service state
Mutex mServiceLock;
@@ -506,8 +489,8 @@
RingBuffer<String8> mEventLog;
Mutex mLogLock;
- // UID of last user.
- int mLastUserId;
+ // Currently allowed user IDs
+ std::set<userid_t> mAllowedUsers;
/**
* Get the camera state for a given camera id.
@@ -556,7 +539,7 @@
/**
* Handle a notification that the current device user has changed.
*/
- void doUserSwitch(int newUserId);
+ void doUserSwitch(const int32_t* newUserId, size_t length);
/**
* Add an event log message.
@@ -582,7 +565,8 @@
/**
* Add an event log message that the current device user has been switched.
*/
- void logUserSwitch(int oldUserId, int newUserId);
+ void logUserSwitch(const std::set<userid_t>& oldUserIds,
+ const std::set<userid_t>& newUserIds);
/**
* Add an event log message that a device has been removed by the HAL
@@ -713,6 +697,11 @@
int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,
int halVersion, int deviceVersion, apiLevel effectiveApiLevel,
/*out*/sp<BasicClient>* client);
+
+ status_t checkCameraAccess(const String16& opPackageName);
+
+ static String8 toString(std::set<userid_t> intSet);
+
};
template<class Func>
@@ -789,15 +778,6 @@
if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {
return ret;
}
- int userId = multiuser_get_user_id(clientUid);
-
- if (userId != mLastUserId && clientPid != getpid() ) {
- // If no previous user ID had been set, set to the user of the caller.
- logUserSwitch(mLastUserId, userId);
- LOG_ALWAYS_FATAL_IF(mLastUserId != DEFAULT_LAST_USER_ID,
- "Invalid state: Should never update user ID here unless was default");
- mLastUserId = userId;
- }
// Check the shim parameters after acquiring lock, if they have already been updated and
// we were doing a shim update, return immediately
diff --git a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
index 9c4f9cd..b6f6677 100644
--- a/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
+++ b/services/camera/libcameraservice/api2/CameraDeviceClient.cpp
@@ -691,15 +691,10 @@
return BAD_VALUE;
}
- // Also returns BAD_VALUE if stream ID was not valid
+ // Also returns BAD_VALUE if stream ID was not valid, or stream already
+ // has been used
res = mDevice->prepare(streamId);
- if (res == BAD_VALUE) {
- ALOGE("%s: Camera %d: Unexpected BAD_VALUE when preparing stream, but we"
- " already checked and the stream ID (%d) should be valid.",
- __FUNCTION__, mCameraId, streamId);
- }
-
return res;
}
diff --git a/services/camera/libcameraservice/common/CameraModule.cpp b/services/camera/libcameraservice/common/CameraModule.cpp
index 064ff71..c662853 100644
--- a/services/camera/libcameraservice/common/CameraModule.cpp
+++ b/services/camera/libcameraservice/common/CameraModule.cpp
@@ -31,6 +31,7 @@
// Keys added in HAL3.3
if (deviceVersion < CAMERA_DEVICE_API_VERSION_3_3) {
+ const size_t NUM_DERIVED_KEYS_HAL3_3 = 3;
Vector<uint8_t> controlModes;
uint8_t data = ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE;
chars.update(ANDROID_CONTROL_AE_LOCK_AVAILABLE, &data, /*count*/1);
@@ -78,6 +79,17 @@
}
chars.update(ANDROID_CONTROL_AVAILABLE_MODES, controlModes);
+
+ entry = chars.find(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS);
+ Vector<int32_t> availableCharsKeys;
+ availableCharsKeys.setCapacity(entry.count + NUM_DERIVED_KEYS_HAL3_3);
+ for (size_t i = 0; i < entry.count; i++) {
+ availableCharsKeys.push(entry.data.i32[i]);
+ }
+ availableCharsKeys.push(ANDROID_CONTROL_AE_LOCK_AVAILABLE);
+ availableCharsKeys.push(ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE);
+ availableCharsKeys.push(ANDROID_CONTROL_AVAILABLE_MODES);
+ chars.update(ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, availableCharsKeys);
}
return;
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index d2c2482..445c9c2 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -1342,6 +1342,8 @@
status_t Camera3Device::prepare(int streamId) {
ATRACE_CALL();
ALOGV("%s: Camera %d: Preparing stream %d", __FUNCTION__, mId, streamId);
+ Mutex::Autolock il(mInterfaceLock);
+ Mutex::Autolock l(mLock);
sp<Camera3StreamInterface> stream;
ssize_t outputStreamIdx = mOutputStreams.indexOfKey(streamId);
@@ -1353,14 +1355,12 @@
stream = mOutputStreams.editValueAt(outputStreamIdx);
if (stream->isUnpreparable() || stream->hasOutstandingBuffers() ) {
- ALOGE("%s: Camera %d: Stream %d has already been a request target",
- __FUNCTION__, mId, streamId);
+ CLOGE("Stream %d has already been a request target", streamId);
return BAD_VALUE;
}
if (mRequestThread->isStreamPending(stream)) {
- ALOGE("%s: Camera %d: Stream %d is already a target in a pending request",
- __FUNCTION__, mId, streamId);
+ CLOGE("Stream %d is already a target in a pending request", streamId);
return BAD_VALUE;
}
diff --git a/services/camera/libcameraservice/utils/ClientManager.h b/services/camera/libcameraservice/utils/ClientManager.h
index aa40a2d..5afb7a3 100644
--- a/services/camera/libcameraservice/utils/ClientManager.h
+++ b/services/camera/libcameraservice/utils/ClientManager.h
@@ -432,15 +432,17 @@
auto iter = evicted.cbegin();
- // Remove evicted clients from list
- mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
- [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
- if (curClientPtr->getKey() == (*iter)->getKey()) {
- iter++;
- return true;
- }
- return false;
- }), mClients.end());
+ if (iter != evicted.cend()) {
+ // Remove evicted clients from list
+ mClients.erase(std::remove_if(mClients.begin(), mClients.end(),
+ [&iter] (std::shared_ptr<ClientDescriptor<KEY, VALUE>>& curClientPtr) {
+ if (curClientPtr->getKey() == (*iter)->getKey()) {
+ iter++;
+ return true;
+ }
+ return false;
+ }), mClients.end());
+ }
mClients.push_back(client);
mRemovedCondition.broadcast();