Merge "Remove start() parameter from extractors"
diff --git a/media/libaaudio/examples/utils/AAudioArgsParser.h b/media/libaaudio/examples/utils/AAudioArgsParser.h
index 0e61589..ece9e6a 100644
--- a/media/libaaudio/examples/utils/AAudioArgsParser.h
+++ b/media/libaaudio/examples/utils/AAudioArgsParser.h
@@ -185,18 +185,26 @@
mNumberOfBursts = numBursts;
}
+ int32_t getFramesPerCallback() const {
+ return mFramesPerCallback;
+ }
+ void setFramesPerCallback(int32_t size) {
+ mFramesPerCallback = size;
+ }
+
/**
* Apply these parameters to a stream builder.
* @param builder
*/
void applyParameters(AAudioStreamBuilder *builder) const {
- AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
- AAudioStreamBuilder_setFormat(builder, mFormat);
- AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
AAudioStreamBuilder_setBufferCapacityInFrames(builder, mBufferCapacity);
+ AAudioStreamBuilder_setChannelCount(builder, mChannelCount);
AAudioStreamBuilder_setDeviceId(builder, mDeviceId);
- AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
+ AAudioStreamBuilder_setFormat(builder, mFormat);
+ AAudioStreamBuilder_setFramesPerDataCallback(builder, mFramesPerCallback);
AAudioStreamBuilder_setPerformanceMode(builder, mPerformanceMode);
+ AAudioStreamBuilder_setSampleRate(builder, mSampleRate);
+ AAudioStreamBuilder_setSharingMode(builder, mSharingMode);
// Call P functions if supported.
loadFutureFunctions();
@@ -232,6 +240,7 @@
aaudio_input_preset_t mInputPreset = AAUDIO_UNSPECIFIED;
int32_t mNumberOfBursts = AAUDIO_UNSPECIFIED;
+ int32_t mFramesPerCallback = AAUDIO_UNSPECIFIED;
};
class AAudioArgsParser : public AAudioParameters {
@@ -297,6 +306,9 @@
case 'y':
setContentType(atoi(&arg[2]));
break;
+ case 'z':
+ setFramesPerCallback(atoi(&arg[2]));
+ break;
default:
unrecognized = true;
break;
@@ -350,6 +362,7 @@
printf(" -u{usage} eg. 14 for AAUDIO_USAGE_GAME\n");
printf(" -x to use EXCLUSIVE mode\n");
printf(" -y{contentType} eg. 1 for AAUDIO_CONTENT_TYPE_SPEECH\n");
+ printf(" -z{callbackSize} or block size, in frames, default = 0\n");
}
static aaudio_performance_mode_t parsePerformanceMode(char c) {
@@ -406,6 +419,9 @@
printf(" Capacity: requested = %d, actual = %d\n", getBufferCapacity(),
AAudioStream_getBufferCapacityInFrames(stream));
+ printf(" CallbackSize: requested = %d, actual = %d\n", getFramesPerCallback(),
+ AAudioStream_getFramesPerDataCallback(stream));
+
printf(" SharingMode: requested = %s, actual = %s\n",
getSharingModeText(getSharingMode()),
getSharingModeText(AAudioStream_getSharingMode(stream)));
diff --git a/media/libaaudio/src/legacy/AudioStreamRecord.cpp b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
index dbf00a9..40e22ac 100644
--- a/media/libaaudio/src/legacy/AudioStreamRecord.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamRecord.cpp
@@ -57,6 +57,9 @@
// Try to create an AudioRecord
+ const aaudio_session_id_t requestedSessionId = builder.getSessionId();
+ const audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
+
// TODO Support UNSPECIFIED in AudioRecord. For now, use stereo if unspecified.
int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
? 2 : getSamplesPerFrame();
@@ -66,17 +69,21 @@
: builder.getBufferCapacity();
- audio_input_flags_t flags = AUDIO_INPUT_FLAG_NONE;
+ audio_input_flags_t flags;
aaudio_performance_mode_t perfMode = getPerformanceMode();
switch (perfMode) {
case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
- flags = (audio_input_flags_t) (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW);
+ // If the app asks for a sessionId then it means they want to use effects.
+ // So don't use RAW flag.
+ flags = (audio_input_flags_t) ((requestedSessionId == AAUDIO_SESSION_ID_NONE)
+ ? (AUDIO_INPUT_FLAG_FAST | AUDIO_INPUT_FLAG_RAW)
+ : (AUDIO_INPUT_FLAG_FAST));
break;
case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
case AAUDIO_PERFORMANCE_MODE_NONE:
default:
- // No flags.
+ flags = AUDIO_INPUT_FLAG_NONE;
break;
}
@@ -141,9 +148,6 @@
.tags = ""
};
- aaudio_session_id_t requestedSessionId = builder.getSessionId();
- audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
-
// ----------- open the AudioRecord ---------------------
// Might retry, but never more than once.
for (int i = 0; i < 2; i ++) {
diff --git a/media/libaaudio/src/legacy/AudioStreamTrack.cpp b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
index 1572f0d..1ac2558 100644
--- a/media/libaaudio/src/legacy/AudioStreamTrack.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamTrack.cpp
@@ -59,18 +59,25 @@
return result;
}
+ const aaudio_session_id_t requestedSessionId = builder.getSessionId();
+ const audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
+
// Try to create an AudioTrack
// Use stereo if unspecified.
int32_t samplesPerFrame = (getSamplesPerFrame() == AAUDIO_UNSPECIFIED)
? 2 : getSamplesPerFrame();
audio_channel_mask_t channelMask = audio_channel_out_mask_from_count(samplesPerFrame);
- audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE;
+ audio_output_flags_t flags;
aaudio_performance_mode_t perfMode = getPerformanceMode();
switch(perfMode) {
case AAUDIO_PERFORMANCE_MODE_LOW_LATENCY:
// Bypass the normal mixer and go straight to the FAST mixer.
- flags = (audio_output_flags_t)(AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW);
+ // If the app asks for a sessionId then it means they want to use effects.
+ // So don't use RAW flag.
+ flags = (audio_output_flags_t) ((requestedSessionId == AAUDIO_SESSION_ID_NONE)
+ ? (AUDIO_OUTPUT_FLAG_FAST | AUDIO_OUTPUT_FLAG_RAW)
+ : (AUDIO_OUTPUT_FLAG_FAST));
break;
case AAUDIO_PERFORMANCE_MODE_POWER_SAVING:
@@ -81,6 +88,7 @@
case AAUDIO_PERFORMANCE_MODE_NONE:
default:
// No flags. Use a normal mixer in front of the FAST mixer.
+ flags = AUDIO_OUTPUT_FLAG_NONE;
break;
}
@@ -135,11 +143,6 @@
.tags = ""
};
- static_assert(AAUDIO_UNSPECIFIED == AUDIO_SESSION_ALLOCATE, "Session IDs should match");
-
- aaudio_session_id_t requestedSessionId = builder.getSessionId();
- audio_session_t sessionId = AAudioConvert_aaudioToAndroidSessionId(requestedSessionId);
-
mAudioTrack = new AudioTrack();
mAudioTrack->set(
AUDIO_STREAM_DEFAULT, // ignored because we pass attributes below
diff --git a/media/libmediaextractor/include/media/DataSourceBase.h b/media/libmediaextractor/include/media/DataSourceBase.h
index 8ce6592..af5b83d 100644
--- a/media/libmediaextractor/include/media/DataSourceBase.h
+++ b/media/libmediaextractor/include/media/DataSourceBase.h
@@ -66,7 +66,7 @@
virtual void close() {};
- virtual ssize_t getAvailableSize(status_t * /*err*/) {
+ virtual status_t getAvailableSize(off64_t /*offset*/, off64_t * /*size*/) {
return -1;
}
diff --git a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
index eba78ed..9dd5e4c 100644
--- a/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
+++ b/media/libmediaplayer2/MediaPlayer2AudioOutput.cpp
@@ -299,14 +299,14 @@
status_t MediaPlayer2AudioOutput::open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
- audio_format_t format, int bufferCount,
+ audio_format_t format,
AudioCallback cb, void *cookie,
audio_output_flags_t flags,
const audio_offload_info_t *offloadInfo,
bool doNotReconnect,
uint32_t suggestedFrameCount) {
- ALOGV("open(%u, %d, 0x%x, 0x%x, %d, %d 0x%x)", sampleRate, channelCount, channelMask,
- format, bufferCount, mSessionId, flags);
+ ALOGV("open(%u, %d, 0x%x, 0x%x, %d 0x%x)", sampleRate, channelCount, channelMask,
+ format, mSessionId, flags);
// offloading is only supported in callback mode for now.
// offloadInfo must be present if offload flag is set
@@ -316,36 +316,8 @@
}
// compute frame count for the AudioTrack internal buffer
- size_t frameCount;
- if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) {
- frameCount = 0; // AudioTrack will get frame count from AudioFlinger
- } else {
- // try to estimate the buffer processing fetch size from AudioFlinger.
- // framesPerBuffer is approximate and generally correct, except when it's not :-).
- uint32_t afSampleRate;
- size_t afFrameCount;
- if (AudioSystem::getOutputFrameCount(&afFrameCount, mStreamType) != NO_ERROR) {
- return NO_INIT;
- }
- if (AudioSystem::getOutputSamplingRate(&afSampleRate, mStreamType) != NO_ERROR) {
- return NO_INIT;
- }
- const size_t framesPerBuffer =
- (unsigned long long)sampleRate * afFrameCount / afSampleRate;
-
- if (bufferCount == 0) {
- // use suggestedFrameCount
- bufferCount = (suggestedFrameCount + framesPerBuffer - 1) / framesPerBuffer;
- }
- // Check argument bufferCount against the mininum buffer count
- if (bufferCount != 0 && bufferCount < mMinBufferCount) {
- ALOGV("bufferCount (%d) increased to %d", bufferCount, mMinBufferCount);
- bufferCount = mMinBufferCount;
- }
- // if frameCount is 0, then AudioTrack will get frame count from AudioFlinger
- // which will be the minimum size permitted.
- frameCount = bufferCount * framesPerBuffer;
- }
+ const size_t frameCount =
+ ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) ? 0 : suggestedFrameCount;
if (channelMask == CHANNEL_MASK_USE_CHANNEL_ORDER) {
channelMask = audio_channel_out_mask_from_count(channelCount);
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
index 5d5b8e4..ee67abf 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2AudioOutput.h
@@ -58,7 +58,7 @@
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
- audio_format_t format, int bufferCount,
+ audio_format_t format,
AudioCallback cb, void *cookie,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
const audio_offload_info_t *offloadInfo = NULL,
diff --git a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
index 55d812b..846441e 100644
--- a/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
+++ b/media/libmediaplayer2/include/mediaplayer2/MediaPlayer2Interface.h
@@ -47,7 +47,6 @@
class Parcel;
struct ANativeWindowWrapper;
-#define DEFAULT_AUDIOSINK_BUFFERCOUNT 4
#define DEFAULT_AUDIOSINK_BUFFERSIZE 1200
#define DEFAULT_AUDIOSINK_SAMPLERATE 44100
@@ -103,7 +102,6 @@
virtual status_t open(
uint32_t sampleRate, int channelCount, audio_channel_mask_t channelMask,
audio_format_t format=AUDIO_FORMAT_PCM_16_BIT,
- int bufferCount=DEFAULT_AUDIOSINK_BUFFERCOUNT,
AudioCallback cb = NULL,
void *cookie = NULL,
audio_output_flags_t flags = AUDIO_OUTPUT_FLAG_NONE,
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp
index 57d1147..f41a431 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Drm.cpp
@@ -147,9 +147,10 @@
}
uint32_t psshSize = pssh.tellp();
- const uint8_t* psshPtr = reinterpret_cast<const uint8_t*>(pssh.str().c_str());
- const char *psshHex = DrmUUID::arrayToHex(psshPtr, psshSize).string();
- ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO PSSH: size: %u %s", psshSize, psshHex);
+ std::string psshBase = pssh.str();
+ const auto* psshPtr = reinterpret_cast<const uint8_t*>(psshBase.c_str());
+ ALOGV("retrieveDrmInfo: MEDIA_DRM_INFO PSSH: size: %u %s", psshSize,
+ DrmUUID::arrayToHex(psshPtr, psshSize).string());
// 1) Write PSSH bytes
playerMsg->add_values()->set_bytes_value(
diff --git a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
index c5ce15a..452b781 100644
--- a/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
+++ b/media/libmediaplayer2/nuplayer2/NuPlayer2Renderer.cpp
@@ -1918,7 +1918,6 @@
numChannels,
(audio_channel_mask_t)channelMask,
audioFormat,
- 0 /* bufferCount - unused */,
&NuPlayer2::Renderer::AudioSinkCallback,
this,
(audio_output_flags_t)offloadFlags,
@@ -2004,7 +2003,6 @@
numChannels,
(audio_channel_mask_t)channelMask,
AUDIO_FORMAT_PCM_16_BIT,
- 0 /* bufferCount - unused */,
mUseAudioCallback ? &NuPlayer2::Renderer::AudioSinkCallback : NULL,
mUseAudioCallback ? this : NULL,
(audio_output_flags_t)pcmFlags,
diff --git a/media/libstagefright/NuCachedSource2.cpp b/media/libstagefright/NuCachedSource2.cpp
index 81ca3e7..7025af7 100644
--- a/media/libstagefright/NuCachedSource2.cpp
+++ b/media/libstagefright/NuCachedSource2.cpp
@@ -571,12 +571,19 @@
return mCacheOffset + mCache->totalSize();
}
-size_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) const {
+status_t NuCachedSource2::getAvailableSize(off64_t offset, off64_t *size) {
Mutex::Autolock autoLock(mLock);
- return approxDataRemaining_l(finalStatus);
+ status_t finalStatus = UNKNOWN_ERROR;
+ *size = approxDataRemaining_l(offset, &finalStatus);
+ return finalStatus;
}
-size_t NuCachedSource2::approxDataRemaining_l(status_t *finalStatus) const {
+size_t NuCachedSource2::approxDataRemaining(status_t *finalStatus) const {
+ Mutex::Autolock autoLock(mLock);
+ return approxDataRemaining_l(mLastAccessPos, finalStatus);
+}
+
+size_t NuCachedSource2::approxDataRemaining_l(off64_t offset, status_t *finalStatus) const {
*finalStatus = mFinalStatus;
if (mFinalStatus != OK && mNumRetriesLeft > 0) {
@@ -584,9 +591,10 @@
*finalStatus = OK;
}
+ offset = offset >= 0 ? offset : mLastAccessPos;
off64_t lastBytePosCached = mCacheOffset + mCache->totalSize();
- if (mLastAccessPos < lastBytePosCached) {
- return lastBytePosCached - mLastAccessPos;
+ if (offset < lastBytePosCached) {
+ return lastBytePosCached - offset;
}
return 0;
}
diff --git a/media/libstagefright/NuMediaExtractor.cpp b/media/libstagefright/NuMediaExtractor.cpp
index 0a4dfce..f94648c 100644
--- a/media/libstagefright/NuMediaExtractor.cpp
+++ b/media/libstagefright/NuMediaExtractor.cpp
@@ -780,9 +780,8 @@
int64_t *durationUs, bool *eos) const {
Mutex::Autolock autoLock(mLock);
- status_t finalStatus;
- ssize_t cachedDataRemaining =
- mDataSource->getAvailableSize(&finalStatus);
+ off64_t cachedDataRemaining = -1;
+ status_t finalStatus = mDataSource->getAvailableSize(-1, &cachedDataRemaining);
int64_t bitrate;
if (cachedDataRemaining >= 0
diff --git a/media/libstagefright/include/NuCachedSource2.h b/media/libstagefright/include/NuCachedSource2.h
index 5591525..596efb8 100644
--- a/media/libstagefright/include/NuCachedSource2.h
+++ b/media/libstagefright/include/NuCachedSource2.h
@@ -53,9 +53,7 @@
return mName;
}
- ssize_t getAvailableSize(status_t *finalStatus) {
- return approxDataRemaining(finalStatus);
- }
+ status_t getAvailableSize(off64_t offset, off64_t *size);
////////////////////////////////////////////////////////////////////////////
@@ -141,7 +139,7 @@
ssize_t readInternal(off64_t offset, void *data, size_t size);
status_t seekInternal_l(off64_t offset);
- size_t approxDataRemaining_l(status_t *finalStatus) const;
+ size_t approxDataRemaining_l(off64_t offset, status_t *finalStatus) const;
void restartPrefetcherIfNecessary_l(
bool ignoreLowWaterThreshold = false, bool force = false);
diff --git a/media/mtp/OWNERS b/media/mtp/OWNERS
index 219307b..1928ba8 100644
--- a/media/mtp/OWNERS
+++ b/media/mtp/OWNERS
@@ -1 +1,7 @@
-zhangjerry@google.com
+set noparent
+
+marcone@google.com
+jsharkey@android.com
+jameswei@google.com
+rmojumder@google.com
+
diff --git a/media/ndk/Android.bp b/media/ndk/Android.bp
index 417f1df..05c8582 100644
--- a/media/ndk/Android.bp
+++ b/media/ndk/Android.bp
@@ -39,6 +39,7 @@
"NdkMediaCrypto.cpp",
"NdkMediaDataSource.cpp",
"NdkMediaExtractor.cpp",
+ "NdkMediaError.cpp",
"NdkMediaFormat.cpp",
"NdkMediaMuxer.cpp",
"NdkMediaDrm.cpp",
@@ -106,6 +107,7 @@
srcs: [
"NdkMediaDataSourceCallbacks.cpp",
+ "NdkMediaError.cpp",
],
include_dirs: [
diff --git a/media/ndk/NdkMediaDataSourceCallbacks.cpp b/media/ndk/NdkMediaDataSourceCallbacks.cpp
index 4338048..1efcaa0 100644
--- a/media/ndk/NdkMediaDataSourceCallbacks.cpp
+++ b/media/ndk/NdkMediaDataSourceCallbacks.cpp
@@ -17,6 +17,7 @@
//#define LOG_NDEBUG 0
#define LOG_TAG "NdkMediaDataSourceCallbacks"
+#include "NdkMediaErrorPriv.h"
#include "NdkMediaDataSourceCallbacksPriv.h"
#include <media/DataSource.h>
diff --git a/media/ndk/NdkMediaError.cpp b/media/ndk/NdkMediaError.cpp
new file mode 100644
index 0000000..2facd8c
--- /dev/null
+++ b/media/ndk/NdkMediaError.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#include <media/NdkMediaError.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/Errors.h>
+#include <utils/Log.h>
+
+using namespace android;
+
+media_status_t translate_error(status_t err) {
+
+ if (err == OK) {
+ return AMEDIA_OK;
+ } else if (err == ERROR_END_OF_STREAM) {
+ return AMEDIA_ERROR_END_OF_STREAM;
+ } else if (err == ERROR_IO) {
+ return AMEDIA_ERROR_IO;
+ }
+
+ ALOGE("sf error code: %d", err);
+ return AMEDIA_ERROR_UNKNOWN;
+}
+
+status_t reverse_translate_error(media_status_t err) {
+
+ if (err == AMEDIA_OK) {
+ return OK;
+ } else if (err == AMEDIA_ERROR_END_OF_STREAM) {
+ return ERROR_END_OF_STREAM;
+ } else if (err == AMEDIA_ERROR_IO) {
+ return ERROR_IO;
+ }
+
+ ALOGE("ndk error code: %d", err);
+ return UNKNOWN_ERROR;
+}
diff --git a/media/ndk/NdkMediaErrorPriv.h b/media/ndk/NdkMediaErrorPriv.h
new file mode 100644
index 0000000..f5e2f02
--- /dev/null
+++ b/media/ndk/NdkMediaErrorPriv.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 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 _NDK_MEDIA_ERROR_PRIV_H
+#define _NDK_MEDIA_ERROR_PRIV_H
+
+#include <media/NdkMediaError.h>
+#include <utils/Errors.h>
+
+using namespace android;
+
+media_status_t translate_error(status_t);
+
+status_t reverse_translate_error(media_status_t);
+
+#endif // _NDK_MEDIA_ERROR_PRIV_H
diff --git a/media/ndk/NdkMediaExtractor.cpp b/media/ndk/NdkMediaExtractor.cpp
index 60b15d4..a6adee4 100644
--- a/media/ndk/NdkMediaExtractor.cpp
+++ b/media/ndk/NdkMediaExtractor.cpp
@@ -21,6 +21,7 @@
#include <media/NdkMediaError.h>
#include <media/NdkMediaExtractor.h>
#include <media/NdkMediaFormatPriv.h>
+#include "NdkMediaErrorPriv.h"
#include "NdkMediaDataSourcePriv.h"
@@ -40,19 +41,6 @@
using namespace android;
-static media_status_t translate_error(status_t err) {
- if (err == OK) {
- return AMEDIA_OK;
- } else if (err == ERROR_END_OF_STREAM) {
- return AMEDIA_ERROR_END_OF_STREAM;
- } else if (err == ERROR_IO) {
- return AMEDIA_ERROR_IO;
- }
-
- ALOGE("sf error code: %d", err);
- return AMEDIA_ERROR_UNKNOWN;
-}
-
struct AMediaExtractor {
sp<NuMediaExtractor> mImpl;
sp<ABuffer> mPsshBuf;
@@ -82,12 +70,6 @@
return translate_error(mData->mImpl->setDataSource(fd, offset, length));
}
-EXPORT
-media_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
- return AMediaExtractor_setDataSourceWithHeaders(mData, location, 0, NULL, NULL);
-}
-
-EXPORT
media_status_t AMediaExtractor_setDataSourceWithHeaders(AMediaExtractor *mData,
const char *uri,
int numheaders,
@@ -115,6 +97,11 @@
}
EXPORT
+media_status_t AMediaExtractor_setDataSource(AMediaExtractor *mData, const char *location) {
+ return AMediaExtractor_setDataSourceWithHeaders(mData, location, 0, NULL, NULL);
+}
+
+EXPORT
media_status_t AMediaExtractor_setDataSourceCustom(AMediaExtractor* mData, AMediaDataSource *src) {
return translate_error(mData->mImpl->setDataSource(new NdkDataSource(src)));
}
diff --git a/media/ndk/NdkMediaMuxer.cpp b/media/ndk/NdkMediaMuxer.cpp
index b213fa9..ab709ac 100644
--- a/media/ndk/NdkMediaMuxer.cpp
+++ b/media/ndk/NdkMediaMuxer.cpp
@@ -21,6 +21,7 @@
#include <media/NdkMediaMuxer.h>
#include <media/NdkMediaCodec.h>
#include <media/NdkMediaFormatPriv.h>
+#include "NdkMediaErrorPriv.h"
#include <utils/Log.h>
@@ -36,14 +37,6 @@
using namespace android;
-static media_status_t translate_error(status_t err) {
- if (err == OK) {
- return AMEDIA_OK;
- }
- ALOGE("sf error code: %d", err);
- return AMEDIA_ERROR_UNKNOWN;
-}
-
struct AMediaMuxer {
sp<MediaMuxer> mImpl;
diff --git a/media/ndk/include/media/NdkMediaExtractor.h b/media/ndk/include/media/NdkMediaExtractor.h
index 413bc1a..e3d9fe6 100644
--- a/media/ndk/include/media/NdkMediaExtractor.h
+++ b/media/ndk/include/media/NdkMediaExtractor.h
@@ -73,27 +73,6 @@
media_status_t AMediaExtractor_setDataSource(AMediaExtractor*,
const char *location) __INTRODUCED_IN(21);
-#if __ANDROID_API__ >= 29
-/**
- * Set the |uri| from which the extractor will read,
- * plus additional http headers when initiating the request.
- *
- * Headers will contain corresponding items from |keys| & |values|
- * from indices 0 (inclusive) to numheaders-1 (inclusive):
- *
- * keys[0]:values[0]
- * ...
- * keys[numheaders - 1]:values[numheaders - 1]
- *
- */
-media_status_t AMediaExtractor_setDataSourceWithHeaders(AMediaExtractor*,
- const char *uri,
- int numheaders,
- const char * const *keys,
- const char * const *values) __INTRODUCED_IN(29);
-
-#endif /* __ANDROID_API__ >= 29 */
-
#if __ANDROID_API__ >= 28
/**
diff --git a/media/ndk/libmediandk.map.txt b/media/ndk/libmediandk.map.txt
index d13edfc..e933376 100644
--- a/media/ndk/libmediandk.map.txt
+++ b/media/ndk/libmediandk.map.txt
@@ -186,7 +186,6 @@
AMediaExtractor_setDataSource;
AMediaExtractor_setDataSourceCustom; # introduced=28
AMediaExtractor_setDataSourceFd;
- AMediaExtractor_setDataSourceWithHeaders; # introduced=29
AMediaExtractor_unselectTrack;
AMediaFormat_clear; # introduced=29
AMediaFormat_copy; # introduced=29
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index c577589..f23e426 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -73,6 +73,7 @@
LOCAL_C_INCLUDES += \
frameworks/av/services/audiopolicy/common/include \
frameworks/av/services/audiopolicy/engine/interface \
+ $(call include-path-for, audio-utils) \
LOCAL_STATIC_LIBRARIES := \
libaudiopolicycomponents
@@ -109,7 +110,8 @@
LOCAL_C_INCLUDES += \
frameworks/av/services/audiopolicy/common/include \
- frameworks/av/services/audiopolicy/engine/interface
+ frameworks/av/services/audiopolicy/engine/interface \
+ $(call include-path-for, audio-utils) \
LOCAL_CFLAGS := -Wall -Werror
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 72d5a8c..df3b41e 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -33,6 +33,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, public AudioIODescriptorInterface
+ , public ClientMapHandler<RecordClientDescriptor>
{
public:
explicit AudioInputDescriptor(const sp<IOProfile>& profile,
@@ -42,10 +43,10 @@
status_t dump(int fd);
- 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
- const sp<IOProfile> mProfile; // I/O profile this output derives from
+ audio_io_handle_t mIoHandle = AUDIO_IO_HANDLE_NONE; // input handle
+ audio_devices_t mDevice = AUDIO_DEVICE_NONE; // current device this input is routed to
+ AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
+ const sp<IOProfile> mProfile; // I/O profile this output derives from
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
@@ -82,7 +83,6 @@
void stop();
void close();
- RecordClientMap& clientsMap() { return mClients; }
RecordClientVector getClientsForSession(audio_session_t session);
RecordClientVector clientsList(bool activeOnly = false,
audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
@@ -91,8 +91,8 @@
void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
- audio_patch_handle_t mPatchHandle;
- audio_port_handle_t mId;
+ audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+ audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
// Because a preemptible capture session can preempt another one, we end up in an endless loop
// situation were each session is allowed to restart after being preempted,
// thus preempting the other one which restarts and so on.
@@ -100,10 +100,8 @@
// a particular input started and prevent preemption of this active input by this session.
// We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
SortedVector<audio_session_t> mPreemptedSessions;
- AudioPolicyClientInterface *mClientInterface;
- int32_t mGlobalActiveCount; // non-client-specific activity ref count
-
- RecordClientMap mClients;
+ AudioPolicyClientInterface * const mClientInterface;
+ int32_t mGlobalActiveCount = 0; // non-client-specific activity ref count
};
class AudioInputCollection :
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index 27b1c93..257209a 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -17,6 +17,7 @@
#pragma once
#include <sys/types.h>
+
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/KeyedVector.h>
@@ -36,6 +37,7 @@
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
+ , public ClientMapHandler<TrackClientDescriptor>
{
public:
AudioOutputDescriptor(const sp<AudioPort>& port,
@@ -59,9 +61,21 @@
audio_devices_t device,
uint32_t delayMs,
bool force);
- virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);
+
+ /**
+ * Changes the stream active count and mActiveClients only.
+ * This does not change the client->active() state or the output descriptor's
+ * global active count.
+ */
+ virtual void changeStreamActiveCount(const sp<TrackClientDescriptor>& client, int delta);
uint32_t streamActiveCount(audio_stream_type_t stream) const
{ return mActiveCount[stream]; }
+
+ /**
+ * Changes the client->active() state and the output descriptor's global active count,
+ * along with the stream active count and mActiveClients.
+ * The client must be previously added by the base class addClient().
+ */
void setClientActive(const sp<TrackClientDescriptor>& client, bool active);
bool isActive(uint32_t inPastMs = 0) const;
@@ -81,26 +95,51 @@
audio_patch_handle_t getPatchHandle() const override;
void setPatchHandle(audio_patch_handle_t handle) override;
- TrackClientMap& clientsMap() { return mClients; }
TrackClientVector clientsList(bool activeOnly = false,
routing_strategy strategy = STRATEGY_NONE, bool preferredDeviceOnly = false) const;
- sp<AudioPort> mPort;
- audio_devices_t mDevice; // current device this output is routed to
+ // override ClientMapHandler to abort when removing a client when active.
+ void removeClient(audio_port_handle_t portId) override {
+ auto client = getClient(portId);
+ LOG_ALWAYS_FATAL_IF(client.get() == nullptr,
+ "%s(%d): nonexistent client portId %d", __func__, mId, portId);
+ // it is possible that when a client is removed, we could remove its
+ // associated active count by calling changeStreamActiveCount(),
+ // but that would be hiding a problem, so we log fatal instead.
+ auto it2 = mActiveClients.find(client);
+ LOG_ALWAYS_FATAL_IF(it2 != mActiveClients.end(),
+ "%s(%d) removing client portId %d which is active (count %zu)",
+ __func__, mId, portId, it2->second);
+ ClientMapHandler<TrackClientDescriptor>::removeClient(portId);
+ }
+
+ using ActiveClientMap = std::map<sp<TrackClientDescriptor>, size_t /* count */>;
+ // required for duplicating thread
+ const ActiveClientMap& getActiveClients() const {
+ return mActiveClients;
+ }
+
+ audio_devices_t mDevice = AUDIO_DEVICE_NONE; // current device this output is routed to
nsecs_t mStopTime[AUDIO_STREAM_CNT];
- float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
- int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
+ int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
// device selection. See checkDeviceMuteStrategies()
- AudioPolicyClientInterface *mClientInterface;
- AudioMix *mPolicyMix; // non NULL when used by a dynamic policy
+ AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
protected:
+ const sp<AudioPort> mPort;
+ AudioPolicyClientInterface * const mClientInterface;
+ float mCurVolume[AUDIO_STREAM_CNT]; // current stream volume in dB
uint32_t mActiveCount[AUDIO_STREAM_CNT]; // number of streams of each type active on this output
- uint32_t mGlobalActiveCount; // non-client-specific active count
- audio_patch_handle_t mPatchHandle;
- audio_port_handle_t mId;
- TrackClientMap mClients;
+ uint32_t mGlobalActiveCount = 0; // non-client-specific active count
+ audio_patch_handle_t mPatchHandle = AUDIO_PATCH_HANDLE_NONE;
+ audio_port_handle_t mId = AUDIO_PORT_HANDLE_NONE;
+
+ // The ActiveClientMap shows the clients that contribute to the streams counts
+ // and may include upstream clients from a duplicating thread.
+ // Compare with the ClientMap (mClients) which are external AudioTrack clients of the
+ // output descriptor (and do not count internal PatchTracks).
+ ActiveClientMap mActiveClients;
};
// Audio output driven by a software mixer in audio flinger.
@@ -121,7 +160,8 @@
virtual bool isFixedVolume(audio_devices_t device);
virtual sp<AudioOutputDescriptor> subOutput1() { return mOutput1; }
virtual sp<AudioOutputDescriptor> subOutput2() { return mOutput2; }
- virtual void changeStreamActiveCount(audio_stream_type_t stream, int delta);
+ void changeStreamActiveCount(
+ const sp<TrackClientDescriptor>& client, int delta) override;
virtual bool setVolume(float volume,
audio_stream_type_t stream,
audio_devices_t device,
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 1a3300d..8d7914b 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -47,6 +47,7 @@
status_t dump(int fd, int spaces, int index);
virtual status_t dump(String8& dst, int spaces, int index);
+ virtual std::string toShortString() const;
audio_port_handle_t portId() const { return mPortId; }
uid_t uid() const { return mUid; }
@@ -90,6 +91,7 @@
using ClientDescriptor::dump;
status_t dump(String8& dst, int spaces, int index) override;
+ std::string toShortString() const override;
audio_output_flags_t flags() const { return mFlags; }
audio_stream_type_t stream() const { return mStream; }
@@ -161,8 +163,87 @@
};
typedef std::vector< sp<TrackClientDescriptor> > TrackClientVector;
-typedef std::map< audio_port_handle_t, sp<TrackClientDescriptor> > TrackClientMap;
typedef std::vector< sp<RecordClientDescriptor> > RecordClientVector;
-typedef std::map< audio_port_handle_t, sp<RecordClientDescriptor> > RecordClientMap;
+
+// A Map that associates a portId with a client (type T)
+// which is either TrackClientDescriptor or RecordClientDescriptor.
+
+template<typename T>
+class ClientMapHandler {
+public:
+ virtual ~ClientMapHandler() = default;
+
+ // Track client management
+ void addClient(const sp<T> &client) {
+ const audio_port_handle_t portId = client->portId();
+ LOG_ALWAYS_FATAL_IF(!mClients.emplace(portId, client).second,
+ "%s(%d): attempting to add client that already exists", __func__, portId);
+ }
+ sp<T> getClient(audio_port_handle_t portId) const {
+ auto it = mClients.find(portId);
+ if (it == mClients.end()) return nullptr;
+ return it->second;
+ }
+ virtual void removeClient(audio_port_handle_t portId) {
+ LOG_ALWAYS_FATAL_IF(mClients.erase(portId) == 0,
+ "%s(%d): client does not exist", __func__, portId);
+ }
+ size_t getClientCount() const {
+ return mClients.size();
+ }
+ String8 dump() const {
+ String8 result;
+ size_t index = 0;
+ for (const auto& client: getClientIterable()) {
+ client->dump(result, 2, index++);
+ }
+ return result;
+ }
+
+ // helper types
+ using ClientMap = std::map<audio_port_handle_t, sp<T>>;
+ using ClientMapIterator = typename ClientMap::const_iterator; // ClientMap is const qualified
+ class ClientIterable {
+ public:
+ explicit ClientIterable(const ClientMapHandler<T> &ref) : mClientMapHandler(ref) { }
+
+ class iterator {
+ public:
+ // traits
+ using iterator_category = std::forward_iterator_tag;
+ using value_type = sp<T>;
+ using difference_type = ptrdiff_t;
+ using pointer = const sp<T>*; // Note: const
+ using reference = const sp<T>&; // Note: const
+
+ // implementation
+ explicit iterator(const ClientMapIterator &it) : mIt(it) { }
+ iterator& operator++() /* prefix */ { ++mIt; return *this; }
+ reference operator* () const { return mIt->second; }
+ reference operator->() const { return mIt->second; } // as if sp<>
+ difference_type operator-(const iterator& rhs) {return mIt - rhs.mIt; }
+ bool operator==(const iterator& rhs) const { return mIt == rhs.mIt; }
+ bool operator!=(const iterator& rhs) const { return mIt != rhs.mIt; }
+ private:
+ ClientMapIterator mIt;
+ };
+
+ iterator begin() const { return iterator{mClientMapHandler.mClients.begin()}; }
+ iterator end() const { return iterator{mClientMapHandler.mClients.end()}; }
+
+ private:
+ const ClientMapHandler<T>& mClientMapHandler; // iterating does not modify map.
+ };
+
+ // return an iterable object that can be used in a range-based-for to enumerate clients.
+ // this iterable does not allow modification, it should be used as a temporary.
+ ClientIterable getClientIterable() const {
+ return ClientIterable{*this};
+ }
+
+private:
+ // ClientMap maps a portId to a client descriptor (both uniquely identify each other).
+ ClientMap mClients;
+};
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index d9d0d6b..8ef7707 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -29,10 +29,8 @@
AudioInputDescriptor::AudioInputDescriptor(const sp<IOProfile>& profile,
AudioPolicyClientInterface *clientInterface)
- : mIoHandle(0),
- mDevice(AUDIO_DEVICE_NONE), mPolicyMix(NULL),
- mProfile(profile), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0),
- mClientInterface(clientInterface), mGlobalActiveCount(0)
+ : mProfile(profile)
+ , mClientInterface(clientInterface)
{
if (profile != NULL) {
profile->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
@@ -115,12 +113,12 @@
bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
{
- for (const auto &client : mClients) {
- if (client.second->active() &&
- ((client.second->source() == source) ||
+ for (const auto &client : getClientIterable()) {
+ if (client->active() &&
+ ((client->source() == source) ||
((source == AUDIO_SOURCE_VOICE_RECOGNITION) &&
- (client.second->source() == AUDIO_SOURCE_HOTWORD) &&
- client.second->isSoundTrigger()))) {
+ (client->source() == AUDIO_SOURCE_HOTWORD) &&
+ client->isSoundTrigger()))) {
return true;
}
}
@@ -132,14 +130,14 @@
audio_source_t source = AUDIO_SOURCE_DEFAULT;
int32_t priority = -1;
- for (const auto &client : mClients) {
- if (activeOnly && !client.second->active() ) {
+ for (const auto &client : getClientIterable()) {
+ if (activeOnly && !client->active() ) {
continue;
}
- int32_t curPriority = source_priority(client.second->source());
+ int32_t curPriority = source_priority(client->source());
if (curPriority > priority) {
priority = curPriority;
- source = client.second->source();
+ source = client->source();
}
}
return source;
@@ -148,10 +146,10 @@
bool AudioInputDescriptor::isSoundTrigger() const {
// sound trigger and non sound trigger clients are not mixed on a given input
// so check only first client
- if (mClients.size() == 0) {
+ if (getClientCount() == 0) {
return false;
}
- return mClients.cbegin()->second->isSoundTrigger();
+ return getClientIterable().begin()->isSoundTrigger();
}
audio_patch_handle_t AudioInputDescriptor::getPatchHandle() const
@@ -162,9 +160,9 @@
void AudioInputDescriptor::setPatchHandle(audio_patch_handle_t handle)
{
mPatchHandle = handle;
- for (const auto &client : mClients) {
- if (client.second->active()) {
- updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client.second);
+ for (const auto &client : getClientIterable()) {
+ if (client->active()) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
}
}
}
@@ -265,8 +263,9 @@
void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
{
- if (mClients.find(client->portId()) == mClients.end()
- || active == client->active()) {
+ LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
+ "%s(%d) does not exist on input descriptor", __func__, client->portId());
+ if (active == client->active()) {
return;
}
@@ -276,7 +275,8 @@
ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
mGlobalActiveCount = 1;
}
- mGlobalActiveCount += active ? 1 : -1;
+ const int delta = active ? 1 : -1;
+ mGlobalActiveCount += delta;
if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
@@ -314,9 +314,9 @@
audio_session_t session)
{
RecordClientVector clients;
- for (const auto &client : mClients) {
- if (client.second->session() == session) {
- clients.push_back(client.second);
+ for (const auto &client : getClientIterable()) {
+ if (client->session() == session) {
+ clients.push_back(client);
}
}
return clients;
@@ -326,11 +326,11 @@
bool preferredDeviceOnly) const
{
RecordClientVector clients;
- for (const auto &client : mClients) {
- if ((!activeOnly || client.second->active())
- && (source == AUDIO_SOURCE_DEFAULT || source == client.second->source())
- && (!preferredDeviceOnly || client.second->hasPreferredDevice())) {
- clients.push_back(client.second);
+ for (const auto &client : getClientIterable()) {
+ if ((!activeOnly || client->active())
+ && (source == AUDIO_SOURCE_DEFAULT || source == client->source())
+ && (!preferredDeviceOnly || client->hasPreferredDevice())) {
+ clients.push_back(client);
}
}
return clients;
@@ -338,29 +338,16 @@
status_t AudioInputDescriptor::dump(int fd)
{
- const size_t SIZE = 256;
- char buffer[SIZE];
String8 result;
- snprintf(buffer, SIZE, " ID: %d\n", getId());
- result.append(buffer);
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %d\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", mDevice);
- result.append(buffer);
-
- write(fd, result.string(), result.size());
-
- size_t index = 0;
- result = " AudioRecord clients:\n";
- for (const auto& client: mClients) {
- client.second->dump(result, 2, index++);
- }
- result.append(" \n");
+ result.appendFormat(" ID: %d\n", getId());
+ result.appendFormat(" Sampling rate: %d\n", mSamplingRate);
+ result.appendFormat(" Format: %d\n", mFormat);
+ result.appendFormat(" Channels: %08x\n", mChannelMask);
+ result.appendFormat(" Devices %08x\n", mDevice);
+ result.append(" AudioRecord Clients:\n");
+ result.append(ClientMapHandler<RecordClientDescriptor>::dump());
+ result.append("\n");
write(fd, result.string(), result.size());
return NO_ERROR;
}
@@ -427,10 +414,8 @@
{
for (size_t i = 0; i < size(); i++) {
sp<AudioInputDescriptor> inputDesc = valueAt(i);
- for (const auto& client : inputDesc->clientsMap()) {
- if (client.second->portId() == portId) {
- return inputDesc;
- }
+ if (inputDesc->getClient(portId) != nullptr) {
+ return inputDesc;
}
}
return 0;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 9327e7e..03685ab 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -34,8 +34,8 @@
AudioOutputDescriptor::AudioOutputDescriptor(const sp<AudioPort>& port,
AudioPolicyClientInterface *clientInterface)
- : mPort(port), mDevice(AUDIO_DEVICE_NONE), mClientInterface(clientInterface),
- mPolicyMix(NULL), mGlobalActiveCount(0), mPatchHandle(AUDIO_PATCH_HANDLE_NONE), mId(0)
+ : mPort(port)
+ , mClientInterface(clientInterface)
{
// clear usage count for all stream types
for (int i = 0; i < AUDIO_STREAM_CNT; i++) {
@@ -103,35 +103,62 @@
}
}
-void AudioOutputDescriptor::changeStreamActiveCount(audio_stream_type_t stream,
- int delta)
+void AudioOutputDescriptor::changeStreamActiveCount(const sp<TrackClientDescriptor>& client,
+ int delta)
{
+ if (delta == 0) return;
+ const audio_stream_type_t stream = client->stream();
if ((delta + (int)mActiveCount[stream]) < 0) {
- ALOGW("%s invalid delta %d for stream %d, active count %d",
- __FUNCTION__, delta, stream, mActiveCount[stream]);
- mActiveCount[stream] = 0;
- return;
+ // any mismatched active count will abort.
+ LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, active stream count %d",
+ __func__, client->toShortString().c_str(), delta, mActiveCount[stream]);
+ // mActiveCount[stream] = 0;
+ // return;
}
mActiveCount[stream] += delta;
+
+ if (delta > 0) {
+ mActiveClients[client] += delta;
+ } else {
+ auto it = mActiveClients.find(client);
+ if (it == mActiveClients.end()) { // client not found!
+ LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, inactive client",
+ __func__, client->toShortString().c_str(), delta);
+ } else if (it->second < -delta) { // invalid delta!
+ LOG_ALWAYS_FATAL("%s(%s) invalid delta %d, active client count %zu",
+ __func__, client->toShortString().c_str(), delta, it->second);
+ }
+ it->second += delta;
+ if (it->second == 0) {
+ (void)mActiveClients.erase(it);
+ }
+ }
+
ALOGV("%s stream %d, count %d", __FUNCTION__, stream, mActiveCount[stream]);
}
void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
{
- if (mClients.find(client->portId()) == mClients.end()
- || active == client->active()) {
+ LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
+ "%s(%d) does not exist on output descriptor", __func__, client->portId());
+
+ if (active == client->active()) {
+ ALOGW("%s(%s): ignored active: %d, current stream count %d",
+ __func__, client->toShortString().c_str(),
+ active, mActiveCount[client->stream()]);
return;
}
-
- changeStreamActiveCount(client->stream(), active ? 1 : -1);
+ const int delta = active ? 1 : -1;
+ changeStreamActiveCount(client, delta);
// Handle non-client-specific activity ref count
int32_t oldGlobalActiveCount = mGlobalActiveCount;
if (!active && mGlobalActiveCount < 1) {
- ALOGW("%s invalid deactivation with globalRefCount %d", __FUNCTION__, mGlobalActiveCount);
+ ALOGW("%s(%s): invalid deactivation with globalRefCount %d",
+ __func__, client->toShortString().c_str(), mGlobalActiveCount);
mGlobalActiveCount = 1;
}
- mGlobalActiveCount += active ? 1 : -1;
+ mGlobalActiveCount += delta;
if ((oldGlobalActiveCount == 0) && (mGlobalActiveCount > 0)) {
if ((mPolicyMix != NULL) && ((mPolicyMix->mCbFlags & AudioMix::kCbFlagNotifyActivity) != 0))
@@ -239,11 +266,11 @@
bool preferredDeviceOnly) const
{
TrackClientVector clients;
- for (const auto &client : mClients) {
- if ((!activeOnly || client.second->active())
- && (strategy == STRATEGY_NONE || strategy == client.second->strategy())
- && (!preferredDeviceOnly || client.second->hasPreferredDevice())) {
- clients.push_back(client.second);
+ for (const auto &client : getClientIterable()) {
+ if ((!activeOnly || client->active())
+ && (strategy == STRATEGY_NONE || strategy == client->strategy())
+ && (!preferredDeviceOnly || client->hasPreferredDevice())) {
+ clients.push_back(client);
}
}
return clients;
@@ -251,34 +278,31 @@
status_t AudioOutputDescriptor::dump(int fd)
{
- const size_t SIZE = 256;
- char buffer[SIZE];
String8 result;
- snprintf(buffer, SIZE, " ID: %d\n", mId);
- result.append(buffer);
- snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate);
- result.append(buffer);
- snprintf(buffer, SIZE, " Format: %08x\n", mFormat);
- result.append(buffer);
- snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask);
- result.append(buffer);
- snprintf(buffer, SIZE, " Devices %08x\n", device());
- result.append(buffer);
- snprintf(buffer, SIZE, " Stream volume activeCount muteCount\n");
- result.append(buffer);
+ result.appendFormat(" ID: %d\n", mId);
+ result.appendFormat(" Sampling rate: %d\n", mSamplingRate);
+ result.appendFormat(" Format: %08x\n", mFormat);
+ result.appendFormat(" Channels: %08x\n", mChannelMask);
+ result.appendFormat(" Devices: %08x\n", device());
+ result.appendFormat(" Global active count: %u\n", mGlobalActiveCount);
+ result.append(" Stream volume activeCount muteCount\n");
for (int i = 0; i < (int)AUDIO_STREAM_CNT; i++) {
- snprintf(buffer, SIZE, " %02d %.03f %02d %02d\n",
+ result.appendFormat(" %02d %.03f %02d %02d\n",
i, mCurVolume[i], streamActiveCount((audio_stream_type_t)i), mMuteCount[i]);
- result.append(buffer);
}
-
- result.append(" AudioTrack clients:\n");
- size_t index = 0;
- for (const auto& client : mClients) {
- client.second->dump(result, 2, index++);
+ result.append(" AudioTrack Clients:\n");
+ result.append(ClientMapHandler<TrackClientDescriptor>::dump());
+ result.append("\n");
+ if (mActiveClients.size() > 0) {
+ result.append(" AudioTrack active (stream) clients:\n");
+ size_t index = 0;
+ for (const auto& clientPair : mActiveClients) {
+ result.appendFormat(" Refcount: %zu", clientPair.second);
+ clientPair.first->dump(result, 2, index++);
+ }
+ result.append(" \n");
}
- result.append(" \n");
write(fd, result.string(), result.size());
return NO_ERROR;
@@ -306,14 +330,10 @@
status_t SwAudioOutputDescriptor::dump(int fd)
{
- const size_t SIZE = 256;
- char buffer[SIZE];
String8 result;
- snprintf(buffer, SIZE, " Latency: %d\n", mLatency);
- result.append(buffer);
- snprintf(buffer, SIZE, " Flags %08x\n", mFlags);
- result.append(buffer);
+ result.appendFormat(" Latency: %d\n", mLatency);
+ result.appendFormat(" Flags %08x\n", mFlags);
write(fd, result.string(), result.size());
AudioOutputDescriptor::dump(fd);
@@ -361,15 +381,15 @@
}
}
-void SwAudioOutputDescriptor::changeStreamActiveCount(audio_stream_type_t stream,
- int delta)
+void SwAudioOutputDescriptor::changeStreamActiveCount(const sp<TrackClientDescriptor>& client,
+ int delta)
{
// forward usage count change to attached outputs
if (isDuplicated()) {
- mOutput1->changeStreamActiveCount(stream, delta);
- mOutput2->changeStreamActiveCount(stream, delta);
+ mOutput1->changeStreamActiveCount(client, delta);
+ mOutput2->changeStreamActiveCount(client, delta);
}
- AudioOutputDescriptor::changeStreamActiveCount(stream, delta);
+ AudioOutputDescriptor::changeStreamActiveCount(client, delta);
}
bool SwAudioOutputDescriptor::isFixedVolume(audio_devices_t device)
@@ -765,10 +785,8 @@
{
for (size_t i = 0; i < size(); i++) {
sp<SwAudioOutputDescriptor> outputDesc = valueAt(i);
- for (const auto& client : outputDesc->clientsMap()) {
- if (client.second->portId() == portId) {
- return outputDesc;
- }
+ if (outputDesc->getClient(portId) != nullptr) {
+ return outputDesc;
}
}
return 0;
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 0d65a31..c237cef 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "APM_ClientDescriptor"
//#define LOG_NDEBUG 0
+#include <sstream>
#include <utils/Log.h>
#include <utils/String8.h>
#include "AudioGain.h"
@@ -44,10 +45,18 @@
return status;
}
+std::string ClientDescriptor::toShortString() const
+{
+ std::stringstream ss;
+
+ ss << "PortId: " << mPortId << " SessionId: " << mSessionId << " Uid: " << mUid;
+ return ss.str();
+}
+
status_t ClientDescriptor::dump(String8& out, int spaces, int index)
{
out.appendFormat("%*sClient %d:\n", spaces, "", index+1);
- out.appendFormat("%*s- Port ID: %d Session Id: %d UID: %d\n", spaces, "",
+ out.appendFormat("%*s- Port Id: %d Session Id: %d UID: %d\n", spaces, "",
mPortId, mSessionId, mUid);
out.appendFormat("%*s- Format: %08x Sampling rate: %d Channels: %08x\n", spaces, "",
mConfig.format, mConfig.sample_rate, mConfig.channel_mask);
@@ -65,6 +74,14 @@
return NO_ERROR;
}
+std::string TrackClientDescriptor::toShortString() const
+{
+ std::stringstream ss;
+
+ ss << ClientDescriptor::toShortString() << " Stream: " << mStream;
+ return ss.str();
+}
+
status_t RecordClientDescriptor::dump(String8& out, int spaces, int index)
{
ClientDescriptor::dump(out, spaces, index);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 380f0fb..42777f6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -910,7 +910,7 @@
getStrategyForAttr(&attributes),
*flags);
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
- outputDesc->clientsMap().emplace(*portId, clientDesc);
+ outputDesc->addClient(clientDesc);
ALOGV(" getOutputForAttr() returns output %d selectedDeviceId %d for port ID %d",
*output, *selectedDeviceId, *portId);
@@ -1013,6 +1013,23 @@
String8 address = outputDevices.size() > 0 ? outputDevices.itemAt(0)->mAddress
: String8("");
+ // MSD patch may be using the only output stream that can service this request. Release
+ // MSD patch to prioritize this request over any active output on MSD.
+ AudioPatchCollection msdPatches = getMsdPatches();
+ for (size_t i = 0; i < msdPatches.size(); i++) {
+ const auto& patch = msdPatches[i];
+ for (size_t j = 0; j < patch->mPatch.num_sinks; ++j) {
+ const struct audio_port_config *sink = &patch->mPatch.sinks[j];
+ if (sink->type == AUDIO_PORT_TYPE_DEVICE &&
+ (sink->ext.device.type & device) != AUDIO_DEVICE_NONE &&
+ (address.isEmpty() || strncmp(sink->ext.device.address, address.string(),
+ AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
+ releaseAudioPatch(patch->mHandle, mUidCached);
+ break;
+ }
+ }
+ }
+
status = outputDesc->open(config, device, address, stream, *flags, &output);
// only accept an output with the requested parameters
@@ -1093,16 +1110,16 @@
const AudioPatchCollection AudioPolicyManager::getMsdPatches() const {
AudioPatchCollection msdPatches;
- audio_module_handle_t msdModuleHandle = mHwModules.getModuleFromName(
- AUDIO_HARDWARE_MODULE_ID_MSD)->getHandle();
- if (msdModuleHandle == AUDIO_MODULE_HANDLE_NONE) return msdPatches;
- for (size_t i = 0; i < mAudioPatches.size(); ++i) {
- sp<AudioPatch> patch = mAudioPatches.valueAt(i);
- for (size_t j = 0; j < patch->mPatch.num_sources; ++j) {
- const struct audio_port_config *source = &patch->mPatch.sources[j];
- if (source->type == AUDIO_PORT_TYPE_DEVICE &&
- source->ext.device.hw_module == msdModuleHandle) {
- msdPatches.addAudioPatch(patch->mHandle, patch);
+ sp<HwModule> msdModule = mHwModules.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
+ if (msdModule != 0) {
+ for (size_t i = 0; i < mAudioPatches.size(); ++i) {
+ sp<AudioPatch> patch = mAudioPatches.valueAt(i);
+ for (size_t j = 0; j < patch->mPatch.num_sources; ++j) {
+ const struct audio_port_config *source = &patch->mPatch.sources[j];
+ if (source->type == AUDIO_PORT_TYPE_DEVICE &&
+ source->ext.device.hw_module == msdModule->getHandle()) {
+ msdPatches.addAudioPatch(patch->mHandle, patch);
+ }
}
}
}
@@ -1320,7 +1337,7 @@
ALOGW("startOutput() no output for client %d", portId);
return BAD_VALUE;
}
- sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
+ sp<TrackClientDescriptor> client = outputDesc->getClient(portId);
ALOGV("startOutput() output %d, stream %d, session %d",
outputDesc->mIoHandle, client->stream(), client->session());
@@ -1513,7 +1530,7 @@
ALOGW("stopOutput() no output for client %d", portId);
return BAD_VALUE;
}
- sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
+ sp<TrackClientDescriptor> client = outputDesc->getClient(portId);
ALOGV("stopOutput() output %d, stream %d, session %d",
outputDesc->mIoHandle, client->stream(), client->session());
@@ -1614,10 +1631,15 @@
sp<SwAudioOutputDescriptor> outputDesc = mOutputs.getOutputForClient(portId);
if (outputDesc == 0) {
+ // If an output descriptor is closed due to a device routing change,
+ // then there are race conditions with releaseOutput from tracks
+ // that may be destroyed (with no PlaybackThread) or a PlaybackThread
+ // destroyed shortly thereafter.
+ //
+ // Here we just log a warning, instead of a fatal error.
ALOGW("releaseOutput() no output for client %d", portId);
return;
}
- sp<TrackClientDescriptor> client = outputDesc->clientsMap()[portId];
ALOGV("releaseOutput() %d", outputDesc->mIoHandle);
@@ -1632,10 +1654,12 @@
mpClientInterface->onAudioPortListUpdate();
}
}
- outputDesc->clientsMap().erase(portId);
+ // stopOutput() needs to be successfully called before releaseOutput()
+ // otherwise there may be inaccurate stream reference counts.
+ // This is checked in outputDesc->removeClient below.
+ outputDesc->removeClient(portId);
}
-
status_t AudioPolicyManager::getInputForAttr(const audio_attributes_t *attr,
audio_io_handle_t *input,
audio_session_t session,
@@ -1793,7 +1817,7 @@
*attr, *config, requestedDeviceId,
inputSource,flags, isSoundTrigger);
inputDesc = mInputs.valueFor(*input);
- inputDesc->clientsMap().emplace(*portId, clientDesc);
+ inputDesc->addClient(clientDesc);
ALOGV("getInputForAttr() returns input %d type %d selectedDeviceId %d for port ID %d",
*input, *inputType, *selectedDeviceId, *portId);
@@ -1968,7 +1992,7 @@
return BAD_VALUE;
}
audio_io_handle_t input = inputDesc->mIoHandle;
- sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
+ sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
if (client->active()) {
ALOGW("%s input %d client %d already started", __FUNCTION__, input, client->portId());
return INVALID_OPERATION;
@@ -2137,7 +2161,7 @@
return BAD_VALUE;
}
audio_io_handle_t input = inputDesc->mIoHandle;
- sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
+ sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
if (!client->active()) {
ALOGW("%s input %d client %d already stopped", __FUNCTION__, input, client->portId());
return INVALID_OPERATION;
@@ -2196,15 +2220,15 @@
ALOGW("%s no input for client %d", __FUNCTION__, portId);
return;
}
- sp<RecordClientDescriptor> client = inputDesc->clientsMap()[portId];
+ sp<RecordClientDescriptor> client = inputDesc->getClient(portId);
audio_io_handle_t input = inputDesc->mIoHandle;
ALOGV("%s %d", __FUNCTION__, input);
- inputDesc->clientsMap().erase(portId);
+ inputDesc->removeClient(portId);
- if (inputDesc->clientsMap().size() > 0) {
- ALOGV("%s %zu clients remaining", __FUNCTION__, inputDesc->clientsMap().size());
+ if (inputDesc->getClientCount() > 0) {
+ ALOGV("%s(%d) %zu clients remaining", __func__, portId, inputDesc->getClientCount());
return;
}
@@ -3311,11 +3335,10 @@
SortedVector<routing_strategy> affectedStrategies;
for (size_t i = 0; i < mOutputs.size(); i++) {
sp<AudioOutputDescriptor> outputDesc = mOutputs.valueAt(i);
- TrackClientMap clients = outputDesc->clientsMap();
- for (const auto& client : clients) {
- if (client.second->hasPreferredDevice() && client.second->uid() == uid) {
- client.second->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
- affectedStrategies.add(getStrategy(client.second->stream()));
+ for (const auto& client : outputDesc->getClientIterable()) {
+ if (client->hasPreferredDevice() && client->uid() == uid) {
+ client->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
+ affectedStrategies.add(getStrategy(client->stream()));
}
}
}
@@ -3328,11 +3351,10 @@
SortedVector<audio_source_t> affectedSources;
for (size_t i = 0; i < mInputs.size(); i++) {
sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
- RecordClientMap clients = inputDesc->clientsMap();
- for (const auto& client : clients) {
- if (client.second->hasPreferredDevice() && client.second->uid() == uid) {
- client.second->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
- affectedSources.add(client.second->source());
+ for (const auto& client : inputDesc->getClientIterable()) {
+ if (client->hasPreferredDevice() && client->uid() == uid) {
+ client->setPreferredDeviceId(AUDIO_PORT_HANDLE_NONE);
+ affectedSources.add(client->source());
}
}
}
@@ -4529,10 +4551,9 @@
// and as they were also referenced on the other output, the reference
// count for their stream type must be adjusted accordingly on
// the other output.
- bool wasActive = outputDesc2->isActive();
- for (int j = 0; j < AUDIO_STREAM_CNT; j++) {
- int activeCount = dupOutputDesc->streamActiveCount((audio_stream_type_t)j);
- outputDesc2->changeStreamActiveCount((audio_stream_type_t)j,-activeCount);
+ const bool wasActive = outputDesc2->isActive();
+ for (const auto &clientPair : dupOutputDesc->getActiveClients()) {
+ outputDesc2->changeStreamActiveCount(clientPair.first, -clientPair.second);
}
// stop() will be a no op if the output is still active but is needed in case all
// active streams refcounts where cleared above
@@ -4561,6 +4582,22 @@
removeOutput(output);
mPreviousOutputs = mOutputs;
+
+ // MSD patches may have been released to support a non-MSD direct output. Reset MSD patch if
+ // no direct outputs are open.
+ if (getMsdAudioOutDeviceTypes() != AUDIO_DEVICE_NONE) {
+ bool directOutputOpen = false;
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ if (mOutputs[i]->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) {
+ directOutputOpen = true;
+ break;
+ }
+ }
+ if (!directOutputOpen) {
+ ALOGV("no direct outputs open, reset MSD patch");
+ setMsdPatch();
+ }
+ }
}
void AudioPolicyManager::closeInput(audio_io_handle_t input)
diff --git a/services/audiopolicy/tests/Android.mk b/services/audiopolicy/tests/Android.mk
index b739b88..513312e 100644
--- a/services/audiopolicy/tests/Android.mk
+++ b/services/audiopolicy/tests/Android.mk
@@ -6,6 +6,7 @@
frameworks/av/services/audiopolicy \
frameworks/av/services/audiopolicy/common/include \
frameworks/av/services/audiopolicy/engine/interface \
+ $(call include-path-for, audio-utils) \
LOCAL_SHARED_LIBRARIES := \
libaudiopolicymanagerdefault \