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

Commit a40c017b authored by Jean-Michel Trivi's avatar Jean-Michel Trivi Committed by Android (Google) Code Review
Browse files

Merge "Dynamic audio policies: allow device passing for RENDER mixes" into nyc-dev

parents 102c5122 e8924115
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -23829,6 +23829,7 @@ package android.media.audiopolicy {
  public static class AudioMix.Builder {
    ctor public AudioMix.Builder(android.media.audiopolicy.AudioMixingRule) throws java.lang.IllegalArgumentException;
    method public android.media.audiopolicy.AudioMix build() throws java.lang.IllegalArgumentException;
    method public android.media.audiopolicy.AudioMix.Builder setDevice(android.media.AudioDeviceInfo) throws java.lang.IllegalArgumentException;
    method public android.media.audiopolicy.AudioMix.Builder setFormat(android.media.AudioFormat) throws java.lang.IllegalArgumentException;
    method public android.media.audiopolicy.AudioMix.Builder setRouteFlags(int) throws java.lang.IllegalArgumentException;
  }
+84 −9
Original line number Diff line number Diff line
@@ -17,7 +17,9 @@
package android.media.audiopolicy;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioSystem;

@@ -36,19 +38,28 @@ public class AudioMix {
    private int mRouteFlags;
    private String mRegistrationId;
    private int mMixType = MIX_TYPE_INVALID;

    // written by AudioPolicy
    int mMixState = MIX_STATE_DISABLED;
    int mCallbackFlags;

    // initialized in constructor, read by AudioPolicyConfig
    final int mDeviceId;
    final String mDeviceAddress;

    /**
     * All parameters are guaranteed valid through the Builder.
     */
    private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) {
    private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
            int deviceId, String deviceAddress) {
        mRule = rule;
        mFormat = format;
        mRouteFlags = routeFlags;
        mRegistrationId = null;
        mMixType = rule.getTargetMixType();
        mCallbackFlags = callbackFlags;
        mDeviceId = deviceId;
        mDeviceAddress = deviceAddress;
    }

    // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
@@ -74,6 +85,8 @@ public class AudioMix {
    @SystemApi
    public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1;

    private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK;

    // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h
    /**
     * @hide
@@ -172,6 +185,8 @@ public class AudioMix {
        private AudioFormat mFormat = null;
        private int mRouteFlags = 0;
        private int mCallbackFlags = 0;
        private int mDeviceId = -1;
        private String mDeviceAddress = null;

        /**
         * @hide
@@ -200,7 +215,7 @@ public class AudioMix {
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public Builder setMixingRule(AudioMixingRule rule)
        Builder setMixingRule(AudioMixingRule rule)
                throws IllegalArgumentException {
            if (rule == null) {
                throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
@@ -216,7 +231,7 @@ public class AudioMix {
         * @return the same Builder instance.
         * @throws IllegalArgumentException
         */
        public Builder setCallbackFlags(int flags) throws IllegalArgumentException {
        Builder setCallbackFlags(int flags) throws IllegalArgumentException {
            if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) {
                throw new IllegalArgumentException("Illegal callback flags 0x"
                        + Integer.toHexString(flags).toUpperCase());
@@ -225,6 +240,19 @@ public class AudioMix {
            return this;
        }

        /**
         * @hide
         * Only used by AudioPolicyConfig, not a public API.
         * @param deviceId
         * @param address
         * @return the same Builder instance.
         */
        Builder setDevice(int deviceId, String address) {
            mDeviceId = deviceId;
            mDeviceAddress = address;
            return this;
        }

        /**
         * Sets the {@link AudioFormat} for the mix.
         * @param format a non-null {@link AudioFormat} instance.
@@ -242,7 +270,8 @@ public class AudioMix {
        }

        /**
         * Sets the routing behavior for the mix.
         * Sets the routing behavior for the mix. If not set, routing behavior will default to
         * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}.
         * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK},
         *     {@link AudioMix#ROUTE_FLAG_RENDER}
         * @return the same Builder instance.
@@ -254,14 +283,40 @@ public class AudioMix {
            if (routeFlags == 0) {
                throw new IllegalArgumentException("Illegal empty route flags");
            }
            if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) {
            if ((routeFlags & ROUTE_FLAG_SUPPORTED) == 0) {
                throw new IllegalArgumentException("Invalid route flags 0x"
                        + Integer.toHexString(routeFlags) + "when creating an AudioMix");
                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
            }
            if ((routeFlags & ~ROUTE_FLAG_SUPPORTED) != 0) {
                throw new IllegalArgumentException("Unknown route flags 0x"
                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
            }
            mRouteFlags = routeFlags;
            return this;
        }

        /**
         * Sets the audio device used for playback. Cannot be used in the context of an audio
         * policy used to inject audio to be recorded, or in a mix whose route flags doesn't
         * specify {@link AudioMix#ROUTE_FLAG_RENDER}.
         * @param device a non-null AudioDeviceInfo describing the audio device to play the output
         *     of this mix.
         * @return the same Builder instance
         * @throws IllegalArgumentException
         */
        @SystemApi
        public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException {
            if (device == null) {
                throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument");
            }
            if (!device.isSink()) {
                throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
            }
            mDeviceId = device.getId();
            mDeviceAddress = device.getAddress();
            return this;
        }

        /**
         * Combines all of the settings and return a new {@link AudioMix} object.
         * @return a new {@link AudioMix} object
@@ -273,8 +328,13 @@ public class AudioMix {
                throw new IllegalArgumentException("Illegal null AudioMixingRule");
            }
            if (mRouteFlags == 0) {
                // no route flags set, use default
                mRouteFlags = ROUTE_FLAG_RENDER;
                // no route flags set, use default as described in Builder.setRouteFlags(int)
                mRouteFlags = ROUTE_FLAG_LOOP_BACK;
            }
            // can't do loop back AND render at same time in this implementation
            if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) {
                throw new IllegalArgumentException("Unsupported route behavior combination 0x" +
                        Integer.toHexString(mRouteFlags));
            }
            if (mFormat == null) {
                // FIXME Can we eliminate this?  Will AudioMix work with an unspecified sample rate?
@@ -284,7 +344,22 @@ public class AudioMix {
                }
                mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
            }
            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags);
            if (mDeviceId != -1) {
                if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
                    throw new IllegalArgumentException(
                            "Can't have audio device without flag ROUTE_FLAG_RENDER");
                }
                if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) {
                    throw new IllegalArgumentException("Unsupported device on non-playback mix");
                }
            } else {
                if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) {
                    throw new IllegalArgumentException(
                            "Can't have flag ROUTE_FLAG_RENDER without an audio device");
                }
            }
            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceId,
                    mDeviceAddress);
        }
    }
}
+15 −2
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package android.media.audiopolicy;

import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioPatch;
import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.os.Parcel;
import android.os.Parcelable;
@@ -81,6 +83,9 @@ public class AudioPolicyConfig implements Parcelable {
            dest.writeInt(mix.getRouteFlags());
            // write callback flags
            dest.writeInt(mix.mCallbackFlags);
            // write device information
            dest.writeInt(mix.mDeviceId);
            dest.writeString(mix.mDeviceAddress);
            // write mix format
            dest.writeInt(mix.getFormat().getSampleRate());
            dest.writeInt(mix.getFormat().getEncoding());
@@ -104,6 +109,8 @@ public class AudioPolicyConfig implements Parcelable {
            mixBuilder.setRouteFlags(routeFlags);
            // read callback flags
            mixBuilder.setCallbackFlags(in.readInt());
            // read device information
            mixBuilder.setDevice(in.readInt(), in.readString());
            // read mix format
            int sampleRate = in.readInt();
            int encoding = in.readInt();
@@ -197,8 +204,14 @@ public class AudioPolicyConfig implements Parcelable {
        int mixIndex = 0;
        for (AudioMix mix : mMixes) {
            if (!mRegistrationId.isEmpty()) {
                if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) ==
                        AudioMix.ROUTE_FLAG_LOOP_BACK) {
                    mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
                            + mixIndex++);
                } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) ==
                        AudioMix.ROUTE_FLAG_RENDER) {
                    mix.setRegistration(mix.mDeviceAddress);
                }
            } else {
                mix.setRegistration("");
            }