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