blob: 1806662c463d61423e912961b29780a59424bfc2 [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.media.audiopolicy;
import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.media.AudioFormat;
import android.media.AudioSystem;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* @hide
*/
@SystemApi
public class AudioMix {
private AudioMixingRule mRule;
private AudioFormat mFormat;
private int mRouteFlags;
private String mRegistrationId;
private int mMixType = MIX_TYPE_INVALID;
/**
* All parameters are guaranteed valid through the Builder.
*/
private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags) {
mRule = rule;
mFormat = format;
mRouteFlags = routeFlags;
mRegistrationId = null;
mMixType = rule.getTargetMixType();
}
/**
* An audio mix behavior where the output of the mix is sent to the original destination of
* the audio signal, i.e. an output device for an output mix, or a recording for an input mix.
*/
@SystemApi
public static final int ROUTE_FLAG_RENDER = 0x1;
/**
* An audio mix behavior where the output of the mix is rerouted back to the framework and
* is accessible for injection or capture through the {@link AudioTrack} and {@link AudioRecord}
* APIs.
*/
@SystemApi
public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1;
/**
* @hide
* Invalid mix type, default value.
*/
public static final int MIX_TYPE_INVALID = -1;
/**
* @hide
* Mix type indicating playback streams are mixed.
*/
public static final int MIX_TYPE_PLAYERS = 0;
/**
* @hide
* Mix type indicating recording streams are mixed.
*/
public static final int MIX_TYPE_RECORDERS = 1;
int getRouteFlags() {
return mRouteFlags;
}
AudioFormat getFormat() {
return mFormat;
}
AudioMixingRule getRule() {
return mRule;
}
/** @hide */
public int getMixType() {
return mMixType;
}
void setRegistration(String regId) {
mRegistrationId = regId;
}
/** @hide */
public String getRegistration() {
return mRegistrationId;
}
/** @hide */
@Override
public int hashCode() {
return Objects.hash(mRouteFlags, mRule, mMixType, mFormat);
}
/** @hide */
@IntDef(flag = true,
value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } )
@Retention(RetentionPolicy.SOURCE)
public @interface RouteFlags {}
/**
* Builder class for {@link AudioMix} objects
*
*/
@SystemApi
public static class Builder {
private AudioMixingRule mRule = null;
private AudioFormat mFormat = null;
private int mRouteFlags = 0;
/**
* @hide
* Only used by AudioPolicyConfig, not a public API.
*/
Builder() { }
/**
* Construct an instance for the given {@link AudioMixingRule}.
* @param rule a non-null {@link AudioMixingRule} instance.
* @throws IllegalArgumentException
*/
@SystemApi
public Builder(AudioMixingRule rule)
throws IllegalArgumentException {
if (rule == null) {
throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
}
mRule = rule;
}
/**
* @hide
* Only used by AudioPolicyConfig, not a public API.
* @param rule
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
public Builder setMixingRule(AudioMixingRule rule)
throws IllegalArgumentException {
if (rule == null) {
throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
}
mRule = rule;
return this;
}
/**
* Sets the {@link AudioFormat} for the mix.
* @param format a non-null {@link AudioFormat} instance.
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
@SystemApi
public Builder setFormat(AudioFormat format)
throws IllegalArgumentException {
if (format == null) {
throw new IllegalArgumentException("Illegal null AudioFormat argument");
}
mFormat = format;
return this;
}
/**
* Sets the routing behavior for the mix.
* @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK},
* {@link AudioMix#ROUTE_FLAG_RENDER}
* @return the same Builder instance.
* @throws IllegalArgumentException
*/
@SystemApi
public Builder setRouteFlags(@RouteFlags int routeFlags)
throws IllegalArgumentException {
if (routeFlags == 0) {
throw new IllegalArgumentException("Illegal empty route flags");
}
if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) {
throw new IllegalArgumentException("Invalid route flags 0x"
+ Integer.toHexString(routeFlags) + "when creating an AudioMix");
}
mRouteFlags = routeFlags;
return this;
}
/**
* Combines all of the settings and return a new {@link AudioMix} object.
* @return a new {@link AudioMix} object
* @throws IllegalArgumentException if no {@link AudioMixingRule} has been set.
*/
@SystemApi
public AudioMix build() throws IllegalArgumentException {
if (mRule == null) {
throw new IllegalArgumentException("Illegal null AudioMixingRule");
}
if (mRouteFlags == 0) {
// no route flags set, use default
mRouteFlags = ROUTE_FLAG_RENDER;
}
if (mFormat == null) {
int rate = AudioSystem.getPrimaryOutputSamplingRate();
if (rate <= 0) {
rate = 44100;
}
mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
}
return new AudioMix(mRule, mFormat, mRouteFlags);
}
}
}