Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 287d330c authored by Nadav Bar's avatar Nadav Bar
Browse files

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
parent 93fb84c8
Loading
Loading
Loading
Loading
+2 −7
Original line number Original line Diff line number Diff line
@@ -86,6 +86,7 @@ status_t AudioMix::readFromParcel(Parcel *parcel)
    mDeviceAddress = parcel->readString8();
    mDeviceAddress = parcel->readString8();
    mCbFlags = (uint32_t)parcel->readInt32();
    mCbFlags = (uint32_t)parcel->readInt32();
    mAllowPrivilegedPlaybackCapture = parcel->readBool();
    mAllowPrivilegedPlaybackCapture = parcel->readBool();
    mVoiceCommunicationCaptureAllowed = parcel->readBool();
    size_t size = (size_t)parcel->readInt32();
    size_t size = (size_t)parcel->readInt32();
    if (size > MAX_CRITERIA_PER_MIX) {
    if (size > MAX_CRITERIA_PER_MIX) {
        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->writeString8(mDeviceAddress);
    parcel->writeInt32(mCbFlags);
    parcel->writeInt32(mCbFlags);
    parcel->writeBool(mAllowPrivilegedPlaybackCapture);
    parcel->writeBool(mAllowPrivilegedPlaybackCapture);
    parcel->writeBool(mVoiceCommunicationCaptureAllowed);
    size_t size = mCriteria.size();
    size_t size = mCriteria.size();
    if (size > MAX_CRITERIA_PER_MIX) {
    if (size > MAX_CRITERIA_PER_MIX) {
        size = MAX_CRITERIA_PER_MIX;
        size = MAX_CRITERIA_PER_MIX;
@@ -206,11 +208,4 @@ bool AudioMix::isDeviceAffinityCompatible() const {
            && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
            && (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
} // namespace android
+2 −8
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@
#ifndef ANDROID_AUDIO_POLICY_H
#ifndef ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H
#define ANDROID_AUDIO_POLICY_H


#include <functional>
#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include <media/AudioDeviceTypeAddr.h>
#include <media/AudioDeviceTypeAddr.h>
#include <system/audio.h>
#include <system/audio.h>
@@ -113,13 +112,6 @@ public:
    /** returns true if this mix can be used for uid-device affinity routing */
    /** returns true if this mix can be used for uid-device affinity routing */
    bool isDeviceAffinityCompatible() const;
    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;
    mutable Vector<AudioMixMatchCriterion> mCriteria;
    uint32_t        mMixType;
    uint32_t        mMixType;
    audio_config_t  mFormat;
    audio_config_t  mFormat;
@@ -129,6 +121,8 @@ public:
    uint32_t        mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
    uint32_t        mCbFlags; // flags indicating which callbacks to use, see kCbFlag*
    /** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
    /** Ignore the AUDIO_FLAG_NO_MEDIA_PROJECTION */
    bool            mAllowPrivilegedPlaybackCapture = false;
    bool            mAllowPrivilegedPlaybackCapture = false;
    /** Indicates if the caller can capture voice communication output */
    bool            mVoiceCommunicationCaptureAllowed = false;
};
};




+4 −0
Original line number Original line Diff line number Diff line
@@ -224,6 +224,10 @@ AudioPolicyMixCollection::MixMatchStatus AudioPolicyMixCollection::mixMatch(
                hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
                hasFlag(attributes.flags, AUDIO_FLAG_NO_MEDIA_PROJECTION)) {
                return MixMatchStatus::NO_MATCH;
                return MixMatchStatus::NO_MATCH;
            }
            }
            if (attributes.usage == AUDIO_USAGE_VOICE_COMMUNICATION &&
                !mix->mVoiceCommunicationCaptureAllowed) {
                return MixMatchStatus::NO_MATCH;
            }
            if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
            if (!(attributes.usage == AUDIO_USAGE_UNKNOWN ||
                  attributes.usage == AUDIO_USAGE_MEDIA ||
                  attributes.usage == AUDIO_USAGE_MEDIA ||
                  attributes.usage == AUDIO_USAGE_GAME ||
                  attributes.usage == AUDIO_USAGE_GAME ||
+0 −1
Original line number Original line Diff line number Diff line
@@ -26,7 +26,6 @@ LOCAL_SHARED_LIBRARIES := \
    libaudioutils \
    libaudioutils \
    libaudiofoundation \
    libaudiofoundation \
    libhardware_legacy \
    libhardware_legacy \
    libaudiopolicy \
    libaudiopolicymanager \
    libaudiopolicymanager \
    libmedia_helper \
    libmedia_helper \
    libmediametrics \
    libmediametrics \
+5 −17
Original line number Original line Diff line number Diff line
@@ -1215,26 +1215,14 @@ status_t AudioPolicyService::registerPolicyMixes(const Vector<AudioMix>& mixes,
        return PERMISSION_DENIED;
        return PERMISSION_DENIED;
    }
    }


    // Require CAPTURE_VOICE_COMMUNICATION_OUTPUT if one of the
    // If one of the mixes has needCaptureVoiceCommunicationOutput set to true, then we
    // mixes is a render|loopback mix that aim to capture audio played with
    // need to verify that the caller still has CAPTURE_VOICE_COMMUNICATION_OUTPUT
    // USAGE_VOICE_COMMUNICATION.
    bool needCaptureVoiceCommunicationOutput =
    bool needCaptureVoiceCommunicationOutput =
        std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
        std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
            return is_mix_loopback_render(mix.mRouteFlags) &&
            return mix.mVoiceCommunicationCaptureAllowed; });
                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).
    bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
    bool needCaptureMediaOutput = std::any_of(mixes.begin(), mixes.end(), [](auto& mix) {
            return mix.mAllowPrivilegedPlaybackCapture &&
            return mix.mAllowPrivilegedPlaybackCapture; });
                mix.hasMatchingRuleForUsage([] (auto usage) {
                    return usage != AUDIO_USAGE_VOICE_COMMUNICATION;
                });
            });


    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    const uid_t callingUid = IPCThreadState::self()->getCallingUid();
    const pid_t callingPid = IPCThreadState::self()->getCallingPid();
    const pid_t callingPid = IPCThreadState::self()->getCallingPid();