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

Commit b09f621a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "APM: uid-device affinity: fix for multiple concurrent apps" into qt-dev

parents b14e4295 e2f34be1
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -159,4 +159,29 @@ void AudioMix::setMatchUid(uid_t uid) const {
    mCriteria.add(crit);
}

bool AudioMix::hasUidRule(bool match, uid_t uid) const {
    const uint32_t rule = match ? RULE_MATCH_UID : RULE_EXCLUDE_UID;
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == rule
                && mCriteria[i].mValue.mUid == uid) {
            return true;
        }
    }
    return false;
}

bool AudioMix::hasMatchUidRule() const {
    for (size_t i = 0; i < mCriteria.size(); i++) {
        if (mCriteria[i].mRule == RULE_MATCH_UID) {
            return true;
        }
    }
    return false;
}

bool AudioMix::isDeviceAffinityCompatible() const {
    return ((mMixType == MIX_TYPE_PLAYERS)
            && (mRouteFlags == MIX_ROUTE_FLAG_RENDER));
}

} // namespace android
+6 −0
Original line number Diff line number Diff line
@@ -106,6 +106,12 @@ public:

    void setExcludeUid(uid_t uid) const;
    void setMatchUid(uid_t uid) const;
    /** returns true if this mix has a rule to match or exclude the given uid */
    bool hasUidRule(bool match, uid_t uid) const;
    /** returns true if this mix has a rule for uid match (any uid) */
    bool hasMatchUidRule() const;
    /** returns true if this mix can be used for uid-device affinity routing */
    bool isDeviceAffinityCompatible() const;

    mutable Vector<AudioMixMatchCriterion> mCriteria;
    uint32_t        mMixType;
+10 −0
Original line number Diff line number Diff line
@@ -89,6 +89,16 @@ public:

    status_t getInputMixForAttr(audio_attributes_t attr, sp<AudioPolicyMix> *policyMix);

    /**
     * Updates the mix rules in order to make streams associated with the given uid
     * be routed to the given audio devices.
     * @param uid the uid for which the device affinity is set
     * @param devices the vector of devices that this uid may be routed to. A typical
     *    use is to pass the devices associated with a given zone in a multi-zone setup.
     * @return NO_ERROR if the update was successful, INVALID_OPERATION otherwise.
     *    An example of failure is when there are already rules in place to restrict
     *    a mix to the given uid (i.e. when a MATCH_UID rule was set for it).
     */
    status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);
    status_t removeUidDeviceAffinities(uid_t uid);
    status_t getDevicesForUid(uid_t uid, Vector<AudioDeviceTypeAddr>& devices) const;
+28 −9
Original line number Diff line number Diff line
@@ -400,13 +400,29 @@ status_t AudioPolicyMixCollection::getInputMixForAttr(

status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
        const Vector<AudioDeviceTypeAddr>& devices) {
    // verify feasibility: for each player mix: if it already contains a
    //    "match uid" rule for this uid, return an error
    //    (adding a uid-device affinity would result in contradictory rules)
    for (size_t i = 0; i < size(); i++) {
        const AudioPolicyMix* mix = valueAt(i).get();
        if (!mix->isDeviceAffinityCompatible()) {
            continue;
        }
        if (mix->hasUidRule(true /*match*/, uid)) {
            return INVALID_OPERATION;
        }
    }

    // remove existing rules for this uid
    removeUidDeviceAffinities(uid);

    // for each player mix: add a rule to match or exclude the uid based on the device
    // for each player mix:
    //   IF    device is not a target for the mix,
    //     AND it doesn't have a "match uid" rule
    //   THEN add a rule to exclude the uid
    for (size_t i = 0; i < size(); i++) {
        const AudioPolicyMix *mix = valueAt(i).get();
        if (mix->mMixType != MIX_TYPE_PLAYERS) {
        if (!mix->isDeviceAffinityCompatible()) {
            continue;
        }
        // check if this mix goes to a device in the list of devices
@@ -418,14 +434,16 @@ status_t AudioPolicyMixCollection::setUidDeviceAffinities(uid_t uid,
                break;
            }
        }
        if (deviceMatch) {
            mix->setMatchUid(uid);
        } else {
        if (!deviceMatch && !mix->hasMatchUidRule()) {
            // this mix doesn't go to one of the listed devices for the given uid,
            // and it's not already restricting the mix on a uid,
            // modify its rules to exclude the uid
            if (!mix->hasUidRule(false /*match*/, uid)) {
                // no need to do it again if uid is already excluded
                mix->setExcludeUid(uid);
            }
        }
    }

    return NO_ERROR;
}
@@ -435,14 +453,15 @@ status_t AudioPolicyMixCollection::removeUidDeviceAffinities(uid_t uid) {
    for (size_t i = 0; i < size(); i++) {
        bool foundUidRule = false;
        const AudioPolicyMix *mix = valueAt(i).get();
        if (mix->mMixType != MIX_TYPE_PLAYERS) {
        if (!mix->isDeviceAffinityCompatible()) {
            continue;
        }
        std::vector<size_t> criteriaToRemove;
        for (size_t j = 0; j < mix->mCriteria.size(); j++) {
            const uint32_t rule = mix->mCriteria[j].mRule;
            // is this rule affecting the uid?
            if ((rule == RULE_EXCLUDE_UID || rule == RULE_MATCH_UID)
            // is this rule excluding the uid? (not considering uid match rules
            // as those are not used for uid-device affinity)
            if (rule == RULE_EXCLUDE_UID
                    && uid == mix->mCriteria[j].mValue.mUid) {
                foundUidRule = true;
                criteriaToRemove.insert(criteriaToRemove.begin(), j);