1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.media.audiopolicy; 18 19 import android.annotation.IntDef; 20 import android.annotation.SystemApi; 21 import android.media.AudioFormat; 22 import android.media.AudioSystem; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.Objects; 27 28 /** 29 * @hide 30 */ 31 @SystemApi 32 public class AudioMix { 33 34 private AudioMixingRule mRule; 35 private AudioFormat mFormat; 36 private int mRouteFlags; 37 private String mRegistrationId; 38 private int mMixType = MIX_TYPE_INVALID; 39 40 /** 41 * All parameters are guaranteed valid through the Builder. 42 */ AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags)43 private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags) { 44 mRule = rule; 45 mFormat = format; 46 mRouteFlags = routeFlags; 47 mRegistrationId = null; 48 mMixType = rule.getTargetMixType(); 49 } 50 51 /** 52 * An audio mix behavior where the output of the mix is sent to the original destination of 53 * the audio signal, i.e. an output device for an output mix, or a recording for an input mix. 54 */ 55 @SystemApi 56 public static final int ROUTE_FLAG_RENDER = 0x1; 57 /** 58 * An audio mix behavior where the output of the mix is rerouted back to the framework and 59 * is accessible for injection or capture through the {@link AudioTrack} and {@link AudioRecord} 60 * APIs. 61 */ 62 @SystemApi 63 public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1; 64 65 /** 66 * @hide 67 * Invalid mix type, default value. 68 */ 69 public static final int MIX_TYPE_INVALID = -1; 70 /** 71 * @hide 72 * Mix type indicating playback streams are mixed. 73 */ 74 public static final int MIX_TYPE_PLAYERS = 0; 75 /** 76 * @hide 77 * Mix type indicating recording streams are mixed. 78 */ 79 public static final int MIX_TYPE_RECORDERS = 1; 80 getRouteFlags()81 int getRouteFlags() { 82 return mRouteFlags; 83 } 84 getFormat()85 AudioFormat getFormat() { 86 return mFormat; 87 } 88 getRule()89 AudioMixingRule getRule() { 90 return mRule; 91 } 92 93 /** @hide */ getMixType()94 public int getMixType() { 95 return mMixType; 96 } 97 setRegistration(String regId)98 void setRegistration(String regId) { 99 mRegistrationId = regId; 100 } 101 102 /** @hide */ getRegistration()103 public String getRegistration() { 104 return mRegistrationId; 105 } 106 107 /** @hide */ 108 @Override hashCode()109 public int hashCode() { 110 return Objects.hash(mRouteFlags, mRule, mMixType, mFormat); 111 } 112 113 /** @hide */ 114 @IntDef(flag = true, 115 value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } ) 116 @Retention(RetentionPolicy.SOURCE) 117 public @interface RouteFlags {} 118 119 /** 120 * Builder class for {@link AudioMix} objects 121 * 122 */ 123 @SystemApi 124 public static class Builder { 125 private AudioMixingRule mRule = null; 126 private AudioFormat mFormat = null; 127 private int mRouteFlags = 0; 128 129 /** 130 * @hide 131 * Only used by AudioPolicyConfig, not a public API. 132 */ Builder()133 Builder() { } 134 135 /** 136 * Construct an instance for the given {@link AudioMixingRule}. 137 * @param rule a non-null {@link AudioMixingRule} instance. 138 * @throws IllegalArgumentException 139 */ 140 @SystemApi Builder(AudioMixingRule rule)141 public Builder(AudioMixingRule rule) 142 throws IllegalArgumentException { 143 if (rule == null) { 144 throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); 145 } 146 mRule = rule; 147 } 148 149 /** 150 * @hide 151 * Only used by AudioPolicyConfig, not a public API. 152 * @param rule 153 * @return the same Builder instance. 154 * @throws IllegalArgumentException 155 */ setMixingRule(AudioMixingRule rule)156 public Builder setMixingRule(AudioMixingRule rule) 157 throws IllegalArgumentException { 158 if (rule == null) { 159 throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); 160 } 161 mRule = rule; 162 return this; 163 } 164 165 /** 166 * Sets the {@link AudioFormat} for the mix. 167 * @param format a non-null {@link AudioFormat} instance. 168 * @return the same Builder instance. 169 * @throws IllegalArgumentException 170 */ 171 @SystemApi setFormat(AudioFormat format)172 public Builder setFormat(AudioFormat format) 173 throws IllegalArgumentException { 174 if (format == null) { 175 throw new IllegalArgumentException("Illegal null AudioFormat argument"); 176 } 177 mFormat = format; 178 return this; 179 } 180 181 /** 182 * Sets the routing behavior for the mix. 183 * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, 184 * {@link AudioMix#ROUTE_FLAG_RENDER} 185 * @return the same Builder instance. 186 * @throws IllegalArgumentException 187 */ 188 @SystemApi setRouteFlags(@outeFlags int routeFlags)189 public Builder setRouteFlags(@RouteFlags int routeFlags) 190 throws IllegalArgumentException { 191 if (routeFlags == 0) { 192 throw new IllegalArgumentException("Illegal empty route flags"); 193 } 194 if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) { 195 throw new IllegalArgumentException("Invalid route flags 0x" 196 + Integer.toHexString(routeFlags) + "when creating an AudioMix"); 197 } 198 mRouteFlags = routeFlags; 199 return this; 200 } 201 202 /** 203 * Combines all of the settings and return a new {@link AudioMix} object. 204 * @return a new {@link AudioMix} object 205 * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set. 206 */ 207 @SystemApi build()208 public AudioMix build() throws IllegalArgumentException { 209 if (mRule == null) { 210 throw new IllegalArgumentException("Illegal null AudioMixingRule"); 211 } 212 if (mRouteFlags == 0) { 213 // no route flags set, use default 214 mRouteFlags = ROUTE_FLAG_RENDER; 215 } 216 if (mFormat == null) { 217 int rate = AudioSystem.getPrimaryOutputSamplingRate(); 218 if (rate <= 0) { 219 rate = 44100; 220 } 221 mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); 222 } 223 return new AudioMix(mRule, mFormat, mRouteFlags); 224 } 225 } 226 } 227