Merge "mediacodec: add seccomp filter for arm/arm64" into nyc-dev
diff --git a/include/media/AudioPolicy.h b/include/media/AudioPolicy.h
index a171493..c769a62 100644
--- a/include/media/AudioPolicy.h
+++ b/include/media/AudioPolicy.h
@@ -97,6 +97,7 @@
// definitions for audio recording configuration updates
// which update type is reported
+#define RECORD_CONFIG_EVENT_NONE -1
#define RECORD_CONFIG_EVENT_START 1
#define RECORD_CONFIG_EVENT_STOP 0
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h
index 7011858..901a0fd 100644
--- a/include/media/AudioSystem.h
+++ b/include/media/AudioSystem.h
@@ -32,8 +32,8 @@
typedef void (*audio_error_callback)(status_t err);
typedef void (*dynamic_policy_callback)(int event, String8 regId, int val);
typedef void (*record_config_callback)(int event, int session, int source,
- const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
class IAudioFlinger;
class IAudioPolicyService;
@@ -150,9 +150,9 @@
// Allocate a new unique ID for use as an audio session ID or I/O handle.
// If unable to contact AudioFlinger, returns AUDIO_UNIQUE_ID_ALLOCATE instead.
// FIXME If AudioFlinger were to ever exhaust the unique ID namespace,
- // this method could fail by returning either AUDIO_UNIQUE_ID_ALLOCATE
+ // this method could fail by returning either a reserved ID like AUDIO_UNIQUE_ID_ALLOCATE
// or an unspecified existing unique ID.
- static audio_unique_id_t newAudioUniqueId();
+ static audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
static void acquireAudioSessionId(int audioSession, pid_t pid);
static void releaseAudioSessionId(int audioSession, pid_t pid);
@@ -427,7 +427,7 @@
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
private:
Mutex mLock;
diff --git a/include/media/IAudioFlinger.h b/include/media/IAudioFlinger.h
index 3b69ecf..e28f79d 100644
--- a/include/media/IAudioFlinger.h
+++ b/include/media/IAudioFlinger.h
@@ -182,7 +182,7 @@
virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const = 0;
- virtual audio_unique_id_t newAudioUniqueId() = 0;
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
virtual void acquireAudioSessionId(int audioSession, pid_t pid) = 0;
virtual void releaseAudioSessionId(int audioSession, pid_t pid) = 0;
diff --git a/include/media/IAudioPolicyServiceClient.h b/include/media/IAudioPolicyServiceClient.h
index 8c3459d..d94ad00 100644
--- a/include/media/IAudioPolicyServiceClient.h
+++ b/include/media/IAudioPolicyServiceClient.h
@@ -41,7 +41,8 @@
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source,
const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig) = 0;
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle) = 0;
};
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 4489d37..4a7fc62 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -35,7 +35,7 @@
struct ABuffer;
struct MemoryDealer;
-struct DescribeColorFormatParams;
+struct DescribeColorFormat2Params;
struct ACodec : public AHierarchicalStateMachine, public CodecBase {
ACodec();
@@ -442,10 +442,10 @@
OMX_ERRORTYPE error = OMX_ErrorUndefined,
status_t internalError = UNKNOWN_ERROR);
- static bool describeDefaultColorFormat(DescribeColorFormatParams &describeParams);
+ static bool describeDefaultColorFormat(DescribeColorFormat2Params &describeParams);
static bool describeColorFormat(
const sp<IOMX> &omx, IOMX::node_id node,
- DescribeColorFormatParams &describeParams);
+ DescribeColorFormat2Params &describeParams);
status_t requestIDRFrame();
status_t setParameters(const sp<AMessage> ¶ms);
diff --git a/include/media/stagefright/CameraSource.h b/include/media/stagefright/CameraSource.h
index 3d00d30..64c3044 100644
--- a/include/media/stagefright/CameraSource.h
+++ b/include/media/stagefright/CameraSource.h
@@ -244,12 +244,15 @@
* The following variables are used in VIDEO_BUFFER_MODE_BUFFER_QUEUE mode.
*/
static const size_t kConsumerBufferCount = 8;
+ static const nsecs_t kMemoryBaseAvailableTimeoutNs = 200000000; // 200ms
// Consumer and producer of the buffer queue between this class and camera.
sp<BufferItemConsumer> mVideoBufferConsumer;
sp<IGraphicBufferProducer> mVideoBufferProducer;
// Memory used to send the buffers to encoder, where sp<IMemory> stores VideoNativeMetadata.
sp<IMemoryHeap> mMemoryHeapBase;
List<sp<IMemory>> mMemoryBases;
+ // The condition that will be signaled when there is an entry available in mMemoryBases.
+ Condition mMemoryBaseAvailableCond;
// A mapping from ANativeWindowBuffer sent to encoder to BufferItem received from camera.
// This is protected by mLock.
KeyedVector<ANativeWindowBuffer*, BufferItem> mReceivedBufferItemMap;
diff --git a/include/media/stagefright/CodecBase.h b/include/media/stagefright/CodecBase.h
index cbf9839..3131090 100644
--- a/include/media/stagefright/CodecBase.h
+++ b/include/media/stagefright/CodecBase.h
@@ -78,7 +78,7 @@
virtual size_t countBuffers() = 0;
virtual IOMX::buffer_id bufferIDAt(size_t index) const = 0;
virtual sp<ABuffer> bufferAt(size_t index) const = 0;
- virtual sp<NativeHandle> handleAt(size_t index) { return NULL; };
+ virtual sp<NativeHandle> handleAt(size_t index) const { return NULL; };
virtual sp<RefBase> memRefAt(size_t index) const { return NULL; }
protected:
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index ec57d96..1701f80 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -231,7 +231,7 @@
// mNotificationFramesAct is initialized in openRecord_l
if (sessionId == AUDIO_SESSION_ALLOCATE) {
- mSessionId = AudioSystem::newAudioUniqueId();
+ mSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
} else {
mSessionId = sessionId;
}
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 1607af5..1af5660 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -394,11 +394,11 @@
return result;
}
-audio_unique_id_t AudioSystem::newAudioUniqueId()
+audio_unique_id_t AudioSystem::newAudioUniqueId(audio_unique_id_use_t use)
{
const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
if (af == 0) return AUDIO_UNIQUE_ID_ALLOCATE;
- return af->newAudioUniqueId();
+ return af->newAudioUniqueId(use);
}
void AudioSystem::acquireAudioSessionId(int audioSession, pid_t pid)
@@ -1246,7 +1246,8 @@
void AudioSystem::AudioPolicyServiceClient::onRecordingConfigurationUpdate(
int event, audio_session_t session, audio_source_t source,
- const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig) {
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle) {
record_config_callback cb = NULL;
{
Mutex::Autolock _l(AudioSystem::gLock);
@@ -1254,7 +1255,7 @@
}
if (cb != NULL) {
- cb(event, session, source, clientConfig, deviceConfig);
+ cb(event, session, source, clientConfig, deviceConfig, patchHandle);
}
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index f0074b6..36c1d10 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -438,7 +438,7 @@
mNotificationFramesReq = notificationFrames;
mNotificationFramesAct = 0;
if (sessionId == AUDIO_SESSION_ALLOCATE) {
- mSessionId = AudioSystem::newAudioUniqueId();
+ mSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
} else {
mSessionId = sessionId;
}
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index 0bf503a..e1de111 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -612,10 +612,11 @@
return (uint32_t) reply.readInt32();
}
- virtual audio_unique_id_t newAudioUniqueId()
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32((int32_t) use);
status_t status = remote()->transact(NEW_AUDIO_SESSION_ID, data, &reply);
audio_unique_id_t id = AUDIO_SESSION_ALLOCATE;
if (status == NO_ERROR) {
@@ -1208,7 +1209,7 @@
} break;
case NEW_AUDIO_SESSION_ID: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
- reply->writeInt32(newAudioUniqueId());
+ reply->writeInt32(newAudioUniqueId((audio_unique_id_use_t) data.readInt32()));
return NO_ERROR;
} break;
case ACQUIRE_AUDIO_SESSION_ID: {
diff --git a/media/libmedia/IAudioPolicyServiceClient.cpp b/media/libmedia/IAudioPolicyServiceClient.cpp
index 0aeaf3c..5f931e5 100644
--- a/media/libmedia/IAudioPolicyServiceClient.cpp
+++ b/media/libmedia/IAudioPolicyServiceClient.cpp
@@ -82,7 +82,7 @@
void onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig) {
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle) {
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyServiceClient::getInterfaceDescriptor());
data.writeInt32(event);
@@ -90,6 +90,7 @@
data.writeInt32(source);
writeAudioConfigBaseToParcel(data, clientConfig);
writeAudioConfigBaseToParcel(data, deviceConfig);
+ data.writeInt32(patchHandle);
remote()->transact(RECORDING_CONFIGURATION_UPDATE, data, &reply, IBinder::FLAG_ONEWAY);
}
};
@@ -128,7 +129,9 @@
audio_config_base_t deviceConfig;
readAudioConfigBaseFromParcel(data, &clientConfig);
readAudioConfigBaseFromParcel(data, &deviceConfig);
- onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig);
+ audio_patch_handle_t patchHandle = (audio_patch_handle_t) data.readInt32();
+ onRecordingConfigurationUpdate(event, session, source, &clientConfig, &deviceConfig,
+ patchHandle);
return NO_ERROR;
} break;
default:
diff --git a/media/libmedia/IMediaSource.cpp b/media/libmedia/IMediaSource.cpp
index b988c46..1770fb8 100644
--- a/media/libmedia/IMediaSource.cpp
+++ b/media/libmedia/IMediaSource.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "BpMediaSource"
#include <utils/Log.h>
+#include <utils/CallStack.h>
+
#include <inttypes.h>
#include <stdint.h>
#include <sys/types.h>
@@ -109,9 +111,16 @@
BpMediaSource(const sp<IBinder>& impl)
: BpInterface<IMediaSource>(impl)
{
+ mStarted = false;
}
virtual status_t start(MetaData *params) {
+ if (mStarted) {
+ ALOGD("Source was started previously from:");
+ mStartStack.log(LOG_TAG);
+ ALOGD("Now from:");
+ CallStack stack(LOG_TAG);
+ }
ALOGV("start");
Parcel data, reply;
data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -119,6 +128,10 @@
params->writeToParcel(data);
}
status_t ret = remote()->transact(START, data, &reply);
+ if (ret == NO_ERROR) {
+ mStarted = true;
+ mStartStack.update();
+ }
if (ret == NO_ERROR && params) {
ALOGW("ignoring potentially modified MetaData from start");
ALOGW("input:");
@@ -131,6 +144,7 @@
}
virtual status_t stop() {
+ mStarted = false;
ALOGV("stop");
Parcel data, reply;
data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
@@ -205,7 +219,8 @@
// NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
// XXX: could we use this for caching, or does metadata change on the fly?
sp<MetaData> mMetaData;
-
+ bool mStarted;
+ CallStack mStartStack;
};
IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");
@@ -315,6 +330,9 @@
reply->writeInt32(offset);
reply->writeInt32(usedSize);
buf->meta_data()->writeToParcel(*reply);
+ if (buf->mMemory == NULL) {
+ buf->release();
+ }
} else {
// buffer is small: copy it
if (buf->mMemory != NULL) {
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 337e963..7e502af 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -63,7 +63,7 @@
mLeftVolume = mRightVolume = 1.0;
mVideoWidth = mVideoHeight = 0;
mLockThreadId = 0;
- mAudioSessionId = AudioSystem::newAudioUniqueId();
+ mAudioSessionId = AudioSystem::newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
AudioSystem::acquireAudioSessionId(mAudioSessionId, -1);
mSendLevel = 0;
mRetransmitEndpointValid = false;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 44279ce..6c54e3f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -746,7 +746,7 @@
if (!mPaused) {
mRenderer->pause();
}
- restartAudioFromOffload(
+ restartAudio(
currentPositionUs, true /* forceNonOffload */,
true /* needsToCreateAudioDecoder */);
if (!mPaused) {
@@ -1149,7 +1149,7 @@
positionUs = mPreviousSeekTimeUs;
}
- restartAudioFromOffload(
+ restartAudio(
positionUs, false /* forceNonOffload */,
reason == Renderer::kDueToError /* needsToCreateAudioDecoder */);
}
@@ -1488,11 +1488,8 @@
mRenderer->closeAudioSink();
}
-void NuPlayer::restartAudioFromOffload(
+void NuPlayer::restartAudio(
int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder) {
- if (!mOffloadAudio) {
- return;
- }
mAudioDecoder->pause();
mAudioDecoder.clear();
++mAudioDecoderGeneration;
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index 5e48b30..a55aa5f 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -233,7 +233,7 @@
void tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo);
void closeAudioSink();
- void restartAudioFromOffload(
+ void restartAudio(
int64_t currentPositionUs, bool forceNonOffload, bool needsToCreateAudioDecoder);
void determineAudioModeChange();
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index ec33478..ba40876 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -32,6 +32,12 @@
const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs
+// Buffer Underflow/Prepare/StartServer/Overflow Marks
+const int64_t NuPlayer::RTSPSource::kUnderflowMarkUs = 1000000ll;
+const int64_t NuPlayer::RTSPSource::kPrepareMarkUs = 3000000ll;
+const int64_t NuPlayer::RTSPSource::kStartServerMarkUs = 5000000ll;
+const int64_t NuPlayer::RTSPSource::kOverflowMarkUs = 10000000ll;
+
NuPlayer::RTSPSource::RTSPSource(
const sp<AMessage> ¬ify,
const sp<IMediaHTTPService> &httpService,
@@ -51,6 +57,7 @@
mFinalResult(OK),
mDisconnectReplyID(0),
mBuffering(false),
+ mInPreparationPhase(true),
mSeekGeneration(0),
mEOSTimeoutAudio(0),
mEOSTimeoutVideo(0) {
@@ -127,29 +134,6 @@
msg->postAndAwaitResponse(&dummy);
}
-void NuPlayer::RTSPSource::pause() {
- int64_t mediaDurationUs = 0;
- getDuration(&mediaDurationUs);
- for (size_t index = 0; index < mTracks.size(); index++) {
- TrackInfo *info = &mTracks.editItemAt(index);
- sp<AnotherPacketSource> source = info->mSource;
-
- // Check if EOS or ERROR is received
- if (source != NULL && source->isFinished(mediaDurationUs)) {
- return;
- }
- }
- if (mHandler != NULL) {
- mHandler->pause();
- }
-}
-
-void NuPlayer::RTSPSource::resume() {
- if (mHandler != NULL) {
- mHandler->resume();
- }
-}
-
status_t NuPlayer::RTSPSource::feedMoreTSData() {
Mutex::Autolock _l(mBufferingLock);
return mFinalResult;
@@ -324,6 +308,73 @@
mHandler->seek(seekTimeUs);
}
+void NuPlayer::RTSPSource::schedulePollBuffering() {
+ sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
+ msg->post(1000000ll); // 1 second intervals
+}
+
+void NuPlayer::RTSPSource::checkBuffering(
+ bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
+ size_t numTracks = mTracks.size();
+ size_t preparedCount, underflowCount, overflowCount, startCount;
+ preparedCount = underflowCount = overflowCount = startCount = 0;
+ for (size_t i = 0; i < numTracks; ++i) {
+ status_t finalResult;
+ TrackInfo *info = &mTracks.editItemAt(i);
+ sp<AnotherPacketSource> src = info->mSource;
+ int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);
+
+ // isFinished when duration is 0 checks for EOS result only
+ if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
+ ++preparedCount;
+ }
+
+ if (src->isFinished(/* duration */ 0)) {
+ ++overflowCount;
+ } else {
+ if (bufferedDurationUs < kUnderflowMarkUs) {
+ ++underflowCount;
+ }
+ if (bufferedDurationUs > kOverflowMarkUs) {
+ ++overflowCount;
+ }
+ if (bufferedDurationUs < kStartServerMarkUs) {
+ ++startCount;
+ }
+ }
+ }
+
+ *prepared = (preparedCount == numTracks);
+ *underflow = (underflowCount > 0);
+ *overflow = (overflowCount == numTracks);
+ *startServer = (startCount > 0);
+}
+
+void NuPlayer::RTSPSource::onPollBuffering() {
+ bool prepared, underflow, overflow, startServer;
+ checkBuffering(&prepared, &underflow, &overflow, &startServer);
+
+ if (prepared && mInPreparationPhase) {
+ mInPreparationPhase = false;
+ notifyPrepared();
+ }
+
+ if (!mInPreparationPhase && underflow) {
+ startBufferingIfNecessary();
+ }
+
+ if (overflow && mHandler != NULL) {
+ stopBufferingIfNecessary();
+ mHandler->pause();
+ }
+
+ if (startServer && mHandler != NULL) {
+ mHandler->resume();
+ }
+
+ schedulePollBuffering();
+}
+
void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
if (msg->what() == kWhatDisconnect) {
sp<AReplyToken> replyID;
@@ -348,6 +399,9 @@
performSeek(seekTimeUs);
return;
+ } else if (msg->what() == kWhatPollBuffering) {
+ onPollBuffering();
+ return;
}
CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -372,7 +426,7 @@
}
notifyFlagsChanged(flags);
- notifyPrepared();
+ schedulePollBuffering();
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h
index 6438a1e..a6a7644 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.h
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h
@@ -43,8 +43,6 @@
virtual void prepareAsync();
virtual void start();
virtual void stop();
- virtual void pause();
- virtual void resume();
virtual status_t feedMoreTSData();
@@ -65,6 +63,7 @@
kWhatNotify = 'noti',
kWhatDisconnect = 'disc',
kWhatPerformSeek = 'seek',
+ kWhatPollBuffering = 'poll',
};
enum State {
@@ -79,6 +78,12 @@
kFlagIncognito = 1,
};
+ // Buffer Prepare/Underflow/Overflow/Resume Marks
+ static const int64_t kPrepareMarkUs;
+ static const int64_t kUnderflowMarkUs;
+ static const int64_t kOverflowMarkUs;
+ static const int64_t kStartServerMarkUs;
+
struct TrackInfo {
sp<AnotherPacketSource> mSource;
@@ -100,6 +105,7 @@
sp<AReplyToken> mDisconnectReplyID;
Mutex mBufferingLock;
bool mBuffering;
+ bool mInPreparationPhase;
sp<ALooper> mLooper;
sp<MyHandler> mHandler;
@@ -126,6 +132,9 @@
void finishDisconnectIfPossible();
void performSeek(int64_t seekTimeUs);
+ void schedulePollBuffering();
+ void checkBuffering(bool *prepared, bool *underflow, bool *overflow, bool *startServer);
+ void onPollBuffering();
bool haveSufficientDataOnAllTracks();
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ee573f0..d0651f3 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -52,6 +52,7 @@
#include <OMX_AsString.h>
#include "include/avc_utils.h"
+#include "omx/OMXUtils.h"
namespace android {
@@ -101,15 +102,6 @@
}
}
-template<class T>
-static void InitOMXParams(T *params) {
- params->nSize = sizeof(T);
- params->nVersion.s.nVersionMajor = 1;
- params->nVersion.s.nVersionMinor = 0;
- params->nVersion.s.nRevision = 0;
- params->nVersion.s.nStep = 0;
-}
-
struct MessageList : public RefBase {
MessageList() {
}
@@ -3985,11 +3977,11 @@
}
// static
-bool ACodec::describeDefaultColorFormat(DescribeColorFormatParams ¶ms) {
- MediaImage &image = params.sMediaImage;
+bool ACodec::describeDefaultColorFormat(DescribeColorFormat2Params ¶ms) {
+ MediaImage2 &image = params.sMediaImage;
memset(&image, 0, sizeof(image));
- image.mType = MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
+ image.mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
image.mNumPlanes = 0;
const OMX_COLOR_FORMATTYPE fmt = params.eColorFormat;
@@ -4024,9 +4016,10 @@
}
// set-up YUV format
- image.mType = MediaImage::MEDIA_IMAGE_TYPE_YUV;
+ image.mType = MediaImage2::MEDIA_IMAGE_TYPE_YUV;
image.mNumPlanes = 3;
image.mBitDepth = 8;
+ image.mBitDepthAllocated = 8;
image.mPlane[image.Y].mOffset = 0;
image.mPlane[image.Y].mColInc = 1;
image.mPlane[image.Y].mRowInc = params.nStride;
@@ -4099,26 +4092,34 @@
// static
bool ACodec::describeColorFormat(
const sp<IOMX> &omx, IOMX::node_id node,
- DescribeColorFormatParams &describeParams)
+ DescribeColorFormat2Params &describeParams)
{
OMX_INDEXTYPE describeColorFormatIndex;
if (omx->getExtensionIndex(
node, "OMX.google.android.index.describeColorFormat",
- &describeColorFormatIndex) != OK ||
- omx->getParameter(
- node, describeColorFormatIndex,
- &describeParams, sizeof(describeParams)) != OK) {
- return describeDefaultColorFormat(describeParams);
+ &describeColorFormatIndex) == OK) {
+ DescribeColorFormatParams describeParamsV1(describeParams);
+ if (omx->getParameter(
+ node, describeColorFormatIndex,
+ &describeParamsV1, sizeof(describeParamsV1)) == OK) {
+ describeParams.initFromV1(describeParamsV1);
+ return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ }
+ } else if (omx->getExtensionIndex(
+ node, "OMX.google.android.index.describeColorFormat2", &describeColorFormatIndex) == OK
+ && omx->getParameter(
+ node, describeColorFormatIndex, &describeParams, sizeof(describeParams)) == OK) {
+ return describeParams.sMediaImage.mType != MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
}
- return describeParams.sMediaImage.mType !=
- MediaImage::MEDIA_IMAGE_TYPE_UNKNOWN;
+
+ return describeDefaultColorFormat(describeParams);
}
// static
bool ACodec::isFlexibleColorFormat(
const sp<IOMX> &omx, IOMX::node_id node,
uint32_t colorFormat, bool usingNativeBuffers, OMX_U32 *flexibleEquivalent) {
- DescribeColorFormatParams describeParams;
+ DescribeColorFormat2Params describeParams;
InitOMXParams(&describeParams);
describeParams.eColorFormat = (OMX_COLOR_FORMATTYPE)colorFormat;
// reasonable dummy values
@@ -4134,11 +4135,11 @@
return false;
}
- const MediaImage &img = describeParams.sMediaImage;
- if (img.mType == MediaImage::MEDIA_IMAGE_TYPE_YUV) {
- if (img.mNumPlanes != 3 ||
- img.mPlane[img.Y].mHorizSubsampling != 1 ||
- img.mPlane[img.Y].mVertSubsampling != 1) {
+ const MediaImage2 &img = describeParams.sMediaImage;
+ if (img.mType == MediaImage2::MEDIA_IMAGE_TYPE_YUV) {
+ if (img.mNumPlanes != 3
+ || img.mPlane[img.Y].mHorizSubsampling != 1
+ || img.mPlane[img.Y].mVertSubsampling != 1) {
return false;
}
@@ -4188,7 +4189,7 @@
notify->setInt32("color-format", videoDef->eColorFormat);
if (mNativeWindow == NULL) {
- DescribeColorFormatParams describeParams;
+ DescribeColorFormat2Params describeParams;
InitOMXParams(&describeParams);
describeParams.eColorFormat = videoDef->eColorFormat;
describeParams.nFrameWidth = videoDef->nFrameWidth;
@@ -4204,12 +4205,13 @@
&describeParams.sMediaImage,
sizeof(describeParams.sMediaImage)));
- MediaImage *img = &describeParams.sMediaImage;
- ALOGV("[%s] MediaImage { F(%ux%u) @%u+%u+%u @%u+%u+%u @%u+%u+%u }",
- mComponentName.c_str(), img->mWidth, img->mHeight,
- img->mPlane[0].mOffset, img->mPlane[0].mColInc, img->mPlane[0].mRowInc,
- img->mPlane[1].mOffset, img->mPlane[1].mColInc, img->mPlane[1].mRowInc,
- img->mPlane[2].mOffset, img->mPlane[2].mColInc, img->mPlane[2].mRowInc);
+ MediaImage2 &img = describeParams.sMediaImage;
+ MediaImage2::PlaneInfo *plane = img.mPlane;
+ ALOGV("[%s] MediaImage { F(%ux%u) @%u+%d+%d @%u+%d+%d @%u+%d+%d }",
+ mComponentName.c_str(), img.mWidth, img.mHeight,
+ plane[0].mOffset, plane[0].mColInc, plane[0].mRowInc,
+ plane[1].mOffset, plane[1].mColInc, plane[1].mRowInc,
+ plane[2].mOffset, plane[2].mColInc, plane[2].mRowInc);
}
}
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 68e02e7..557971d 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -72,8 +72,10 @@
$(TOP)/external/tremolo \
$(TOP)/external/libvpx/libwebm \
$(TOP)/system/netd/include \
+ $(call include-path-for, audio-utils)
LOCAL_SHARED_LIBRARIES := \
+ libaudioutils \
libbinder \
libcamera_client \
libcutils \
diff --git a/media/libstagefright/CameraSource.cpp b/media/libstagefright/CameraSource.cpp
index 64d4302..4f88d9c 100644
--- a/media/libstagefright/CameraSource.cpp
+++ b/media/libstagefright/CameraSource.cpp
@@ -919,6 +919,7 @@
mReceivedBufferItemMap.removeItemsAt(index);
mVideoBufferConsumer->releaseBuffer(buffer);
mMemoryBases.push_back(frame);
+ mMemoryBaseAvailableCond.signal();
} else if (mCameraRecordingProxy != NULL) {
mCameraRecordingProxy->releaseRecordingFrame(frame);
} else if (mCamera != NULL) {
@@ -1122,10 +1123,13 @@
return;
}
- if (mMemoryBases.empty()) {
- ALOGW("%s: No available memory base. Dropping a recording frame.", __FUNCTION__);
- mVideoBufferConsumer->releaseBuffer(buffer);
- return;
+ while (mMemoryBases.empty()) {
+ if (mMemoryBaseAvailableCond.waitRelative(mLock, kMemoryBaseAvailableTimeoutNs) ==
+ TIMED_OUT) {
+ ALOGW("Waiting on an available memory base timed out. Dropping a recording frame.");
+ mVideoBufferConsumer->releaseBuffer(buffer);
+ return;
+ }
}
++mNumFramesReceived;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index d520cb3..ef0e17f 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -2404,10 +2404,14 @@
updateTrackSizeEstimate();
if (mOwner->exceedsFileSizeLimit()) {
+ ALOGW("Recorded file size exceeds limit %" PRId64 "bytes",
+ mOwner->mMaxFileSizeLimitBytes);
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0);
break;
}
if (mOwner->exceedsFileDurationLimit()) {
+ ALOGW("Recorded file duration exceeds limit %" PRId64 "microseconds",
+ mOwner->mMaxFileDurationLimitUs);
mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0);
break;
}
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index fb1f401..fbdf56f 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -2498,7 +2498,7 @@
ICrypto::DestinationType dst_type = ICrypto::kDestinationTypeOpaqueHandle;
if (info->mNativeHandle != NULL) {
- dst_pointer = (void *)info->mNativeHandle.get();
+ dst_pointer = (void *)info->mNativeHandle->handle();
dst_type = ICrypto::kDestinationTypeNativeHandle;
} else if ((mFlags & kFlagIsSecure) == 0) {
dst_type = ICrypto::kDestinationTypeVmPointer;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 680c0c6..15e3845 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -20,6 +20,7 @@
#include "include/WAVExtractor.h"
+#include <audio_utils/primitives.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -36,6 +37,7 @@
enum {
WAVE_FORMAT_PCM = 0x0001,
+ WAVE_FORMAT_IEEE_FLOAT = 0x0003,
WAVE_FORMAT_ALAW = 0x0006,
WAVE_FORMAT_MULAW = 0x0007,
WAVE_FORMAT_MSGSM = 0x0031,
@@ -177,6 +179,7 @@
mWaveFormat = U16_LE_AT(formatSpec);
if (mWaveFormat != WAVE_FORMAT_PCM
+ && mWaveFormat != WAVE_FORMAT_IEEE_FLOAT
&& mWaveFormat != WAVE_FORMAT_ALAW
&& mWaveFormat != WAVE_FORMAT_MULAW
&& mWaveFormat != WAVE_FORMAT_MSGSM
@@ -214,24 +217,6 @@
mBitsPerSample = U16_LE_AT(&formatSpec[14]);
- if (mWaveFormat == WAVE_FORMAT_PCM
- || mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
- if (mBitsPerSample != 8 && mBitsPerSample != 16
- && mBitsPerSample != 24) {
- return ERROR_UNSUPPORTED;
- }
- } else if (mWaveFormat == WAVE_FORMAT_MSGSM) {
- if (mBitsPerSample != 0) {
- return ERROR_UNSUPPORTED;
- }
- } else {
- CHECK(mWaveFormat == WAVE_FORMAT_MULAW
- || mWaveFormat == WAVE_FORMAT_ALAW);
- if (mBitsPerSample != 8) {
- return ERROR_UNSUPPORTED;
- }
- }
-
if (mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
uint16_t validBitsPerSample = U16_LE_AT(&formatSpec[18]);
if (validBitsPerSample != mBitsPerSample) {
@@ -263,17 +248,34 @@
// In a WAVE_EXT header, the first two bytes of the GUID stored at byte 24 contain
// the sample format, using the same definitions as a regular WAV header
mWaveFormat = U16_LE_AT(&formatSpec[24]);
- if (mWaveFormat != WAVE_FORMAT_PCM
- && mWaveFormat != WAVE_FORMAT_ALAW
- && mWaveFormat != WAVE_FORMAT_MULAW) {
- return ERROR_UNSUPPORTED;
- }
if (memcmp(&formatSpec[26], WAVEEXT_SUBFORMAT, 14)) {
ALOGE("unsupported GUID");
return ERROR_UNSUPPORTED;
}
}
+ if (mWaveFormat == WAVE_FORMAT_PCM) {
+ if (mBitsPerSample != 8 && mBitsPerSample != 16
+ && mBitsPerSample != 24 && mBitsPerSample != 32) {
+ return ERROR_UNSUPPORTED;
+ }
+ } else if (mWaveFormat == WAVE_FORMAT_IEEE_FLOAT) {
+ if (mBitsPerSample != 32) { // TODO we don't support double
+ return ERROR_UNSUPPORTED;
+ }
+ }
+ else if (mWaveFormat == WAVE_FORMAT_MSGSM) {
+ if (mBitsPerSample != 0) {
+ return ERROR_UNSUPPORTED;
+ }
+ } else if (mWaveFormat == WAVE_FORMAT_MULAW || mWaveFormat == WAVE_FORMAT_ALAW) {
+ if (mBitsPerSample != 8) {
+ return ERROR_UNSUPPORTED;
+ }
+ } else {
+ return ERROR_UNSUPPORTED;
+ }
+
mValidFormat = true;
} else if (!memcmp(chunkHeader, "data", 4)) {
if (mValidFormat) {
@@ -284,6 +286,7 @@
switch (mWaveFormat) {
case WAVE_FORMAT_PCM:
+ case WAVE_FORMAT_IEEE_FLOAT:
mTrackMeta->setCString(
kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_RAW);
break;
@@ -475,46 +478,39 @@
buffer->set_range(0, n);
- if (mWaveFormat == WAVE_FORMAT_PCM || mWaveFormat == WAVE_FORMAT_EXTENSIBLE) {
+ // TODO: add capability to return data as float PCM instead of 16 bit PCM.
+ if (mWaveFormat == WAVE_FORMAT_PCM) {
if (mBitsPerSample == 8) {
// Convert 8-bit unsigned samples to 16-bit signed.
+ // Create new buffer with 2 byte wide samples
MediaBuffer *tmp;
CHECK_EQ(mGroup->acquire_buffer(&tmp), (status_t)OK);
-
- // The new buffer holds the sample number of samples, but each
- // one is 2 bytes wide.
tmp->set_range(0, 2 * n);
- int16_t *dst = (int16_t *)tmp->data();
- const uint8_t *src = (const uint8_t *)buffer->data();
- ssize_t numBytes = n;
-
- while (numBytes-- > 0) {
- *dst++ = ((int16_t)(*src) - 128) * 256;
- ++src;
- }
-
+ memcpy_to_i16_from_u8((int16_t *)tmp->data(), (const uint8_t *)buffer->data(), n);
buffer->release();
buffer = tmp;
} else if (mBitsPerSample == 24) {
- // Convert 24-bit signed samples to 16-bit signed.
+ // Convert 24-bit signed samples to 16-bit signed in place
+ const size_t numSamples = n / 3;
- const uint8_t *src =
- (const uint8_t *)buffer->data() + buffer->range_offset();
- int16_t *dst = (int16_t *)src;
+ memcpy_to_i16_from_p24((int16_t *)buffer->data(), (const uint8_t *)buffer->data(), numSamples);
+ buffer->set_range(0, 2 * numSamples);
+ } else if (mBitsPerSample == 32) {
+ // Convert 32-bit signed samples to 16-bit signed in place
+ const size_t numSamples = n / 4;
- size_t numSamples = buffer->range_length() / 3;
- for (size_t i = 0; i < numSamples; ++i) {
- int32_t x = (int32_t)(src[0] | src[1] << 8 | src[2] << 16);
- x = (x << 8) >> 8; // sign extension
+ memcpy_to_i16_from_i32((int16_t *)buffer->data(), (const int32_t *)buffer->data(), numSamples);
+ buffer->set_range(0, 2 * numSamples);
+ }
+ } else if (mWaveFormat == WAVE_FORMAT_IEEE_FLOAT) {
+ if (mBitsPerSample == 32) {
+ // Convert 32-bit float samples to 16-bit signed in place
+ const size_t numSamples = n / 4;
- x = x >> 8;
- *dst++ = (int16_t)x;
- src += 3;
- }
-
- buffer->set_range(buffer->range_offset(), 2 * numSamples);
+ memcpy_to_i16_from_float((int16_t *)buffer->data(), (const float *)buffer->data(), numSamples);
+ buffer->set_range(0, 2 * numSamples);
}
}
diff --git a/media/libstagefright/include/AACExtractor.h b/media/libstagefright/include/AACExtractor.h
index e231e62..bd4c41c 100644
--- a/media/libstagefright/include/AACExtractor.h
+++ b/media/libstagefright/include/AACExtractor.h
@@ -36,6 +36,7 @@
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "AACExtractor"; }
protected:
virtual ~AACExtractor();
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index 0770397..ba2b674 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -36,6 +36,7 @@
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "AMRExtractor"; }
protected:
virtual ~AMRExtractor();
diff --git a/media/libstagefright/include/AVIExtractor.h b/media/libstagefright/include/AVIExtractor.h
index ff5dcb5..3be505c 100644
--- a/media/libstagefright/include/AVIExtractor.h
+++ b/media/libstagefright/include/AVIExtractor.h
@@ -36,6 +36,7 @@
size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "AVIExtractor"; }
protected:
virtual ~AVIExtractor();
diff --git a/media/libstagefright/include/DRMExtractor.h b/media/libstagefright/include/DRMExtractor.h
index a035d8c..3dc7df8 100644
--- a/media/libstagefright/include/DRMExtractor.h
+++ b/media/libstagefright/include/DRMExtractor.h
@@ -38,6 +38,7 @@
virtual sp<IMediaSource> getTrack(size_t index);
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "DRMExtractor"; }
protected:
virtual ~DRMExtractor();
diff --git a/media/libstagefright/include/FLACExtractor.h b/media/libstagefright/include/FLACExtractor.h
index a6e6c1d..5d030b1 100644
--- a/media/libstagefright/include/FLACExtractor.h
+++ b/media/libstagefright/include/FLACExtractor.h
@@ -36,6 +36,7 @@
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "FLACExtractor"; }
protected:
virtual ~FLACExtractor();
diff --git a/media/libstagefright/include/MPEG2PSExtractor.h b/media/libstagefright/include/MPEG2PSExtractor.h
index e815f0e..c8abfb6 100644
--- a/media/libstagefright/include/MPEG2PSExtractor.h
+++ b/media/libstagefright/include/MPEG2PSExtractor.h
@@ -40,6 +40,7 @@
virtual sp<MetaData> getMetaData();
virtual uint32_t flags() const;
+ virtual const char * name() { return "MPEG2PSExtractor"; }
protected:
virtual ~MPEG2PSExtractor();
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index 9907572..e5c24ca 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -44,6 +44,7 @@
virtual sp<MetaData> getMetaData();
virtual uint32_t flags() const;
+ virtual const char * name() { return "MPEG2TSExtractor"; }
private:
friend struct MPEG2TSSource;
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index cff976d..3e8fb7c 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -58,6 +58,7 @@
virtual sp<MetaData> getMetaData();
virtual uint32_t flags() const;
+ virtual const char * name() { return "MPEG4Extractor"; }
// for DRM
virtual char* getDrmTrackInfo(size_t trackID, int *len);
diff --git a/media/libstagefright/include/MidiExtractor.h b/media/libstagefright/include/MidiExtractor.h
index 333277b..5a7d90e 100644
--- a/media/libstagefright/include/MidiExtractor.h
+++ b/media/libstagefright/include/MidiExtractor.h
@@ -60,6 +60,7 @@
virtual sp<MetaData> getTrackMetaData(size_t index, uint32_t flags);
virtual sp<MetaData> getMetaData();
+ virtual const char * name() { return "MidiExtractor"; }
protected:
virtual ~MidiExtractor();
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index 732894c..b1cb91d 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -29,8 +29,6 @@
struct OMXMaster;
class GraphicBufferSource;
-status_t StatusFromOMXError(OMX_ERRORTYPE err);
-
struct OMXNodeInstance {
OMXNodeInstance(
OMX *owner, const sp<IOMXObserver> &observer, const char *name);
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index a1d6b00..592e7cf 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -46,6 +46,8 @@
virtual uint32_t flags() const;
+ virtual const char * name() { return "MatroskaExtractor"; }
+
protected:
virtual ~MatroskaExtractor();
diff --git a/media/libstagefright/omx/Android.mk b/media/libstagefright/omx/Android.mk
index 804afe9..e4fbd81 100644
--- a/media/libstagefright/omx/Android.mk
+++ b/media/libstagefright/omx/Android.mk
@@ -7,6 +7,7 @@
OMX.cpp \
OMXMaster.cpp \
OMXNodeInstance.cpp \
+ OMXUtils.cpp \
SimpleSoftOMXComponent.cpp \
SoftOMXComponent.cpp \
SoftOMXPlugin.cpp \
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 6be289b..970f6f5 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -31,6 +31,7 @@
#include <utils/threads.h>
#include "OMXMaster.h"
+#include "OMXUtils.h"
#include <OMX_AsString.h>
#include <OMX_Component.h>
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 7380ab2..82d5ba3 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -22,6 +22,7 @@
#include "../include/OMXNodeInstance.h"
#include "OMXMaster.h"
+#include "OMXUtils.h"
#include "GraphicBufferSource.h"
#include <OMX_Component.h>
@@ -89,16 +90,6 @@
// TRICKY: this is needed so formatting macros expand before substitution
#define WITH_STATS(fmt, ...) WITH_STATS_WRAPPER(fmt, ##__VA_ARGS__)
-template<class T>
-static void InitOMXParams(T *params) {
- memset(params, 0, sizeof(T));
- params->nSize = sizeof(T);
- params->nVersion.s.nVersionMajor = 1;
- params->nVersion.s.nVersionMinor = 0;
- params->nVersion.s.nRevision = 0;
- params->nVersion.s.nStep = 0;
-}
-
namespace android {
struct BufferMeta {
@@ -245,20 +236,6 @@
return mNodeID;
}
-status_t StatusFromOMXError(OMX_ERRORTYPE err) {
- switch (err) {
- case OMX_ErrorNone:
- return OK;
- case OMX_ErrorUnsupportedSetting:
- case OMX_ErrorUnsupportedIndex:
- return ERROR_UNSUPPORTED;
- case OMX_ErrorInsufficientResources:
- return NO_MEMORY;
- default:
- return UNKNOWN_ERROR;
- }
-}
-
status_t OMXNodeInstance::freeNode(OMXMaster *master) {
CLOG_LIFE(freeNode, "handle=%p", mHandle);
static int32_t kMaxNumIterations = 10;
@@ -468,38 +445,40 @@
OMX_INDEXTYPE index;
OMX_ERRORTYPE err = OMX_GetExtensionIndex(mHandle, name, &index);
- if (err != OMX_ErrorNone) {
+ if (err == OMX_ErrorNone) {
+ EnableAndroidNativeBuffersParams params;
+ InitOMXParams(¶ms);
+ params.nPortIndex = portIndex;
+ params.enable = enable;
+
+ err = OMX_SetParameter(mHandle, index, ¶ms);
+ CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
+ portString(portIndex), portIndex, enable);
+ if (!graphic) {
+ if (err == OMX_ErrorNone) {
+ mSecureBufferType[portIndex] =
+ enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
+ } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
+ mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
+ }
+ }
+ } else {
CLOG_ERROR_IF(enable, getExtensionIndex, err, "%s", name);
- return StatusFromOMXError(err);
- }
-
- EnableAndroidNativeBuffersParams params;
- InitOMXParams(¶ms);
- params.nPortIndex = portIndex;
- params.enable = enable;
-
- err = OMX_SetParameter(mHandle, index, ¶ms);
- CLOG_IF_ERROR(setParameter, err, "%s(%#x): %s:%u en=%d", name, index,
- portString(portIndex), portIndex, enable);
- if (!graphic) {
- if (err == OK) {
- mSecureBufferType[portIndex] =
- enable ? kSecureBufferTypeNativeHandle : kSecureBufferTypeOpaque;
- } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
-
- // BEGIN ALTERNATE SIGNALING FOR USING NATIVE HANDLES
+ if (!graphic) {
+ // Extension not supported, check for manual override with system property
+ // This is a temporary workaround until partners support the OMX extension
char value[PROPERTY_VALUE_MAX];
if (property_get("media.mediadrmservice.enable", value, NULL)
- && (!strcmp("1", value) || !strcasecmp("true", value))) {
+ && (!strcmp("1", value) || !strcasecmp("true", value))) {
CLOG_CONFIG(enableNativeBuffers, "system property override: using native-handles");
mSecureBufferType[portIndex] = kSecureBufferTypeNativeHandle;
- return OK;
+ } else if (mSecureBufferType[portIndex] == kSecureBufferTypeUnknown) {
+ mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
}
- // END ALTERNATE SIGNALING FOR USING NATIVE HANDLES
-
- mSecureBufferType[portIndex] = kSecureBufferTypeOpaque;
+ err = OMX_ErrorNone;
}
}
+
return StatusFromOMXError(err);
}
diff --git a/media/libstagefright/omx/OMXUtils.cpp b/media/libstagefright/omx/OMXUtils.cpp
new file mode 100644
index 0000000..799696c
--- /dev/null
+++ b/media/libstagefright/omx/OMXUtils.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "OMXUtils"
+
+#include <string.h>
+
+#include <media/hardware/HardwareAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include "OMXUtils.h"
+
+namespace android {
+
+status_t StatusFromOMXError(OMX_ERRORTYPE err) {
+ switch (err) {
+ case OMX_ErrorNone:
+ return OK;
+ case OMX_ErrorUnsupportedSetting:
+ case OMX_ErrorUnsupportedIndex:
+ return ERROR_UNSUPPORTED; // this is a media specific error
+ case OMX_ErrorInsufficientResources:
+ return NO_MEMORY;
+ case OMX_ErrorInvalidComponentName:
+ case OMX_ErrorComponentNotFound:
+ return NAME_NOT_FOUND;
+ default:
+ return UNKNOWN_ERROR;
+ }
+}
+
+/**************************************************************************************************/
+
+DescribeColorFormatParams::DescribeColorFormatParams(const DescribeColorFormat2Params ¶ms) {
+ InitOMXParams(this);
+
+ eColorFormat = params.eColorFormat;
+ nFrameWidth = params.nFrameWidth;
+ nFrameHeight = params.nFrameHeight;
+ nStride = params.nStride;
+ nSliceHeight = params.nSliceHeight;
+ bUsingNativeBuffers = params.bUsingNativeBuffers;
+ // we don't copy media images as this conversion is only used pre-query
+};
+
+void DescribeColorFormat2Params::initFromV1(const DescribeColorFormatParams ¶ms) {
+ InitOMXParams(this);
+
+ eColorFormat = params.eColorFormat;
+ nFrameWidth = params.nFrameWidth;
+ nFrameHeight = params.nFrameHeight;
+ nStride = params.nStride;
+ nSliceHeight = params.nSliceHeight;
+ bUsingNativeBuffers = params.bUsingNativeBuffers;
+ sMediaImage.initFromV1(params.sMediaImage);
+};
+
+void MediaImage2::initFromV1(const MediaImage &image) {
+ memset(this, 0, sizeof(*this));
+
+ if (image.mType != MediaImage::MEDIA_IMAGE_TYPE_YUV) {
+ mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ return;
+ }
+
+ for (size_t ix = 0; ix < image.mNumPlanes; ++ix) {
+ if (image.mPlane[ix].mHorizSubsampling > INT32_MAX
+ || image.mPlane[ix].mVertSubsampling > INT32_MAX) {
+ mType = MediaImage2::MEDIA_IMAGE_TYPE_UNKNOWN;
+ return;
+ }
+ }
+
+ mType = (MediaImage2::Type)image.mType;
+ mNumPlanes = image.mNumPlanes;
+ mWidth = image.mWidth;
+ mHeight = image.mHeight;
+ mBitDepth = image.mBitDepth;
+ mBitDepthAllocated = 8;
+ for (size_t ix = 0; ix < image.mNumPlanes; ++ix) {
+ mPlane[ix].mOffset = image.mPlane[ix].mOffset;
+ mPlane[ix].mColInc = image.mPlane[ix].mColInc;
+ mPlane[ix].mRowInc = image.mPlane[ix].mRowInc;
+ mPlane[ix].mHorizSubsampling = (int32_t)image.mPlane[ix].mHorizSubsampling;
+ mPlane[ix].mVertSubsampling = (int32_t)image.mPlane[ix].mVertSubsampling;
+ }
+}
+
+/**************************************************************************************************/
+
+} // namespace android
+
diff --git a/media/libstagefright/omx/OMXUtils.h b/media/libstagefright/omx/OMXUtils.h
new file mode 100644
index 0000000..0c5e537
--- /dev/null
+++ b/media/libstagefright/omx/OMXUtils.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OMX_UTILS_H_
+#define OMX_UTILS_H_
+
+/***** DO NOT USE THIS INCLUDE!!! INTERAL ONLY!!! UNLESS YOU RESIDE IN media/libstagefright *****/
+
+// OMXUtils contains omx-specific utility functions for stagefright/omx library
+// TODO: move ACodec and OMXClient into this library
+
+namespace android {
+
+template<class T>
+static void InitOMXParams(T *params) {
+ memset(params, 0, sizeof(T));
+ params->nSize = sizeof(T);
+ params->nVersion.s.nVersionMajor = 1;
+ params->nVersion.s.nVersionMinor = 0;
+ params->nVersion.s.nRevision = 0;
+ params->nVersion.s.nStep = 0;
+}
+
+status_t StatusFromOMXError(OMX_ERRORTYPE err);
+
+} // namespace android
+
+#endif
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index eedbb42..6fa83fa 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -235,7 +235,7 @@
sp<AMessage> msg = new AMessage('paus', this);
mPauseGeneration++;
msg->setInt32("pausecheck", mPauseGeneration);
- msg->post(kPauseDelayUs);
+ msg->post();
}
void resume() {
@@ -979,6 +979,11 @@
case 'accu':
{
+ if (mSeekPending) {
+ ALOGV("Stale access unit.");
+ break;
+ }
+
int32_t timeUpdate;
if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
size_t trackIndex;
@@ -1070,6 +1075,12 @@
ALOGW("This is a live stream, ignoring pause request.");
break;
}
+
+ if (mPausing) {
+ ALOGV("This stream is already paused.");
+ break;
+ }
+
mCheckPending = true;
++mCheckGeneration;
mPausing = true;
diff --git a/media/mtp/Android.mk b/media/mtp/Android.mk
index 3af0956..cb7e4aa 100644
--- a/media/mtp/Android.mk
+++ b/media/mtp/Android.mk
@@ -37,7 +37,7 @@
LOCAL_MODULE:= libmtp
-LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST
+LOCAL_CFLAGS := -DMTP_DEVICE -DMTP_HOST -Wall -Wextra -Werror
LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libusbhost libbinder
diff --git a/media/mtp/MtpDataPacket.cpp b/media/mtp/MtpDataPacket.cpp
index d0ec2a6..0381edf 100644
--- a/media/mtp/MtpDataPacket.cpp
+++ b/media/mtp/MtpDataPacket.cpp
@@ -456,7 +456,7 @@
// look at the length field to see if the data spans multiple packets
uint32_t totalLength = MtpPacket::getUInt32(MTP_CONTAINER_LENGTH_OFFSET);
allocate(totalLength);
- while (totalLength > length) {
+ while (totalLength > static_cast<uint32_t>(length)) {
request->buffer = mBuffer + length;
request->buffer_length = totalLength - length;
int ret = transfer(request);
diff --git a/media/mtp/MtpDevice.cpp b/media/mtp/MtpDevice.cpp
index 7d7ea13..a398aca 100644
--- a/media/mtp/MtpDevice.cpp
+++ b/media/mtp/MtpDevice.cpp
@@ -505,6 +505,7 @@
int remaining = size;
mRequest.reset();
mRequest.setParameter(1, handle);
+ bool error = false;
if (sendRequest(MTP_OPERATION_SEND_OBJECT)) {
// send data header
writeDataHeader(MTP_OPERATION_SEND_OBJECT, remaining);
@@ -514,7 +515,9 @@
while (remaining > 0) {
int count = read(srcFD, buffer, sizeof(buffer));
if (count > 0) {
- int written = mData.write(mRequestOut, buffer, count);
+ if (mData.write(mRequestOut, buffer, count) < 0) {
+ error = true;
+ }
// FIXME check error
remaining -= count;
} else {
@@ -523,7 +526,7 @@
}
}
MtpResponseCode ret = readResponse();
- return (remaining == 0 && ret == MTP_RESPONSE_OK);
+ return (remaining == 0 && ret == MTP_RESPONSE_OK && !error);
}
bool MtpDevice::deleteObject(MtpObjectHandle handle) {
diff --git a/media/mtp/MtpPacket.cpp b/media/mtp/MtpPacket.cpp
index bab1335..35ecb4f 100644
--- a/media/mtp/MtpPacket.cpp
+++ b/media/mtp/MtpPacket.cpp
@@ -69,7 +69,7 @@
char buffer[500];
char* bufptr = buffer;
- for (int i = 0; i < mPacketSize; i++) {
+ for (size_t i = 0; i < mPacketSize; i++) {
sprintf(bufptr, "%02X ", mBuffer[i]);
bufptr += strlen(bufptr);
if (i % DUMP_BYTES_PER_ROW == (DUMP_BYTES_PER_ROW - 1)) {
diff --git a/media/mtp/MtpProperty.cpp b/media/mtp/MtpProperty.cpp
index d58e2a4..2be2d79 100644
--- a/media/mtp/MtpProperty.cpp
+++ b/media/mtp/MtpProperty.cpp
@@ -544,7 +544,7 @@
MtpPropertyValue* result = new MtpPropertyValue[length];
for (uint32_t i = 0; i < length; i++)
if (!readValue(packet, result[i])) {
- delete result;
+ delete [] result;
return NULL;
}
return result;
diff --git a/media/mtp/MtpRequestPacket.cpp b/media/mtp/MtpRequestPacket.cpp
index 40b11b0..471967f 100644
--- a/media/mtp/MtpRequestPacket.cpp
+++ b/media/mtp/MtpRequestPacket.cpp
@@ -44,11 +44,12 @@
}
// request packet should have 12 byte header followed by 0 to 5 32-bit arguments
- if (ret >= MTP_CONTAINER_HEADER_SIZE
- && ret <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
- && ((ret - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
- mPacketSize = ret;
- mParameterCount = (ret - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
+ const size_t read_size = static_cast<size_t>(ret);
+ if (read_size >= MTP_CONTAINER_HEADER_SIZE
+ && read_size <= MTP_CONTAINER_HEADER_SIZE + 5 * sizeof(uint32_t)
+ && ((read_size - MTP_CONTAINER_HEADER_SIZE) & 3) == 0) {
+ mPacketSize = read_size;
+ mParameterCount = (read_size - MTP_CONTAINER_HEADER_SIZE) / sizeof(uint32_t);
} else {
ALOGE("Malformed MTP request packet");
ret = -1;
diff --git a/media/mtp/MtpServer.cpp b/media/mtp/MtpServer.cpp
index 3e0f239..90f1a77 100644
--- a/media/mtp/MtpServer.cpp
+++ b/media/mtp/MtpServer.cpp
@@ -923,9 +923,7 @@
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // image bit depth
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // parent
if (!mData.getUInt16(temp16)) return MTP_RESPONSE_INVALID_PARAMETER;
- uint16_t associationType = temp16;
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER;
- uint32_t associationDesc = temp32; // association desc
if (!mData.getUInt32(temp32)) return MTP_RESPONSE_INVALID_PARAMETER; // sequence number
MtpStringBuffer name, created, modified;
if (!mData.getString(name)) return MTP_RESPONSE_INVALID_PARAMETER; // file name
@@ -1102,7 +1100,6 @@
}
strcpy(fileSpot, name);
- int type = entry->d_type;
if (entry->d_type == DT_DIR) {
deleteRecursive(pathbuf);
rmdir(pathbuf);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0a3a832..ada1580 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -175,7 +175,7 @@
mHardwareStatus(AUDIO_HW_IDLE),
mMasterVolume(1.0f),
mMasterMute(false),
- mNextUniqueId(1),
+ mNextUniqueId(AUDIO_UNIQUE_ID_USE_MAX), // zero has a special meaning, so unavailable
mMode(AUDIO_MODE_INVALID),
mBtNrecIsOff(false),
mIsLowRamDevice(true),
@@ -611,6 +611,11 @@
PlaybackThread *effectThread = NULL;
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
+ if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
+ ALOGE("createTrack() invalid session ID %d", *sessionId);
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
lSessionId = *sessionId;
// check if an effect chain with the same session ID is present on another
// output thread and move it here.
@@ -626,7 +631,7 @@
}
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -1481,10 +1486,14 @@
client = registerPid(pid);
if (sessionId != NULL && *sessionId != AUDIO_SESSION_ALLOCATE) {
+ if (audio_unique_id_get_use(*sessionId) != AUDIO_UNIQUE_ID_USE_SESSION) {
+ lStatus = BAD_VALUE;
+ goto Exit;
+ }
lSessionId = *sessionId;
} else {
// if no audio session id is provided, create one here
- lSessionId = nextUniqueId();
+ lSessionId = nextUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
if (sessionId != NULL) {
*sessionId = lSessionId;
}
@@ -1617,7 +1626,7 @@
mHardwareStatus = AUDIO_HW_IDLE;
}
- audio_module_handle_t handle = nextUniqueId();
+ audio_module_handle_t handle = nextUniqueId(AUDIO_UNIQUE_ID_USE_MODULE);
mAudioHwDevs.add(handle, new AudioHwDevice(handle, name, dev, flags));
ALOGI("loadHwModule() Loaded %s audio interface from %s (%s) handle %d",
@@ -1762,8 +1771,14 @@
}
audio_hw_device_t *hwDevHal = outHwDev->hwDevice();
+
if (*output == AUDIO_IO_HANDLE_NONE) {
- *output = nextUniqueId();
+ *output = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
+ } else {
+ // Audio Policy does not currently request a specific output handle.
+ // If this is ever needed, see openInput_l() for example code.
+ ALOGE("openOutput_l requested output handle %d is not AUDIO_IO_HANDLE_NONE", *output);
+ return 0;
}
mHardwareStatus = AUDIO_HW_OUTPUT_OPEN;
@@ -1880,7 +1895,7 @@
return AUDIO_IO_HANDLE_NONE;
}
- audio_io_handle_t id = nextUniqueId();
+ audio_io_handle_t id = nextUniqueId(AUDIO_UNIQUE_ID_USE_OUTPUT);
DuplicatingThread *thread = new DuplicatingThread(this, thread1, id, mSystemReady);
thread->addOutputTrack(thread2);
mPlaybackThreads.add(id, thread);
@@ -2034,8 +2049,18 @@
return 0;
}
+ // Audio Policy can request a specific handle for hardware hotword.
+ // The goal here is not to re-open an already opened input.
+ // It is to use a pre-assigned I/O handle.
if (*input == AUDIO_IO_HANDLE_NONE) {
- *input = nextUniqueId();
+ *input = nextUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
+ } else if (audio_unique_id_get_use(*input) != AUDIO_UNIQUE_ID_USE_INPUT) {
+ ALOGE("openInput_l() requested input handle %d is invalid", *input);
+ return 0;
+ } else if (mRecordThreads.indexOfKey(*input) >= 0) {
+ // This should not happen in a transient state with current design.
+ ALOGE("openInput_l() requested input handle %d is already assigned", *input);
+ return 0;
}
audio_config_t halconfig = *config;
@@ -2239,9 +2264,9 @@
}
-audio_unique_id_t AudioFlinger::newAudioUniqueId()
+audio_unique_id_t AudioFlinger::newAudioUniqueId(audio_unique_id_use_t use)
{
- return nextUniqueId();
+ return nextUniqueId(use);
}
void AudioFlinger::acquireAudioSessionId(int audioSession, pid_t pid)
@@ -2363,6 +2388,23 @@
return;
}
+// checkThread_l() must be called with AudioFlinger::mLock held
+AudioFlinger::ThreadBase *AudioFlinger::checkThread_l(audio_io_handle_t ioHandle) const
+{
+ ThreadBase *thread = NULL;
+ switch (audio_unique_id_get_use(ioHandle)) {
+ case AUDIO_UNIQUE_ID_USE_OUTPUT:
+ thread = checkPlaybackThread_l(ioHandle);
+ break;
+ case AUDIO_UNIQUE_ID_USE_INPUT:
+ thread = checkRecordThread_l(ioHandle);
+ break;
+ default:
+ break;
+ }
+ return thread;
+}
+
// checkPlaybackThread_l() must be called with AudioFlinger::mLock held
AudioFlinger::PlaybackThread *AudioFlinger::checkPlaybackThread_l(audio_io_handle_t output) const
{
@@ -2382,9 +2424,14 @@
return mRecordThreads.valueFor(input).get();
}
-uint32_t AudioFlinger::nextUniqueId()
+audio_unique_id_t AudioFlinger::nextUniqueId(audio_unique_id_use_t use)
{
- return (uint32_t) android_atomic_inc(&mNextUniqueId);
+ int32_t base = android_atomic_add(AUDIO_UNIQUE_ID_USE_MAX, &mNextUniqueId);
+ // We have no way of recovering from wraparound
+ LOG_ALWAYS_FATAL_IF(base == 0, "unique ID overflow");
+ LOG_ALWAYS_FATAL_IF((unsigned) use >= (unsigned) AUDIO_UNIQUE_ID_USE_MAX);
+ ALOG_ASSERT(audio_unique_id_get_use(base) == AUDIO_UNIQUE_ID_USE_UNSPECIFIED);
+ return (audio_unique_id_t) (base | use);
}
AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() const
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index f2f11e3..858ebbb 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -196,7 +196,7 @@
virtual uint32_t getInputFramesLost(audio_io_handle_t ioHandle) const;
- virtual audio_unique_id_t newAudioUniqueId();
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
virtual void acquireAudioSessionId(int audioSession, pid_t pid);
@@ -517,6 +517,7 @@
};
+ ThreadBase *checkThread_l(audio_io_handle_t ioHandle) const;
PlaybackThread *checkPlaybackThread_l(audio_io_handle_t output) const;
MixerThread *checkMixerThread_l(audio_io_handle_t output) const;
RecordThread *checkRecordThread_l(audio_io_handle_t input) const;
@@ -547,15 +548,17 @@
const sp<AudioIoDescriptor>& ioDesc,
pid_t pid = 0);
- // Allocate an audio_io_handle_t, session ID, effect ID, or audio_module_handle_t.
+ // Allocate an audio_unique_id_t.
+ // Specific types are audio_io_handle_t, audio_session_t, effect ID (int),
+ // audio_module_handle_t, and audio_patch_handle_t.
// They all share the same ID space, but the namespaces are actually independent
// because there are separate KeyedVectors for each kind of ID.
- // The return value is uint32_t, but is cast to signed for some IDs.
+ // The return value is cast to the specific type depending on how the ID will be used.
// FIXME This API does not handle rollover to zero (for unsigned IDs),
// or from positive to negative (for signed IDs).
// Thus it may fail by returning an ID of the wrong sign,
// or by returning a non-unique ID.
- uint32_t nextUniqueId();
+ audio_unique_id_t nextUniqueId(audio_unique_id_use_t use);
status_t moveEffectChain_l(int sessionId,
PlaybackThread *srcThread,
diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp
index a6cb9c0..5fcc0fe 100644
--- a/services/audioflinger/PatchPanel.cpp
+++ b/services/audioflinger/PatchPanel.cpp
@@ -349,7 +349,7 @@
exit:
ALOGV("createAudioPatch() status %d", status);
if (status == NO_ERROR) {
- *handle = audioflinger->nextUniqueId();
+ *handle = audioflinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_PATCH);
newPatch->mHandle = *handle;
newPatch->mHalHandle = halHandle;
mPatches.add(newPatch);
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e056ef2..a684c1e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -468,6 +468,7 @@
{AUDIO_DEVICE_OUT_AUX_LINE, "AUX_LINE"},
{AUDIO_DEVICE_OUT_SPEAKER_SAFE, "SPEAKER_SAFE"},
{AUDIO_DEVICE_OUT_IP, "IP"},
+ {AUDIO_DEVICE_OUT_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
}, mappingsIn[] = {
{AUDIO_DEVICE_IN_COMMUNICATION, "COMMUNICATION"},
@@ -491,6 +492,7 @@
{AUDIO_DEVICE_IN_BLUETOOTH_A2DP, "BLUETOOTH_A2DP"},
{AUDIO_DEVICE_IN_LOOPBACK, "LOOPBACK"},
{AUDIO_DEVICE_IN_IP, "IP"},
+ {AUDIO_DEVICE_IN_BUS, "BUS"},
{AUDIO_DEVICE_NONE, "NONE"}, // must be last
};
String8 result;
@@ -1340,7 +1342,7 @@
ALOGV("createEffect_l() got effect %p on chain %p", effect.get(), chain.get());
if (effect == 0) {
- int id = mAudioFlinger->nextUniqueId();
+ audio_unique_id_t id = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
// Check CPU and memory usage
lStatus = AudioSystem::registerEffect(desc, mId, chain->strategy(), sessionId, id);
if (lStatus != NO_ERROR) {
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index 40ca899..1c41ce1 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -332,14 +332,15 @@
virtual void onAudioPatchListUpdate() = 0;
- virtual audio_unique_id_t newAudioUniqueId() = 0;
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use) = 0;
virtual void onDynamicPolicyMixStateUpdate(String8 regId, int32_t state) = 0;
virtual void onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source,
const struct audio_config_base *clientConfig,
- const struct audio_config_base *deviceConfig) = 0;
+ const struct audio_config_base *deviceConfig,
+ audio_patch_handle_t patchHandle) = 0;
};
extern "C" AudioPolicyInterface* createAudioPolicyManager(AudioPolicyClientInterface *clientInterface);
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 77c0d07..46309ed 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -18,6 +18,7 @@
#include "AudioPort.h"
#include "AudioSession.h"
+#include "AudioSessionInfoProvider.h"
#include <utils/Errors.h>
#include <system/audio.h>
#include <utils/SortedVector.h>
@@ -30,7 +31,7 @@
// descriptor for audio inputs. Used to maintain current configuration of each opened audio input
// and keep track of the usage of this input.
-class AudioInputDescriptor: public AudioPortConfig
+class AudioInputDescriptor: public AudioPortConfig, public AudioSessionInfoProvider
{
public:
AudioInputDescriptor(const sp<IOProfile>& profile);
@@ -44,7 +45,6 @@
audio_io_handle_t mIoHandle; // input handle
audio_devices_t mDevice; // current device this input is routed to
AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
- audio_patch_handle_t mPatchHandle;
const sp<IOProfile> mProfile; // I/O profile this output derives from
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
@@ -65,7 +65,14 @@
sp<AudioSession> getAudioSession(audio_session_t session) const;
AudioSessionCollection getActiveAudioSessions() const;
+ // implementation of AudioSessionInfoProvider
+ virtual audio_config_base_t getConfig() const;
+ virtual audio_patch_handle_t getPatchHandle() const;
+
+ void setPatchHandle(audio_patch_handle_t handle);
+
private:
+ audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
// audio sessions attached to this input
AudioSessionCollection mSessions;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index f8439be..dd3f8ae 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -71,9 +71,11 @@
audio_module_handle_t getModuleHandle() const;
+ audio_patch_handle_t getPatchHandle() const { return mPatchHandle; };
+ void setPatchHandle(audio_patch_handle_t handle) { mPatchHandle = handle; };
+
sp<AudioPort> mPort;
audio_devices_t mDevice; // current device this output is routed to
- audio_patch_handle_t mPatchHandle;
uint32_t mRefCount[AUDIO_STREAM_CNT]; // number of streams of each type using this output
nsecs_t mStopTime[AUDIO_STREAM_CNT];
float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
@@ -83,6 +85,7 @@
AudioPolicyClientInterface *mClientInterface;
protected:
+ audio_patch_handle_t mPatchHandle;
audio_port_handle_t mId;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
index 5958f4f..211ec98 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPort.h
@@ -66,6 +66,7 @@
virtual void attach(const sp<HwModule>& module);
bool isAttached() { return mModule != 0; }
+ // Audio port IDs are in a different namespace than AudioFlinger unique IDs
static audio_port_handle_t getNextUniqueId();
virtual void toAudioPort(struct audio_port *port) const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
index 799410b..388c25d 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSession.h
@@ -22,12 +22,13 @@
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <media/AudioPolicy.h>
+#include "AudioSessionInfoProvider.h"
namespace android {
class AudioPolicyClientInterface;
-class AudioSession : public RefBase
+class AudioSession : public RefBase, public AudioSessionInfoUpdateListener
{
public:
AudioSession(audio_session_t session,
@@ -58,14 +59,14 @@
uint32_t changeOpenCount(int delta);
uint32_t changeActiveCount(int delta);
- void setDeviceConfig(audio_format_t format, uint32_t sampleRate,
- audio_channel_mask_t channelMask);
+ void setInfoProvider(AudioSessionInfoProvider *provider);
+ // implementation of AudioSessionInfoUpdateListener
+ virtual void onSessionInfoUpdate() const;
private:
const audio_session_t mSession;
const audio_source_t mInputSource;
const struct audio_config_base mConfig;
- struct audio_config_base mDeviceConfig;
const audio_input_flags_t mFlags;
const uid_t mUid;
bool mIsSoundTrigger;
@@ -73,14 +74,17 @@
uint32_t mActiveCount;
AudioMix* mPolicyMix; // non NULL when used by a dynamic policy
AudioPolicyClientInterface* mClientInterface;
+ const AudioSessionInfoProvider* mInfoProvider;
};
class AudioSessionCollection :
- public DefaultKeyedVector<audio_session_t, sp<AudioSession> >
+ public DefaultKeyedVector<audio_session_t, sp<AudioSession> >,
+ public AudioSessionInfoUpdateListener
{
public:
status_t addSession(audio_session_t session,
- const sp<AudioSession>& audioSession);
+ const sp<AudioSession>& audioSession,
+ AudioSessionInfoProvider *provider);
status_t removeSession(audio_session_t session);
@@ -90,6 +94,9 @@
bool hasActiveSession() const;
bool isSourceActive(audio_source_t source) const;
+ // implementation of AudioSessionInfoUpdateListener
+ virtual void onSessionInfoUpdate() const;
+
status_t dump(int fd, int spaces) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
new file mode 100644
index 0000000..e0037fc
--- /dev/null
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioSessionInfoProvider.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+namespace android {
+
+/**
+ * Interface for input descriptors to implement so dependent audio sessions can query information
+ * about their context
+ */
+class AudioSessionInfoProvider
+{
+public:
+ virtual ~AudioSessionInfoProvider() {};
+
+ virtual audio_config_base_t getConfig() const = 0;
+
+ virtual audio_patch_handle_t getPatchHandle() const = 0;
+
+};
+
+class AudioSessionInfoUpdateListener
+{
+public:
+ virtual ~AudioSessionInfoUpdateListener() {};
+
+ virtual void onSessionInfoUpdate() const = 0;;
+};
+
+} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 5523aff..d4992b0 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -28,8 +28,8 @@
AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile)
: mIoHandle(0),
- mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL), mPatchHandle(0),
- mProfile(profile), mId(0)
+ mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
+ mProfile(profile), mPatchHandle(0), mId(0)
{
if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -150,14 +150,31 @@
status_t AudioInputDescriptor::addAudioSession(audio_session_t session,
const sp<AudioSession>& audioSession) {
- audioSession->setDeviceConfig(mFormat, mSamplingRate, mChannelMask);
- return mSessions.addSession(session, audioSession);
+ return mSessions.addSession(session, audioSession, /*AudioSessionInfoProvider*/this);
}
status_t AudioInputDescriptor::removeAudioSession(audio_session_t session) {
return mSessions.removeSession(session);
}
+audio_port_handle_t AudioInputDescriptor::getPatchHandle() const
+{
+ return mPatchHandle;
+}
+
+void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
+{
+ mPatchHandle = handle;
+ mSessions.onSessionInfoUpdate();
+}
+
+audio_config_base_t AudioInputDescriptor::getConfig() const
+{
+ const audio_config_base_t config = { .sample_rate = mSamplingRate, .channel_mask = mChannelMask,
+ .format = mFormat };
+ return config;
+}
+
status_t AudioInputDescriptor::dump(int fd)
{
const size_t SIZE = 256;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 5d0f03f..0fe1a84 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -34,7 +34,7 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
: mPort(port), mDevice(AUDIO_DEVICE_NONE),
- mPatchHandle(0), mClientInterface(clientInterface), mId(0)
+ mClientInterface(clientInterface), mPatchHandle(0), mId(0)
{
// clear usage count for all stream types
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
index bda59ad..031444b 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPort.cpp
@@ -36,6 +36,7 @@
mModule = module;
}
+// Note that is a different namespace than AudioFlinger unique IDs
audio_port_handle_t AudioPort::getNextUniqueId()
{
return static_cast<audio_port_handle_t>(android_atomic_inc(&mNextUniqueId));
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
index 2a0b477..ce9c170 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioSession.cpp
@@ -38,9 +38,9 @@
AudioPolicyClientInterface *clientInterface) :
mSession(session), mInputSource(inputSource),
mConfig({ .format = format, .sample_rate = sampleRate, .channel_mask = channelMask}),
- mDeviceConfig(AUDIO_CONFIG_BASE_INITIALIZER),
mFlags(flags), mUid(uid), mIsSoundTrigger(isSoundTrigger),
- mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface)
+ mOpenCount(1), mActiveCount(0), mPolicyMix(policyMix), mClientInterface(clientInterface),
+ mInfoProvider(NULL)
{
}
@@ -66,25 +66,31 @@
}
mActiveCount += delta;
ALOGV("%s active count %d", __FUNCTION__, mActiveCount);
+ int event = RECORD_CONFIG_EVENT_NONE;
if ((oldActiveCount == 0) && (mActiveCount > 0)) {
- // if input maps to a dynamic policy with an activity listener, notify of state change
- if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
- {
- mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
- MIX_STATE_MIXING);
- }
- mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
- mSession, mInputSource, &mConfig, &mDeviceConfig);
+ event = RECORD_CONFIG_EVENT_START;
} else if ((oldActiveCount > 0) && (mActiveCount == 0)) {
+ event = RECORD_CONFIG_EVENT_STOP;
+ }
+
+ if (event != RECORD_CONFIG_EVENT_NONE) {
+ // Dynamic policy callback:
// if input maps to a dynamic policy with an activity listener, notify of state change
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
{
mClientInterface->onDynamicPolicyMixStateUpdate(mPolicyMix->mRegistrationId,
- MIX_STATE_IDLE);
+ (event == RECORD_CONFIG_EVENT_START) ? MIX_STATE_MIXING : MIX_STATE_IDLE);
}
- mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_STOP,
- mSession, mInputSource, &mConfig, &mDeviceConfig);
+
+ // Recording configuration callback:
+ const AudioSessionInfoProvider* provider = mInfoProvider;
+ const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+ AUDIO_CONFIG_BASE_INITIALIZER;
+ const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+ AUDIO_PATCH_HANDLE_NONE;
+ mClientInterface->onRecordingConfigurationUpdate(event, mSession, mInputSource,
+ &mConfig, &deviceConfig, patchHandle);
}
return mActiveCount;
@@ -104,11 +110,24 @@
return false;
}
-void AudioSession::setDeviceConfig(audio_format_t format, uint32_t sampleRate,
- audio_channel_mask_t channelMask) {
- mDeviceConfig.format = format;
- mDeviceConfig.sample_rate = sampleRate;
- mDeviceConfig.channel_mask = channelMask;
+void AudioSession::setInfoProvider(AudioSessionInfoProvider *provider)
+{
+ mInfoProvider = provider;
+}
+
+void AudioSession::onSessionInfoUpdate() const
+{
+ if (mActiveCount > 0) {
+ // resend the callback after requerying the informations from the info provider
+ const AudioSessionInfoProvider* provider = mInfoProvider;
+ const audio_config_base_t deviceConfig = (provider != NULL) ? provider->getConfig() :
+ AUDIO_CONFIG_BASE_INITIALIZER;
+ const audio_patch_handle_t patchHandle = (provider != NULL) ? provider->getPatchHandle() :
+ AUDIO_PATCH_HANDLE_NONE;
+ mClientInterface->onRecordingConfigurationUpdate(RECORD_CONFIG_EVENT_START,
+ mSession, mInputSource,
+ &mConfig, &deviceConfig, patchHandle);
+ }
}
status_t AudioSession::dump(int fd, int spaces, int index) const
@@ -145,7 +164,8 @@
}
status_t AudioSessionCollection::addSession(audio_session_t session,
- const sp<AudioSession>& audioSession)
+ const sp<AudioSession>& audioSession,
+ AudioSessionInfoProvider *provider)
{
ssize_t index = indexOfKey(session);
@@ -153,6 +173,7 @@
ALOGW("addSession() session %d already in", session);
return ALREADY_EXISTS;
}
+ audioSession->setInfoProvider(provider);
add(session, audioSession);
ALOGV("addSession() session %d client %d source %d",
session, audioSession->uid(), audioSession->inputSource());
@@ -168,6 +189,7 @@
return ALREADY_EXISTS;
}
ALOGV("removeSession() session %d", session);
+ valueAt(index)->setInfoProvider(NULL);
removeItemsAt(index);
return NO_ERROR;
}
@@ -214,6 +236,13 @@
return false;
}
+void AudioSessionCollection::onSessionInfoUpdate() const
+{
+ for (size_t i = 0; i < size(); i++) {
+ valueAt(i)->onSessionInfoUpdate();
+ }
+}
+
status_t AudioSessionCollection::dump(int fd, int spaces) const
{
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index f613f94..c6ed53e 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -50,6 +50,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_FM),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_AUX_LINE),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_IP),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_OUT_BUS),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_AMBIENT),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUILTIN_MIC),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET),
@@ -72,6 +73,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BLUETOOTH_A2DP),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_LOOPBACK),
MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_IP),
+ MAKE_STRING_FROM_ENUM(AUDIO_DEVICE_IN_BUS),
};
template<>
diff --git a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
index c65de92..8221496 100755
--- a/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
+++ b/services/audiopolicy/engineconfigurable/parameter-framework/plugin/Android.mk
@@ -1,5 +1,7 @@
LOCAL_PATH := $(call my-dir)
+ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
+
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
@@ -33,3 +35,4 @@
include $(BUILD_SHARED_LIBRARY)
+endif # ifneq ($(USE_CUSTOM_PARAMETER_FRAMEWORK), true)
diff --git a/services/audiopolicy/enginedefault/src/Engine.cpp b/services/audiopolicy/enginedefault/src/Engine.cpp
index 37f79fe..43664e6 100755
--- a/services/audiopolicy/enginedefault/src/Engine.cpp
+++ b/services/audiopolicy/enginedefault/src/Engine.cpp
@@ -141,13 +141,22 @@
case AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO:
if (config != AUDIO_POLICY_FORCE_NONE &&
config != AUDIO_POLICY_FORCE_HDMI_SYSTEM_AUDIO_ENFORCED) {
- ALOGW("setForceUse() invalid config %d forHDMI_SYSTEM_AUDIO", config);
+ ALOGW("setForceUse() invalid config %d for HDMI_SYSTEM_AUDIO", config);
+ }
+ mForceUse[usage] = config;
+ break;
+ case AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND:
+ if (config != AUDIO_POLICY_FORCE_NONE &&
+ config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER &&
+ config != AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS) {
+ ALOGW("setForceUse() invalid config %d for ENCODED_SURROUND", config);
+ return BAD_VALUE;
}
mForceUse[usage] = config;
break;
default:
ALOGW("setForceUse() invalid usage %d", usage);
- break;
+ break; // TODO return BAD_VALUE?
}
return NO_ERROR;
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 758673b..584aadf 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#define LOG_TAG "APM::AudioPolicyManager"
+#define LOG_TAG "AudioPolicyManager"
//#define LOG_NDEBUG 0
//#define VERY_VERBOSE_LOGGING
@@ -567,6 +567,7 @@
{
ALOGV("setForceUse() usage %d, config %d, mPhoneState %d", usage, config, mEngine->getPhoneState());
+ audio_policy_forced_cfg_t originalConfig = mEngine->getForceUse(usage);
if (mEngine->setForceUse(usage, config) != NO_ERROR) {
ALOGW("setForceUse() could not set force cfg %d for usage %d", config, usage);
return;
@@ -579,6 +580,33 @@
checkA2dpSuspend();
checkOutputForAllStrategies();
updateDevicesAndOutputs();
+
+ // Did surround forced use change?
+ if ((usage == AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND)
+ && (originalConfig != config)) {
+ const char *device_address = "";
+ // Is it currently connected? If so then cycle the connection
+ // so that the supported surround formats will be reloaded.
+ //
+ // FIXME As S/PDIF is not a removable device we have to handle this differently.
+ // Probably by updating the device descriptor directly and manually
+ // tearing down active playback on S/PDIF
+ if (getDeviceConnectionState(AUDIO_DEVICE_OUT_HDMI, device_address) ==
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
+ // Disconnect and reconnect output devices so that the surround
+ // encodings can be updated.
+ const char *device_name = "";
+ // disconnect
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
+ AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE,
+ device_address, device_name);
+ // reconnect
+ setDeviceConnectionStateInt(AUDIO_DEVICE_OUT_HDMI,
+ AUDIO_POLICY_DEVICE_STATE_AVAILABLE,
+ device_address, device_name);
+ }
+ }
+
if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
audio_devices_t newDevice = getNewOutputDevice(mPrimaryOutput, true /*fromCache*/);
updateCallRouting(newDevice);
@@ -1765,7 +1793,7 @@
for(size_t input_index = 0; input_index < mInputs.size(); input_index++) {
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
- ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (patch_index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -2115,6 +2143,9 @@
snprintf(buffer, SIZE, " Force use for hdmi system audio %d\n",
mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_HDMI_SYSTEM_AUDIO));
result.append(buffer);
+ snprintf(buffer, SIZE, " Force use for encoded surround output %d\n",
+ mEngine->getForceUse(AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND));
+ result.append(buffer);
snprintf(buffer, SIZE, " TTS output %s\n", mTtsOutputAvailable ? "available" : "not available");
result.append(buffer);
snprintf(buffer, SIZE, " Master mono: %s\n", mMasterMono ? "on" : "off");
@@ -2784,8 +2815,8 @@
audio_io_handle_t *ioHandle,
audio_devices_t *device)
{
- *session = (audio_session_t)mpClientInterface->newAudioUniqueId();
- *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId();
+ *session = (audio_session_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_SESSION);
+ *ioHandle = (audio_io_handle_t)mpClientInterface->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_INPUT);
*device = getDeviceAndMixForInputSource(AUDIO_SOURCE_HOTWORD);
return mSoundTriggerSessions.acquireSession(*session, *ioHandle);
@@ -3939,7 +3970,7 @@
nextAudioPortGeneration();
- ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -3968,7 +3999,7 @@
nextAudioPortGeneration();
- ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
@@ -4153,12 +4184,12 @@
{
audio_devices_t device = AUDIO_DEVICE_NONE;
- ssize_t index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
ALOGV("getNewOutputDevice() device %08x forced by patch %d",
- outputDesc->device(), outputDesc->mPatchHandle);
+ outputDesc->device(), outputDesc->getPatchHandle());
return outputDesc->device();
}
}
@@ -4214,12 +4245,12 @@
{
sp<AudioInputDescriptor> inputDesc = mInputs.valueFor(input);
- ssize_t index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ ssize_t index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
if (index >= 0) {
sp<AudioPatch> patchDesc = mAudioPatches.valueAt(index);
if (patchDesc->mUid != mUidCached) {
ALOGV("getNewInputDevice() device %08x forced by patch %d",
- inputDesc->mDevice, inputDesc->mPatchHandle);
+ inputDesc->mDevice, inputDesc->getPatchHandle());
return inputDesc->mDevice;
}
}
@@ -4513,7 +4544,7 @@
// Doing this check here allows the caller to call setOutputDevice() without conditions
if ((device == AUDIO_DEVICE_NONE || device == prevDevice) &&
!force &&
- outputDesc->mPatchHandle != 0) {
+ outputDesc->getPatchHandle() != 0) {
ALOGV("setOutputDevice() setting same device 0x%04x or null device", device);
return muteWaitMs;
}
@@ -4540,7 +4571,7 @@
if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
}
sp< AudioPatch> patchDesc;
audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4566,7 +4597,7 @@
if (patchHandle) {
*patchHandle = patchDesc->mHandle;
}
- outputDesc->mPatchHandle = patchDesc->mHandle;
+ outputDesc->setPatchHandle(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
}
@@ -4601,7 +4632,7 @@
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(outputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(outputDesc->getPatchHandle());
}
if (index < 0) {
return INVALID_OPERATION;
@@ -4609,7 +4640,7 @@
sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, delayMs);
ALOGV("resetOutputDevice() releaseAudioPatch returned %d", status);
- outputDesc->mPatchHandle = 0;
+ outputDesc->setPatchHandle(0);
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
@@ -4645,7 +4676,7 @@
if (patchHandle && *patchHandle != AUDIO_PATCH_HANDLE_NONE) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
}
sp< AudioPatch> patchDesc;
audio_patch_handle_t afPatchHandle = AUDIO_PATCH_HANDLE_NONE;
@@ -4670,7 +4701,7 @@
if (patchHandle) {
*patchHandle = patchDesc->mHandle;
}
- inputDesc->mPatchHandle = patchDesc->mHandle;
+ inputDesc->setPatchHandle(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
}
@@ -4687,7 +4718,7 @@
if (patchHandle) {
index = mAudioPatches.indexOfKey(*patchHandle);
} else {
- index = mAudioPatches.indexOfKey(inputDesc->mPatchHandle);
+ index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
}
if (index < 0) {
return INVALID_OPERATION;
@@ -4695,7 +4726,7 @@
sp< AudioPatch> patchDesc = mAudioPatches.valueAt(index);
status_t status = mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
ALOGV("resetInputDevice() releaseAudioPatch returned %d", status);
- inputDesc->mPatchHandle = 0;
+ inputDesc->setPatchHandle(0);
removeAudioPatch(patchDesc->mHandle);
nextAudioPortGeneration();
mpClientInterface->onAudioPatchListUpdate();
@@ -5144,6 +5175,84 @@
}
}
+// Modify the list of surround sound formats supported.
+void AudioPolicyManager::filterSurroundFormats(FormatVector &formats) {
+
+ audio_policy_forced_cfg_t forceUse = mEngine->getForceUse(
+ AUDIO_POLICY_FORCE_FOR_ENCODED_SURROUND);
+ ALOGI("%s: forced use = %d", __FUNCTION__, forceUse);
+
+ // Analyze original support for various formats.
+ bool supportsRawSurround = false;
+ bool supportsIEC61937 = false;
+ for (size_t formatIndex = 0; formatIndex < formats.size(); formatIndex++) {
+ audio_format_t format = formats[formatIndex];
+ ALOGI("%s: original formats: #%x", __FUNCTION__, format);
+ switch (format) {
+ case AUDIO_FORMAT_AC3:
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_HD:
+ supportsRawSurround = true;
+ break;
+ case AUDIO_FORMAT_IEC61937:
+ supportsIEC61937 = true;
+ break;
+ default:
+ break;
+ }
+ }
+ ALOGI("%s: supportsRawSurround = %d, supportsIEC61937 = %d",
+ __FUNCTION__, supportsRawSurround, supportsIEC61937);
+
+ // Modify formats based on surround preferences.
+ // If NEVER, remove support for surround formats.
+ if ((forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_NEVER)
+ && (supportsRawSurround || supportsIEC61937)) {
+ // Remove surround sound related formats.
+ for (size_t formatIndex = 0; formatIndex < formats.size(); ) {
+ audio_format_t format = formats[formatIndex];
+ switch(format) {
+ case AUDIO_FORMAT_AC3:
+ case AUDIO_FORMAT_E_AC3:
+ case AUDIO_FORMAT_DTS:
+ case AUDIO_FORMAT_DTS_HD:
+ case AUDIO_FORMAT_IEC61937:
+ ALOGI("%s: remove #%x", __FUNCTION__, format);
+ formats.removeAt(formatIndex);
+ break;
+ default:
+ formatIndex++; // keep it
+ break;
+ }
+ }
+ supportsRawSurround = false;
+ supportsIEC61937 = false;
+ }
+ // If ALWAYS, add support for raw surround formats if all are missing.
+ // This assumes that if any of these formats are reported by the HAL
+ // then the report is valid and should not be modified.
+ if ((forceUse == AUDIO_POLICY_FORCE_ENCODED_SURROUND_ALWAYS)
+ && !supportsRawSurround) {
+ formats.add(AUDIO_FORMAT_AC3);
+ formats.add(AUDIO_FORMAT_E_AC3);
+ formats.add(AUDIO_FORMAT_DTS);
+ formats.add(AUDIO_FORMAT_DTS_HD);
+ supportsRawSurround = true;
+ }
+ // Add support for IEC61937 if raw surround supported.
+ // The HAL could do this but add it here, just in case.
+ if (supportsRawSurround && !supportsIEC61937) {
+ formats.add(AUDIO_FORMAT_IEC61937);
+ // supportsIEC61937 = true;
+ }
+ // Just for debugging.
+ for (size_t formatIndex = 0; formatIndex < formats.size(); formatIndex++) {
+ audio_format_t format = formats[formatIndex];
+ ALOGI("%s: final formats: #%x", __FUNCTION__, format);
+ }
+}
+
void AudioPolicyManager::updateAudioProfiles(audio_io_handle_t ioHandle,
AudioProfileVector &profiles)
{
@@ -5153,14 +5262,16 @@
if (profiles.hasDynamicFormat()) {
reply = mpClientInterface->getParameters(ioHandle,
String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS));
- ALOGV("%s: supported formats %s", __FUNCTION__, reply.string());
+ ALOGI("%s: supported formats %s", __FUNCTION__, reply.string());
AudioParameter repliedParameters(reply);
if (repliedParameters.get(
String8(AUDIO_PARAMETER_STREAM_SUP_FORMATS), reply) != NO_ERROR) {
ALOGE("%s: failed to retrieve format, bailing out", __FUNCTION__);
return;
}
- profiles.setFormats(formatsFromString(reply.string()));
+ FormatVector formats = formatsFromString(reply.string());
+ filterSurroundFormats(formats);
+ profiles.setFormats(formats);
}
const FormatVector &supportedFormats = profiles.getSupportedFormats();
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index fb9b46b..38700fc 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -582,6 +582,9 @@
// Audio Policy Engine Interface.
AudioPolicyManagerInterface *mEngine;
private:
+ // Add or remove AC3 DTS encodings based on user preferences.
+ void filterSurroundFormats(FormatVector &formats);
+
// If any, resolve any "dynamic" fields of an Audio Profiles collection
void updateAudioProfiles(audio_io_handle_t ioHandle, AudioProfileVector &profiles);
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index ce6b2dc..f1c0d1a 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -221,15 +221,16 @@
void AudioPolicyService::AudioPolicyClient::onRecordingConfigurationUpdate(
int event, audio_session_t session, audio_source_t source,
- const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
mAudioPolicyService->onRecordingConfigurationUpdate(event, session, source,
- clientConfig, deviceConfig);
+ clientConfig, deviceConfig, patchHandle);
}
-audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId()
+audio_unique_id_t AudioPolicyService::AudioPolicyClient::newAudioUniqueId(audio_unique_id_use_t use)
{
- return AudioSystem::newAudioUniqueId();
+ return AudioSystem::newAudioUniqueId(use);
}
}; // namespace android
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 45f260a..94e0701 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -240,20 +240,20 @@
void AudioPolicyService::onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig)
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
{
mOutputCommandThread->recordingConfigurationUpdateCommand(event, session, source,
- clientConfig, deviceConfig);
+ clientConfig, deviceConfig, patchHandle);
}
void AudioPolicyService::doOnRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig)
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle)
{
Mutex::Autolock _l(mNotificationClientsLock);
for (size_t i = 0; i < mNotificationClients.size(); i++) {
mNotificationClients.valueAt(i)->onRecordingConfigurationUpdate(event, session, source,
- clientConfig, deviceConfig);
+ clientConfig, deviceConfig, patchHandle);
}
}
@@ -321,11 +321,12 @@
void AudioPolicyService::NotificationClient::onRecordingConfigurationUpdate(
int event, audio_session_t session, audio_source_t source,
- const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
if (mAudioPolicyServiceClient != 0) {
mAudioPolicyServiceClient->onRecordingConfigurationUpdate(event, session, source,
- clientConfig, deviceConfig);
+ clientConfig, deviceConfig, patchHandle);
}
}
@@ -607,7 +608,8 @@
}
mLock.unlock();
svc->doOnRecordingConfigurationUpdate(data->mEvent, data->mSession,
- data->mSource, &data->mClientConfig, &data->mDeviceConfig);
+ data->mSource, &data->mClientConfig, &data->mDeviceConfig,
+ data->mPatchHandle);
mLock.lock();
} break;
default:
@@ -872,7 +874,8 @@
void AudioPolicyService::AudioCommandThread::recordingConfigurationUpdateCommand(
int event, audio_session_t session, audio_source_t source,
- const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig)
+ const audio_config_base_t *clientConfig, const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle)
{
sp<AudioCommand>command = new AudioCommand();
command->mCommand = RECORDING_CONFIGURATION_UPDATE;
@@ -882,6 +885,7 @@
data->mSource = source;
data->mClientConfig = *clientConfig;
data->mDeviceConfig = *deviceConfig;
+ data->mPatchHandle = patchHandle;
command->mParam = data;
ALOGV("AudioCommandThread() adding recording configuration update event %d, source %d",
event, source);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 7089014..cecd617 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -230,10 +230,10 @@
void doOnDynamicPolicyMixStateUpdate(String8 regId, int32_t state);
void onRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
void doOnRecordingConfigurationUpdate(int event, audio_session_t session,
audio_source_t source, const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
private:
AudioPolicyService() ANDROID_API;
@@ -309,7 +309,8 @@
int event, audio_session_t session,
audio_source_t source,
const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
@@ -407,6 +408,7 @@
audio_source_t mSource;
struct audio_config_base mClientConfig;
struct audio_config_base mDeviceConfig;
+ audio_patch_handle_t mPatchHandle;
};
Mutex mLock;
@@ -518,9 +520,9 @@
virtual void onRecordingConfigurationUpdate(int event,
audio_session_t session, audio_source_t source,
const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig, audio_patch_handle_t patchHandle);
- virtual audio_unique_id_t newAudioUniqueId();
+ virtual audio_unique_id_t newAudioUniqueId(audio_unique_id_use_t use);
private:
AudioPolicyService *mAudioPolicyService;
@@ -541,7 +543,8 @@
int event, audio_session_t session,
audio_source_t source,
const audio_config_base_t *clientConfig,
- const audio_config_base_t *deviceConfig);
+ const audio_config_base_t *deviceConfig,
+ audio_patch_handle_t patchHandle);
void setAudioPortCallbacksEnabled(bool enabled);
// IBinder::DeathRecipient
diff --git a/services/mediadrm/mediadrmserver.rc b/services/mediadrm/mediadrmserver.rc
index c22ec7c..374d24b 100644
--- a/services/mediadrm/mediadrmserver.rc
+++ b/services/mediadrm/mediadrmserver.rc
@@ -1,5 +1,5 @@
service mediadrm /system/bin/mediadrmserver
class main
- user mediadrm
- group drmrpc
+ user media
+ group mediadrm drmrpc
ioprio rt 4
diff --git a/services/mediaextractor/MediaExtractorService.cpp b/services/mediaextractor/MediaExtractorService.cpp
index cd20635..a2b35f6 100644
--- a/services/mediaextractor/MediaExtractorService.cpp
+++ b/services/mediaextractor/MediaExtractorService.cpp
@@ -18,12 +18,35 @@
//#define LOG_NDEBUG 0
#include <utils/Log.h>
+#include <utils/Vector.h>
+
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaExtractor.h>
#include "MediaExtractorService.h"
namespace android {
+typedef struct {
+ String8 mime;
+ String8 name;
+ pid_t owner;
+ wp<MediaExtractor> extractor;
+ String8 toString() {
+ String8 str = name;
+ str.append(" for mime ");
+ str.append(mime);
+ str.append(String8::format(", pid %d: ", owner));
+ if (extractor.promote() == NULL) {
+ str.append("deleted");
+ } else {
+ str.append("active");
+ }
+ return str;
+ }
+} ExtractorInstance;
+
+static Vector<ExtractorInstance> extractors;
+
sp<IMediaExtractor> MediaExtractorService::makeExtractor(
const sp<IDataSource> &remoteSource, const char *mime) {
ALOGV("@@@ MediaExtractorService::makeExtractor for %s", mime);
@@ -36,9 +59,35 @@
ret.get(),
ret == NULL ? "" : ret->name());
+ if (ret != NULL) {
+ ExtractorInstance ex;
+ ex.mime = mime == NULL ? "NULL" : mime;
+ ex.name = ret->name();
+ ex.owner = IPCThreadState::self()->getCallingPid();
+ ex.extractor = ret;
+
+ if (extractors.size() > 10) {
+ extractors.resize(10);
+ }
+ extractors.push_front(ex);
+ }
+
return ret;
}
+status_t MediaExtractorService::dump(int fd, const Vector<String16>& args) {
+ String8 out;
+ out.append("Recent extractors, most recent first:\n");
+ for (size_t i = 0; i < extractors.size(); i++) {
+ ExtractorInstance ex = extractors.itemAt(i);
+ out.append(" ");
+ out.append(ex.toString());
+ out.append("\n");
+ }
+ write(fd, out.string(), out.size());
+ return OK;
+}
+
status_t MediaExtractorService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags)
diff --git a/services/mediaextractor/MediaExtractorService.h b/services/mediaextractor/MediaExtractorService.h
index 9c75042..078af0c 100644
--- a/services/mediaextractor/MediaExtractorService.h
+++ b/services/mediaextractor/MediaExtractorService.h
@@ -34,6 +34,7 @@
static const char* getServiceName() { return "media.extractor"; }
virtual sp<IMediaExtractor> makeExtractor(const sp<IDataSource> &source, const char *mime);
+ virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags);