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.media.AudioFormat;
20e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Triviimport android.media.AudioManager;
21e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Triviimport android.media.AudioPatch;
22ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Triviimport android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
23a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.os.Parcel;
24a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.os.Parcelable;
25a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport android.util.Log;
26a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
27a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Triviimport java.util.ArrayList;
281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Triviimport java.util.Objects;
29a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
30a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi/**
31a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * @hide
32a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi * Internal storage class for AudioPolicy configuration.
33a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi */
34a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivipublic class AudioPolicyConfig implements Parcelable {
35a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
36a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private static final String TAG = "AudioPolicyConfig";
37a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
388fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    protected ArrayList<AudioMix> mMixes;
390212be5150fb9fb3c340f3c7e51f6126372cc6f9Jean-Michel Trivi    protected int mDuckingPolicy = AudioPolicy.FOCUS_POLICY_DUCKING_IN_APP;
408fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
411b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private String mRegistrationId = null;
428fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
438fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    protected AudioPolicyConfig(AudioPolicyConfig conf) {
448fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        mMixes = conf.mMixes;
458fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
46a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
47a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    AudioPolicyConfig(ArrayList<AudioMix> mixes) {
48a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mMixes = mixes;
49a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
50a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
51a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    /**
52a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * Add an {@link AudioMix} to be part of the audio policy being built.
53a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * @param mix a non-null {@link AudioMix} to be part of the audio policy.
54a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * @return the same Builder instance.
55a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     * @throws IllegalArgumentException
56a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi     */
57a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public void addMix(AudioMix mix) throws IllegalArgumentException {
58a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        if (mix == null) {
59a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            throw new IllegalArgumentException("Illegal null AudioMix argument");
60a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
61a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mMixes.add(mix);
62a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
63a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
645a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    public ArrayList<AudioMix> getMixes() {
655a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi        return mMixes;
665a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi    }
675a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi
68a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @Override
691b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    public int hashCode() {
701b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        return Objects.hash(mMixes);
711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
731b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    @Override
74a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public int describeContents() {
75a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return 0;
76a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
77a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
78a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    @Override
79a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public void writeToParcel(Parcel dest, int flags) {
80a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        dest.writeInt(mMixes.size());
81a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        for (AudioMix mix : mMixes) {
82a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix route flags
83a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            dest.writeInt(mix.getRouteFlags());
845a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            // write callback flags
855a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            dest.writeInt(mix.mCallbackFlags);
86e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            // write device information
874ad39885f2e6e79ae1faaa41ae240eeffcefd368Jean-Michel Trivi            dest.writeInt(mix.mDeviceSystemType);
88e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            dest.writeString(mix.mDeviceAddress);
89a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix format
90a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            dest.writeInt(mix.getFormat().getSampleRate());
91a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            dest.writeInt(mix.getFormat().getEncoding());
92a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            dest.writeInt(mix.getFormat().getChannelMask());
93a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix rules
94ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
95a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            dest.writeInt(criteria.size());
96ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi            for (AudioMixMatchCriterion criterion : criteria) {
971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                criterion.writeToParcel(dest);
98a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
99a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
100a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
101a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
102a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    private AudioPolicyConfig(Parcel in) {
103a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        mMixes = new ArrayList<AudioMix>();
104a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        int nbMixes = in.readInt();
105a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        for (int i = 0 ; i < nbMixes ; i++) {
106a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            final AudioMix.Builder mixBuilder = new AudioMix.Builder();
107a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // read mix route flags
108a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            int routeFlags = in.readInt();
109a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mixBuilder.setRouteFlags(routeFlags);
1105a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            // read callback flags
1115a56109d1f5c00404c8f0e4281b9ac1392d72886Jean-Michel Trivi            mixBuilder.setCallbackFlags(in.readInt());
112e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            // read device information
113e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi            mixBuilder.setDevice(in.readInt(), in.readString());
114a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // read mix format
115a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            int sampleRate = in.readInt();
116a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            int encoding = in.readInt();
117a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            int channelMask = in.readInt();
118a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            final AudioFormat format = new AudioFormat.Builder().setSampleRate(sampleRate)
119a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                    .setChannelMask(channelMask).setEncoding(encoding).build();
120a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mixBuilder.setFormat(format);
121a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // read mix rules
122a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            int nbRules = in.readInt();
123a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            AudioMixingRule.Builder ruleBuilder = new AudioMixingRule.Builder();
124a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            for (int j = 0 ; j < nbRules ; j++) {
125a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                // read the matching rules
1261b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                ruleBuilder.addRuleFromParcel(in);
127a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
128a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mixBuilder.setMixingRule(ruleBuilder.build());
129a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            mMixes.add(mixBuilder.build());
130a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
131a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
132a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
133a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    public static final Parcelable.Creator<AudioPolicyConfig> CREATOR
134a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            = new Parcelable.Creator<AudioPolicyConfig>() {
135a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        /**
136a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * Rebuilds an AudioPolicyConfig previously stored with writeToParcel().
137a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @param p Parcel object to read the AudioPolicyConfig from
138a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         * @return a new AudioPolicyConfig created from the data in the parcel
139a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi         */
140a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public AudioPolicyConfig createFromParcel(Parcel p) {
141a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return new AudioPolicyConfig(p);
142a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
143a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        public AudioPolicyConfig[] newArray(int size) {
144a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            return new AudioPolicyConfig[size];
145a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
146a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    };
147a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi
1488fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    public String toLogFriendlyString () {
149a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        String textDump = new String("android.media.audiopolicy.AudioPolicyConfig:\n");
1501b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        textDump += mMixes.size() + " AudioMix: "+ mRegistrationId + "\n";
151a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        for(AudioMix mix : mMixes) {
152a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix route flags
153a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            textDump += "* route flags=0x" + Integer.toHexString(mix.getRouteFlags()) + "\n";
154a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix format
155a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            textDump += "  rate=" + mix.getFormat().getSampleRate() + "Hz\n";
156a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            textDump += "  encoding=" + mix.getFormat().getEncoding() + "\n";
157a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            textDump += "  channels=0x";
158a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            textDump += Integer.toHexString(mix.getFormat().getChannelMask()).toUpperCase() +"\n";
159a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            // write mix rules
160ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi            final ArrayList<AudioMixMatchCriterion> criteria = mix.getRule().getCriteria();
161ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi            for (AudioMixMatchCriterion criterion : criteria) {
162a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                switch(criterion.mRule) {
163a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                    case AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_USAGE:
164a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        textDump += "  exclude usage ";
165a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        textDump += criterion.mAttr.usageToString();
166a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        break;
167a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                    case AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE:
168a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        textDump += "  match usage ";
169a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        textDump += criterion.mAttr.usageToString();
170a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        break;
1711b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    case AudioMixingRule.RULE_EXCLUDE_ATTRIBUTE_CAPTURE_PRESET:
1721b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        textDump += "  exclude capture preset ";
1731b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        textDump += criterion.mAttr.getCapturePreset();
1741b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        break;
1751b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                    case AudioMixingRule.RULE_MATCH_ATTRIBUTE_CAPTURE_PRESET:
1761b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        textDump += "  match capture preset ";
1771b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        textDump += criterion.mAttr.getCapturePreset();
1781b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                        break;
1794d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                    case AudioMixingRule.RULE_MATCH_UID:
1804d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                        textDump += "  match UID ";
181ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi                        textDump += criterion.mIntProp;
1824d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                        break;
1834d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                    case AudioMixingRule.RULE_EXCLUDE_UID:
1844d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                        textDump += "  exclude UID ";
185ba6b4b400d850ba18fcb9d5bf9789d490f390accJean-Michel Trivi                        textDump += criterion.mIntProp;
1864d4b3d54c6bad3ecc71f2003abd398a2f135a052Jean-Michel Trivi                        break;
187a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                    default:
188a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                        textDump += "invalid rule!";
189a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                }
190a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi                textDump += "\n";
191a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi            }
192a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        }
193a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi        return textDump;
194a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi    }
1958fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
1961b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    protected void setRegistration(String regId) {
1971b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        final boolean currentRegNull = (mRegistrationId == null) || mRegistrationId.isEmpty();
1981b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        final boolean newRegNull = (regId == null) || regId.isEmpty();
1991b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (!currentRegNull && !newRegNull && !mRegistrationId.equals(regId)) {
2001b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            Log.e(TAG, "Invalid registration transition from " + mRegistrationId + " to " + regId);
2011b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            return;
2021b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        }
2031b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        mRegistrationId = regId == null ? "" : regId;
2048fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        int mixIndex = 0;
2058fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        for (AudioMix mix : mMixes) {
2061b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            if (!mRegistrationId.isEmpty()) {
207e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_LOOP_BACK) ==
208e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                        AudioMix.ROUTE_FLAG_LOOP_BACK) {
209e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    mix.setRegistration(mRegistrationId + "mix" + mixTypeId(mix.getMixType()) + ":"
210e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                            + mixIndex++);
211e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                } else if ((mix.getRouteFlags() & AudioMix.ROUTE_FLAG_RENDER) ==
212e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                        AudioMix.ROUTE_FLAG_RENDER) {
213e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                    mix.setRegistration(mix.mDeviceAddress);
214e8924115f9a57d35149da89c2a1bd920fdd0fe39Jean-Michel Trivi                }
2151b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            } else {
2161b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi                mix.setRegistration("");
2171b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi            }
2188fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi        }
2198fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi    }
2208fdb0d4defb6ee2ca8057d3442ead36b408b6c17Jean-Michel Trivi
2211b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    private static String mixTypeId(int type) {
2221b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        if (type == AudioMix.MIX_TYPE_PLAYERS) return "p";
2231b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        else if (type == AudioMix.MIX_TYPE_RECORDERS) return "r";
2241b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        else return "i";
2251b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
2261b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi
2271b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    protected String getRegistration() {
2281b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi        return mRegistrationId;
2291b3541d5eedb332ea01066b4a78a2d06d5304044Jean-Michel Trivi    }
230a8b6bd88cfb010c9e9aa1339e504fd593919e1e0Jean-Michel Trivi}
231