Merge "RecordBufferConverter: Release converter buffer after conversion" into qt-dev
diff --git a/camera/ndk/include/camera/NdkCameraMetadataTags.h b/camera/ndk/include/camera/NdkCameraMetadataTags.h
index ef5f26c..4563b41 100644
--- a/camera/ndk/include/camera/NdkCameraMetadataTags.h
+++ b/camera/ndk/include/camera/NdkCameraMetadataTags.h
@@ -7670,6 +7670,24 @@
* <li>ACAMERA_LENS_POSE_REFERENCE</li>
* <li>ACAMERA_LENS_DISTORTION</li>
* </ul>
+ * <p>The field of view of all non-RAW physical streams must be the same or as close as
+ * possible to that of non-RAW logical streams. If the requested FOV is outside of the
+ * range supported by the physical camera, the physical stream for that physical camera
+ * will use either the maximum or minimum scaler crop region, depending on which one is
+ * closer to the requested FOV. For example, for a logical camera with wide-tele lens
+ * configuration where the wide lens is the default, if the logical camera's crop region
+ * is set to maximum, the physical stream for the tele lens will be configured to its
+ * maximum crop region. On the other hand, if the logical camera has a normal-wide lens
+ * configuration where the normal lens is the default, when the logical camera's crop
+ * region is set to maximum, the FOV of the logical streams will be that of the normal
+ * lens. The FOV of the physical streams for the wide lens will be the same as the
+ * logical stream, by making the crop region smaller than its active array size to
+ * compensate for the smaller focal length.</p>
+ * <p>Even if the underlying physical cameras have different RAW characteristics (such as
+ * size or CFA pattern), a logical camera can still advertise RAW capability. In this
+ * case, when the application configures a RAW stream, the camera device will make sure
+ * the active physical camera will remain active to ensure consistent RAW output
+ * behavior, and not switch to other physical cameras.</p>
* <p>To maintain backward compatibility, the capture request and result metadata tags
* required for basic camera functionalities will be solely based on the
* logical camera capabiltity. Other request and result metadata tags, on the other
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index e284cda..a1c81f3 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -150,6 +150,7 @@
AAC,
HEVC,
MP3,
+ PCM,
OTHER
};
@@ -270,6 +271,8 @@
mType = AAC;
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
mType = MP3;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ mType = PCM;
}
}
@@ -1054,6 +1057,27 @@
AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
}
+ if (mType == PCM) {
+ int32_t bitPerFrame = 16;
+ int32_t bigEndian = 0;
+ AMediaFormat *meta = AMediaFormat_new();
+ if (getFormat(meta) == AMEDIA_OK && meta != NULL) {
+ AMediaFormat_getInt32(meta,
+ AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &bitPerFrame);
+ AMediaFormat_getInt32(meta,
+ AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &bigEndian);
+ }
+ AMediaFormat_delete(meta);
+ if (bigEndian == 1 && bitPerFrame == 16) {
+ // Big-endian -> little-endian
+ uint16_t *dstData = (uint16_t *)frame->data() + frame->range_offset();
+ uint16_t *srcData = (uint16_t *)frame->data() + frame->range_offset();
+ for (size_t i = 0; i < frame->range_length() / 2; i++) {
+ dstData[i] = ntohs(srcData[i]);
+ }
+ }
+ }
+
*out = frame;
return AMEDIA_OK;
@@ -1170,6 +1194,51 @@
////////////////////////////////////////////////////////////////////////////////
+enum WaveID {
+ MKV_RIFF_WAVE_FORMAT_PCM = 0x0001,
+ MKV_RIFF_WAVE_FORMAT_ADPCM_ms = 0x0002,
+ MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav = 0x0011,
+ MKV_RIFF_WAVE_FORMAT_MPEGL12 = 0x0050,
+ MKV_RIFF_WAVE_FORMAT_MPEGL3 = 0x0055,
+ MKV_RIFF_WAVE_FORMAT_WMAV1 = 0x0160,
+ MKV_RIFF_WAVE_FORMAT_WMAV2 = 0x0161,
+};
+
+static const char *MKVWave2MIME(uint16_t id) {
+ switch (id) {
+ case MKV_RIFF_WAVE_FORMAT_MPEGL12:
+ return MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;
+
+ case MKV_RIFF_WAVE_FORMAT_MPEGL3:
+ return MEDIA_MIMETYPE_AUDIO_MPEG;
+
+ case MKV_RIFF_WAVE_FORMAT_PCM:
+ return MEDIA_MIMETYPE_AUDIO_RAW;
+
+ case MKV_RIFF_WAVE_FORMAT_ADPCM_ms:
+ return MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
+ case MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav:
+ return MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
+
+ case MKV_RIFF_WAVE_FORMAT_WMAV1:
+ case MKV_RIFF_WAVE_FORMAT_WMAV2:
+ return MEDIA_MIMETYPE_AUDIO_WMA;
+ default:
+ ALOGW("unknown wave %x", id);
+ return "";
+ };
+}
+
+static bool isMkvAudioCsdSizeOK(const char* mime, size_t csdSize) {
+ if ((!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) && csdSize < 50) ||
+ (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) && csdSize < 20) ||
+ (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA) && csdSize < 28) ||
+ (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) && csdSize < 30)) {
+ return false;
+ }
+ return true;
+}
+
// trans all FOURCC to lower char
static uint32_t FourCCtoLower(uint32_t fourcc) {
uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
@@ -2036,20 +2105,40 @@
} else if (!strcmp("A_FLAC", codecID)) {
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
+ } else if (!strcmp("A_MPEG/L2", codecID)) {
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
+ } else if (!strcmp("A_PCM/INT/LIT", codecID) ||
+ !strcmp("A_PCM/INT/BIG", codecID)) {
+ AMediaFormat_setString(meta,
+ AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
+ int32_t bigEndian = !strcmp("A_PCM/INT/BIG", codecID) ? 1: 0;
+ AMediaFormat_setInt32(meta,
+ AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, bigEndian);
} else if ((!strcmp("A_MS/ACM", codecID))) {
- if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
+ if ((NULL == codecPrivate) || (codecPrivateSize < 18)) {
ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
continue;
} else {
uint16_t ID = *(uint16_t *)codecPrivate;
- if (ID == 0x0055) {
- AMediaFormat_setString(meta,
- AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
+ const char* mime = MKVWave2MIME(ID);
+ ALOGV("A_MS/ACM type is %s", mime);
+ if (!strncasecmp("audio/", mime, 6) &&
+ isMkvAudioCsdSizeOK(mime, codecPrivateSize)) {
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
} else {
- ALOGW("A_MS/ACM unsupported type , continue");
+ ALOGE("A_MS/ACM continue, unsupported audio type=%s, csdSize:%zu",
+ mime, codecPrivateSize);
continue;
}
+ if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA)) {
+ addESDSFromCodecPrivate(meta, true, codecPrivate, codecPrivateSize);
+ } else if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) ||
+ !strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM)) {
+ uint32_t blockAlign = *(uint16_t*)(codecPrivate + 12);
+ addESDSFromCodecPrivate(meta, true, &blockAlign, sizeof(blockAlign));
+ }
}
} else {
ALOGW("%s is not supported.", codecID);
@@ -2058,6 +2147,7 @@
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, atrack->GetBitDepth());
break;
}
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index dd620e3..7b0d31f 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -97,8 +97,7 @@
status_t status = binder->linkToDeath(mAAudioClient);
// TODO review what we should do if this fails
if (status != NO_ERROR) {
- ALOGE("getAAudioService: linkToDeath(mAAudioClient = %p) returned %d",
- mAAudioClient.get(), status);
+ ALOGE("%s() - linkToDeath() returned %d", __func__, status);
}
mAAudioService = interface_cast<IAAudioService>(binder);
needToRegister = true;
diff --git a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
index 67955e8..b6e8472 100644
--- a/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
+++ b/media/libaaudio/src/binding/SharedMemoryParcelable.cpp
@@ -157,5 +157,4 @@
void SharedMemoryParcelable::dump() {
ALOGD("mFd = %d", mFd.get());
ALOGD("mSizeInBytes = %d", mSizeInBytes);
- ALOGD("mResolvedAddress = %p", mResolvedAddress);
}
diff --git a/media/libaaudio/src/client/AAudioFlowGraph.cpp b/media/libaaudio/src/client/AAudioFlowGraph.cpp
index 3e43c6b..8f2c488 100644
--- a/media/libaaudio/src/client/AAudioFlowGraph.cpp
+++ b/media/libaaudio/src/client/AAudioFlowGraph.cpp
@@ -38,7 +38,7 @@
int32_t sinkChannelCount) {
AudioFloatOutputPort *lastOutput = nullptr;
- ALOGD("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
+ ALOGV("%s() source format = 0x%08x, channels = %d, sink format = 0x%08x, channels = %d",
__func__, sourceFormat, sourceChannelCount, sinkFormat, sinkChannelCount);
switch (sourceFormat) {
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index ec270f3..db98d58 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -195,13 +195,13 @@
if (isDataCallbackSet()) {
mCallbackFrames = builder.getFramesPerDataCallback();
if (mCallbackFrames > getBufferCapacity() / 2) {
- ALOGE("%s - framesPerCallback too big = %d, capacity = %d",
+ ALOGW("%s - framesPerCallback too big = %d, capacity = %d",
__func__, mCallbackFrames, getBufferCapacity());
result = AAUDIO_ERROR_OUT_OF_RANGE;
goto error;
} else if (mCallbackFrames < 0) {
- ALOGE("%s - framesPerCallback negative", __func__);
+ ALOGW("%s - framesPerCallback negative", __func__);
result = AAUDIO_ERROR_OUT_OF_RANGE;
goto error;
@@ -225,7 +225,7 @@
aaudio_result_t AudioStreamInternal::close() {
aaudio_result_t result = AAUDIO_OK;
- ALOGD("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
+ ALOGV("%s(): mServiceStreamHandle = 0x%08X", __func__, mServiceStreamHandle);
if (mServiceStreamHandle != AAUDIO_HANDLE_INVALID) {
// Don't close a stream while it is running.
aaudio_stream_state_t currentState = getState();
@@ -236,7 +236,7 @@
result = waitForStateChange(currentState, &nextState,
timeoutNanoseconds);
if (result != AAUDIO_OK) {
- ALOGE("%s() waitForStateChange() returned %d %s",
+ ALOGW("%s() waitForStateChange() returned %d %s",
__func__, result, AAudio_convertResultToText(result));
}
}
@@ -283,17 +283,17 @@
{
int64_t startTime;
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("requestStart() mServiceStreamHandle invalid");
+ ALOGD("requestStart() mServiceStreamHandle invalid");
return AAUDIO_ERROR_INVALID_STATE;
}
if (isActive()) {
- ALOGE("requestStart() already active");
+ ALOGD("requestStart() already active");
return AAUDIO_ERROR_INVALID_STATE;
}
aaudio_stream_state_t originalState = getState();
if (originalState == AAUDIO_STREAM_STATE_DISCONNECTED) {
- ALOGE("requestStart() but DISCONNECTED");
+ ALOGD("requestStart() but DISCONNECTED");
return AAUDIO_ERROR_DISCONNECTED;
}
setState(AAUDIO_STREAM_STATE_STARTING);
@@ -356,8 +356,8 @@
}
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("requestStopInternal() mServiceStreamHandle invalid = 0x%08X",
- mServiceStreamHandle);
+ ALOGW("%s() mServiceStreamHandle invalid = 0x%08X",
+ __func__, mServiceStreamHandle);
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -370,7 +370,7 @@
aaudio_result_t AudioStreamInternal::registerThread() {
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("registerThread() mServiceStreamHandle invalid");
+ ALOGW("%s() mServiceStreamHandle invalid", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
return mServiceInterface.registerAudioThread(mServiceStreamHandle,
@@ -380,7 +380,7 @@
aaudio_result_t AudioStreamInternal::unregisterThread() {
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("unregisterThread() mServiceStreamHandle invalid");
+ ALOGW("%s() mServiceStreamHandle invalid", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
diff --git a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
index e1443d9..164ad2b 100644
--- a/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternalPlay.cpp
@@ -65,7 +65,7 @@
return result;
}
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("%s() mServiceStreamHandle invalid", __func__);
+ ALOGW("%s() mServiceStreamHandle invalid", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
@@ -77,7 +77,7 @@
aaudio_result_t AudioStreamInternalPlay::requestFlush() {
if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
- ALOGE("%s() mServiceStreamHandle invalid", __func__);
+ ALOGW("%s() mServiceStreamHandle invalid", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}
diff --git a/media/libaaudio/src/core/AAudioAudio.cpp b/media/libaaudio/src/core/AAudioAudio.cpp
index 8ae2644..44d5122 100644
--- a/media/libaaudio/src/core/AAudioAudio.cpp
+++ b/media/libaaudio/src/core/AAudioAudio.cpp
@@ -246,18 +246,20 @@
AAudioStream** streamPtr)
{
AudioStream *audioStream = nullptr;
+ aaudio_stream_id_t id = 0;
// Please leave these logs because they are very helpful when debugging.
- ALOGD("%s() called ----------------------------------------", __func__);
+ ALOGI("%s() called ----------------------------------------", __func__);
AudioStreamBuilder *streamBuilder = COMMON_GET_FROM_BUILDER_OR_RETURN(streamPtr);
aaudio_result_t result = streamBuilder->build(&audioStream);
- ALOGD("AAudioStreamBuilder_openStream() returns %d = %s for (%p) ----------------",
- result, AAudio_convertResultToText(result), audioStream);
if (result == AAUDIO_OK) {
audioStream->registerPlayerBase();
*streamPtr = (AAudioStream*) audioStream;
+ id = audioStream->getId();
} else {
*streamPtr = nullptr;
}
+ ALOGI("%s() returns %d = %s for s#%u ----------------",
+ __func__, result, AAudio_convertResultToText(result), id);
return result;
}
@@ -275,8 +277,9 @@
{
aaudio_result_t result = AAUDIO_ERROR_NULL;
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- ALOGD("%s(%p) called ---------------", __func__, stream);
if (audioStream != nullptr) {
+ aaudio_stream_id_t id = audioStream->getId();
+ ALOGD("%s(s#%u) called ---------------", __func__, id);
result = audioStream->safeClose();
// Close will only fail if called illegally, for example, from a callback.
// That would result in deleting an active stream, which would cause a crash.
@@ -286,42 +289,39 @@
} else {
ALOGW("%s attempt to close failed. Close it from another thread.", __func__);
}
+ ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
}
- // We're potentially freeing `stream` above, so its use here makes some
- // static analysis tools unhappy. Casting to uintptr_t helps assure
- // said tools that we're not doing anything bad here.
- ALOGD("%s(%#" PRIxPTR ") returned %d ---------", __func__,
- reinterpret_cast<uintptr_t>(stream), result);
return result;
}
AAUDIO_API aaudio_result_t AAudioStream_requestStart(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- ALOGD("%s(%p) called --------------", __func__, stream);
+ aaudio_stream_id_t id = audioStream->getId();
+ ALOGD("%s(s#%u) called --------------", __func__, id);
aaudio_result_t result = audioStream->systemStart();
- ALOGD("%s(%p) returned %d ---------", __func__, stream, result);
+ ALOGD("%s(s#%u) returned %d ---------", __func__, id, result);
return result;
}
AAUDIO_API aaudio_result_t AAudioStream_requestPause(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- ALOGD("%s(%p) called", __func__, stream);
+ ALOGD("%s(s#%u) called", __func__, audioStream->getId());
return audioStream->systemPause();
}
AAUDIO_API aaudio_result_t AAudioStream_requestFlush(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- ALOGD("%s(%p) called", __func__, stream);
+ ALOGD("%s(s#%u) called", __func__, audioStream->getId());
return audioStream->safeFlush();
}
AAUDIO_API aaudio_result_t AAudioStream_requestStop(AAudioStream* stream)
{
AudioStream *audioStream = convertAAudioStreamToAudioStream(stream);
- ALOGD("%s(%p) called", __func__, stream);
+ ALOGD("%s(s#%u) called", __func__, audioStream->getId());
return audioStream->systemStopFromApp();
}
@@ -371,7 +371,7 @@
// Don't allow writes when playing with a callback.
if (audioStream->isDataCallbackActive()) {
- ALOGE("Cannot write to a callback stream when running.");
+ ALOGD("Cannot write to a callback stream when running.");
return AAUDIO_ERROR_INVALID_STATE;
}
diff --git a/media/libaaudio/src/core/AAudioStreamParameters.cpp b/media/libaaudio/src/core/AAudioStreamParameters.cpp
index e5bda30..c9711da 100644
--- a/media/libaaudio/src/core/AAudioStreamParameters.cpp
+++ b/media/libaaudio/src/core/AAudioStreamParameters.cpp
@@ -56,7 +56,7 @@
case AUDIO_FORMAT_PCM_FLOAT:
break; // valid
default:
- ALOGE("audioFormat not valid, audio_format_t = 0x%08x", format);
+ ALOGD("audioFormat not valid, audio_format_t = 0x%08x", format);
return AAUDIO_ERROR_INVALID_FORMAT;
// break;
}
@@ -66,12 +66,12 @@
aaudio_result_t AAudioStreamParameters::validate() const {
if (mSamplesPerFrame != AAUDIO_UNSPECIFIED
&& (mSamplesPerFrame < SAMPLES_PER_FRAME_MIN || mSamplesPerFrame > SAMPLES_PER_FRAME_MAX)) {
- ALOGE("channelCount out of range = %d", mSamplesPerFrame);
+ ALOGD("channelCount out of range = %d", mSamplesPerFrame);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
if (mDeviceId < 0) {
- ALOGE("deviceId out of range = %d", mDeviceId);
+ ALOGD("deviceId out of range = %d", mDeviceId);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
@@ -89,7 +89,7 @@
case AAUDIO_SHARING_MODE_SHARED:
break;
default:
- ALOGE("illegal sharingMode = %d", mSharingMode);
+ ALOGD("illegal sharingMode = %d", mSharingMode);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
@@ -99,12 +99,12 @@
if (mSampleRate != AAUDIO_UNSPECIFIED
&& (mSampleRate < SAMPLE_RATE_HZ_MIN || mSampleRate > SAMPLE_RATE_HZ_MAX)) {
- ALOGE("sampleRate out of range = %d", mSampleRate);
+ ALOGD("sampleRate out of range = %d", mSampleRate);
return AAUDIO_ERROR_INVALID_RATE;
}
if (mBufferCapacity < 0) {
- ALOGE("bufferCapacity out of range = %d", mBufferCapacity);
+ ALOGD("bufferCapacity out of range = %d", mBufferCapacity);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
@@ -113,7 +113,7 @@
case AAUDIO_DIRECTION_OUTPUT:
break; // valid
default:
- ALOGE("direction not valid = %d", mDirection);
+ ALOGD("direction not valid = %d", mDirection);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
@@ -134,7 +134,7 @@
case AAUDIO_USAGE_ASSISTANT:
break; // valid
default:
- ALOGE("usage not valid = %d", mUsage);
+ ALOGD("usage not valid = %d", mUsage);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
@@ -147,7 +147,7 @@
case AAUDIO_CONTENT_TYPE_SPEECH:
break; // valid
default:
- ALOGE("content type not valid = %d", mContentType);
+ ALOGD("content type not valid = %d", mContentType);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
@@ -162,7 +162,7 @@
case AAUDIO_INPUT_PRESET_VOICE_PERFORMANCE:
break; // valid
default:
- ALOGE("input preset not valid = %d", mInputPreset);
+ ALOGD("input preset not valid = %d", mInputPreset);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
@@ -174,7 +174,7 @@
case AAUDIO_ALLOW_CAPTURE_BY_NONE:
break; // valid
default:
- ALOGE("allowed capture policy not valid = %d", mAllowedCapturePolicy);
+ ALOGD("allowed capture policy not valid = %d", mAllowedCapturePolicy);
return AAUDIO_ERROR_ILLEGAL_ARGUMENT;
// break;
}
diff --git a/media/libaaudio/src/core/AudioStream.cpp b/media/libaaudio/src/core/AudioStream.cpp
index 732d45c..25669be 100644
--- a/media/libaaudio/src/core/AudioStream.cpp
+++ b/media/libaaudio/src/core/AudioStream.cpp
@@ -28,9 +28,17 @@
using namespace aaudio;
+
+// Sequential number assigned to streams solely for debugging purposes.
+static aaudio_stream_id_t AAudio_getNextStreamId() {
+ static std::atomic <aaudio_stream_id_t> nextStreamId{1};
+ return nextStreamId++;
+}
+
AudioStream::AudioStream()
: mPlayerBase(new MyPlayerBase(this))
-{
+ , mStreamId(AAudio_getNextStreamId())
+ {
// mThread is a pthread_t of unknown size so we need memset.
memset(&mThread, 0, sizeof(mThread));
setPeriodNanoseconds(0);
@@ -48,22 +56,6 @@
mPlayerBase->clearParentReference(); // remove reference to this AudioStream
}
-static const char *AudioStream_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
- const char *result;
- switch (sharingMode) {
- case AAUDIO_SHARING_MODE_EXCLUSIVE:
- result = "EX";
- break;
- case AAUDIO_SHARING_MODE_SHARED:
- result = "SH";
- break;
- default:
- result = "?!";
- break;
- }
- return result;
-}
-
aaudio_result_t AudioStream::open(const AudioStreamBuilder& builder)
{
// Call here as well because the AAudioService will call this without calling build().
@@ -106,20 +98,6 @@
mDataCallbackUserData = builder.getDataCallbackUserData();
mErrorCallbackUserData = builder.getErrorCallbackUserData();
- // This is very helpful for debugging in the future. Please leave it in.
- ALOGI("open() rate = %d, channels = %d, format = %d, sharing = %s, dir = %s",
- mSampleRate, mSamplesPerFrame, mFormat,
- AudioStream_convertSharingModeToShortText(mSharingMode),
- (getDirection() == AAUDIO_DIRECTION_OUTPUT) ? "OUTPUT" : "INPUT");
- ALOGI("open() device = %d, sessionId = %d, perfMode = %d, callback: %s with frames = %d",
- mDeviceId,
- mSessionId,
- mPerformanceMode,
- (isDataCallbackSet() ? "ON" : "OFF"),
- mFramesPerDataCallback);
- ALOGI("open() usage = %d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
- mUsage, mContentType, mInputPreset, mAllowedCapturePolicy);
-
return AAUDIO_OK;
}
@@ -278,15 +256,15 @@
}
void AudioStream::setState(aaudio_stream_state_t state) {
- ALOGV("%s(%p) from %d to %d", __func__, this, mState, state);
+ ALOGV("%s(%d) from %d to %d", __func__, getId(), mState, state);
// CLOSED is a final state
if (mState == AAUDIO_STREAM_STATE_CLOSED) {
- ALOGE("%s(%p) tried to set to %d but already CLOSED", __func__, this, state);
+ ALOGE("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
// Once DISCONNECTED, we can only move to CLOSED state.
} else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
&& state != AAUDIO_STREAM_STATE_CLOSED) {
- ALOGE("%s(%p) tried to set to %d but already DISCONNECTED", __func__, this, state);
+ ALOGE("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
} else {
mState = state;
@@ -485,7 +463,6 @@
}
AudioStream::MyPlayerBase::~MyPlayerBase() {
- ALOGV("MyPlayerBase::~MyPlayerBase(%p) deleted", this);
}
void AudioStream::MyPlayerBase::registerWithAudioManager() {
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 32713b1..044c979 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -36,6 +36,7 @@
namespace aaudio {
typedef void *(*aaudio_audio_thread_proc_t)(void *);
+typedef uint32_t aaudio_stream_id_t;
class AudioStreamBuilder;
@@ -121,6 +122,12 @@
return AAUDIO_OK;
}
+ // This is only used to identify a stream in the logs without
+ // revealing any pointers.
+ aaudio_stream_id_t getId() {
+ return mStreamId;
+ }
+
virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0;
virtual aaudio_result_t createThread(int64_t periodNanoseconds,
@@ -587,6 +594,8 @@
void *mThreadArg = nullptr;
aaudio_result_t mThreadRegistrationResult = AAUDIO_OK;
+ const aaudio_stream_id_t mStreamId;
+
};
} /* namespace aaudio */
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.cpp b/media/libaaudio/src/core/AudioStreamBuilder.cpp
index 4ef765d..08f4958 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.cpp
+++ b/media/libaaudio/src/core/AudioStreamBuilder.cpp
@@ -104,6 +104,8 @@
}
*streamPtr = nullptr;
+ logParameters();
+
aaudio_result_t result = validate();
if (result != AAUDIO_OK) {
return result;
@@ -217,3 +219,41 @@
return AAUDIO_OK;
}
+
+static const char *AAudio_convertSharingModeToShortText(aaudio_sharing_mode_t sharingMode) {
+ switch (sharingMode) {
+ case AAUDIO_SHARING_MODE_EXCLUSIVE:
+ return "EX";
+ case AAUDIO_SHARING_MODE_SHARED:
+ return "SH";
+ default:
+ return "?!";
+ }
+}
+
+static const char *AAudio_convertDirectionToText(aaudio_direction_t direction) {
+ switch (direction) {
+ case AAUDIO_DIRECTION_OUTPUT:
+ return "OUTPUT";
+ case AAUDIO_DIRECTION_INPUT:
+ return "INPUT";
+ default:
+ return "?!";
+ }
+}
+
+void AudioStreamBuilder::logParameters() const {
+ // This is very helpful for debugging in the future. Please leave it in.
+ ALOGI("rate = %6d, channels = %d, format = %d, sharing = %s, dir = %s",
+ getSampleRate(), getSamplesPerFrame(), getFormat(),
+ AAudio_convertSharingModeToShortText(getSharingMode()),
+ AAudio_convertDirectionToText(getDirection()));
+ ALOGI("device = %6d, sessionId = %d, perfMode = %d, callback: %s with frames = %d",
+ getDeviceId(),
+ getSessionId(),
+ getPerformanceMode(),
+ ((getDataCallbackProc() != nullptr) ? "ON" : "OFF"),
+ mFramesPerDataCallback);
+ ALOGI("usage = %6d, contentType = %d, inputPreset = %d, allowedCapturePolicy = %d",
+ getUsage(), getContentType(), getInputPreset(), getAllowedCapturePolicy());
+}
diff --git a/media/libaaudio/src/core/AudioStreamBuilder.h b/media/libaaudio/src/core/AudioStreamBuilder.h
index a43cfa8..8149af2 100644
--- a/media/libaaudio/src/core/AudioStreamBuilder.h
+++ b/media/libaaudio/src/core/AudioStreamBuilder.h
@@ -102,6 +102,8 @@
virtual aaudio_result_t validate() const override;
+ void logParameters() const;
+
private:
bool mSharingModeMatchRequired = false; // must match sharing mode requested
aaudio_performance_mode_t mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
diff --git a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
index 2edab58..91d2eff 100644
--- a/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
+++ b/media/libaaudio/src/legacy/AudioStreamLegacy.cpp
@@ -206,7 +206,9 @@
void AudioStreamLegacy::onAudioDeviceUpdate(audio_port_handle_t deviceId)
{
- ALOGD("onAudioDeviceUpdate() deviceId %d", (int)deviceId);
+ // Device routing is a common source of errors and DISCONNECTS.
+ // Please leave this log in place.
+ ALOGD("%s() devId %d => %d", __func__, (int) getDeviceId(), (int)deviceId);
if (getDeviceId() != AAUDIO_UNSPECIFIED && getDeviceId() != deviceId &&
getState() != AAUDIO_STREAM_STATE_DISCONNECTED) {
// Note that isDataCallbackActive() is affected by state so call it before DISCONNECTING.
diff --git a/media/libaudioclient/AudioSystem.cpp b/media/libaudioclient/AudioSystem.cpp
index f324669..de82d2b 100644
--- a/media/libaudioclient/AudioSystem.cpp
+++ b/media/libaudioclient/AudioSystem.cpp
@@ -1067,6 +1067,13 @@
return aps->setEffectEnabled(id, enabled);
}
+status_t AudioSystem::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->moveEffectsToIo(ids, io);
+}
+
status_t AudioSystem::isStreamActive(audio_stream_type_t stream, bool* state, uint32_t inPastMs)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 825cd4e..dd95e34 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -89,6 +89,7 @@
GET_MICROPHONES,
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
+ SET_EFFECT_SUSPENDED,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -718,6 +719,18 @@
return reply.readInt32();
}
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ data.writeInt32(sessionId);
+ data.writeInt32(suspended ? 1 : 0);
+ remote()->transact(SET_EFFECT_SUSPENDED, data, &reply);
+ }
+
virtual audio_module_handle_t loadHwModule(const char *name)
{
Parcel data, reply;
@@ -913,6 +926,7 @@
case INVALIDATE_STREAM:
case SET_VOICE_VOLUME:
case MOVE_EFFECTS:
+ case SET_EFFECT_SUSPENDED:
case LOAD_HW_MODULE:
case LIST_AUDIO_PORTS:
case GET_AUDIO_PORT:
@@ -926,6 +940,7 @@
// return status only for non void methods
switch (code) {
case SET_RECORD_SILENCED:
+ case SET_EFFECT_SUSPENDED:
break;
default:
reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
@@ -1371,6 +1386,14 @@
reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
return NO_ERROR;
} break;
+ case SET_EFFECT_SUSPENDED: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int effectId = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
+ bool suspended = data.readInt32() == 1;
+ setEffectSuspended(effectId, sessionId, suspended);
+ return NO_ERROR;
+ } break;
case LOAD_HW_MODULE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
reply->writeInt32(loadHwModule(data.readCString()));
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index bf98c60..4a8bb52 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -103,6 +103,7 @@
LIST_AUDIO_VOLUME_GROUPS,
GET_VOLUME_GROUP_FOR_ATTRIBUTES,
SET_ALLOWED_CAPTURE_POLICY,
+ MOVE_EFFECTS_TO_IO,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -550,6 +551,22 @@
return static_cast <status_t> (reply.readInt32());
}
+ status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(ids.size());
+ for (auto id : ids) {
+ data.writeInt32(id);
+ }
+ data.writeInt32(io);
+ status_t status = remote()->transact(MOVE_EFFECTS_TO_IO, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
+
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
Parcel data, reply;
@@ -1284,6 +1301,7 @@
case GET_OUTPUT_FOR_ATTR:
case ACQUIRE_SOUNDTRIGGER_SESSION:
case RELEASE_SOUNDTRIGGER_SESSION:
+ case MOVE_EFFECTS_TO_IO:
ALOGW("%s: transaction %d received from PID %d",
__func__, code, IPCThreadState::self()->getCallingPid());
// return status only for non void methods
@@ -1700,6 +1718,31 @@
return NO_ERROR;
} break;
+ case MOVE_EFFECTS_TO_IO: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ std::vector<int> ids;
+ int32_t size;
+ status_t status = data.readInt32(&size);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ if (size > MAX_ITEMS_PER_LIST) {
+ return BAD_VALUE;
+ }
+ for (int32_t i = 0; i < size; i++) {
+ int id;
+ status = data.readInt32(&id);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ ids.push_back(id);
+ }
+
+ audio_io_handle_t io = data.readInt32();
+ reply->writeInt32(static_cast <int32_t>(moveEffectsToIo(ids, io)));
+ return NO_ERROR;
+ } break;
+
case IS_STREAM_ACTIVE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_stream_type_t stream = (audio_stream_type_t) data.readInt32();
diff --git a/media/libaudioclient/include/media/AudioSystem.h b/media/libaudioclient/include/media/AudioSystem.h
index 05a1d56..d180bbc 100644
--- a/media/libaudioclient/include/media/AudioSystem.h
+++ b/media/libaudioclient/include/media/AudioSystem.h
@@ -286,6 +286,7 @@
int id);
static status_t unregisterEffect(int id);
static status_t setEffectEnabled(int id, bool enabled);
+ static status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io);
// clear stream to output mapping cache (gStreamOutputMap)
// and output configuration cache (gOutputs)
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index ef0ed0c..dcc18b6 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -457,6 +457,10 @@
virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) = 0;
+
virtual audio_module_handle_t loadHwModule(const char *name) = 0;
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index 95530ac..11983d5 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -114,6 +114,7 @@
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual status_t setEffectEnabled(int id, bool enabled) = 0;
+ virtual status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) = 0;
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0)
const = 0;
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 50c33c6..5fab5be 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -926,7 +926,7 @@
delete session->revBuf;
session->revBuf = NULL;
- session->io = 0;
+ session->id = 0;
}
return 0;
@@ -1155,7 +1155,7 @@
{
size_t i;
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
- if (sSessions[i].io == ioId) {
+ if (sSessions[i].id == sessionId) {
if (sSessions[i].createdMsk & (1 << procId)) {
return NULL;
}
@@ -1163,7 +1163,7 @@
}
}
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
- if (sSessions[i].io == 0) {
+ if (sSessions[i].id == 0) {
sSessions[i].id = sessionId;
sSessions[i].io = ioId;
return &sSessions[i];
@@ -1915,7 +1915,7 @@
status = Session_CreateEffect(session, procId, pInterface);
if (status < 0 && session->createdMsk == 0) {
- session->io = 0;
+ session->id = 0;
}
return status;
}
@@ -1929,7 +1929,7 @@
preproc_effect_t *fx = (preproc_effect_t *)interface;
- if (fx->session->io == 0) {
+ if (fx->session->id == 0) {
return -EINVAL;
}
return Session_ReleaseEffect(fx->session, fx);
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index b1fdb2c..2ca5eee 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -1659,10 +1659,12 @@
return;
}
int32_t colorFormat;
- if (mSoftRenderer != NULL
- && mOutputFormat->contains("hdr-static-info")
+ if (mOutputFormat->contains("hdr-static-info")
&& mOutputFormat->findInt32("color-format", &colorFormat)
- && (colorFormat == OMX_COLOR_FormatYUV420Planar16)) {
+ // check format for OMX only, for C2 the format is always opaque since the
+ // software rendering doesn't go through client
+ && ((mSoftRenderer != NULL && colorFormat == OMX_COLOR_FormatYUV420Planar16)
+ || mOwnerName.equalsIgnoreCase("codec2::software"))) {
int32_t left, top, right, bottom, width, height;
int64_t totalPixel = 0;
if (mOutputFormat->findRect("crop", &left, &top, &right, &bottom)) {
@@ -1958,6 +1960,7 @@
} else {
mFlags &= ~kFlagUsesSoftwareRenderer;
}
+ mOwnerName = owner;
MediaResource::Type resourceType;
if (mComponentName.endsWith(".secure")) {
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index c7b2719..537e4c0 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1756,7 +1756,11 @@
size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
}
- } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
+ } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC ||
+ mime == MEDIA_MIMETYPE_VIDEO_MPEG4 ||
+ mime == MEDIA_MIMETYPE_AUDIO_WMA ||
+ mime == MEDIA_MIMETYPE_AUDIO_MS_ADPCM ||
+ mime == MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) {
std::vector<char> esds(csd0size + 31);
// The written ESDS is actually for an audio stream, but it's enough
// for transporting the CSD to muxers.
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index 52b2765..a08fed1 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -59,6 +59,10 @@
const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
+const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
+const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM = "audio/x-adpcm-ms";
+const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";
+
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 007a09b..1f9e636 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -61,6 +61,10 @@
extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
+extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
+extern const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
+extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;
+
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
diff --git a/media/libstagefright/include/media/stagefright/MediaCodec.h b/media/libstagefright/include/media/stagefright/MediaCodec.h
index 7f6aae6..6cd4265 100644
--- a/media/libstagefright/include/media/stagefright/MediaCodec.h
+++ b/media/libstagefright/include/media/stagefright/MediaCodec.h
@@ -313,6 +313,7 @@
sp<ALooper> mCodecLooper;
sp<CodecBase> mCodec;
AString mComponentName;
+ AString mOwnerName;
sp<MediaCodecInfo> mCodecInfo;
sp<AReplyToken> mReplyID;
uint32_t mFlags;
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 0825cb4..55db699 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -687,6 +687,10 @@
bool updatePid = (input.clientInfo.clientPid == -1);
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
uid_t clientUid = input.clientInfo.clientUid;
+ audio_io_handle_t effectThreadId = AUDIO_IO_HANDLE_NONE;
+ std::vector<int> effectIds;
+
+
if (!isAudioServerOrMediaServerUid(callingUid)) {
ALOGW_IF(clientUid != callingUid,
"%s uid %d tried to pass itself off as %d",
@@ -851,7 +855,10 @@
// no risk of deadlock because AudioFlinger::mLock is held
Mutex::Autolock _dl(thread->mLock);
Mutex::Autolock _sl(effectThread->mLock);
- moveEffectChain_l(sessionId, effectThread, thread, true);
+ if (moveEffectChain_l(sessionId, effectThread, thread) == NO_ERROR) {
+ effectThreadId = thread->id();
+ effectIds = thread->getEffectIds_l(sessionId);
+ }
}
// Look for sync events awaiting for a session to be used.
@@ -885,6 +892,12 @@
goto Exit;
}
+ // effectThreadId is not NONE if an effect chain corresponding to the track session
+ // was found on another thread and must be moved on this thread
+ if (effectThreadId != AUDIO_IO_HANDLE_NONE) {
+ AudioSystem::moveEffectsToIo(effectIds, effectThreadId);
+ }
+
// return handle to client
trackHandle = new TrackHandle(track);
@@ -1225,7 +1238,8 @@
if (output == AUDIO_IO_HANDLE_NONE) {
return BAD_VALUE;
}
- ALOG_ASSERT(stream != AUDIO_STREAM_PATCH, "attempt to change AUDIO_STREAM_PATCH volume");
+ LOG_ALWAYS_FATAL_IF(stream == AUDIO_STREAM_PATCH && value != 1.0f,
+ "AUDIO_STREAM_PATCH must have full scale volume");
AutoMutex lock(mLock);
VolumeInterface *volumeInterface = getVolumeInterface_l(output);
@@ -1630,30 +1644,36 @@
void AudioFlinger::removeNotificationClient(pid_t pid)
{
- Mutex::Autolock _l(mLock);
+ std::vector< sp<AudioFlinger::EffectModule> > removedEffects;
{
- Mutex::Autolock _cl(mClientLock);
- mNotificationClients.removeItem(pid);
- }
+ Mutex::Autolock _l(mLock);
+ {
+ Mutex::Autolock _cl(mClientLock);
+ mNotificationClients.removeItem(pid);
+ }
- ALOGV("%d died, releasing its sessions", pid);
- size_t num = mAudioSessionRefs.size();
- bool removed = false;
- for (size_t i = 0; i < num; ) {
- AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
- ALOGV(" pid %d @ %zu", ref->mPid, i);
- if (ref->mPid == pid) {
- ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
- mAudioSessionRefs.removeAt(i);
- delete ref;
- removed = true;
- num--;
- } else {
- i++;
+ ALOGV("%d died, releasing its sessions", pid);
+ size_t num = mAudioSessionRefs.size();
+ bool removed = false;
+ for (size_t i = 0; i < num; ) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ ALOGV(" pid %d @ %zu", ref->mPid, i);
+ if (ref->mPid == pid) {
+ ALOGV(" removing entry for pid %d session %d", pid, ref->mSessionid);
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ removed = true;
+ num--;
+ } else {
+ i++;
+ }
+ }
+ if (removed) {
+ removedEffects = purgeStaleEffects_l();
}
}
- if (removed) {
- purgeStaleEffects_l();
+ for (auto& effect : removedEffects) {
+ effect->updatePolicyState();
}
}
@@ -1679,18 +1699,35 @@
}
// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
- int EffectId)
+sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+ int effectId)
{
- sp<PlaybackThread> thread;
+ sp<ThreadBase> thread;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
+ if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
ALOG_ASSERT(thread == 0);
thread = mPlaybackThreads.valueAt(i);
}
}
-
+ if (thread != nullptr) {
+ return thread;
+ }
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ if (mRecordThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+ ALOG_ASSERT(thread == 0);
+ thread = mRecordThreads.valueAt(i);
+ }
+ }
+ if (thread != nullptr) {
+ return thread;
+ }
+ for (size_t i = 0; i < mMmapThreads.size(); i++) {
+ if (mMmapThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+ ALOG_ASSERT(thread == 0);
+ thread = mMmapThreads.valueAt(i);
+ }
+ }
return thread;
}
@@ -2425,7 +2462,7 @@
Vector< sp<EffectChain> > effectChains = playbackThread->getEffectChains_l();
for (size_t i = 0; i < effectChains.size(); i ++) {
moveEffectChain_l(effectChains[i]->sessionId(), playbackThread.get(),
- dstThread, true);
+ dstThread);
}
}
}
@@ -2792,31 +2829,40 @@
void AudioFlinger::releaseAudioSessionId(audio_session_t audioSession, pid_t pid)
{
- Mutex::Autolock _l(mLock);
- pid_t caller = IPCThreadState::self()->getCallingPid();
- ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
- const uid_t callerUid = IPCThreadState::self()->getCallingUid();
- if (pid != -1 && isAudioServerUid(callerUid)) { // check must match acquireAudioSessionId()
- caller = pid;
- }
- size_t num = mAudioSessionRefs.size();
- for (size_t i = 0; i < num; i++) {
- AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
- if (ref->mSessionid == audioSession && ref->mPid == caller) {
- ref->mCnt--;
- ALOGV(" decremented refcount to %d", ref->mCnt);
- if (ref->mCnt == 0) {
- mAudioSessionRefs.removeAt(i);
- delete ref;
- purgeStaleEffects_l();
- }
- return;
+ std::vector< sp<EffectModule> > removedEffects;
+ {
+ Mutex::Autolock _l(mLock);
+ pid_t caller = IPCThreadState::self()->getCallingPid();
+ ALOGV("releasing %d from %d for %d", audioSession, caller, pid);
+ const uid_t callerUid = IPCThreadState::self()->getCallingUid();
+ if (pid != -1 && isAudioServerUid(callerUid)) { // check must match acquireAudioSessionId()
+ caller = pid;
}
+ size_t num = mAudioSessionRefs.size();
+ for (size_t i = 0; i < num; i++) {
+ AudioSessionRef *ref = mAudioSessionRefs.itemAt(i);
+ if (ref->mSessionid == audioSession && ref->mPid == caller) {
+ ref->mCnt--;
+ ALOGV(" decremented refcount to %d", ref->mCnt);
+ if (ref->mCnt == 0) {
+ mAudioSessionRefs.removeAt(i);
+ delete ref;
+ std::vector< sp<EffectModule> > effects = purgeStaleEffects_l();
+ removedEffects.insert(removedEffects.end(), effects.begin(), effects.end());
+ }
+ goto Exit;
+ }
+ }
+ // If the caller is audioserver it is likely that the session being released was acquired
+ // on behalf of a process not in notification clients and we ignore the warning.
+ ALOGW_IF(!isAudioServerUid(callerUid),
+ "session id %d not found for pid %d", audioSession, caller);
}
- // If the caller is audioserver it is likely that the session being released was acquired
- // on behalf of a process not in notification clients and we ignore the warning.
- ALOGW_IF(!isAudioServerUid(callerUid),
- "session id %d not found for pid %d", audioSession, caller);
+
+Exit:
+ for (auto& effect : removedEffects) {
+ effect->updatePolicyState();
+ }
}
bool AudioFlinger::isSessionAcquired_l(audio_session_t audioSession)
@@ -2831,11 +2877,12 @@
return false;
}
-void AudioFlinger::purgeStaleEffects_l() {
+std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l() {
ALOGV("purging stale effects");
Vector< sp<EffectChain> > chains;
+ std::vector< sp<EffectModule> > removedEffects;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
sp<PlaybackThread> t = mPlaybackThreads.valueAt(i);
@@ -2847,6 +2894,7 @@
}
}
}
+
for (size_t i = 0; i < mRecordThreads.size(); i++) {
sp<RecordThread> t = mRecordThreads.valueAt(i);
Mutex::Autolock _l(t->mLock);
@@ -2856,6 +2904,15 @@
}
}
+ for (size_t i = 0; i < mMmapThreads.size(); i++) {
+ sp<MmapThread> t = mMmapThreads.valueAt(i);
+ Mutex::Autolock _l(t->mLock);
+ for (size_t j = 0; j < t->mEffectChains.size(); j++) {
+ sp<EffectChain> ec = t->mEffectChains[j];
+ chains.push(ec);
+ }
+ }
+
for (size_t i = 0; i < chains.size(); i++) {
sp<EffectChain> ec = chains[i];
int sessionid = ec->sessionId();
@@ -2884,11 +2941,11 @@
if (effect->purgeHandles()) {
t->checkSuspendOnEffectEnabled_l(effect, false, effect->sessionId());
}
- AudioSystem::unregisterEffect(effect->id());
+ removedEffects.push_back(effect);
}
}
}
- return;
+ return removedEffects;
}
// dumpToThreadLog_l() must be called with AudioFlinger::mLock held
@@ -3380,8 +3437,16 @@
}
}
- if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {
- // handle must be cleared outside lock.
+ if (lStatus == NO_ERROR || lStatus == ALREADY_EXISTS) {
+ // Check CPU and memory usage
+ sp<EffectModule> effect = handle->effect().promote();
+ if (effect != nullptr) {
+ status_t rStatus = effect->updatePolicyState();
+ if (rStatus != NO_ERROR) {
+ lStatus = rStatus;
+ }
+ }
+ } else {
handle.clear();
}
@@ -3413,14 +3478,30 @@
Mutex::Autolock _dl(dstThread->mLock);
Mutex::Autolock _sl(srcThread->mLock);
- return moveEffectChain_l(sessionId, srcThread, dstThread, false);
+ return moveEffectChain_l(sessionId, srcThread, dstThread);
}
+
+void AudioFlinger::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ Mutex::Autolock _l(mLock);
+
+ sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+ if (thread == nullptr) {
+ return;
+ }
+ Mutex::Autolock _sl(thread->mLock);
+ sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+ thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
+}
+
+
// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
AudioFlinger::PlaybackThread *srcThread,
- AudioFlinger::PlaybackThread *dstThread,
- bool reRegister)
+ AudioFlinger::PlaybackThread *dstThread)
{
ALOGV("moveEffectChain_l() session %d from thread %p to thread %p",
sessionId, srcThread, dstThread);
@@ -3476,36 +3557,68 @@
}
strategy = dstChain->strategy();
}
- if (reRegister) {
- AudioSystem::unregisterEffect(effect->id());
- AudioSystem::registerEffect(&effect->desc(),
- dstThread->id(),
- strategy,
- sessionId,
- effect->id());
- AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
- }
effect = chain->getEffectFromId_l(0);
}
if (status != NO_ERROR) {
for (size_t i = 0; i < removed.size(); i++) {
srcThread->addEffect_l(removed[i]);
- if (dstChain != 0 && reRegister) {
- AudioSystem::unregisterEffect(removed[i]->id());
- AudioSystem::registerEffect(&removed[i]->desc(),
- srcThread->id(),
- strategy,
- sessionId,
- removed[i]->id());
- AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
- }
}
}
return status;
}
+status_t AudioFlinger::moveAuxEffectToIo(int EffectId,
+ const sp<PlaybackThread>& dstThread,
+ sp<PlaybackThread> *srcThread)
+{
+ status_t status = NO_ERROR;
+ Mutex::Autolock _l(mLock);
+ sp<PlaybackThread> thread =
+ static_cast<PlaybackThread *>(getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId).get());
+
+ if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
+ Mutex::Autolock _dl(dstThread->mLock);
+ Mutex::Autolock _sl(thread->mLock);
+ sp<EffectChain> srcChain = thread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
+ sp<EffectChain> dstChain;
+ if (srcChain == 0) {
+ return INVALID_OPERATION;
+ }
+
+ sp<EffectModule> effect = srcChain->getEffectFromId_l(EffectId);
+ if (effect == 0) {
+ return INVALID_OPERATION;
+ }
+ thread->removeEffect_l(effect);
+ status = dstThread->addEffect_l(effect);
+ if (status != NO_ERROR) {
+ thread->addEffect_l(effect);
+ status = INVALID_OPERATION;
+ goto Exit;
+ }
+
+ dstChain = effect->chain().promote();
+ if (dstChain == 0) {
+ thread->addEffect_l(effect);
+ status = INVALID_OPERATION;
+ }
+
+Exit:
+ // removeEffect_l() has stopped the effect if it was active so it must be restarted
+ if (effect->state() == EffectModule::ACTIVE ||
+ effect->state() == EffectModule::STOPPING) {
+ effect->start();
+ }
+ }
+
+ if (status == NO_ERROR && srcThread != nullptr) {
+ *srcThread = thread;
+ }
+ return status;
+}
+
bool AudioFlinger::isNonOffloadableGlobalEffectEnabled_l()
{
if (mGlobalEffectEnableTime != 0 &&
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9960f0e..72e669a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -239,6 +239,10 @@
virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) override;
+
virtual audio_module_handle_t loadHwModule(const char *name);
virtual uint32_t getPrimaryOutputSamplingRate();
@@ -369,7 +373,6 @@
AudioHwDevice* findSuitableHwDev_l(audio_module_handle_t module,
audio_devices_t devices);
- void purgeStaleEffects_l();
// Set kEnableExtendedChannels to true to enable greater than stereo output
// for the MixerThread and device sink. Number of channels allowed is
@@ -696,8 +699,11 @@
status_t moveEffectChain_l(audio_session_t sessionId,
PlaybackThread *srcThread,
- PlaybackThread *dstThread,
- bool reRegister);
+ PlaybackThread *dstThread);
+
+ status_t moveAuxEffectToIo(int EffectId,
+ const sp<PlaybackThread>& dstThread,
+ sp<PlaybackThread> *srcThread);
// return thread associated with primary hardware device, or NULL
PlaybackThread *primaryPlaybackThread_l() const;
@@ -706,7 +712,7 @@
// return the playback thread with smallest HAL buffer size, and prefer fast
PlaybackThread *fastPlaybackThread_l() const;
- sp<PlaybackThread> getEffectThread_l(audio_session_t sessionId, int EffectId);
+ sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
void removeClient_l(pid_t pid);
@@ -732,6 +738,8 @@
// Return true if the effect was found in mOrphanEffectChains, false otherwise.
bool updateOrphanEffectChains(const sp<EffectModule>& effect);
+ std::vector< sp<EffectModule> > purgeStaleEffects_l();
+
void broacastParametersToRecordThreads_l(const String8& keyValuePairs);
void forwardParametersToDownstreamPatches_l(
audio_io_handle_t upStream, const String8& keyValuePairs,
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 2b34267..3c4fbba 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -168,6 +168,68 @@
return status;
}
+status_t AudioFlinger::EffectModule::updatePolicyState()
+{
+ status_t status = NO_ERROR;
+ bool doRegister = false;
+ bool registered = false;
+ bool doEnable = false;
+ bool enabled = false;
+ audio_io_handle_t io;
+ uint32_t strategy;
+
+ {
+ Mutex::Autolock _l(mLock);
+ // register effect when first handle is attached and unregister when last handle is removed
+ if (mPolicyRegistered != mHandles.size() > 0) {
+ doRegister = true;
+ mPolicyRegistered = mHandles.size() > 0;
+ if (mPolicyRegistered) {
+ sp <EffectChain> chain = mChain.promote();
+ sp <ThreadBase> thread = mThread.promote();
+
+ if (thread == nullptr || chain == nullptr) {
+ return INVALID_OPERATION;
+ }
+ io = thread->id();
+ strategy = chain->strategy();
+ }
+ }
+ // enable effect when registered according to enable state requested by controlling handle
+ if (mHandles.size() > 0) {
+ EffectHandle *handle = controlHandle_l();
+ if (handle != nullptr && mPolicyEnabled != handle->enabled()) {
+ doEnable = true;
+ mPolicyEnabled = handle->enabled();
+ }
+ }
+ registered = mPolicyRegistered;
+ enabled = mPolicyEnabled;
+ mPolicyLock.lock();
+ }
+ ALOGV("%s name %s id %d session %d doRegister %d registered %d doEnable %d enabled %d",
+ __func__, mDescriptor.name, mId, mSessionId, doRegister, registered, doEnable, enabled);
+ if (doRegister) {
+ if (registered) {
+ status = AudioSystem::registerEffect(
+ &mDescriptor,
+ io,
+ strategy,
+ mSessionId,
+ mId);
+ } else {
+ status = AudioSystem::unregisterEffect(mId);
+ }
+ }
+ if (registered && doEnable) {
+ status = AudioSystem::setEffectEnabled(mId, enabled);
+ }
+ mPolicyLock.unlock();
+
+ return status;
+}
+
+
ssize_t AudioFlinger::EffectModule::removeHandle(EffectHandle *handle)
{
Mutex::Autolock _l(mLock);
@@ -230,7 +292,6 @@
Mutex::Autolock _l(mLock);
ssize_t numHandles = removeHandle_l(handle);
if ((numHandles == 0) && (!mPinned || unpinIfLast)) {
- AudioSystem::unregisterEffect(mId);
sp<AudioFlinger> af = mAudioFlinger.promote();
if (af != 0) {
mLock.unlock();
@@ -943,11 +1004,6 @@
ALOGV("setEnabled %p enabled %d", this, enabled);
if (enabled != isEnabled()) {
- status_t status = AudioSystem::setEffectEnabled(mId, enabled);
- if (enabled && status != NO_ERROR) {
- return status;
- }
-
switch (mState) {
// going from disabled to enabled
case IDLE:
@@ -1253,14 +1309,11 @@
{
bool enabled = false;
Mutex::Autolock _l(mLock);
- for (size_t i = 0; i < mHandles.size(); i++) {
- EffectHandle *handle = mHandles[i];
- if (handle != NULL && !handle->disconnected()) {
- if (handle->hasControl()) {
- enabled = handle->enabled();
- }
- }
+ EffectHandle *handle = controlHandle_l();
+ if (handle != NULL) {
+ enabled = handle->enabled();
}
+ mHandles.clear();
return enabled;
}
@@ -1435,9 +1488,10 @@
result.append("\t\tCould not lock Fx mutex:\n");
}
- result.append("\t\tSession Status State Engine:\n");
- result.appendFormat("\t\t%05d %03d %03d %p\n",
- mSessionId, mStatus, mState, mEffectInterface.get());
+ result.append("\t\tSession Status State Registered Enabled Suspended Engine:\n");
+ result.appendFormat("\t\t%05d %03d %03d %s %s %s %p\n",
+ mSessionId, mStatus, mState, mPolicyRegistered ? "y" : "n", mPolicyEnabled ? "y" : "n",
+ mSuspended ? "y" : "n", mEffectInterface.get());
result.append("\t\tDescriptor:\n");
char uuidStr[64];
@@ -1572,6 +1626,12 @@
mEnabled = true;
+ status_t status = effect->updatePolicyState();
+ if (status != NO_ERROR) {
+ mEnabled = false;
+ return status;
+ }
+
sp<ThreadBase> thread = effect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(effect, true, effect->sessionId());
@@ -1582,7 +1642,7 @@
return NO_ERROR;
}
- status_t status = effect->setEnabled(true);
+ status = effect->setEnabled(true);
if (status != NO_ERROR) {
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
@@ -1625,6 +1685,8 @@
}
mEnabled = false;
+ effect->updatePolicyState();
+
if (effect->suspended()) {
return NO_ERROR;
}
@@ -1660,20 +1722,17 @@
return;
}
mDisconnected = true;
- sp<ThreadBase> thread;
{
sp<EffectModule> effect = mEffect.promote();
if (effect != 0) {
- thread = effect->thread().promote();
- }
- }
- if (thread != 0) {
- thread->disconnectEffectHandle(this, unpinIfLast);
- } else {
- // try to cleanup as much as we can
- sp<EffectModule> effect = mEffect.promote();
- if (effect != 0 && effect->disconnectHandle(this, unpinIfLast) > 0) {
- ALOGW("%s Effect handle %p disconnected after thread destruction", __FUNCTION__, this);
+ sp<ThreadBase> thread = effect->thread().promote();
+ if (thread != 0) {
+ thread->disconnectEffectHandle(this, unpinIfLast);
+ } else if (effect->disconnectHandle(this, unpinIfLast) > 0) {
+ ALOGW("%s Effect handle %p disconnected after thread destruction",
+ __func__, this);
+ }
+ effect->updatePolicyState();
}
}
@@ -1947,6 +2006,16 @@
return 0;
}
+std::vector<int> AudioFlinger::EffectChain::getEffectIds()
+{
+ std::vector<int> ids;
+ Mutex::Autolock _l(mLock);
+ for (size_t i = 0; i < mEffects.size(); i++) {
+ ids.push_back(mEffects[i]->id());
+ }
+ return ids;
+}
+
void AudioFlinger::EffectChain::clearInputBuffer()
{
Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Effects.h b/services/audioflinger/Effects.h
index 58ce351..220874d 100644
--- a/services/audioflinger/Effects.h
+++ b/services/audioflinger/Effects.h
@@ -142,6 +142,8 @@
void addEffectToHal_l();
void release_l();
+ status_t updatePolicyState();
+
void dump(int fd, const Vector<String16>& args);
private:
@@ -204,6 +206,16 @@
static constexpr pid_t INVALID_PID = (pid_t)-1;
// this tid is allowed to call setVolume() without acquiring the mutex.
pid_t mSetVolumeReentrantTid = INVALID_PID;
+
+ // Audio policy effect state management
+ // Mutex protecting transactions with audio policy manager as mLock cannot
+ // be held to avoid cross deadlocks with audio policy mutex
+ Mutex mPolicyLock;
+ // Effect is registered in APM or not
+ bool mPolicyRegistered = false;
+ // Effect enabled state communicated to APM. Enabled state corresponds to
+ // state requested by the EffectHandle with control
+ bool mPolicyEnabled = false;
};
// The EffectHandle class implements the IEffect interface. It provides resources
@@ -334,6 +346,7 @@
sp<EffectModule> getEffectFromDesc_l(effect_descriptor_t *descriptor);
sp<EffectModule> getEffectFromId_l(int id);
sp<EffectModule> getEffectFromType_l(const effect_uuid_t *type);
+ std::vector<int> getEffectIds();
// FIXME use float to improve the dynamic range
bool setVolume_l(uint32_t *left, uint32_t *right, bool force = false);
void resetVolume_l();
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 6fea8be..59ced26 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1306,7 +1306,6 @@
sp<EffectChain> chain;
bool chainCreated = false;
bool effectCreated = false;
- bool effectRegistered = false;
audio_unique_id_t effectId = AUDIO_UNIQUE_ID_USE_UNSPECIFIED;
lStatus = initCheck();
@@ -1342,13 +1341,6 @@
if (effect == 0) {
effectId = mAudioFlinger->nextUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
- // Check CPU and memory usage
- lStatus = AudioSystem::registerEffect(
- desc, mId, chain->strategy(), sessionId, effectId);
- if (lStatus != NO_ERROR) {
- goto Exit;
- }
- effectRegistered = true;
// create a new effect module if none present in the chain
lStatus = chain->createEffect_l(effect, this, desc, effectId, sessionId, pinned);
if (lStatus != NO_ERROR) {
@@ -1378,9 +1370,6 @@
if (effectCreated) {
chain->removeEffect_l(effect);
}
- if (effectRegistered) {
- AudioSystem::unregisterEffect(effectId);
- }
if (chainCreated) {
removeEffectChain_l(chain);
}
@@ -1411,7 +1400,6 @@
}
if (remove) {
mAudioFlinger->updateOrphanEffectChains(effect);
- AudioSystem::unregisterEffect(effect->id());
if (handle->enabled()) {
checkSuspendOnEffectEnabled(effect, false, effect->sessionId());
}
@@ -1432,6 +1420,12 @@
return chain != 0 ? chain->getEffectFromId_l(effectId) : 0;
}
+std::vector<int> AudioFlinger::ThreadBase::getEffectIds_l(audio_session_t sessionId)
+{
+ sp<EffectChain> chain = getEffectChain_l(sessionId);
+ return chain != nullptr ? chain->getEffectIds() : std::vector<int>{};
+}
+
// PlaybackThread::addEffect_l() must be called with AudioFlinger::mLock and
// PlaybackThread::mLock held
status_t AudioFlinger::ThreadBase::addEffect_l(const sp<EffectModule>& effect)
@@ -2732,7 +2726,8 @@
// create a copy of mEffectChains as calling moveEffectChain_l() can reorder some effect chains
Vector< sp<EffectChain> > effectChains = mEffectChains;
for (size_t i = 0; i < effectChains.size(); i ++) {
- mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(), this, this, false);
+ mAudioFlinger->moveEffectChain_l(effectChains[i]->sessionId(),
+ this/* srcThread */, this/* dstThread */);
}
}
@@ -8253,11 +8248,6 @@
status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
{
- // only one chain per input thread
- if (!mEffectChains.isEmpty()) {
- ALOGW("addEffectChain_l() already one chain %p on thread %p", chain.get(), this);
- return INVALID_OPERATION;
- }
ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
chain->setThread(this);
chain->setInBuffer(NULL);
@@ -8277,13 +8267,14 @@
size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
{
ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
- ALOGW_IF(mEffectChains.size() != 1,
- "removeEffectChain_l() %p invalid chain size %zu on thread %p",
- chain.get(), mEffectChains.size(), this);
- if (mEffectChains.size() == 1) {
- mEffectChains.removeAt(0);
+
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ if (chain == mEffectChains[i]) {
+ mEffectChains.removeAt(i);
+ break;
+ }
}
- return 0;
+ return mEffectChains.size();
}
status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 18cb361..37b2d08 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -315,6 +315,7 @@
sp<EffectChain> getEffectChain(audio_session_t sessionId);
// same as getEffectChain() but must be called with ThreadBase mutex locked
sp<EffectChain> getEffectChain_l(audio_session_t sessionId) const;
+ std::vector<int> getEffectIds_l(audio_session_t sessionId);
// add an effect chain to the chain list (mEffectChains)
virtual status_t addEffectChain_l(const sp<EffectChain>& chain) = 0;
// remove an effect chain from the chain list (mEffectChains)
@@ -334,7 +335,8 @@
sp<AudioFlinger::EffectModule> getEffect(audio_session_t sessionId, int effectId);
sp<AudioFlinger::EffectModule> getEffect_l(audio_session_t sessionId, int effectId);
// add and effect module. Also creates the effect chain is none exists for
- // the effects audio session
+ // the effects audio session. Only called in a context of moving an effect
+ // from one thread to another
status_t addEffect_l(const sp< EffectModule>& effect);
// remove and effect module. Also removes the effect chain is this was the last
// effect
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index bbda17f..2ff80c6 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1244,54 +1244,25 @@
status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
{
- status_t status = DEAD_OBJECT;
sp<ThreadBase> thread = mThread.promote();
- if (thread != 0) {
- PlaybackThread *playbackThread = (PlaybackThread *)thread.get();
- sp<AudioFlinger> af = mClient->audioFlinger();
+ if (thread == nullptr) {
+ return DEAD_OBJECT;
+ }
- Mutex::Autolock _l(af->mLock);
+ sp<PlaybackThread> dstThread = (PlaybackThread *)thread.get();
+ sp<PlaybackThread> srcThread; // srcThread is initialized by call to moveAuxEffectToIo()
+ sp<AudioFlinger> af = mClient->audioFlinger();
+ status_t status = af->moveAuxEffectToIo(EffectId, dstThread, &srcThread);
- sp<PlaybackThread> srcThread = af->getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
-
- if (EffectId != 0 && srcThread != 0 && playbackThread != srcThread.get()) {
- Mutex::Autolock _dl(playbackThread->mLock);
- Mutex::Autolock _sl(srcThread->mLock);
- sp<EffectChain> chain = srcThread->getEffectChain_l(AUDIO_SESSION_OUTPUT_MIX);
- if (chain == 0) {
- return INVALID_OPERATION;
- }
-
- sp<EffectModule> effect = chain->getEffectFromId_l(EffectId);
- if (effect == 0) {
- return INVALID_OPERATION;
- }
- srcThread->removeEffect_l(effect);
- status = playbackThread->addEffect_l(effect);
- if (status != NO_ERROR) {
- srcThread->addEffect_l(effect);
- return INVALID_OPERATION;
- }
- // removeEffect_l() has stopped the effect if it was active so it must be restarted
- if (effect->state() == EffectModule::ACTIVE ||
- effect->state() == EffectModule::STOPPING) {
- effect->start();
- }
-
- sp<EffectChain> dstChain = effect->chain().promote();
- if (dstChain == 0) {
- srcThread->addEffect_l(effect);
- return INVALID_OPERATION;
- }
- AudioSystem::unregisterEffect(effect->id());
- AudioSystem::registerEffect(&effect->desc(),
- srcThread->id(),
- dstChain->strategy(),
- AUDIO_SESSION_OUTPUT_MIX,
- effect->id());
- AudioSystem::setEffectEnabled(effect->id(), effect->isEnabled());
+ if (EffectId != 0 && status == NO_ERROR) {
+ status = dstThread->attachAuxEffect(this, EffectId);
+ if (status == NO_ERROR) {
+ AudioSystem::moveEffectsToIo(std::vector<int>(EffectId), dstThread->id());
}
- status = playbackThread->attachAuxEffect(this, EffectId);
+ }
+
+ if (status != NO_ERROR && srcThread != nullptr) {
+ af->moveAuxEffectToIo(EffectId, srcThread, &dstThread);
}
return status;
}
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index a2cf7aa..4b56a46 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -189,6 +189,7 @@
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual status_t setEffectEnabled(int id, bool enabled) = 0;
+ virtual status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) = 0;
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const = 0;
virtual bool isStreamActiveRemotely(audio_stream_type_t stream,
@@ -347,6 +348,10 @@
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) = 0;
+
/* Create a patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/common/include/Volume.h b/services/audiopolicy/common/include/Volume.h
index 54c5c76..1dbd1eb 100644
--- a/services/audiopolicy/common/include/Volume.h
+++ b/services/audiopolicy/common/include/Volume.h
@@ -23,7 +23,6 @@
namespace android {
-
/**
* VolumeSource is the discriminent for volume management on an output.
* It used to be the stream type by legacy, it may be host volume group or a volume curves if
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index e071fe0..37f9d14 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -68,11 +68,13 @@
bool isSourceActive(audio_source_t source) const;
audio_source_t source() const;
bool isSoundTrigger() const;
+ sp<RecordClientDescriptor> getHighestPriorityClient() const;
audio_attributes_t getHighestPriorityAttributes() const;
void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
int32_t activeCount() { return mGlobalActiveCount; }
void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
EffectDescriptorCollection getEnabledEffects() const;
+ EffectDescriptorCollection getActiveEffects() const; // enabled and not suspended
// implementation of AudioIODescriptorInterface
audio_config_base_t getConfig() const override;
audio_patch_handle_t getPatchHandle() const override;
@@ -100,6 +102,10 @@
// implementation of ClientMapHandler<RecordClientDescriptor>
void addClient(const sp<RecordClientDescriptor> &client) override;
+ // Go over all active clients and suspend or restore effects according highest priority
+ // active use case
+ void checkSuspendEffects();
+
private:
void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 7f01dc5..c4eab30 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -29,8 +29,8 @@
{
public:
EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
- int id, int io, int session) :
- mId(id), mIo(io), mSession(session), mEnabled(false),
+ int id, audio_io_handle_t io, audio_session_t session) :
+ mId(id), mIo(io), mSession(session), mEnabled(false), mSuspended(false),
mIsMusicEffect(isMusicEffect)
{
memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
@@ -38,11 +38,12 @@
void dump(String8 *dst, int spaces = 0) const;
- int mId; // effect unique ID
- int mIo; // io the effect is attached to
- int mSession; // audio session the effect is on
- effect_descriptor_t mDesc; // effect descriptor
- bool mEnabled; // enabled state: CPU load being used or not
+ int mId; // effect unique ID
+ audio_io_handle_t mIo; // io the effect is attached to
+ audio_session_t mSession; // audio session the effect is on
+ effect_descriptor_t mDesc; // effect descriptor
+ bool mEnabled; // enabled state: CPU load being used or not
+ bool mSuspended; // enabled but suspended by concurent capture policy
bool isMusicEffect() const { return mIsMusicEffect; }
@@ -59,12 +60,18 @@
int session, int id, bool isMusicEffect);
status_t unregisterEffect(int id);
sp<EffectDescriptor> getEffect(int id) const;
+ EffectDescriptorCollection getEffectsForIo(audio_io_handle_t io) const;
status_t setEffectEnabled(int id, bool enabled);
bool isEffectEnabled(int id) const;
uint32_t getMaxEffectsCpuLoad() const;
uint32_t getMaxEffectsMemory() const;
bool isNonOffloadableEffectEnabled() const;
+ void moveEffects(audio_session_t session,
+ audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput);
+ void moveEffects(const std::vector<int>& ids, audio_io_handle_t dstOutput);
+
void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
private:
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 5b4e2eb..58683be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -128,6 +128,13 @@
audio_attributes_t AudioInputDescriptor::getHighestPriorityAttributes() const
{
audio_attributes_t attributes = { .source = AUDIO_SOURCE_DEFAULT };
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ return topClient ? topClient->attributes() : attributes;
+}
+
+sp<RecordClientDescriptor> AudioInputDescriptor::getHighestPriorityClient() const
+{
+ sp<RecordClientDescriptor> topClient;
for (bool activeOnly : { true, false }) {
int32_t topPriority = -1;
@@ -139,18 +146,18 @@
app_state_t curState = client->appState();
if (curState >= topState) {
int32_t curPriority = source_priority(client->source());
- if (curPriority > topPriority) {
- attributes = client->attributes();
+ if (curPriority >= topPriority) {
+ topClient = client;
topPriority = curPriority;
}
topState = curState;
}
}
- if (attributes.source != AUDIO_SOURCE_DEFAULT) {
+ if (topClient != nullptr) {
break;
}
}
- return attributes;
+ return topClient;
}
bool AudioInputDescriptor::isSoundTrigger() const {
@@ -326,9 +333,10 @@
client->setActive(active);
+ checkSuspendEffects();
+
int event = active ? RECORD_CONFIG_EVENT_START : RECORD_CONFIG_EVENT_STOP;
updateClientRecordingConfiguration(event, client);
-
}
void AudioInputDescriptor::updateClientRecordingConfiguration(
@@ -397,44 +405,90 @@
mEnabledEffects.replaceValueFor(effect->mId, effect);
} else {
mEnabledEffects.removeItem(effect->mId);
+ // always exit from suspend when disabling an effect as only enabled effects
+ // are managed by checkSuspendEffects()
+ if (effect->mSuspended) {
+ effect->mSuspended = false;
+ mClientInterface->setEffectSuspended(effect->mId, effect->mSession, effect->mSuspended);
+ }
}
RecordClientVector clients = getClientsForSession((audio_session_t)effect->mSession);
+ RecordClientVector updatedClients;
+
for (const auto& client : clients) {
sp<EffectDescriptor> clientEffect = client->getEnabledEffects().getEffect(effect->mId);
bool changed = (enabled && clientEffect == nullptr)
|| (!enabled && clientEffect != nullptr);
client->trackEffectEnabled(effect, enabled);
if (changed && client->active()) {
- updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ updatedClients.push_back(client);
}
}
+
+ checkSuspendEffects();
+
+ for (const auto& client : updatedClients) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ }
}
EffectDescriptorCollection AudioInputDescriptor::getEnabledEffects() const
{
- EffectDescriptorCollection enabledEffects;
// report effects for highest priority active source as applied to all clients
- RecordClientVector clients =
- clientsList(true /*activeOnly*/, source(), false /*preferredDeviceOnly*/);
- if (clients.size() > 0) {
- enabledEffects = clients[0]->getEnabledEffects();
+ EffectDescriptorCollection enabledEffects;
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ if (topClient != nullptr) {
+ enabledEffects = topClient->getEnabledEffects();
}
return enabledEffects;
}
-void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state) {
+void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state)
+{
RecordClientVector clients = clientsList(false /*activeOnly*/);
+ RecordClientVector updatedClients;
for (const auto& client : clients) {
if (uid == client->uid()) {
bool wasSilenced = client->isSilenced();
client->setAppState(state);
if (client->active() && wasSilenced != client->isSilenced()) {
- updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ updatedClients.push_back(client);
}
}
}
+
+ checkSuspendEffects();
+
+ for (const auto& client : updatedClients) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ }
+}
+
+void AudioInputDescriptor::checkSuspendEffects()
+{
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ if (topClient == nullptr) {
+ return;
+ }
+
+ for (size_t i = 0; i < mEnabledEffects.size(); i++) {
+ sp<EffectDescriptor> effect = mEnabledEffects.valueAt(i);
+ if (effect->mSession == topClient->session()) {
+ if (effect->mSuspended) {
+ effect->mSuspended = false;
+ mClientInterface->setEffectSuspended(effect->mId,
+ effect->mSession,
+ effect->mSuspended);
+ }
+ } else if (!effect->mSuspended) {
+ effect->mSuspended = true;
+ mClientInterface->setEffectSuspended(effect->mId,
+ effect->mSession,
+ effect->mSuspended);
+ }
+ }
}
void AudioInputDescriptor::dump(String8 *dst) const
@@ -444,7 +498,7 @@
dst->appendFormat(" Format: %d\n", mFormat);
dst->appendFormat(" Channels: %08x\n", mChannelMask);
dst->appendFormat(" Devices %s\n", mDevice->toString().c_str());
- getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
+ mEnabledEffects.dump(dst, 1 /*spaces*/, false /*verbose*/);
dst->append(" AudioRecord Clients:\n");
ClientMapHandler<RecordClientDescriptor>::dump(dst);
dst->append("\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 89f9899..415962a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -30,6 +30,7 @@
dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
dst->appendFormat("%*sName: %s\n", spaces, "", mDesc.name);
dst->appendFormat("%*s%s\n", spaces, "", mEnabled ? "Enabled" : "Disabled");
+ dst->appendFormat("%*s%s\n", spaces, "", mSuspended ? "Suspended" : "Active");
}
EffectDescriptorCollection::EffectDescriptorCollection() :
@@ -63,7 +64,8 @@
desc->name, io, session, id);
ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
- sp<EffectDescriptor> effectDesc = new EffectDescriptor(desc, isMusicEffect, id, io, session);
+ sp<EffectDescriptor> effectDesc =
+ new EffectDescriptor(desc, isMusicEffect, id, io, (audio_session_t)session);
add(id, effectDesc);
return NO_ERROR;
@@ -174,6 +176,43 @@
return MAX_EFFECTS_MEMORY;
}
+void EffectDescriptorCollection::moveEffects(audio_session_t session,
+ audio_io_handle_t srcOutput,
+ audio_io_handle_t dstOutput)
+{
+ ALOGV("%s session %d srcOutput %d dstOutput %d", __func__, session, srcOutput, dstOutput);
+ for (size_t i = 0; i < size(); i++) {
+ sp<EffectDescriptor> effect = valueAt(i);
+ if (effect->mSession == session && effect->mIo == srcOutput) {
+ effect->mIo = dstOutput;
+ }
+ }
+}
+
+void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids,
+ audio_io_handle_t dstOutput)
+{
+ ALOGV("%s num effects %zu, first ID %d, dstOutput %d",
+ __func__, ids.size(), ids.size() ? ids[0] : 0, dstOutput);
+ for (size_t i = 0; i < size(); i++) {
+ sp<EffectDescriptor> effect = valueAt(i);
+ if (std::find(begin(ids), end(ids), effect->mId) != end(ids)) {
+ effect->mIo = dstOutput;
+ }
+ }
+}
+
+EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const
+{
+ EffectDescriptorCollection effects;
+ for (size_t i = 0; i < size(); i++) {
+ if (valueAt(i)->mIo == io) {
+ effects.add(keyAt(i), valueAt(i));
+ }
+ }
+ return effects;
+}
+
void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const
{
if (verbose) {
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
index c487da9..0ee83a2 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_product_strategies.xml
@@ -166,5 +166,20 @@
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
+
+ <!-- Routing Strategy rerouting may be removed as following media??? -->
+ <ProductStrategy name="rerouting">
+ <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+ <Attributes></Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+
+ <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+ <ProductStrategy name="patch">
+ <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+ <Attributes></Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+
</ProductStrategies>
diff --git a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
index 9ec3d77..6e72dc5 100644
--- a/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/automotive/audio_policy_engine_volumes.xml
@@ -188,5 +188,26 @@
<point>100,0</point>
</volume>
</volumeGroup>
+
+ <volumeGroup>
+ <name>rerouting</name>
+ <indexMin>0</indexMin>
+ <indexMax>1</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>patch</name>
+ <indexMin>0</indexMin>
+ <indexMax>1</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
</volumeGroups>
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
index c487da9..adcbd83 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_product_strategies.xml
@@ -166,5 +166,19 @@
<Attributes> <Flags value="AUDIO_FLAG_BEACON"/> </Attributes>
</AttributesGroup>
</ProductStrategy>
+
+ <!-- Routing Strategy rerouting may be removed as following media??? -->
+ <ProductStrategy name="rerouting">
+ <AttributesGroup streamType="AUDIO_STREAM_REROUTING" volumeGroup="rerouting">
+ <Attributes></Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
+
+ <!-- Patch stream needs full scale volume, define it otherwise switch to default... -->
+ <ProductStrategy name="patch">
+ <AttributesGroup streamType="AUDIO_STREAM_PATCH" volumeGroup="patch">
+ <Attributes></Attributes>
+ </AttributesGroup>
+ </ProductStrategy>
</ProductStrategies>
diff --git a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
index 9ec3d77..6e72dc5 100644
--- a/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
+++ b/services/audiopolicy/engineconfigurable/config/example/caremu/audio_policy_engine_volumes.xml
@@ -188,5 +188,26 @@
<point>100,0</point>
</volume>
</volumeGroup>
+
+ <volumeGroup>
+ <name>rerouting</name>
+ <indexMin>0</indexMin>
+ <indexMax>1</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
+ <volumeGroup>
+ <name>patch</name>
+ <indexMin>0</indexMin>
+ <indexMax>1</indexMax>
+ <volume deviceCategory="DEVICE_CATEGORY_HEADSET">
+ <point>0,0</point>
+ <point>100,0</point>
+ </volume>
+ </volumeGroup>
+
</volumeGroups>
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index af29f87..6bd64d6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -142,18 +142,7 @@
__func__, device->toString().c_str(), encodedFormat);
// register new device as available
- index = mAvailableOutputDevices.add(device);
- if (index >= 0) {
- sp<HwModule> module = mHwModules.getModuleForDevice(device, encodedFormat);
- if (module == 0) {
- ALOGD("setDeviceConnectionState() could not find HW module for device %s",
- device->toString().c_str());
- mAvailableOutputDevices.remove(device);
- return INVALID_OPERATION;
- }
- ALOGV("setDeviceConnectionState() module name=%s", module->getName());
- mAvailableOutputDevices[index]->attach(module);
- } else {
+ if (mAvailableOutputDevices.add(device) < 0) {
return NO_MEMORY;
}
@@ -295,13 +284,6 @@
ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
return INVALID_OPERATION;
}
- sp<HwModule> module = mHwModules.getModuleForDevice(device, AUDIO_FORMAT_DEFAULT);
- if (module == NULL) {
- ALOGW("setDeviceConnectionState(): could not find HW module for device %s",
- device->toString().c_str());
- return INVALID_OPERATION;
- }
-
// Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
// parameters on newly connected devices (instead of opening the inputs...)
broadcastDeviceConnectionState(device, state);
@@ -2361,25 +2343,8 @@
}
void AudioPolicyManager::closeAllInputs() {
- bool patchRemoved = false;
-
- 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->getPatchHandle());
- if (patch_index >= 0) {
- sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
- (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
- mAudioPatches.removeItemsAt(patch_index);
- patchRemoved = true;
- }
- inputDesc->close();
- }
- mInputs.clear();
- SoundTrigger::setCaptureState(false);
- nextAudioPortGeneration();
-
- if (patchRemoved) {
- mpClientInterface->onAudioPatchListUpdate();
+ while (mInputs.size() != 0) {
+ closeInput(mInputs.keyAt(0));
}
}
@@ -2481,7 +2446,7 @@
// HW Gain management, do not change the volume
bool applyVolume = false;
if (desc->useHwGain()) {
- if (!(desc->isActive(group) || isInCall())) {
+ if (!(desc->isActive(toVolumeSource(group)) || isInCall())) {
continue;
}
for (const auto &productStrategy : mEngine->getOrderedProductStrategies()) {
@@ -2675,6 +2640,7 @@
}
if (output != mMusicEffectOutput) {
+ mEffects.moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
mpClientInterface->moveEffects(AUDIO_SESSION_OUTPUT_MIX, mMusicEffectOutput, output);
mMusicEffectOutput = output;
}
@@ -2712,7 +2678,6 @@
if (mEffects.getEffect(id) == nullptr) {
return INVALID_OPERATION;
}
-
if (mEffects.isEffectEnabled(id)) {
ALOGW("%s effect %d enabled", __FUNCTION__, id);
setEffectEnabled(id, false);
@@ -2720,6 +2685,16 @@
return mEffects.unregisterEffect(id);
}
+void AudioPolicyManager::cleanUpEffectsForIo(audio_io_handle_t io)
+{
+ EffectDescriptorCollection effects = mEffects.getEffectsForIo(io);
+ for (size_t i = 0; i < effects.size(); i++) {
+ ALOGW("%s removing stale effect %s, id %d on closed IO %d",
+ __func__, effects.valueAt(i)->mDesc.name, effects.keyAt(i), io);
+ unregisterEffect(effects.keyAt(i));
+ }
+}
+
status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
{
sp<EffectDescriptor> effect = mEffects.getEffect(id);
@@ -2734,6 +2709,13 @@
return status;
}
+
+status_t AudioPolicyManager::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+ mEffects.moveEffects(ids, io);
+ return NO_ERROR;
+}
+
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
return mOutputs.isActive(toVolumeSource(stream), inPastMs);
@@ -4105,15 +4087,8 @@
void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
{
ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
-
for (size_t i = 0; i < mInputs.size(); i++) {
- sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
- RecordClientVector clients = inputDesc->clientsList(false /*activeOnly*/);
- for (const auto& client : clients) {
- if (uid == client->uid()) {
- client->setAppState(state);
- }
- }
+ mInputs.valueAt(i)->setAppState(uid, state);
}
}
@@ -4924,6 +4899,8 @@
setMsdPatch();
}
}
+
+ cleanUpEffectsForIo(output);
}
void AudioPolicyManager::closeInput(audio_io_handle_t input)
@@ -4955,6 +4932,8 @@
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
SoundTrigger::setCaptureState(false);
}
+
+ cleanUpEffectsForIo(input);
}
SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index de447fb..3376965 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -200,6 +200,7 @@
int id);
virtual status_t unregisterEffect(int id);
virtual status_t setEffectEnabled(int id, bool enabled);
+ status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override;
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
// return whether a stream is playing remotely, override to change the definition of
@@ -344,7 +345,7 @@
}
virtual const DeviceVector getAvailableOutputDevices() const
{
- return mAvailableOutputDevices.filterForEngine();
+ return mAvailableOutputDevices;
}
virtual const DeviceVector getAvailableInputDevices() const
{
@@ -869,6 +870,8 @@
int delayMs,
uid_t uid,
sp<AudioPatch> *patchDescPtr);
+
+ void cleanUpEffectsForIo(audio_io_handle_t io);
};
};
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 5748334..d51cc6e 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -172,6 +172,13 @@
return af->moveEffects(session, src_output, dst_output);
}
+void AudioPolicyService::AudioPolicyClient::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ mAudioPolicyService->setEffectSuspended(effectId, sessionId, suspended);
+}
+
status_t AudioPolicyService::AudioPolicyClient::createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs)
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 6ad01f7..dcf093b 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -225,6 +225,8 @@
size_t *totSize);
// protects access to mInputSources, mInputSessions, mOutputStreams, mOutputSessions
+ // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+ // those can call back into AudioPolicyService methods and try to acquire the mutex
Mutex mLock;
// Automatic input effects are configured per audio_source_t
KeyedVector< audio_source_t, EffectDescVector* > mInputSources;
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 2eb272e..2e47eb6 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -797,7 +797,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- Mutex::Autolock _l(mEffectsLock);
+ Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->registerEffect(desc, io, strategy, session, id);
}
@@ -807,7 +807,7 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- Mutex::Autolock _l(mEffectsLock);
+ Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->unregisterEffect(id);
}
@@ -817,11 +817,21 @@
if (mAudioPolicyManager == NULL) {
return NO_INIT;
}
- Mutex::Autolock _l(mEffectsLock);
+ Mutex::Autolock _l(mLock);
AutoCallerClear acc;
return mAudioPolicyManager->setEffectEnabled(id, enabled);
}
+status_t AudioPolicyService::moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io)
+{
+ if (mAudioPolicyManager == NULL) {
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ AutoCallerClear acc;
+ return mAudioPolicyManager->moveEffectsToIo(ids, io);
+}
+
bool AudioPolicyService::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
if (uint32_t(stream) >= AUDIO_STREAM_PUBLIC_CNT) {
@@ -973,8 +983,6 @@
return false;
}
Mutex::Autolock _l(mLock);
- Mutex::Autolock _le(mEffectsLock); // isOffloadSupported queries for
- // non-offloadable effects
AutoCallerClear acc;
return mAudioPolicyManager->isOffloadSupported(info);
}
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index f63fa81..5389c08 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1196,6 +1196,17 @@
data->mPatchHandle, data->mSource);
mLock.lock();
} break;
+ case SET_EFFECT_SUSPENDED: {
+ SetEffectSuspendedData *data = (SetEffectSuspendedData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing set effect suspended");
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ mLock.unlock();
+ af->setEffectSuspended(data->mEffectId, data->mSessionId, data->mSuspended);
+ mLock.lock();
+ }
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -1327,6 +1338,23 @@
return sendCommand(command, delayMs);
}
+void AudioPolicyService::AudioCommandThread::setEffectSuspendedCommand(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = SET_EFFECT_SUSPENDED;
+ sp<SetEffectSuspendedData> data = new SetEffectSuspendedData();
+ data->mEffectId = effectId;
+ data->mSessionId = sessionId;
+ data->mSuspended = suspended;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() adding set suspended effectId %d sessionId %d suspended %d",
+ effectId, sessionId, suspended);
+ sendCommand(command);
+}
+
+
void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_port_handle_t portId)
{
sp<AudioCommand> command = new AudioCommand();
@@ -1707,6 +1735,14 @@
return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
}
+void AudioPolicyService::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
+}
+
+
extern "C" {
audio_module_handle_t aps_load_hw_module(void *service __unused,
const char *name);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 189322f..6c19912 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -134,6 +134,7 @@
int id);
virtual status_t unregisterEffect(int id);
virtual status_t setEffectEnabled(int id, bool enabled);
+ status_t moveEffectsToIo(const std::vector<int>& ids, audio_io_handle_t io) override;
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
virtual bool isStreamActiveRemotely(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
virtual bool isSourceActive(audio_source_t source) const;
@@ -292,6 +293,9 @@
void onAudioVolumeGroupChanged(volume_group_t group, int flags);
void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended);
private:
AudioPolicyService() ANDROID_API;
@@ -426,7 +430,8 @@
CHANGED_AUDIOVOLUMEGROUP,
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
- RECORDING_CONFIGURATION_UPDATE
+ RECORDING_CONFIGURATION_UPDATE,
+ SET_EFFECT_SUSPENDED,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -469,6 +474,9 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+ void setEffectSuspendedCommand(int effectId,
+ audio_session_t sessionId,
+ bool suspended);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
class AudioCommandData;
@@ -566,6 +574,13 @@
audio_source_t mSource;
};
+ class SetEffectSuspendedData : public AudioCommandData {
+ public:
+ int mEffectId;
+ audio_session_t mSessionId;
+ bool mSuspended;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -651,6 +666,10 @@
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) override;
+
/* Create a patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
@@ -810,7 +829,6 @@
mutable Mutex mLock; // prevents concurrent access to AudioPolicy manager functions changing
// device connection state or routing
- mutable Mutex mEffectsLock; // serialize access to Effect state within APM.
// Note: lock acquisition order is always mLock > mEffectsLock:
// mLock protects AudioPolicyManager methods that can call into audio flinger
// and possibly back in to audio policy service and acquire mEffectsLock.
@@ -824,6 +842,8 @@
DefaultKeyedVector< int64_t, sp<NotificationClient> > mNotificationClients;
Mutex mNotificationClientsLock; // protects mNotificationClients
// Manage all effects configured in audio_effects.conf
+ // never hold AudioPolicyService::mLock when calling AudioPolicyEffects methods as
+ // those can call back into AudioPolicyService methods and try to acquire the mutex
sp<AudioPolicyEffects> mAudioPolicyEffects;
audio_mode_t mPhoneState;
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 8854eb2..e4c64e5 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -84,6 +84,9 @@
std::vector<effect_descriptor_t> effects __unused,
audio_patch_handle_t patchHandle __unused,
audio_source_t source __unused) override { }
+ void setEffectSuspended(int effectId __unused,
+ audio_session_t sessionId __unused,
+ bool suspended __unused) {}
};
} // namespace android
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index cca4049..a1cb8ee 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -973,11 +973,14 @@
// Make sure the UID is in an active state to use the camera
if (!mUidPolicy->isUidActive(callingUid, String16(clientName8))) {
+ int32_t procState = mUidPolicy->getProcState(callingUid);
ALOGE("Access Denial: can't use the camera from an idle UID pid=%d, uid=%d",
clientPid, clientUid);
return STATUS_ERROR_FMT(ERROR_DISABLED,
- "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background",
- clientName8.string(), clientUid, clientPid, cameraId.string());
+ "Caller \"%s\" (PID %d, UID %d) cannot open camera \"%s\" from background ("
+ "calling UID %d proc state %" PRId32 ")",
+ clientName8.string(), clientUid, clientPid, cameraId.string(),
+ callingUid, procState);
}
// If sensor privacy is enabled then prevent access to the camera
@@ -2736,6 +2739,19 @@
return active;
}
+int32_t CameraService::UidPolicy::getProcState(uid_t uid) {
+ Mutex::Autolock _l(mUidLock);
+ return getProcStateLocked(uid);
+}
+
+int32_t CameraService::UidPolicy::getProcStateLocked(uid_t uid) {
+ int32_t procState = ActivityManager::PROCESS_STATE_UNKNOWN;
+ if (mMonitoredUids.find(uid) != mMonitoredUids.end()) {
+ procState = mMonitoredUids[uid].first;
+ }
+ return procState;
+}
+
void CameraService::UidPolicy::UidPolicy::addOverrideUid(uid_t uid,
String16 callingPackage, bool active) {
updateOverrideUid(uid, callingPackage, active, true);
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 4bcdeb2..a8c2606 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -542,6 +542,7 @@
void unregisterSelf();
bool isUidActive(uid_t uid, String16 callingPackage);
+ int32_t getProcState(uid_t uid);
void onUidGone(uid_t uid, bool disabled);
void onUidActive(uid_t uid);
@@ -558,6 +559,7 @@
virtual void binderDied(const wp<IBinder> &who);
private:
bool isUidActiveLocked(uid_t uid, String16 callingPackage);
+ int32_t getProcStateLocked(uid_t uid);
void updateOverrideUid(uid_t uid, String16 callingPackage, bool active, bool insert);
Mutex mUidLock;
diff --git a/services/camera/libcameraservice/device3/Camera3Device.cpp b/services/camera/libcameraservice/device3/Camera3Device.cpp
index a0d0198..415b2d8 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.cpp
+++ b/services/camera/libcameraservice/device3/Camera3Device.cpp
@@ -132,13 +132,24 @@
bool isLogical = manager->isLogicalCamera(mId.string(), &physicalCameraIds);
if (isLogical) {
for (auto& physicalId : physicalCameraIds) {
- res = manager->getCameraCharacteristics(physicalId, &mPhysicalDeviceInfoMap[physicalId]);
+ res = manager->getCameraCharacteristics(
+ physicalId, &mPhysicalDeviceInfoMap[physicalId]);
if (res != OK) {
SET_ERR_L("Could not retrieve camera %s characteristics: %s (%d)",
physicalId.c_str(), strerror(-res), res);
session->close();
return res;
}
+
+ if (DistortionMapper::isDistortionSupported(mPhysicalDeviceInfoMap[physicalId])) {
+ mDistortionMappers[physicalId].setupStaticInfo(mPhysicalDeviceInfoMap[physicalId]);
+ if (res != OK) {
+ SET_ERR_L("Unable to read camera %s's calibration fields for distortion "
+ "correction", physicalId.c_str());
+ session->close();
+ return res;
+ }
+ }
}
}
@@ -308,7 +319,7 @@
}
if (DistortionMapper::isDistortionSupported(mDeviceInfo)) {
- res = mDistortionMapper.setupStaticInfo(mDeviceInfo);
+ res = mDistortionMappers[mId.c_str()].setupStaticInfo(mDeviceInfo);
if (res != OK) {
SET_ERR_L("Unable to read necessary calibration fields for distortion correction");
return res;
@@ -3503,12 +3514,27 @@
}
// Fix up some result metadata to account for HAL-level distortion correction
- status_t res = mDistortionMapper.correctCaptureResult(&captureResult.mMetadata);
+ status_t res =
+ mDistortionMappers[mId.c_str()].correctCaptureResult(&captureResult.mMetadata);
if (res != OK) {
SET_ERR("Unable to correct capture result metadata for frame %d: %s (%d)",
frameNumber, strerror(res), res);
return;
}
+ for (auto& physicalMetadata : captureResult.mPhysicalMetadatas) {
+ String8 cameraId8(physicalMetadata.mPhysicalCameraId);
+ if (mDistortionMappers.find(cameraId8.c_str()) == mDistortionMappers.end()) {
+ continue;
+ }
+ res = mDistortionMappers[cameraId8.c_str()].correctCaptureResult(
+ &physicalMetadata.mPhysicalCameraMetadata);
+ if (res != OK) {
+ SET_ERR("Unable to correct physical capture result metadata for frame %d: %s (%d)",
+ frameNumber, strerror(res), res);
+ return;
+ }
+ }
+
// Fix up result metadata for monochrome camera.
res = fixupMonochromeTags(mDeviceInfo, captureResult.mMetadata);
if (res != OK) {
@@ -5482,13 +5508,21 @@
// Correct metadata regions for distortion correction if enabled
sp<Camera3Device> parent = mParent.promote();
if (parent != nullptr) {
- res = parent->mDistortionMapper.correctCaptureRequest(
- &(captureRequest->mSettingsList.begin()->metadata));
- if (res != OK) {
- SET_ERR("RequestThread: Unable to correct capture requests "
- "for lens distortion for request %d: %s (%d)",
- halRequest->frame_number, strerror(-res), res);
- return INVALID_OPERATION;
+ List<PhysicalCameraSettings>::iterator it;
+ for (it = captureRequest->mSettingsList.begin();
+ it != captureRequest->mSettingsList.end(); it++) {
+ if (parent->mDistortionMappers.find(it->cameraId) ==
+ parent->mDistortionMappers.end()) {
+ continue;
+ }
+ res = parent->mDistortionMappers[it->cameraId].correctCaptureRequest(
+ &(it->metadata));
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to correct capture requests "
+ "for lens distortion for request %d: %s (%d)",
+ halRequest->frame_number, strerror(-res), res);
+ return INVALID_OPERATION;
+ }
}
}
}
diff --git a/services/camera/libcameraservice/device3/Camera3Device.h b/services/camera/libcameraservice/device3/Camera3Device.h
index d3bb212..f8245df 100644
--- a/services/camera/libcameraservice/device3/Camera3Device.h
+++ b/services/camera/libcameraservice/device3/Camera3Device.h
@@ -1250,8 +1250,10 @@
/**
* Distortion correction support
*/
-
- camera3::DistortionMapper mDistortionMapper;
+ // Map from camera IDs to its corresponding distortion mapper. Only contains
+ // 1 ID if the device isn't a logical multi-camera. Otherwise contains both
+ // logical camera and its physical subcameras.
+ std::unordered_map<std::string, camera3::DistortionMapper> mDistortionMappers;
// Debug tracker for metadata tag value changes
// - Enabled with the -m <taglist> option to dumpsys, such as
diff --git a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
index 1c77581..acb8b3c 100644
--- a/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
+++ b/services/camera/libcameraservice/device3/Camera3OutputStream.cpp
@@ -491,8 +491,11 @@
* sets the mBufferManager if device version is > HAL3.2, which guarantees that the buffer
* manager setup is skipped in below code. Note that HAL3.2 is also excluded here, as some
* HAL3.2 devices may not support the dynamic buffer registeration.
+ * Also Camera3BufferManager does not support display/texture streams as they have its own
+ * buffer management logic.
*/
- if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID) {
+ if (mBufferManager != 0 && mSetId > CAMERA3_STREAM_SET_ID_INVALID &&
+ !(isConsumedByHWComposer() || isConsumedByHWTexture())) {
uint64_t consumerUsage = 0;
getEndpointUsage(&consumerUsage);
StreamInfo streamInfo(
diff --git a/services/mediacodec/main_swcodecservice.cpp b/services/mediacodec/main_swcodecservice.cpp
index a5db031..d91b788 100644
--- a/services/mediacodec/main_swcodecservice.cpp
+++ b/services/mediacodec/main_swcodecservice.cpp
@@ -33,11 +33,12 @@
extern "C" void RegisterCodecServices();
-int main(int argc __unused, char** /*argv*/)
+int main(int argc __unused, char** argv)
{
LOG(INFO) << "media swcodec service starting";
signal(SIGPIPE, SIG_IGN);
SetUpMinijail(kSystemSeccompPolicyPath, kVendorSeccompPolicyPath);
+ strcpy(argv[0], "media.swcodec");
::android::hardware::configureRpcThreadpool(64, false);
diff --git a/services/oboeservice/AAudioClientTracker.cpp b/services/oboeservice/AAudioClientTracker.cpp
index 7264a9b..83704ba 100644
--- a/services/oboeservice/AAudioClientTracker.cpp
+++ b/services/oboeservice/AAudioClientTracker.cpp
@@ -101,7 +101,7 @@
aaudio_result_t
AAudioClientTracker::registerClientStream(pid_t pid, sp<AAudioServiceStreamBase> serviceStream) {
aaudio_result_t result = AAUDIO_OK;
- ALOGV("registerClientStream(%d, %p)\n", pid, serviceStream.get());
+ ALOGV("registerClientStream(%d,)\n", pid);
std::lock_guard<std::mutex> lock(mLock);
sp<NotificationClient> notificationClient = mNotificationClients[pid];
if (notificationClient == 0) {
@@ -118,27 +118,23 @@
aaudio_result_t
AAudioClientTracker::unregisterClientStream(pid_t pid,
sp<AAudioServiceStreamBase> serviceStream) {
- ALOGV("unregisterClientStream(%d, %p)\n", pid, serviceStream.get());
+ ALOGV("unregisterClientStream(%d,)\n", pid);
std::lock_guard<std::mutex> lock(mLock);
auto it = mNotificationClients.find(pid);
if (it != mNotificationClients.end()) {
- ALOGV("unregisterClientStream(%d, %p) found NotificationClient\n",
- pid, serviceStream.get());
+ ALOGV("unregisterClientStream(%d,) found NotificationClient\n", pid);
it->second->unregisterClientStream(serviceStream);
} else {
- ALOGE("unregisterClientStream(%d, %p) missing NotificationClient\n",
- pid, serviceStream.get());
+ ALOGE("unregisterClientStream(%d,) missing NotificationClient\n", pid);
}
return AAUDIO_OK;
}
AAudioClientTracker::NotificationClient::NotificationClient(pid_t pid)
: mProcessId(pid) {
- //ALOGD("NotificationClient(%d) created %p\n", pid, this);
}
AAudioClientTracker::NotificationClient::~NotificationClient() {
- //ALOGD("~NotificationClient() destroyed %p\n", this);
}
int32_t AAudioClientTracker::NotificationClient::getStreamCount() {
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 2fbaeb4..e6a8375 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -132,11 +132,10 @@
if (result != AAUDIO_OK) {
serviceStream.clear();
- ALOGW("openStream(): failed, return %d = %s", result, AAudio_convertResultToText(result));
return result;
} else {
aaudio_handle_t handle = mStreamTracker.addStreamForHandle(serviceStream.get());
- ALOGD("openStream(): handle = 0x%08X", handle);
+ ALOGV("openStream(): handle = 0x%08X", handle);
serviceStream->setHandle(handle);
pid_t pid = request.getProcessId();
AAudioClientTracker::getInstance().registerClientStream(pid, serviceStream);
diff --git a/services/oboeservice/AAudioServiceEndpoint.cpp b/services/oboeservice/AAudioServiceEndpoint.cpp
index 4dfb62a..553754e 100644
--- a/services/oboeservice/AAudioServiceEndpoint.cpp
+++ b/services/oboeservice/AAudioServiceEndpoint.cpp
@@ -90,7 +90,8 @@
std::lock_guard<std::mutex> lock(mLockStreams);
mConnected.store(false);
for (const auto& stream : mRegisteredStreams) {
- ALOGD("disconnectRegisteredStreams() stop and disconnect %p", stream.get());
+ ALOGD("disconnectRegisteredStreams() stop and disconnect port %d",
+ stream->getPortHandle());
stream->stop();
stream->disconnect();
}
diff --git a/services/oboeservice/AAudioServiceEndpoint.h b/services/oboeservice/AAudioServiceEndpoint.h
index 3616fa2..a2f66a5 100644
--- a/services/oboeservice/AAudioServiceEndpoint.h
+++ b/services/oboeservice/AAudioServiceEndpoint.h
@@ -61,7 +61,7 @@
virtual aaudio_result_t startClient(const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
- ALOGD("AAudioServiceEndpoint::startClient(%p, ...) AAUDIO_ERROR_UNAVAILABLE", &client);
+ ALOGD("AAudioServiceEndpoint::startClient(...) AAUDIO_ERROR_UNAVAILABLE");
return AAUDIO_ERROR_UNAVAILABLE;
}
diff --git a/services/oboeservice/AAudioServiceEndpointMMAP.cpp b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
index fbf7d10..447f32c 100644
--- a/services/oboeservice/AAudioServiceEndpointMMAP.cpp
+++ b/services/oboeservice/AAudioServiceEndpointMMAP.cpp
@@ -163,7 +163,9 @@
ALOGD("%s() mMapClient.uid = %d, pid = %d => portHandle = %d\n",
__func__, mMmapClient.clientUid, mMmapClient.clientPid, mPortHandle);
if (status != OK) {
- ALOGE("%s() - openMmapStream() returned status %d", __func__, status);
+ // This can happen if the resource is busy or the config does
+ // not match the hardware.
+ ALOGD("%s() - openMmapStream() returned status %d", __func__, status);
return AAUDIO_ERROR_UNAVAILABLE;
}
@@ -196,9 +198,9 @@
result = AAUDIO_ERROR_UNAVAILABLE;
goto error;
} else {
- ALOGD("%s() createMmapBuffer() returned = %d, buffer_size = %d, burst_size %d"
+ ALOGD("%s() createMmapBuffer() buffer_size = %d fr, burst_size %d fr"
", Sharable FD: %s",
- __func__, status,
+ __func__,
mMmapBufferinfo.buffer_size_frames,
mMmapBufferinfo.burst_size_frames,
isBufferShareable ? "Yes" : "No");
@@ -243,14 +245,13 @@
burstMicros = mFramesPerBurst * static_cast<int64_t>(1000000) / getSampleRate();
} while (burstMicros < burstMinMicros);
- ALOGD("%s() original burst = %d, minMicros = %d, to burst = %d\n",
+ ALOGD("%s() original burst = %d, minMicros = %d => burst = %d\n",
__func__, mMmapBufferinfo.burst_size_frames, burstMinMicros, mFramesPerBurst);
- ALOGD("%s() actual rate = %d, channels = %d"
- ", deviceId = %d, capacity = %d\n",
- __func__, getSampleRate(), getSamplesPerFrame(), deviceId, getBufferCapacity());
+ ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d\n",
+ __func__, getSampleRate(), getSamplesPerFrame(), deviceId);
- ALOGD("%s() format = =x%08x, frame size = %d",
+ ALOGD("%s() format = 0x%08x, frame size = %d",
__func__, getFormat(), calculateBytesPerFrame());
return result;
@@ -262,7 +263,6 @@
aaudio_result_t AAudioServiceEndpointMMAP::close() {
if (mMmapStream != 0) {
- ALOGD("%s() clear() endpoint", __func__);
// Needs to be explicitly cleared or CTS will fail but it is not clear why.
mMmapStream.clear();
// Apparently the above close is asynchronous. An attempt to open a new device
@@ -284,7 +284,7 @@
LOG_ALWAYS_FATAL_IF(tempHandle != mPortHandle,
"%s() port handle not expected to change from %d to %d",
__func__, mPortHandle, tempHandle);
- ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+ ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
return result;
}
@@ -299,26 +299,20 @@
mFramesTransferred.roundUp64(getBufferCapacity());
// Use the port handle that was provided by openMmapStream().
- ALOGV("%s(%p) mPortHandle = %d", __func__, stream.get(), mPortHandle);
+ ALOGV("%s() mPortHandle = %d", __func__, mPortHandle);
return stopClient(mPortHandle);
}
aaudio_result_t AAudioServiceEndpointMMAP::startClient(const android::AudioClient& client,
audio_port_handle_t *clientHandle) {
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
- ALOGD("%s(%p(uid=%d, pid=%d))", __func__, &client, client.clientUid, client.clientPid);
- audio_port_handle_t originalHandle = *clientHandle;
status_t status = mMmapStream->start(client, clientHandle);
- aaudio_result_t result = AAudioConvert_androidToAAudioResult(status);
- ALOGD("%s() , portHandle %d => %d, returns %d", __func__, originalHandle, *clientHandle, result);
- return result;
+ return AAudioConvert_androidToAAudioResult(status);
}
aaudio_result_t AAudioServiceEndpointMMAP::stopClient(audio_port_handle_t clientHandle) {
- ALOGD("%s(portHandle = %d), called", __func__, clientHandle);
if (mMmapStream == nullptr) return AAUDIO_ERROR_NULL;
aaudio_result_t result = AAudioConvert_androidToAAudioResult(mMmapStream->stop(clientHandle));
- ALOGD("%s(portHandle = %d), returns %d", __func__, clientHandle, result);
return result;
}
@@ -371,7 +365,7 @@
// TODO Do we really need a different volume for each channel?
// We get called with an array filled with a single value!
float volume = values[0];
- ALOGD("%s(%p) volume[0] = %f", __func__, this, volume);
+ ALOGD("%s() volume[0] = %f", __func__, volume);
std::lock_guard<std::mutex> lock(mLockStreams);
for(const auto& stream : mRegisteredStreams) {
stream->onVolumeChanged(volume);
@@ -379,7 +373,7 @@
};
void AAudioServiceEndpointMMAP::onRoutingChanged(audio_port_handle_t deviceId) {
- ALOGD("%s(%p) called with dev %d, old = %d", __func__, this, deviceId, getDeviceId());
+ ALOGD("%s() called with dev %d, old = %d", __func__, deviceId, getDeviceId());
if (getDeviceId() != AUDIO_PORT_HANDLE_NONE && getDeviceId() != deviceId) {
disconnectRegisteredStreams();
}
diff --git a/services/oboeservice/AAudioServiceEndpointPlay.cpp b/services/oboeservice/AAudioServiceEndpointPlay.cpp
index 1e1c552..bda4b90 100644
--- a/services/oboeservice/AAudioServiceEndpointPlay.cpp
+++ b/services/oboeservice/AAudioServiceEndpointPlay.cpp
@@ -43,7 +43,6 @@
AAudioServiceEndpointPlay::AAudioServiceEndpointPlay(AAudioService &audioService)
: mStreamInternalPlay(audioService, true) {
- ALOGD("%s(%p) created", __func__, this);
mStreamInternal = &mStreamInternalPlay;
}
diff --git a/services/oboeservice/AAudioServiceStreamShared.cpp b/services/oboeservice/AAudioServiceStreamShared.cpp
index 14742dd..2ca847a 100644
--- a/services/oboeservice/AAudioServiceStreamShared.cpp
+++ b/services/oboeservice/AAudioServiceStreamShared.cpp
@@ -111,7 +111,7 @@
capacityInFrames, MAX_FRAMES_PER_BUFFER);
return AAUDIO_ERROR_OUT_OF_RANGE;
}
- ALOGD("calculateBufferCapacity() requested %d frames, actual = %d",
+ ALOGV("calculateBufferCapacity() requested %d frames, actual = %d",
requestedCapacityFrames, capacityInFrames);
return capacityInFrames;
}
@@ -144,7 +144,7 @@
if (getFormat() == AUDIO_FORMAT_DEFAULT) {
setFormat(AUDIO_FORMAT_PCM_FLOAT);
} else if (getFormat() != AUDIO_FORMAT_PCM_FLOAT) {
- ALOGE("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
+ ALOGD("%s() audio_format_t mAudioFormat = %d, need FLOAT", __func__, getFormat());
result = AAUDIO_ERROR_INVALID_FORMAT;
goto error;
}
@@ -153,7 +153,7 @@
if (getSampleRate() == AAUDIO_UNSPECIFIED) {
setSampleRate(endpoint->getSampleRate());
} else if (getSampleRate() != endpoint->getSampleRate()) {
- ALOGE("%s() mSampleRate = %d, need %d",
+ ALOGD("%s() mSampleRate = %d, need %d",
__func__, getSampleRate(), endpoint->getSampleRate());
result = AAUDIO_ERROR_INVALID_RATE;
goto error;
@@ -163,7 +163,7 @@
if (getSamplesPerFrame() == AAUDIO_UNSPECIFIED) {
setSamplesPerFrame(endpoint->getSamplesPerFrame());
} else if (getSamplesPerFrame() != endpoint->getSamplesPerFrame()) {
- ALOGE("%s() mSamplesPerFrame = %d, need %d",
+ ALOGD("%s() mSamplesPerFrame = %d, need %d",
__func__, getSamplesPerFrame(), endpoint->getSamplesPerFrame());
result = AAUDIO_ERROR_OUT_OF_RANGE;
goto error;
@@ -190,9 +190,6 @@
}
}
- ALOGD("%s() actual rate = %d, channels = %d, deviceId = %d",
- __func__, getSampleRate(), getSamplesPerFrame(), endpoint->getDeviceId());
-
result = endpoint->registerStream(keep);
if (result != AAUDIO_OK) {
goto error;
@@ -227,7 +224,7 @@
{
std::lock_guard<std::mutex> lock(mAudioDataQueueLock);
if (mAudioDataQueue == nullptr) {
- ALOGE("%s(): mUpMessageQueue null! - stream not open", __func__);
+ ALOGW("%s(): mUpMessageQueue null! - stream not open", __func__);
return AAUDIO_ERROR_NULL;
}
// Gather information on the data queue.
@@ -262,7 +259,7 @@
int64_t position = 0;
sp<AAudioServiceEndpoint> endpoint = mServiceEndpointWeak.promote();
if (endpoint == nullptr) {
- ALOGE("%s() has no endpoint", __func__);
+ ALOGW("%s() has no endpoint", __func__);
return AAUDIO_ERROR_INVALID_STATE;
}