summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2014-11-30 15:14:47 -0800
committerEric Laurent <elaurent@google.com>2014-12-09 15:47:19 -0800
commit275e8e9de2e11b4b344f5a201f1f0e51fda02d9c (patch)
treec22e1c0b8541aa04fd6c8d803e4fa6704a84e6e2 /media
parent82a69ea8b090d57bff5e02774688b546a711bbb8 (diff)
downloadframeworks_av-275e8e9de2e11b4b344f5a201f1f0e51fda02d9c.zip
frameworks_av-275e8e9de2e11b4b344f5a201f1f0e51fda02d9c.tar.gz
frameworks_av-275e8e9de2e11b4b344f5a201f1f0e51fda02d9c.tar.bz2
audio policy: add support for custom mixes
Add support for custom mixes in AudioPolicyManager. Two methods are added to register or unregister a list of custom mixes with their attributes and format. getOutputForAttr() and getInputForAttr() first look for a match in registered mixes before defaulting to normal output/input selection Remote submix device connection disconnection now takes address into account to identify the correspnoding custom mix. Bug: 16009464. Change-Id: I3f1c2a485a0fb71b1f984ed0adc9b68aa971e408
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/Android.mk3
-rw-r--r--media/libmedia/AudioPolicy.cpp115
-rw-r--r--media/libmedia/AudioTrack.cpp8
3 files changed, 125 insertions, 1 deletions
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index e012116..a2e0909 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -59,7 +59,8 @@ LOCAL_SRC_FILES:= \
MemoryLeakTrackUtil.cpp \
SoundPool.cpp \
SoundPoolThread.cpp \
- StringArray.cpp
+ StringArray.cpp \
+ AudioPolicy.cpp
LOCAL_SRC_FILES += ../libnbaio/roundup.c
diff --git a/media/libmedia/AudioPolicy.cpp b/media/libmedia/AudioPolicy.cpp
new file mode 100644
index 0000000..d2d0971
--- /dev/null
+++ b/media/libmedia/AudioPolicy.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioPolicy"
+//#define LOG_NDEBUG 0
+#include <utils/Log.h>
+#include <media/AudioPolicy.h>
+
+namespace android {
+
+//
+// AttributeMatchCriterion implementation
+//
+AttributeMatchCriterion::AttributeMatchCriterion(audio_usage_t usage,
+ audio_source_t source,
+ uint32_t rule)
+: mRule(rule)
+{
+ if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+ mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+ mAttr.mUsage = usage;
+ } else {
+ mAttr.mSource = source;
+ }
+}
+
+status_t AttributeMatchCriterion::readFromParcel(Parcel *parcel)
+{
+ mRule = parcel->readInt32();
+ if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
+ mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
+ mAttr.mUsage = (audio_usage_t)parcel->readInt32();
+ } else {
+ mAttr.mSource = (audio_source_t)parcel->readInt32();
+ }
+ return NO_ERROR;
+}
+
+status_t AttributeMatchCriterion::writeToParcel(Parcel *parcel) const
+{
+ parcel->writeInt32(mRule);
+ parcel->writeInt32(mAttr.mUsage);
+ return NO_ERROR;
+}
+
+//
+// AudioMix implementation
+//
+
+status_t AudioMix::readFromParcel(Parcel *parcel)
+{
+ mMixType = parcel->readInt32();
+ mFormat.sample_rate = (uint32_t)parcel->readInt32();
+ mFormat.channel_mask = (audio_channel_mask_t)parcel->readInt32();
+ mFormat.format = (audio_format_t)parcel->readInt32();
+ mRouteFlags = parcel->readInt32();
+ mRegistrationId = parcel->readString8();
+ size_t size = (size_t)parcel->readInt32();
+ if (size > MAX_CRITERIA_PER_MIX) {
+ size = MAX_CRITERIA_PER_MIX;
+ }
+ for (size_t i = 0; i < size; i++) {
+ AttributeMatchCriterion criterion;
+ if (criterion.readFromParcel(parcel) == NO_ERROR) {
+ mCriteria.add(criterion);
+ }
+ }
+ return NO_ERROR;
+}
+
+status_t AudioMix::writeToParcel(Parcel *parcel) const
+{
+ parcel->writeInt32(mMixType);
+ parcel->writeInt32(mFormat.sample_rate);
+ parcel->writeInt32(mFormat.channel_mask);
+ parcel->writeInt32(mFormat.format);
+ parcel->writeInt32(mRouteFlags);
+ parcel->writeString8(mRegistrationId);
+ size_t size = mCriteria.size();
+ if (size > MAX_CRITERIA_PER_MIX) {
+ size = MAX_CRITERIA_PER_MIX;
+ }
+ size_t sizePosition = parcel->dataPosition();
+ parcel->writeInt32(size);
+ size_t finalSize = size;
+ for (size_t i = 0; i < size; i++) {
+ size_t position = parcel->dataPosition();
+ if (mCriteria[i].writeToParcel(parcel) != NO_ERROR) {
+ parcel->setDataPosition(position);
+ finalSize--;
+ }
+ }
+ if (size != finalSize) {
+ size_t position = parcel->dataPosition();
+ parcel->setDataPosition(sizePosition);
+ parcel->writeInt32(finalSize);
+ parcel->setDataPosition(position);
+ }
+ return NO_ERROR;
+}
+
+}; // namespace android
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e4c3c08..d9c3177 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -851,6 +851,10 @@ status_t AudioTrack::getPosition(uint32_t *position)
// due to hardware latency. We leave this behavior for now.
*position = dspFrames;
} else {
+ if (mCblk->mFlags & CBLK_INVALID) {
+ restoreTrack_l("getPosition");
+ }
+
// IAudioTrack::stop() isn't synchronous; we don't know when presentation completes
*position = (mState == STATE_STOPPED || mState == STATE_FLUSHED) ?
0 : updateAndGetPosition_l();
@@ -1946,6 +1950,10 @@ status_t AudioTrack::getTimestamp(AudioTimestamp& timestamp)
break;
}
+ if (mCblk->mFlags & CBLK_INVALID) {
+ restoreTrack_l("getTimestamp");
+ }
+
// The presented frame count must always lag behind the consumed frame count.
// To avoid a race, read the presented frames first. This ensures that presented <= consumed.
status_t status = mAudioTrack->getTimestamp(timestamp);