Fix voice communication audio playback capture

This change fixes the CTS failure in AudioPlaybackCaptureTest caused
by ag/10111312 and ag/10111311.
It contains the following fixes/changes:
  - Mix match for playback capture of USAGE_VOICE_COMMUNICATION now
    also respects a new flag (AudioMix's mVoiceCommunicationCaptureAllowed)
    which is set by AudioService only if the caller explicitly asked
    to capture USAGE_VOICE_COMMUNICATION and have the
    CAPTURE_VOICE_COMMUNICATION_OUTPUT.
  - A permission check on the native side in case
    mVoiceCommunicationCaptureAllowed is set.
  - Code cleanup, mainly in AudioPolicy.h and AudioPolicy.cpp.

This change is accompanied by ag/10242955 on the Java side.

Bug: 148559127
Test: manual
Test: atest PlaybackCaptureTest (with the version prior to ag/10220852)
Test: atest com.google.android.gts.audio.AudioHostTest
Change-Id: I8ae6249f4da1de35e962c838d91f690eb906570e
gugelfrei
Nadav Bar 4 years ago
parent 93fb84c8d5
commit 287d330c85

@ -86,6 +86,7 @@ status_t AudioMix::readFromParcel(Parcel *parcel)
mDeviceAddress = parcel->readString8();
mCbFlags = (uint32_t)parcel->readInt32();
mAllowPrivilegedPlaybackCapture = parcel->readBool();
mVoiceCommunicationCaptureAllowed = parcel->readBool();
size_t size = (size_t)parcel->readInt32();
if (size > MAX_CRITERIA_PER_MIX) {
size = MAX_CRITERIA_PER_MIX;
@ -110,6 +111,7 @@ status_t AudioMix::writeToParcel(Parcel *parcel) const
parcel->writeString8(mDeviceAddress);
parcel->writeInt32(mCbFlags);
parcel->writeBool(mAllowPrivilegedPlaybackCapture);
parcel->writeBool(mVoiceCommunicationCaptureAllowed);
size_t size = mCriteria.size();
if (size > MAX_CRITERIA_PER_MIX) {
size = MAX_CRITERIA_PER_MIX;
@ -206,11 +208,4 @@ bool AudioMix::isDeviceAffinityCompatible() const {
&& (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
}
bool AudioMix::hasMatchingRuleForUsage(std::function<bool (audio_usage_t)>const& func) const {
return std::any_of(mCriteria.begin(), mCriteria.end(), [func](auto& criterion) {
return criterion.mRule == RULE_MATCH_ATTRIBUTE_USAGE
&& func(criterion.mValue.mUsage);
});
}
} // namespace android

@ -18,7 +18,6 @@
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
#include <functional>
#include <binder/Parcel.h>
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
@ -113,13 +112,6 @@ public:
/** returns true if this mix can be used for uid-device affinity routing */
bool isDeviceAffinityCompatible() const;
/**
* returns true if the mix has a capture rule for a usage that
* matches the given predicate
*/
bool hasMatchingRuleForUsage(
std::function<bool (audio_usage_t)>const& func) const;
mutable Vector<AudioMixMatchCriterion> mCriteria;
uint32_t mMixType;
audio_config_t mFormat;
@ -129,6 +121,8 @@ public:
uint32_t mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
/** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
bool mAllowPrivilegedPlaybackCapture = false;
/** Indicates if the caller can capture voice communication output */
bool mVoiceCommunicationCaptureAllowed = false;
};

@ -224,6 +224,10 @@ AudioPolicyMixCollection::MixMatchStatus AudioPolicyMixCollection::mixMatch(
hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
return MixMatchStatus::NO_MATCH;
}
if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION &&
!mix->mVoiceCommunicationCaptureAllowed) {
return MixMatchStatus::NO_MATCH;
}
if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
attributes.usage == AUDIO_USAGE_MEDIA ||
attributes.usage == AUDIO_USAGE_GAME ||

@ -26,7 +26,6 @@ LOCAL_SHARED_LIBRARIES := \
libaudioutils \
libaudiofoundation \
libhardware_legacy \
libaudiopolicy \
libaudiopolicymanager \
libmedia_helper \
libmediametrics \

@ -1215,26 +1215,14 @@ status_t AudioPolicyService::registerPolicyMixes(const Vector<AudioMix>& mixes,
return PERMISSION_DENIED;
}
// Require CAPTURE_VOICE_COMMUNICATION_OUTPUT if one of the
// mixes is a render|loopback mix that aim to capture audio played with
// USAGE_VOICE_COMMUNICATION.
// If one of the mixes has needCaptureVoiceCommunicationOutput set to true, then we
// need to verify that the caller still has CAPTURE_VOICE_COMMUNICATION_OUTPUT
bool needCaptureVoiceCommunicationOutput =
std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
return is_mix_loopback_render(mix.mRouteFlags) &&
mix.hasMatchingRuleForUsage([] (auto usage) {
return usage == AUDIO_USAGE_VOICE_COMMUNICATION;});
});
// Require CAPTURE_MEDIA_OUTPUT if there is a mix for priveliged capture
// which is trying to capture any usage which is not USAGE_VOICE_COMMUNICATION.
// (If USAGE_VOICE_COMMUNICATION should be captured, then CAPTURE_VOICE_COMMUNICATION_OUTPUT
// is required, even if it is not privileged capture).
return mix.mVoiceCommunicationCaptureAllowed; });
bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
return mix.mAllowPrivilegedPlaybackCapture &&
mix.hasMatchingRuleForUsage([] (auto usage) {
return usage != AUDIO_USAGE_VOICE_COMMUNICATION;
});
});
return mix.mAllowPrivilegedPlaybackCapture; });
const uid_t callingUid = IPCThreadState::self()->getCallingUid();
const pid_t callingPid = IPCThreadState::self()->getCallingPid();

Loading…
Cancel
Save