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

Commit bda70da1 authored by Jean-Michel Trivi's avatar Jean-Michel Trivi
Browse files

Dynamic audio policies: multi-zone through uid/device affinity

Setting audio device affinity for a given uid augments all
 audio mix criteria that do not route to the given devices
 to exclude the uid.
AudioPolicyManager: after changing the device affinity,
 check the outputs addressing the devices to re-evaluate
 audio routing

Bug: 111647296
Test: requires device with routing policy started by CarService
Change-Id: I72de54ae067151fe6ac2ec43b78fe544a9fd9888
parent abf2929e
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -21,6 +21,22 @@

namespace android {

//
//  AudioDeviceTypeAddr implementation
//
status_t AudioDeviceTypeAddr::readFromParcel(Parcel *parcel) {
    mType = (audio_devices_t) parcel->readInt32();
    mAddress = parcel->readString8();
    return NO_ERROR;
}

status_t AudioDeviceTypeAddr::writeToParcel(Parcel *parcel) const {
    parcel->writeInt32((int32_t) mType);
    parcel->writeString8(mAddress);
    return NO_ERROR;
}


//
//  AudioMixMatchCriterion implementation
//
@@ -40,11 +56,22 @@ AudioMixMatchCriterion::AudioMixMatchCriterion(audio_usage_t usage,
status_t AudioMixMatchCriterion::readFromParcel(Parcel *parcel)
{
    mRule = parcel->readInt32();
    if (mRule == RULE_MATCH_ATTRIBUTE_USAGE ||
            mRule == RULE_EXCLUDE_ATTRIBUTE_USAGE) {
    switch (mRule) {
    case RULE_MATCH_ATTRIBUTE_USAGE:
    case RULE_EXCLUDE_ATTRIBUTE_USAGE:
        mValue.mUsage = (audio_usage_t) parcel->readInt32();
    } else {
        break;
    case RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
    case RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
        mValue.mSource = (audio_source_t) parcel->readInt32();
        break;
    case RULE_MATCH_UID:
    case RULE_EXCLUDE_UID:
        mValue.mUid = (uid_t) parcel->readInt32();
        break;
    default:
        ALOGE("Trying to build AudioMixMatchCriterion from unknown rule %d", mRule);
        return BAD_VALUE;
    }
    return NO_ERROR;
}
@@ -116,4 +143,11 @@ status_t AudioMix::writeToParcel(Parcel *parcel) const
    return NO_ERROR;
}

void AudioMix::excludeUid(uid_t uid) const {
    AudioMixMatchCriterion crit;
    crit.mRule = RULE_EXCLUDE_UID;
    crit.mValue.mUid = uid;
    mCriteria.add(crit);
}

} // namespace android
+13 −0
Original line number Diff line number Diff line
@@ -1236,6 +1236,19 @@ status_t AudioSystem::registerPolicyMixes(const Vector<AudioMix>& mixes, bool re
    return aps->registerPolicyMixes(mixes, registration);
}

status_t AudioSystem::setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
{
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->setUidDeviceAffinities(uid, devices);
}

status_t AudioSystem::removeUidDeviceAffinities(uid_t uid) {
    const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
    if (aps == 0) return PERMISSION_DENIED;
    return aps->removeUidDeviceAffinities(uid);
}

status_t AudioSystem::startAudioSource(const struct audio_port_config *source,
                                       const audio_attributes_t *attributes,
                                       audio_port_handle_t *portId)
+73 −1
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ enum {
    SET_ASSISTANT_UID,
    SET_A11Y_SERVICES_UIDS,
    IS_HAPTIC_PLAYBACK_SUPPORTED,
    SET_UID_DEVICE_AFFINITY,
    REMOVE_UID_DEVICE_AFFINITY,
};

#define MAX_ITEMS_PER_LIST 1024
@@ -990,6 +992,50 @@ public:
        return reply.readBool();
    }

    virtual status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());

        data.writeInt32((int32_t) uid);
        size_t size = devices.size();
        size_t sizePosition = data.dataPosition();
        data.writeInt32((int32_t) size);
        size_t finalSize = size;
        for (size_t i = 0; i < size; i++) {
            size_t position = data.dataPosition();
            if (devices[i].writeToParcel(&data) != NO_ERROR) {
                data.setDataPosition(position);
                finalSize--;
            }
        }
        if (size != finalSize) {
            size_t position = data.dataPosition();
            data.setDataPosition(sizePosition);
            data.writeInt32(finalSize);
            data.setDataPosition(position);
        }

        status_t status = remote()->transact(SET_UID_DEVICE_AFFINITY, data, &reply);
        if (status == NO_ERROR) {
            status = (status_t)reply.readInt32();
        }
        return status;
    }

    virtual status_t removeUidDeviceAffinities(uid_t uid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());

        data.writeInt32((int32_t) uid);

        status_t status = remote()->transact(REMOVE_UID_DEVICE_AFFINITY, data, &reply);
        if (status == NO_ERROR) {
            status = (status_t)reply.readInt32();
        }
        return status;
    }
};

IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1048,7 +1094,9 @@ status_t BnAudioPolicyService::onTransact(
        case GET_SURROUND_FORMATS:
        case SET_SURROUND_FORMAT_ENABLED:
        case SET_ASSISTANT_UID:
        case SET_A11Y_SERVICES_UIDS: {
        case SET_A11Y_SERVICES_UIDS:
        case SET_UID_DEVICE_AFFINITY:
        case REMOVE_UID_DEVICE_AFFINITY: {
            if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                      __func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1814,6 +1862,30 @@ status_t BnAudioPolicyService::onTransact(
            return NO_ERROR;    
        }

        case SET_UID_DEVICE_AFFINITY: {
            CHECK_INTERFACE(IAudioPolicyService, data, reply);
            const uid_t uid = (uid_t) data.readInt32();
            Vector<AudioDeviceTypeAddr> devices;
            size_t size = (size_t)data.readInt32();
            for (size_t i = 0; i < size; i++) {
                AudioDeviceTypeAddr device;
                if (device.readFromParcel((Parcel*)&data) == NO_ERROR) {
                    devices.add(device);
                }
            }
            status_t status = setUidDeviceAffinities(uid, devices);
            reply->writeInt32(status);
            return NO_ERROR;
        }

        case REMOVE_UID_DEVICE_AFFINITY: {
            CHECK_INTERFACE(IAudioPolicyService, data, reply);
            const uid_t uid = (uid_t) data.readInt32();
            status_t status = removeUidDeviceAffinities(uid);
            reply->writeInt32(status);
            return NO_ERROR;
        }

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
+16 −1
Original line number Diff line number Diff line
@@ -56,6 +56,19 @@ namespace android {
#define MAX_MIXES_PER_POLICY 10
#define MAX_CRITERIA_PER_MIX 20

class AudioDeviceTypeAddr {
public:
    AudioDeviceTypeAddr() {}
    AudioDeviceTypeAddr(audio_devices_t type, String8 address) :
        mType(type), mAddress(address) {}

    status_t readFromParcel(Parcel *parcel);
    status_t writeToParcel(Parcel *parcel) const;

    audio_devices_t mType;
    String8 mAddress;
};

class AudioMixMatchCriterion {
public:
    AudioMixMatchCriterion() {}
@@ -87,7 +100,9 @@ public:
    status_t readFromParcel(Parcel *parcel);
    status_t writeToParcel(Parcel *parcel) const;

    Vector<AudioMixMatchCriterion> mCriteria;
    void excludeUid(uid_t uid) const;

    mutable Vector<AudioMixMatchCriterion> mCriteria;
    uint32_t        mMixType;
    audio_config_t  mFormat;
    uint32_t        mRouteFlags;
+4 −0
Original line number Diff line number Diff line
@@ -325,6 +325,10 @@ public:

    static status_t registerPolicyMixes(const Vector<AudioMix>& mixes, bool registration);

    static status_t setUidDeviceAffinities(uid_t uid, const Vector<AudioDeviceTypeAddr>& devices);

    static status_t removeUidDeviceAffinities(uid_t uid);

    static status_t startAudioSource(const struct audio_port_config *source,
                                     const audio_attributes_t *attributes,
                                     audio_port_handle_t *portId);
Loading