Merge "camera2: Fix empty set handling for eviction." into mnc-dev
diff --git a/camera/Camera.cpp b/camera/Camera.cpp
index 84e0d1c..3a9fb4c 100644
--- a/camera/Camera.cpp
+++ b/camera/Camera.cpp
@@ -71,13 +71,14 @@
// deadlock if we call any method of ICamera here.
}
-sp<Camera> Camera::connect(int cameraId, const String16& opPackageName, int clientUid)
+sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
+ int clientUid)
{
- return CameraBaseT::connect(cameraId, opPackageName, clientUid);
+ return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}
status_t Camera::connectLegacy(int cameraId, int halVersion,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
sp<Camera>& camera)
{
@@ -88,7 +89,7 @@
const sp<ICameraService>& cs = CameraBaseT::getCameraService();
if (cs != 0) {
- status = cs.get()->connectLegacy(cl, cameraId, halVersion, opPackageName,
+ status = cs.get()->connectLegacy(cl, cameraId, halVersion, clientPackageName,
clientUid, /*out*/c->mCamera);
}
if (status == OK && c->mCamera != 0) {
diff --git a/camera/CameraBase.cpp b/camera/CameraBase.cpp
index 0dc0276..5d50aa8 100644
--- a/camera/CameraBase.cpp
+++ b/camera/CameraBase.cpp
@@ -91,7 +91,7 @@
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid)
{
ALOGV("%s: connect", __FUNCTION__);
@@ -102,7 +102,7 @@
if (cs != 0) {
TCamConnectService fnConnectService = TCamTraits::fnConnectService;
- status = (cs.get()->*fnConnectService)(cl, cameraId, opPackageName, clientUid,
+ status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera);
}
if (status == OK && c->mCamera != 0) {
diff --git a/camera/ICameraService.cpp b/camera/ICameraService.cpp
index 192e40d..51a775b 100644
--- a/camera/ICameraService.cpp
+++ b/camera/ICameraService.cpp
@@ -164,7 +164,7 @@
// connect to camera service (android.hardware.Camera)
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
- const String16& opPackageName, int clientUid,
+ const String16 &clientPackageName, int clientUid,
/*out*/
sp<ICamera>& device)
{
@@ -172,7 +172,7 @@
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraClient));
data.writeInt32(cameraId);
- data.writeString16(opPackageName);
+ data.writeString16(clientPackageName);
data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT, data, &reply);
@@ -187,7 +187,7 @@
// connect to camera service (android.hardware.Camera)
virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
int halVersion,
- const String16& opPackageName, int clientUid,
+ const String16 &clientPackageName, int clientUid,
/*out*/sp<ICamera>& device)
{
Parcel data, reply;
@@ -195,7 +195,7 @@
data.writeStrongBinder(IInterface::asBinder(cameraClient));
data.writeInt32(cameraId);
data.writeInt32(halVersion);
- data.writeString16(opPackageName);
+ data.writeString16(clientPackageName);
data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT_LEGACY, data, &reply);
@@ -225,7 +225,7 @@
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device)
@@ -234,7 +234,7 @@
data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(cameraCb));
data.writeInt32(cameraId);
- data.writeString16(opPackageName);
+ data.writeString16(clientPackageName);
data.writeInt32(clientUid);
remote()->transact(BnCameraService::CONNECT_DEVICE, data, &reply);
@@ -374,11 +374,11 @@
sp<ICameraClient> cameraClient =
interface_cast<ICameraClient>(data.readStrongBinder());
int32_t cameraId = data.readInt32();
- const String16 opPackageName = data.readString16();
+ const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp<ICamera> camera;
status_t status = connect(cameraClient, cameraId,
- opPackageName, clientUid, /*out*/camera);
+ clientName, clientUid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
@@ -394,11 +394,11 @@
sp<ICameraDeviceCallbacks> cameraClient =
interface_cast<ICameraDeviceCallbacks>(data.readStrongBinder());
int32_t cameraId = data.readInt32();
- const String16 opPackageName = data.readString16();
+ const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp<ICameraDeviceUser> camera;
status_t status = connectDevice(cameraClient, cameraId,
- opPackageName, clientUid, /*out*/camera);
+ clientName, clientUid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
@@ -454,11 +454,11 @@
interface_cast<ICameraClient>(data.readStrongBinder());
int32_t cameraId = data.readInt32();
int32_t halVersion = data.readInt32();
- const String16 opPackageName = data.readString16();
+ const String16 clientName = data.readString16();
int32_t clientUid = data.readInt32();
sp<ICamera> camera;
status_t status = connectLegacy(cameraClient, cameraId, halVersion,
- opPackageName, clientUid, /*out*/camera);
+ clientName, clientUid, /*out*/camera);
reply->writeNoException();
reply->writeInt32(status);
if (camera != NULL) {
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/Camera.h b/include/camera/Camera.h
index 25d75f7..2b60842 100644
--- a/include/camera/Camera.h
+++ b/include/camera/Camera.h
@@ -71,11 +71,11 @@
// construct a camera client from an existing remote
static sp<Camera> create(const sp<ICamera>& camera);
static sp<Camera> connect(int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid);
static status_t connectLegacy(int cameraId, int halVersion,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid, sp<Camera>& camera);
virtual ~Camera();
diff --git a/include/camera/ICameraService.h b/include/camera/ICameraService.h
index 38bff3e..cad275e 100644
--- a/include/camera/ICameraService.h
+++ b/include/camera/ICameraService.h
@@ -109,7 +109,7 @@
*/
virtual status_t connect(const sp<ICameraClient>& cameraClient,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) = 0;
@@ -117,7 +117,7 @@
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device) = 0;
@@ -141,7 +141,7 @@
*/
virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) = 0;
diff --git a/include/media/AudioResamplerPublic.h b/include/media/AudioResamplerPublic.h
index 53b8c13..6cf2ca9 100644
--- a/include/media/AudioResamplerPublic.h
+++ b/include/media/AudioResamplerPublic.h
@@ -143,6 +143,16 @@
return required * (double)speed + 1 + 1; // accounting for rounding dependencies
}
+// Identifies sample rates that we associate with music
+// and thus eligible for better resampling and fast capture.
+// This is somewhat less than 44100 to allow for pitch correction
+// involving resampling as well as asynchronous resampling.
+#define AUDIO_PROCESSING_MUSIC_RATE 40000
+
+static inline bool isMusicRate(uint32_t sampleRate) {
+ return sampleRate >= AUDIO_PROCESSING_MUSIC_RATE;
+}
+
} // namespace android
// ---------------------------------------------------------------------------
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/services/camera/libcameraservice/utils/RingBuffer.h b/include/media/RingBuffer.h
similarity index 100%
rename from services/camera/libcameraservice/utils/RingBuffer.h
rename to include/media/RingBuffer.h
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/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/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..3db4a58 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.get() == 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.get() == 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/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/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/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 5a0deec..4851528 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1082,6 +1082,16 @@
mSeqNumber, firstSeqNumberInPlaylist,
firstSeqNumberInPlaylist + (int32_t)mPlaylist->size() - 1);
+ if (mTSParser != NULL) {
+ mTSParser->signalEOS(ERROR_END_OF_STREAM);
+ // Use an empty buffer; we don't have any new data, just want to extract
+ // potential new access units after flush. Reset mSeqNumber to
+ // lastSeqNumberInPlaylist such that we set the correct access unit
+ // properties in extractAndQueueAccessUnitsFromTs.
+ sp<ABuffer> buffer = new ABuffer(0);
+ mSeqNumber = lastSeqNumberInPlaylist;
+ extractAndQueueAccessUnitsFromTs(buffer);
+ }
notifyError(ERROR_END_OF_STREAM);
} else {
// It's possible that we were never able to download the playlist.
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/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index 0d071b2..e8b2219 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -746,6 +746,7 @@
}
mPayloadStarted = false;
+ mEOSReached = false;
mBuffer->setRange(0, 0);
bool clearFormat = false;
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 7b5b46a..baf3b15 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -56,6 +56,8 @@
if (clearFormat) {
mFormat.clear();
}
+
+ mEOSReached = false;
}
// Parse AC3 header assuming the current ptr is start position of syncframe,
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/AudioMixer.cpp b/services/audioflinger/AudioMixer.cpp
index 959c140..586c737 100644
--- a/services/audioflinger/AudioMixer.cpp
+++ b/services/audioflinger/AudioMixer.cpp
@@ -708,11 +708,10 @@
// FIXME this is flawed for dynamic sample rates, as we choose the resampler
// quality level based on the initial ratio, but that could change later.
// Should have a way to distinguish tracks with static ratios vs. dynamic ratios.
- if (!((trackSampleRate == 44100 && devSampleRate == 48000) ||
- (trackSampleRate == 48000 && devSampleRate == 44100))) {
- quality = AudioResampler::DYN_LOW_QUALITY;
- } else {
+ if (isMusicRate(trackSampleRate)) {
quality = AudioResampler::DEFAULT_QUALITY;
+ } else {
+ quality = AudioResampler::DYN_LOW_QUALITY;
}
// TODO: Remove MONO_HACK. Resampler sees #channels after the downmixer
diff --git a/services/audioflinger/BufferProviders.cpp b/services/audioflinger/BufferProviders.cpp
index 77bf4ac..8a580e8 100644
--- a/services/audioflinger/BufferProviders.cpp
+++ b/services/audioflinger/BufferProviders.cpp
@@ -292,46 +292,8 @@
ALOGV("RemixBufferProvider(%p)(%#x, %#x, %#x) %zu %zu",
this, format, inputChannelMask, outputChannelMask,
mInputChannels, mOutputChannels);
-
- const audio_channel_representation_t inputRepresentation =
- audio_channel_mask_get_representation(inputChannelMask);
- const audio_channel_representation_t outputRepresentation =
- audio_channel_mask_get_representation(outputChannelMask);
- const uint32_t inputBits = audio_channel_mask_get_bits(inputChannelMask);
- const uint32_t outputBits = audio_channel_mask_get_bits(outputChannelMask);
-
- switch (inputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- switch (outputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- memcpy_by_index_array_initialization(mIdxAry, ARRAY_SIZE(mIdxAry),
- outputBits, inputBits);
- return;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- // TODO: output channel index mask not currently allowed
- // fall through
- default:
- break;
- }
- break;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- switch (outputRepresentation) {
- case AUDIO_CHANNEL_REPRESENTATION_POSITION:
- memcpy_by_index_array_initialization_src_index(mIdxAry, ARRAY_SIZE(mIdxAry),
- outputBits, inputBits);
- return;
- case AUDIO_CHANNEL_REPRESENTATION_INDEX:
- // TODO: output channel index mask not currently allowed
- // fall through
- default:
- break;
- }
- break;
- default:
- break;
- }
- LOG_ALWAYS_FATAL("invalid channel mask conversion from %#x to %#x",
- inputChannelMask, outputChannelMask);
+ (void) memcpy_by_index_array_initialization_from_channel_mask(
+ mIdxAry, ARRAY_SIZE(mIdxAry), outputChannelMask, inputChannelMask);
}
void RemixBufferProvider::copyFrames(void *dst, const void *src, size_t frames)
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/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index f2af312..594ed05 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2679,13 +2679,23 @@
if (exitPending()) {
break;
}
- releaseWakeLock_l();
+ bool released = false;
+ // The following works around a bug in the offload driver. Ideally we would release
+ // the wake lock every time, but that causes the last offload buffer(s) to be
+ // dropped while the device is on battery, so we need to hold a wake lock during
+ // the drain phase.
+ if (mBytesRemaining && !(mDrainSequence & 1)) {
+ releaseWakeLock_l();
+ released = true;
+ }
mWakeLockUids.clear();
mActiveTracksGeneration++;
ALOGV("wait async completion");
mWaitWorkCV.wait(mLock);
ALOGV("async completion/wake");
- acquireWakeLock_l();
+ if (released) {
+ acquireWakeLock_l();
+ }
standbyTime = systemTime() + standbyDelay;
sleepTime = 0;
@@ -5335,11 +5345,11 @@
}
initFastCapture =
// either capture sample rate is same as (a reasonable) primary output sample rate
- (((primaryOutputSampleRate == 44100 || primaryOutputSampleRate == 48000) &&
+ ((isMusicRate(primaryOutputSampleRate) &&
(mSampleRate == primaryOutputSampleRate)) ||
// or primary output sample rate is unknown, and capture sample rate is reasonable
((primaryOutputSampleRate == 0) &&
- ((mSampleRate == 44100 || mSampleRate == 48000)))) &&
+ isMusicRate(mSampleRate))) &&
// and the buffer size is < 12 ms
(mFrameCount * 1000) / mSampleRate < 12;
break;
@@ -6442,6 +6452,9 @@
return NO_ERROR;
}
+ ALOGV("RecordBufferConverter updateParameters srcMask:%#x dstMask:%#x"
+ " srcFormat:%#x dstFormat:%#x srcRate:%u dstRate:%u",
+ srcChannelMask, dstChannelMask, srcFormat, dstFormat, srcSampleRate, dstSampleRate);
const bool valid =
audio_is_input_channel(srcChannelMask)
&& audio_is_input_channel(dstChannelMask)
@@ -6698,9 +6711,7 @@
(mInput->stream->common.get_sample_rate(&mInput->stream->common)
<= (AUDIO_RESAMPLER_DOWN_RATIO_MAX * samplingRate)) &&
audio_channel_count_from_in_mask(
- mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_2 &&
- (channelMask == AUDIO_CHANNEL_IN_MONO ||
- channelMask == AUDIO_CHANNEL_IN_STEREO)) {
+ mInput->stream->common.get_channels(&mInput->stream->common)) <= FCC_8) {
status = NO_ERROR;
}
if (status == NO_ERROR) {
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index e6a767f..4eef02f2 100755
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -20,7 +20,7 @@
// For mixed output and inputs, the policy will use max mixer sampling rates.
// Do not limit sampling rate otherwise
-#define MAX_MIXER_SAMPLING_RATE 48000
+#define MAX_MIXER_SAMPLING_RATE 192000
// For mixed output and inputs, the policy will use max mixer channel count.
// Do not limit channel count otherwise
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index 64f883a..afcd073 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -272,6 +272,12 @@
(audio_channel_mask_t)ConfigParsingUtils::stringToEnum(sOutChannelsNameToEnumTable,
ARRAY_SIZE(sOutChannelsNameToEnumTable),
str);
+ if (channelMask == 0) { // if not found, check the channel index table
+ channelMask = (audio_channel_mask_t)
+ ConfigParsingUtils::stringToEnum(sIndexChannelsNameToEnumTable,
+ ARRAY_SIZE(sIndexChannelsNameToEnumTable),
+ str);
+ }
if (channelMask != 0) {
mChannelMasks.add(channelMask);
}
@@ -605,9 +611,13 @@
// For mixed output and inputs, use max mixer sampling rates. Do not
// limit sampling rate otherwise
+ // For inputs, also see checkCompatibleSamplingRate().
if (mType != AUDIO_PORT_TYPE_MIX) {
maxRate = UINT_MAX;
}
+ // TODO: should mSamplingRates[] be ordered in terms of our preference
+ // and we return the first (and hence most preferred) match? This is of concern if
+ // we want to choose 96kHz over 192kHz for USB driver stability or resource constraints.
for (size_t i = 0; i < mSamplingRates.size(); i ++) {
if ((mSamplingRates[i] > samplingRate) && (mSamplingRates[i] <= maxRate)) {
samplingRate = mSamplingRates[i];
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 0c02d93..d1ee400 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -768,6 +768,9 @@
if (stream != AUDIO_STREAM_MUSIC) {
flags = (audio_output_flags_t)(flags &~AUDIO_OUTPUT_FLAG_DEEP_BUFFER);
}
+ if (stream == AUDIO_STREAM_TTS) {
+ flags = AUDIO_OUTPUT_FLAG_TTS;
+ }
sp<IOProfile> profile;
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 3f80faf..59e1c37 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -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) {
@@ -1057,24 +1035,19 @@
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
- const status_t result = checkCameraAccess(opPackageName);
- if (result != NO_ERROR) {
- return result;
- }
-
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<Client> client = nullptr;
ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED,
- opPackageName, clientUid, API_1, false, false, /*out*/client);
+ clientPackageName, clientUid, API_1, false, false, /*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(opPackageName),
+ logRejected(id, getCallingPid(), String8(clientPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1086,16 +1059,11 @@
status_t CameraService::connectLegacy(
const sp<ICameraClient>& cameraClient,
int cameraId, int halVersion,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
- const status_t result = checkCameraAccess(opPackageName);
- if (result != NO_ERROR) {
- return result;
- }
-
String8 id = String8::format("%d", cameraId);
int apiVersion = mModule->getModuleApiVersion();
if (halVersion != CAMERA_HAL_API_VERSION_UNSPECIFIED &&
@@ -1108,18 +1076,18 @@
*/
ALOGE("%s: camera HAL module version %x doesn't support connecting to legacy HAL devices!",
__FUNCTION__, apiVersion);
- logRejected(id, getCallingPid(), String8(opPackageName),
+ logRejected(id, getCallingPid(), String8(clientPackageName),
String8("HAL module version doesn't support legacy HAL connections"));
return INVALID_OPERATION;
}
status_t ret = NO_ERROR;
sp<Client> client = nullptr;
- ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, opPackageName,
+ ret = connectHelper<ICameraClient,Client>(cameraClient, id, halVersion, clientPackageName,
clientUid, API_1, true, false, /*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(opPackageName),
+ logRejected(id, getCallingPid(), String8(clientPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1131,25 +1099,20 @@
status_t CameraService::connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device) {
- const status_t result = checkCameraAccess(opPackageName);
- if (result != NO_ERROR) {
- return result;
- }
-
status_t ret = NO_ERROR;
String8 id = String8::format("%d", cameraId);
sp<CameraDeviceClient> client = nullptr;
ret = connectHelper<ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, id,
- CAMERA_HAL_API_VERSION_UNSPECIFIED, opPackageName, clientUid, API_2, false, false,
+ CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, API_2, false, false,
/*out*/client);
if(ret != NO_ERROR) {
- logRejected(id, getCallingPid(), String8(opPackageName),
+ logRejected(id, getCallingPid(), String8(clientPackageName),
String8::format("%s (%d)", strerror(-ret), ret));
return ret;
}
@@ -1544,24 +1507,24 @@
}
void CameraService::logDisconnected(const char* cameraId, int clientPid,
- const char* opPackageName) {
+ const char* clientPackage) {
// Log the clients evicted
logEvent(String8::format("DISCONNECT device %s client for package %s (PID %d)", cameraId,
- opPackageName, clientPid));
+ clientPackage, clientPid));
}
void CameraService::logConnected(const char* cameraId, int clientPid,
- const char* opPackageName) {
+ const char* clientPackage) {
// Log the clients evicted
logEvent(String8::format("CONNECT device %s client for package %s (PID %d)", cameraId,
- opPackageName, clientPid));
+ clientPackage, clientPid));
}
void CameraService::logRejected(const char* cameraId, int clientPid,
- const char* opPackageName, const char* reason) {
+ const char* clientPackage, const char* reason) {
// Log the client rejected
logEvent(String8::format("REJECT device %s client for package %s (PID %d), reason: (%s)",
- cameraId, opPackageName, clientPid, reason));
+ cameraId, clientPackage, clientPid, reason));
}
void CameraService::logUserSwitch(int oldUserId, int newUserId) {
@@ -1598,6 +1561,21 @@
// Permission checks
switch (code) {
+ case BnCameraService::CONNECT:
+ case BnCameraService::CONNECT_DEVICE:
+ case BnCameraService::CONNECT_LEGACY: {
+ if (pid != selfPid) {
+ // we're called from a different process, do the real check
+ if (!checkCallingPermission(
+ String16("android.permission.CAMERA"))) {
+ const int uid = getCallingUid();
+ ALOGE("Permission Denial: "
+ "can't use the camera pid=%d, uid=%d", pid, uid);
+ return PERMISSION_DENIED;
+ }
+ }
+ break;
+ }
case BnCameraService::NOTIFY_SYSTEM_EVENT: {
if (pid != selfPid) {
// Ensure we're being called by system_server, or similar process with
@@ -1617,38 +1595,6 @@
return BnCameraService::onTransact(code, data, reply, flags);
}
-status_t CameraService::checkCameraAccess(const String16& opPackageName) {
- const int pid = getCallingPid();
-
- if (pid == getpid()) {
- return NO_ERROR;
- }
-
- const int uid = getCallingUid();
-
- if (!checkCallingPermission(String16("android.permission.CAMERA"))) {
- ALOGE("Permission Denial: can't use the camera pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- }
-
- AppOpsManager appOps;
- const int32_t result = appOps.noteOp(AppOpsManager::OP_CAMERA, uid, opPackageName);
-
- switch (result) {
- case AppOpsManager::MODE_ERRORED: {
- ALOGE("App op OP_CAMERA errored: can't use the camera pid=%d, uid=%d", pid, uid);
- return PERMISSION_DENIED;
- } break;
-
- case AppOpsManager::MODE_IGNORED: {
- ALOGE("App op OP_CAMERA ignored: can't use the camera pid=%d, uid=%d", pid, uid);
- return INVALID_OPERATION;
- } break;
- }
-
- return NO_ERROR;
-}
-
// We share the media players for shutter and recording sound for all clients.
// A reference count is kept to determine when we will actually release the
// media players.
@@ -1701,13 +1647,13 @@
CameraService::Client::Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- const String16& opPackageName,
+ const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid) :
CameraService::BasicClient(cameraService,
IInterface::asBinder(cameraClient),
- opPackageName,
+ clientPackageName,
cameraId, cameraFacing,
clientPid, clientUid,
servicePid)
@@ -1734,11 +1680,11 @@
CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
- const String16& opPackageName,
+ const String16& clientPackageName,
int cameraId, int cameraFacing,
int clientPid, uid_t clientUid,
int servicePid):
- mOpPackageName(opPackageName), mDisconnected(false)
+ mClientPackageName(clientPackageName), mDisconnected(false)
{
mCameraService = cameraService;
mRemoteBinder = remoteCallback;
@@ -1766,7 +1712,7 @@
mCameraService->removeByClient(this);
mCameraService->logDisconnected(String8::format("%d", mCameraId), mClientPid,
- String8(mOpPackageName));
+ String8(mClientPackageName));
sp<IBinder> remote = getRemote();
if (remote != nullptr) {
@@ -1781,7 +1727,7 @@
}
String16 CameraService::BasicClient::getPackageName() const {
- return mOpPackageName;
+ return mClientPackageName;
}
@@ -1801,20 +1747,26 @@
{
ALOGV("%s: Start camera ops, package name = %s, client UID = %d",
- __FUNCTION__, String8(mOpPackageName).string(), mClientUid);
+ __FUNCTION__, String8(mClientPackageName).string(), mClientUid);
}
mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA,
- mOpPackageName, mOpsCallback);
+ mClientPackageName, mOpsCallback);
res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA,
- mClientUid, mOpPackageName);
+ mClientUid, mClientPackageName);
- if (res != AppOpsManager::MODE_ALLOWED) {
+ if (res == AppOpsManager::MODE_ERRORED) {
ALOGI("Camera %d: Access for \"%s\" has been revoked",
- mCameraId, String8(mOpPackageName).string());
+ mCameraId, String8(mClientPackageName).string());
return PERMISSION_DENIED;
}
+ if (res == AppOpsManager::MODE_IGNORED) {
+ ALOGI("Camera %d: Access for \"%s\" has been restricted",
+ mCameraId, String8(mClientPackageName).string());
+ return INVALID_OPERATION;
+ }
+
mOpsActive = true;
// Transition device availability listeners from PRESENT -> NOT_AVAILABLE
@@ -1829,7 +1781,7 @@
if (mOpsActive) {
// Notify app ops that the camera is available again
mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid,
- mOpPackageName);
+ mClientPackageName);
mOpsActive = false;
auto rejected = {ICameraServiceListener::STATUS_NOT_PRESENT,
@@ -1854,7 +1806,7 @@
void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) {
String8 name(packageName);
- String8 myName(mOpPackageName);
+ String8 myName(mClientPackageName);
if (op != AppOpsManager::OP_CAMERA) {
ALOGW("Unexpected app ops notification received: %d", op);
@@ -1863,7 +1815,7 @@
int32_t res;
res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA,
- mClientUid, mOpPackageName);
+ mClientUid, mClientPackageName);
ALOGV("checkOp returns: %d, %s ", res,
res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" :
res == AppOpsManager::MODE_IGNORED ? "IGNORED" :
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 502fcfa..1041550 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -38,9 +38,9 @@
#include "CameraFlashlight.h"
#include "common/CameraModule.h"
+#include "media/RingBuffer.h"
#include "utils/AutoConditionLock.h"
#include "utils/ClientManager.h"
-#include "utils/RingBuffer.h"
#include <set>
#include <string>
@@ -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;
@@ -126,19 +112,19 @@
virtual status_t getCameraVendorTagDescriptor(/*out*/ sp<VendorTagDescriptor>& desc);
virtual status_t connect(const sp<ICameraClient>& cameraClient, int cameraId,
- const String16& opPackageName, int clientUid,
+ const String16& clientPackageName, int clientUid,
/*out*/
sp<ICamera>& device);
virtual status_t connectLegacy(const sp<ICameraClient>& cameraClient, int cameraId,
- int halVersion, const String16& opPackageName, int clientUid,
+ int halVersion, const String16& clientPackageName, int clientUid,
/*out*/
sp<ICamera>& device);
virtual status_t connectDevice(
const sp<ICameraDeviceCallbacks>& cameraCb,
int cameraId,
- const String16& opPackageName,
+ const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICameraDeviceUser>& device);
@@ -223,7 +209,7 @@
protected:
BasicClient(const sp<CameraService>& cameraService,
const sp<IBinder>& remoteCallback,
- const String16& opPackageName,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
@@ -242,7 +228,7 @@
sp<CameraService> mCameraService; // immutable after constructor
int mCameraId; // immutable after constructor
int mCameraFacing; // immutable after constructor
- const String16 mOpPackageName;
+ const String16 mClientPackageName;
pid_t mClientPid;
uid_t mClientUid; // immutable after constructor
pid_t mServicePid; // immutable after constructor
@@ -309,7 +295,7 @@
// Interface used by CameraService
Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
- const String16& opPackageName,
+ const String16& clientPackageName,
int cameraId,
int cameraFacing,
int clientPid,
@@ -480,7 +466,7 @@
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
status_t connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId, int halVersion,
- const String16& opPackageName, int clientUid, apiLevel effectiveApiLevel,
+ const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,
bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device);
@@ -713,8 +699,6 @@
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);
};
template<class Func>
@@ -763,11 +747,11 @@
template<class CALLBACK, class CLIENT>
status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
- int halVersion, const String16& opPackageName, int clientUid,
+ int halVersion, const String16& clientPackageName, int clientUid,
apiLevel effectiveApiLevel, bool legacyMode, bool shimUpdateOnly,
/*out*/sp<CLIENT>& device) {
status_t ret = NO_ERROR;
- String8 clientName8(opPackageName);
+ String8 clientName8(clientPackageName);
int clientPid = getCallingPid();
ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) for HAL version %s and "
@@ -838,7 +822,7 @@
int facing = -1;
int deviceVersion = getDeviceVersion(id, /*out*/&facing);
sp<BasicClient> tmp = nullptr;
- if((ret = makeClient(this, cameraCb, opPackageName, cameraId, facing, clientPid,
+ if((ret = makeClient(this, cameraCb, clientPackageName, cameraId, facing, clientPid,
clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel,
/*out*/&tmp)) != NO_ERROR) {
return ret;
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/Camera2ClientBase.cpp b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
index 9b2e143..ba0b264 100644
--- a/services/camera/libcameraservice/common/Camera2ClientBase.cpp
+++ b/services/camera/libcameraservice/common/Camera2ClientBase.cpp
@@ -118,7 +118,7 @@
ALOGI("Closed Camera %d. Client was: %s (PID %d, UID %u)",
TClientBase::mCameraId,
- String8(TClientBase::mOpPackageName).string(),
+ String8(TClientBase::mClientPackageName).string(),
mInitialClientPid, TClientBase::mClientUid);
}
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/mediaresourcemanager/ResourceManagerService.cpp b/services/mediaresourcemanager/ResourceManagerService.cpp
index 3c093f9..e2b6695 100644
--- a/services/mediaresourcemanager/ResourceManagerService.cpp
+++ b/services/mediaresourcemanager/ResourceManagerService.cpp
@@ -126,8 +126,8 @@
}
}
}
- result.append(" Logs:\n");
- result.append(mServiceLog->toString());
+ result.append(" Events logs (most recent at top):\n");
+ result.append(mServiceLog->toString(" " /* linePrefix */));
write(fd, result.string(), result.size());
return OK;
diff --git a/services/mediaresourcemanager/ServiceLog.cpp b/services/mediaresourcemanager/ServiceLog.cpp
index be7b308..791e797 100644
--- a/services/mediaresourcemanager/ServiceLog.cpp
+++ b/services/mediaresourcemanager/ServiceLog.cpp
@@ -27,28 +27,37 @@
namespace android {
-ServiceLog::ServiceLog() : mMaxNum(kDefaultMaxNum) {}
-ServiceLog::ServiceLog(size_t maxNum) : mMaxNum(maxNum) {}
+ServiceLog::ServiceLog() : mMaxNum(kDefaultMaxNum), mLogs(mMaxNum) {}
+ServiceLog::ServiceLog(size_t maxNum) : mMaxNum(maxNum), mLogs(mMaxNum) {}
void ServiceLog::add(const String8 &log) {
Mutex::Autolock lock(mLock);
time_t now = time(0);
char buf[64];
strftime(buf, sizeof(buf), "%m-%d %T", localtime(&now));
- String8 formattedLog = String8::format("%s %s", buf, log.string());
- if (mLogs.add(formattedLog) == mMaxNum) {
- mLogs.removeAt(0);
- }
+ mLogs.add(String8::format("%s %s", buf, log.string()));
}
-String8 ServiceLog::toString() const {
+String8 ServiceLog::toString(const char *linePrefix) const {
Mutex::Autolock lock(mLock);
String8 result;
- for (size_t i = 0; i < mLogs.size(); ++i) {
- result.append(mLogs[i]);
- result.append("\n");
+ for (const auto& log : mLogs) {
+ addLine(log.string(), linePrefix, &result);
+ }
+ if (mLogs.size() == mMaxNum) {
+ addLine("...", linePrefix, &result);
+ } else if (mLogs.size() == 0) {
+ addLine("[no events yet]", linePrefix, &result);
}
return result;
}
+void ServiceLog::addLine(const char *log, const char *prefix, String8 *result) const {
+ if (prefix != NULL) {
+ result->append(prefix);
+ }
+ result->append(log);
+ result->append("\n");
+}
+
} // namespace android
diff --git a/services/mediaresourcemanager/ServiceLog.h b/services/mediaresourcemanager/ServiceLog.h
index 14814ff..a6f16eb 100644
--- a/services/mediaresourcemanager/ServiceLog.h
+++ b/services/mediaresourcemanager/ServiceLog.h
@@ -23,6 +23,8 @@
#include <utils/threads.h>
#include <utils/Vector.h>
+#include "media/RingBuffer.h"
+
namespace android {
class ServiceLog : public RefBase {
@@ -31,12 +33,14 @@
ServiceLog(size_t maxNum);
void add(const String8 &log);
- String8 toString() const;
+ String8 toString(const char *linePrefix = NULL) const;
private:
- int mMaxNum;
+ size_t mMaxNum;
mutable Mutex mLock;
- Vector<String8> mLogs;
+ RingBuffer<String8> mLogs;
+
+ void addLine(const char *log, const char *prefix, String8 *result) const;
};
// ----------------------------------------------------------------------------
diff --git a/services/mediaresourcemanager/test/ServiceLog_test.cpp b/services/mediaresourcemanager/test/ServiceLog_test.cpp
index 6ddcb87..9172499 100644
--- a/services/mediaresourcemanager/test/ServiceLog_test.cpp
+++ b/services/mediaresourcemanager/test/ServiceLog_test.cpp
@@ -34,35 +34,48 @@
};
TEST_F(ServiceLogTest, addThenToString) {
+ String8 logString;
+
mServiceLog->add(String8("log1"));
- EXPECT_TRUE(mServiceLog->toString().contains("log1"));
- ALOGV("toString:\n%s", mServiceLog->toString().string());
+ logString = mServiceLog->toString();
+ EXPECT_TRUE(logString.contains("log1"));
+ ALOGV("toString:\n%s", logString.string());
+
+ static const char kTestLogPrefix[] = "testlogprefix: ";
+ logString = mServiceLog->toString(kTestLogPrefix);
+ EXPECT_TRUE(logString.contains(kTestLogPrefix));
+ EXPECT_TRUE(logString.contains("log1"));
+ ALOGV("toString:\n%s", logString.string());
mServiceLog->add(String8("log2"));
- EXPECT_TRUE(mServiceLog->toString().contains("log1"));
- EXPECT_TRUE(mServiceLog->toString().contains("log2"));
- ALOGV("toString:\n%s", mServiceLog->toString().string());
+ logString = mServiceLog->toString();
+ EXPECT_TRUE(logString.contains("log1"));
+ EXPECT_TRUE(logString.contains("log2"));
+ ALOGV("toString:\n%s", logString.string());
mServiceLog->add(String8("log3"));
- EXPECT_TRUE(mServiceLog->toString().contains("log1"));
- EXPECT_TRUE(mServiceLog->toString().contains("log2"));
- EXPECT_TRUE(mServiceLog->toString().contains("log3"));
- ALOGV("toString:\n%s", mServiceLog->toString().string());
+ logString = mServiceLog->toString();
+ EXPECT_TRUE(logString.contains("log1"));
+ EXPECT_TRUE(logString.contains("log2"));
+ EXPECT_TRUE(logString.contains("log3"));
+ ALOGV("toString:\n%s", logString.string());
mServiceLog->add(String8("log4"));
- EXPECT_FALSE(mServiceLog->toString().contains("log1"));
- EXPECT_TRUE(mServiceLog->toString().contains("log2"));
- EXPECT_TRUE(mServiceLog->toString().contains("log3"));
- EXPECT_TRUE(mServiceLog->toString().contains("log4"));
- ALOGV("toString:\n%s", mServiceLog->toString().string());
+ logString = mServiceLog->toString();
+ EXPECT_FALSE(logString.contains("log1"));
+ EXPECT_TRUE(logString.contains("log2"));
+ EXPECT_TRUE(logString.contains("log3"));
+ EXPECT_TRUE(logString.contains("log4"));
+ ALOGV("toString:\n%s", logString.string());
mServiceLog->add(String8("log5"));
- EXPECT_FALSE(mServiceLog->toString().contains("log1"));
- EXPECT_FALSE(mServiceLog->toString().contains("log2"));
- EXPECT_TRUE(mServiceLog->toString().contains("log3"));
- EXPECT_TRUE(mServiceLog->toString().contains("log4"));
- EXPECT_TRUE(mServiceLog->toString().contains("log5"));
- ALOGV("toString:\n%s", mServiceLog->toString().string());
+ logString = mServiceLog->toString();
+ EXPECT_FALSE(logString.contains("log1"));
+ EXPECT_FALSE(logString.contains("log2"));
+ EXPECT_TRUE(logString.contains("log3"));
+ EXPECT_TRUE(logString.contains("log4"));
+ EXPECT_TRUE(logString.contains("log5"));
+ ALOGV("toString:\n%s", logString.string());
}
} // namespace android