1a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/*
2a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Copyright (C) 2014 The Android Open Source Project
3a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
4a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Licensed under the Apache License, Version 2.0 (the "License");
5a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * you may not use this file except in compliance with the License.
6a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * You may obtain a copy of the License at
7a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
8a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *      http://www.apache.org/licenses/LICENSE-2.0
9a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi *
10a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Unless required by applicable law or agreed to in writing, software
11a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * distributed under the License is distributed on an "AS IS" BASIS,
12a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * See the License for the specific language governing permissions and
14a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * limitations under the License.
15a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */
16a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
17a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipackage android.media.audiopolicy;
18a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
19a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.annotation.IntDef;
20e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Triviimport android.annotation.NonNull;
211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport android.annotation.SystemApi;
22e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Triviimport android.media.AudioDeviceInfo;
23a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.AudioFormat;
24a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.media.AudioSystem;
25a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
26a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.lang.annotation.Retention;
27a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.lang.annotation.RetentionPolicy;
281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport java.util.Objects;
29a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
30a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/**
318fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi * @hide
32a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */
331b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi@SystemApi
34a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipublic class AudioMix {
35a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
36a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private AudioMixingRule mRule;
37a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private AudioFormat mFormat;
38a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private int mRouteFlags;
391b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private int mMixType = MIX_TYPE_INVALID;
40e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi
41e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi    // written by AudioPolicy
425a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    int mMixState = MIX_STATE_DISABLED;
435a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    int mCallbackFlags;
444ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi    String mDeviceAddress;
45a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
46e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi    // initialized in constructor, read by AudioPolicyConfig
474ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi    final int mDeviceSystemType; // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
48e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi
49a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
50a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * All parameters are guaranteed valid through the Builder.
51a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
52e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi    private AudioMix(AudioMixingRule rule, AudioFormat format, int routeFlags, int callbackFlags,
534ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            int deviceType, String deviceAddress) {
54a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mRule = rule;
55a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mFormat = format;
56a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mRouteFlags = routeFlags;
571b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        mMixType = rule.getTargetMixType();
585a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        mCallbackFlags = callbackFlags;
594ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        mDeviceSystemType = deviceType;
604ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        mDeviceAddress = (deviceAddress == null) ? new String("") : deviceAddress;
61a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
62a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
635a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    // CALLBACK_FLAG_* values: keep in sync with AudioMix::kCbFlag* values defined
645a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    // in frameworks/av/include/media/AudioPolicy.h
655a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    /** @hide */
665a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    public final static int CALLBACK_FLAG_NOTIFY_ACTIVITY = 0x1;
675a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    // when adding new MIX_FLAG_* flags, add them to this mask of authorized masks:
685a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    private final static int CALLBACK_FLAGS_ALL = CALLBACK_FLAG_NOTIFY_ACTIVITY;
695a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi
705a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    // ROUTE_FLAG_* values: keep in sync with MIX_ROUTE_FLAG_* values defined
715a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    // in frameworks/av/include/media/AudioPolicy.h
72a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
73a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * An audio mix behavior where the output of the mix is sent to the original destination of
74a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * the audio signal, i.e. an output device for an output mix, or a recording for an input mix.
75a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
77a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static final int ROUTE_FLAG_RENDER    = 0x1;
78a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
79a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * An audio mix behavior where the output of the mix is rerouted back to the framework and
801b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * is accessible for injection or capture through the {@link AudioTrack} and {@link AudioRecord}
81a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * APIs.
82a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
831b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
84a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static final int ROUTE_FLAG_LOOP_BACK = 0x1 << 1;
85a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
86e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi    private static final int ROUTE_FLAG_SUPPORTED = ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK;
87e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi
88cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    // MIX_TYPE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h
891b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    /**
901b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * @hide
911b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * Invalid mix type, default value.
921b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     */
931b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public static final int MIX_TYPE_INVALID = -1;
941b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    /**
951b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * @hide
961b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * Mix type indicating playback streams are mixed.
971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     */
981b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public static final int MIX_TYPE_PLAYERS = 0;
991b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    /**
1001b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * @hide
1011b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     * Mix type indicating recording streams are mixed.
1021b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi     */
1031b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public static final int MIX_TYPE_RECORDERS = 1;
1041b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
105cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi
106cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    // MIX_STATE_* values to keep in sync with frameworks/av/include/media/AudioPolicy.h
107cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    /**
108cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * @hide
109cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * State of a mix before its policy is enabled.
110cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     */
111cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    @SystemApi
112cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    public static final int MIX_STATE_DISABLED = -1;
113cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    /**
114cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * @hide
115cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * State of a mix when there is no audio to mix.
116cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     */
117cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    @SystemApi
118cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    public static final int MIX_STATE_IDLE = 0;
119cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    /**
120cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * @hide
121cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * State of a mix that is actively mixing audio.
122cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     */
123cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    @SystemApi
124cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    public static final int MIX_STATE_MIXING = 1;
125cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi
126cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    /**
127cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * @hide
128cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * The current mixing state.
129cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     * @return one of {@link #MIX_STATE_DISABLED}, {@link #MIX_STATE_IDLE},
130cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     *          {@link #MIX_STATE_MIXING}.
131cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi     */
132cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    @SystemApi
133cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    public int getMixState() {
134cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi        return mMixState;
135cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi    }
136cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi
137cc98c67ef7f1548766e0b742eb041579e74ba225Jean-Michel Trivi
138a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    int getRouteFlags() {
139a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return mRouteFlags;
140a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
141a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
142a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    AudioFormat getFormat() {
143a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return mFormat;
144a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
145a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
146a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    AudioMixingRule getRule() {
147a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return mRule;
148a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
149a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
1501b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    /** @hide */
1511b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public int getMixType() {
1521b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        return mMixType;
1531b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
1541b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
1558fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    void setRegistration(String regId) {
1564ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        mDeviceAddress = regId;
1578fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
1588fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
1598fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    /** @hide */
1608fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public String getRegistration() {
1614ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        return mDeviceAddress;
1628fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
1638fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
164a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /** @hide */
1657db2d8f1cc19238f3bf627b081462e3e062686dfJean-Michel Trivi    public boolean isAffectingUsage(int usage) {
1667db2d8f1cc19238f3bf627b081462e3e062686dfJean-Michel Trivi        return mRule.isAffectingUsage(usage);
1677db2d8f1cc19238f3bf627b081462e3e062686dfJean-Michel Trivi    }
1687db2d8f1cc19238f3bf627b081462e3e062686dfJean-Michel Trivi
1697db2d8f1cc19238f3bf627b081462e3e062686dfJean-Michel Trivi    /** @hide */
1701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @Override
171af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi    public boolean equals(Object o) {
172af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi        if (this == o) return true;
173af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi        if (o == null || getClass() != o.getClass()) return false;
174af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi
175af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi        final AudioMix that = (AudioMix) o;
176af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi        return (this.mRouteFlags == that.mRouteFlags)
177af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi                && (this.mRule == that.mRule)
178af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi                && (this.mMixType == that.mMixType)
179af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi                && (this.mFormat == that.mFormat);
180af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi    }
181af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi
182af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi    /** @hide */
183af576a0e4fa9c9fe06a185007d5f201d80e4ebd1Jean-Michel Trivi    @Override
1841b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public int hashCode() {
1851b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        return Objects.hash(mRouteFlags, mRule, mMixType, mFormat);
1861b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
1871b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
1881b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    /** @hide */
189a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @IntDef(flag = true,
190a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            value = { ROUTE_FLAG_RENDER, ROUTE_FLAG_LOOP_BACK } )
191a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @Retention(RetentionPolicy.SOURCE)
192a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public @interface RouteFlags {}
193a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
194a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
195a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * Builder class for {@link AudioMix} objects
196a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     *
197a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
1981b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @SystemApi
199a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static class Builder {
200a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        private AudioMixingRule mRule = null;
201a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        private AudioFormat mFormat = null;
202a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        private int mRouteFlags = 0;
2035a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        private int mCallbackFlags = 0;
2044ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        // an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
2054ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        private int mDeviceSystemType = AudioSystem.DEVICE_NONE;
206e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        private String mDeviceAddress = null;
207a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
208a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
209a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @hide
210a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Only used by AudioPolicyConfig, not a public API.
211a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
212a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        Builder() { }
213a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
214a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
215a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Construct an instance for the given {@link AudioMixingRule}.
216a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param rule a non-null {@link AudioMixingRule} instance.
217a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException
218a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
2191b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        @SystemApi
220a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public Builder(AudioMixingRule rule)
221a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throws IllegalArgumentException {
222a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (rule == null) {
223a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
224a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
225a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mRule = rule;
226a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
227a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
228a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
229a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @hide
230a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Only used by AudioPolicyConfig, not a public API.
231a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param rule
232a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return the same Builder instance.
233a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException
234a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
235e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        Builder setMixingRule(AudioMixingRule rule)
236a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throws IllegalArgumentException {
237a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (rule == null) {
238a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioMixingRule argument");
239a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
240a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mRule = rule;
241a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return this;
242a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
243a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
244a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
2455a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         * @hide
2465a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         * Only used by AudioPolicyConfig, not a public API.
2475a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         * @param callbackFlags which callbacks are called from native
2485a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         * @return the same Builder instance.
2495a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         * @throws IllegalArgumentException
2505a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi         */
251e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        Builder setCallbackFlags(int flags) throws IllegalArgumentException {
2525a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            if ((flags != 0) && ((flags & CALLBACK_FLAGS_ALL) == 0)) {
2535a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                throw new IllegalArgumentException("Illegal callback flags 0x"
2545a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi                        + Integer.toHexString(flags).toUpperCase());
2555a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            }
2565a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            mCallbackFlags = flags;
2575a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            return this;
2585a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        }
2595a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi
2605a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        /**
261e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @hide
262e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * Only used by AudioPolicyConfig, not a public API.
2634ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi         * @param deviceType an AudioSystem.DEVICE_* value, not AudioDeviceInfo.TYPE_*
264e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @param address
265e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @return the same Builder instance.
266e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         */
2674ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi        Builder setDevice(int deviceType, String address) {
2684ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            mDeviceSystemType = deviceType;
269e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            mDeviceAddress = address;
270e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            return this;
271e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        }
272e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi
273e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        /**
274a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Sets the {@link AudioFormat} for the mix.
275a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param format a non-null {@link AudioFormat} instance.
276a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return the same Builder instance.
277a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException
278a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
2791b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        @SystemApi
280a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public Builder setFormat(AudioFormat format)
281a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throws IllegalArgumentException {
282a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (format == null) {
283a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioFormat argument");
284a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
285a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mFormat = format;
286a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return this;
287a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
288a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
289a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
290e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * Sets the routing behavior for the mix. If not set, routing behavior will default to
291e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * {@link AudioMix#ROUTE_FLAG_LOOP_BACK}.
292a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param routeFlags one of {@link AudioMix#ROUTE_FLAG_LOOP_BACK},
293a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         *     {@link AudioMix#ROUTE_FLAG_RENDER}
294a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return the same Builder instance.
295a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException
296a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
2971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        @SystemApi
298a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public Builder setRouteFlags(@RouteFlags int routeFlags)
299a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throws IllegalArgumentException {
300a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (routeFlags == 0) {
301a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal empty route flags");
302a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
303e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            if ((routeFlags & ROUTE_FLAG_SUPPORTED) == 0) {
304a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Invalid route flags 0x"
305e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
306e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            }
307e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            if ((routeFlags & ~ROUTE_FLAG_SUPPORTED) != 0) {
308e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                throw new IllegalArgumentException("Unknown route flags 0x"
309e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                        + Integer.toHexString(routeFlags) + "when configuring an AudioMix");
310a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
311a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mRouteFlags = routeFlags;
312a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return this;
313a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
314a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
315a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
316e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * Sets the audio device used for playback. Cannot be used in the context of an audio
317e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * policy used to inject audio to be recorded, or in a mix whose route flags doesn't
318e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * specify {@link AudioMix#ROUTE_FLAG_RENDER}.
319e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @param device a non-null AudioDeviceInfo describing the audio device to play the output
320e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         *     of this mix.
321e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @return the same Builder instance
322e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         * @throws IllegalArgumentException
323e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi         */
324e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        @SystemApi
325e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        public Builder setDevice(@NonNull AudioDeviceInfo device) throws IllegalArgumentException {
326e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            if (device == null) {
327e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioDeviceInfo argument");
328e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            }
329e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            if (!device.isSink()) {
330e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                throw new IllegalArgumentException("Unsupported device type on mix, not a sink");
331e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            }
3324ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            mDeviceSystemType = AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType());
333e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            mDeviceAddress = device.getAddress();
334e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            return this;
335e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        }
336e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi
337e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi        /**
338a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Combines all of the settings and return a new {@link AudioMix} object.
339a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return a new {@link AudioMix} object
340a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @throws IllegalArgumentException if no {@link AudioMixingRule} has been set.
341a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
3421b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        @SystemApi
343a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public AudioMix build() throws IllegalArgumentException {
344a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (mRule == null) {
345a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                throw new IllegalArgumentException("Illegal null AudioMixingRule");
346a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
347a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (mRouteFlags == 0) {
348e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                // no route flags set, use default as described in Builder.setRouteFlags(int)
349e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                mRouteFlags = ROUTE_FLAG_LOOP_BACK;
350e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            }
351e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            // can't do loop back AND render at same time in this implementation
352e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            if (mRouteFlags == (ROUTE_FLAG_RENDER | ROUTE_FLAG_LOOP_BACK)) {
353e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                throw new IllegalArgumentException("Unsupported route behavior combination 0x" +
354e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                        Integer.toHexString(mRouteFlags));
355a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
356a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            if (mFormat == null) {
3571cbf9b3741ec486c3ffce08f145501eb1ca73640Glenn Kasten                // FIXME Can we eliminate this?  Will AudioMix work with an unspecified sample rate?
358a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                int rate = AudioSystem.getPrimaryOutputSamplingRate();
359a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                if (rate <= 0) {
360a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                    rate = 44100;
361a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                }
362a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                mFormat = new AudioFormat.Builder().setSampleRate(rate).build();
363a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
3644ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            if ((mDeviceSystemType != AudioSystem.DEVICE_NONE)
3654ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    && (mDeviceSystemType != AudioSystem.DEVICE_OUT_REMOTE_SUBMIX)
3664ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    && (mDeviceSystemType != AudioSystem.DEVICE_IN_REMOTE_SUBMIX)) {
367e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                if ((mRouteFlags & ROUTE_FLAG_RENDER) == 0) {
368e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    throw new IllegalArgumentException(
369e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                            "Can't have audio device without flag ROUTE_FLAG_RENDER");
370e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                }
371e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                if (mRule.getTargetMixType() != AudioMix.MIX_TYPE_PLAYERS) {
372e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    throw new IllegalArgumentException("Unsupported device on non-playback mix");
373e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                }
374e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            } else {
375e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                if ((mRouteFlags & ROUTE_FLAG_RENDER) == ROUTE_FLAG_RENDER) {
376e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    throw new IllegalArgumentException(
377e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                            "Can't have flag ROUTE_FLAG_RENDER without an audio device");
378e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                }
3794ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                if ((mRouteFlags & ROUTE_FLAG_SUPPORTED) == ROUTE_FLAG_LOOP_BACK) {
3804ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    if (mRule.getTargetMixType() == MIX_TYPE_PLAYERS) {
3814ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                        mDeviceSystemType = AudioSystem.DEVICE_OUT_REMOTE_SUBMIX;
3824ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    } else if (mRule.getTargetMixType() == MIX_TYPE_RECORDERS) {
3834ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                        mDeviceSystemType = AudioSystem.DEVICE_IN_REMOTE_SUBMIX;
3844ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    } else {
3854ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                        throw new IllegalArgumentException("Unknown mixing rule type");
3864ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                    }
3874ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi                }
388e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            }
3894ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            return new AudioMix(mRule, mFormat, mRouteFlags, mCallbackFlags, mDeviceSystemType,
390e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    mDeviceAddress);
391a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
392a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
393a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi}
394