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 int mMixState = MIX_STATE_DISABLED; 40 int mCallbackFlags; 41 42 /** 43 * All parameters are guaranteed valid through the Builder. 44 */ AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags)45 private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags) { 46 mRule = rule; 47 mFormat = format; 48 mRouteFlags = routeFlags; 49 mRegistrationId = null; 50 mMixType = rule.getTargetMixType(); 51 mCallbackFlags = callbackFlags; 52 } 53 54 // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined 55 // in frameworks/av/include/media/AudioPolicy.h 56 /** @hide */ 57 public final static int CALLBACK_FLAG_NOTIFY_ACTIVITY = 0x1; 58 // when adding new MIX_FLAG_* flags, add them to this mask of authorized masks: 59 private final static int CALLBACK_FLAGS_ALL = CALLBACK_FLAG_NOTIFY_ACTIVITY; 60 61 // ROUTE_FLAG_* values: keep in sync with MIX_ROUTE_FLAG_* values defined 62 // in frameworks/av/include/media/AudioPolicy.h 63 /** 64 * An audio mix behavior where the output of the mix is sent to the original destination of 65 * the audio signal, i.e. an output device for an output mix, or a recording for an input mix. 66 */ 67 @SystemApi 68 public static final int ROUTE_FLAG_RENDER = 0x1; 69 /** 70 * An audio mix behavior where the output of the mix is rerouted back to the framework and 71 * is accessible for injection or capture through the {@link AudioTrack} and {@link AudioRecord} 72 * APIs. 73 */ 74 @SystemApi 75 public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1; 76 77 // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h 78 /** 79 * @hide 80 * Invalid mix type, default value. 81 */ 82 public static final int MIX_TYPE_INVALID = -1; 83 /** 84 * @hide 85 * Mix type indicating playback streams are mixed. 86 */ 87 public static final int MIX_TYPE_PLAYERS = 0; 88 /** 89 * @hide 90 * Mix type indicating recording streams are mixed. 91 */ 92 public static final int MIX_TYPE_RECORDERS = 1; 93 94 95 // MIX_STATE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h 96 /** 97 * @hide 98 * State of a mix before its policy is enabled. 99 */ 100 @SystemApi 101 public static final int MIX_STATE_DISABLED = -1; 102 /** 103 * @hide 104 * State of a mix when there is no audio to mix. 105 */ 106 @SystemApi 107 public static final int MIX_STATE_IDLE = 0; 108 /** 109 * @hide 110 * State of a mix that is actively mixing audio. 111 */ 112 @SystemApi 113 public static final int MIX_STATE_MIXING = 1; 114 115 /** 116 * @hide 117 * The current mixing state. 118 * @return one of {@link #MIX_STATE_DISABLED}, {@link #MIX_STATE_IDLE}, 119 * {@link #MIX_STATE_MIXING}. 120 */ 121 @SystemApi getMixState()122 public int getMixState() { 123 return mMixState; 124 } 125 126 getRouteFlags()127 int getRouteFlags() { 128 return mRouteFlags; 129 } 130 getFormat()131 AudioFormat getFormat() { 132 return mFormat; 133 } 134 getRule()135 AudioMixingRule getRule() { 136 return mRule; 137 } 138 139 /** @hide */ getMixType()140 public int getMixType() { 141 return mMixType; 142 } 143 setRegistration(String regId)144 void setRegistration(String regId) { 145 mRegistrationId = regId; 146 } 147 148 /** @hide */ getRegistration()149 public String getRegistration() { 150 return mRegistrationId; 151 } 152 153 /** @hide */ 154 @Override hashCode()155 public int hashCode() { 156 return Objects.hash(mRouteFlags, mRule, mMixType, mFormat); 157 } 158 159 /** @hide */ 160 @IntDef(flag = true, 161 value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } ) 162 @Retention(RetentionPolicy.SOURCE) 163 public @interface RouteFlags {} 164 165 /** 166 * Builder class for {@link AudioMix} objects 167 * 168 */ 169 @SystemApi 170 public static class Builder { 171 private AudioMixingRule mRule = null; 172 private AudioFormat mFormat = null; 173 private int mRouteFlags = 0; 174 private int mCallbackFlags = 0; 175 176 /** 177 * @hide 178 * Only used by AudioPolicyConfig, not a public API. 179 */ Builder()180 Builder() { } 181 182 /** 183 * Construct an instance for the given {@link AudioMixingRule}. 184 * @param rule a non-null {@link AudioMixingRule} instance. 185 * @throws IllegalArgumentException 186 */ 187 @SystemApi Builder(AudioMixingRule rule)188 public Builder(AudioMixingRule rule) 189 throws IllegalArgumentException { 190 if (rule == null) { 191 throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); 192 } 193 mRule = rule; 194 } 195 196 /** 197 * @hide 198 * Only used by AudioPolicyConfig, not a public API. 199 * @param rule 200 * @return the same Builder instance. 201 * @throws IllegalArgumentException 202 */ setMixingRule(AudioMixingRule rule)203 public Builder setMixingRule(AudioMixingRule rule) 204 throws IllegalArgumentException { 205 if (rule == null) { 206 throw new IllegalArgumentException("Illegal null AudioMixingRule argument"); 207 } 208 mRule = rule; 209 return this; 210 } 211 212 /** 213 * @hide 214 * Only used by AudioPolicyConfig, not a public API. 215 * @param callbackFlags which callbacks are called from native 216 * @return the same Builder instance. 217 * @throws IllegalArgumentException 218 */ setCallbackFlags(int flags)219 public Builder setCallbackFlags(int flags) throws IllegalArgumentException { 220 if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) { 221 throw new IllegalArgumentException("Illegal callback flags 0x" 222 + Integer.toHexString(flags).toUpperCase()); 223 } 224 mCallbackFlags = flags; 225 return this; 226 } 227 228 /** 229 * Sets the {@link AudioFormat} for the mix. 230 * @param format a non-null {@link AudioFormat} instance. 231 * @return the same Builder instance. 232 * @throws IllegalArgumentException 233 */ 234 @SystemApi setFormat(AudioFormat format)235 public Builder setFormat(AudioFormat format) 236 throws IllegalArgumentException { 237 if (format == null) { 238 throw new IllegalArgumentException("Illegal null AudioFormat argument"); 239 } 240 mFormat = format; 241 return this; 242 } 243 244 /** 245 * Sets the routing behavior for the mix. 246 * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK}, 247 * {@link AudioMix#ROUTE_FLAG_RENDER} 248 * @return the same Builder instance. 249 * @throws IllegalArgumentException 250 */ 251 @SystemApi setRouteFlags(@outeFlags int routeFlags)252 public Builder setRouteFlags(@RouteFlags int routeFlags) 253 throws IllegalArgumentException { 254 if (routeFlags == 0) { 255 throw new IllegalArgumentException("Illegal empty route flags"); 256 } 257 if ((routeFlags & (ROUTE_FLAG_LOOP_BACK | ROUTE_FLAG_RENDER)) == 0) { 258 throw new IllegalArgumentException("Invalid route flags 0x" 259 + Integer.toHexString(routeFlags) + "when creating an AudioMix"); 260 } 261 mRouteFlags = routeFlags; 262 return this; 263 } 264 265 /** 266 * Combines all of the settings and return a new {@link AudioMix} object. 267 * @return a new {@link AudioMix} object 268 * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set. 269 */ 270 @SystemApi build()271 public AudioMix build() throws IllegalArgumentException { 272 if (mRule == null) { 273 throw new IllegalArgumentException("Illegal null AudioMixingRule"); 274 } 275 if (mRouteFlags == 0) { 276 // no route flags set, use default 277 mRouteFlags = ROUTE_FLAG_RENDER; 278 } 279 if (mFormat == null) { 280 int rate = AudioSystem.getPrimaryOutputSamplingRate(); 281 if (rate <= 0) { 282 rate = 44100; 283 } 284 mFormat = new AudioFormat.Builder().setSampleRate(rate).build(); 285 } 286 return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags); 287 } 288 } 289 } 290