启用 AAOS 路由
xref: /packages/services/Car/service/res/values/config.xml
<resources>
<bool name="audioUseDynamicRouting">true</bool>
</resources>
如果设为 false,路由和大部分 CarAudioService 将被停用,并且 AAOS 会回退到 AudioService 的默认行为。
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioService.java
202 public CarAudioService(Context context) {
203 mContext = context;
204 mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
205 mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
206 mUseDynamicRouting = mContext.getResources().getBoolean(R.bool.audioUseDynamicRouting);
207 mPersistMasterMuteState = mContext.getResources().getBoolean(
208 R.bool.audioPersistMasterMuteState);
209 mUidToZoneMap = new HashMap<>();
210 }
211
212 /**
213 * Dynamic routing and volume groups are set only if
214 * {@link #mUseDynamicRouting} is {@code true}. Otherwise, this service runs in legacy mode.
215 */
216 @Override
217 public void init() {
218 synchronized (mImplLock) {
219 if (mUseDynamicRouting) {
220 // Enumerate all output bus device ports
221 AudioDeviceInfo[] deviceInfos = mAudioManager.getDevices(
222 AudioManager.GET_DEVICES_OUTPUTS);
223 if (deviceInfos.length == 0) {
224 Log.e(CarLog.TAG_AUDIO, "No output device available, ignore");
225 return;
226 }
227 SparseArray<CarAudioDeviceInfo> busToCarAudioDeviceInfo = new SparseArray<>();
228 for (AudioDeviceInfo info : deviceInfos) {
229 Log.v(CarLog.TAG_AUDIO, String.format("output id=%d address=%s type=%s",
230 info.getId(), info.getAddress(), info.getType()));
231 if (info.getType() == AudioDeviceInfo.TYPE_BUS) {
232 final CarAudioDeviceInfo carInfo = new CarAudioDeviceInfo(info);
233 // See also the audio_policy_configuration.xml,
234 // the bus number should be no less than zero.
235 if (carInfo.getBusNumber() >= 0) {
236 busToCarAudioDeviceInfo.put(carInfo.getBusNumber(), carInfo);
237 Log.i(CarLog.TAG_AUDIO, "Valid bus found " + carInfo);
238 }
239 }
240 }
241 setupDynamicRouting(busToCarAudioDeviceInfo);
242 } else {
243 Log.i(CarLog.TAG_AUDIO, "Audio dynamic routing not enabled, run in legacy mode");
244 setupLegacyVolumeChangedListener();
245 }
246
247 // Restore master mute state if applicable
248 if (mPersistMasterMuteState) {
249 boolean storedMasterMute = Settings.Global.getInt(mContext.getContentResolver(),
250 VOLUME_SETTINGS_KEY_MASTER_MUTE, 0) != 0;
251 setMasterMute(storedMasterMute, 0);
252 }
253 }
254 }
解析config.xml文件,如果audioUseDynamicRouting是true,则mUseDynamicRouting也是true,执行init函数的时候将走动态路由策略。
a.通过AudioManager获取到所以输出总线设备
b.过滤出type是AudioDeviceInfo.TYPE_BUS的输出设备,然后重新封装到CarAudioDeviceInfo中
c.设置动态路由
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioDeviceInfo.java
41 /**
42 * Parse device address. Expected format is BUS%d_%s, address, usage hint
43 * @return valid address (from 0 to positive) or -1 for invalid address.
44 */
45 static int parseDeviceAddress(String address) {
46 String[] words = address.split("_");
47 int addressParsed = -1;
48 if (words[0].toLowerCase().startsWith("bus")) {
49 try {
50 addressParsed = Integer.parseInt(words[0].substring(3));
51 } catch (NumberFormatException e) {
52 //ignore
53 }
54 }
55 if (addressParsed < 0) {
56 return -1;
57 }
58 return addressParsed;
59 }
.....................................
77 CarAudioDeviceInfo(AudioDeviceInfo audioDeviceInfo) {
78 mAudioDeviceInfo = audioDeviceInfo;
79 mBusNumber = parseDeviceAddress(audioDeviceInfo.getAddress());
80 mSampleRate = getMaxSampleRate(audioDeviceInfo);
81 mEncodingFormat = getEncodingFormat(audioDeviceInfo);
82 mChannelCount = getMaxChannels(audioDeviceInfo);
83 final AudioGain audioGain = Preconditions.checkNotNull(
84 getAudioGain(), "No audio gain on device port " + audioDeviceInfo);
85 mDefaultGain = audioGain.defaultValue();
86 mMaxGain = audioGain.maxValue();
87 mMinGain = audioGain.minValue();
88
89 mCurrentGain = -1; // Not initialized till explicitly set
90 }
解析device address获取到busNumber,找到bus和第一个"_"中间的字符截取出来转成int。
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioService.java
99 private static final String[] AUDIO_CONFIGURATION_PATHS = new String[] {
100 "/vendor/etc/car_audio_configuration.xml",
101 "/system/etc/car_audio_configuration.xml"
102 };
...........................
439 private void setupDynamicRouting(SparseArray<CarAudioDeviceInfo> busToCarAudioDeviceInfo) {
440 final AudioPolicy.Builder builder = new AudioPolicy.Builder(mContext);
441 builder.setLooper(Looper.getMainLooper());
442
443 mCarAudioConfigurationPath = getAudioConfigurationPath();
444 if (mCarAudioConfigurationPath != null) {
445 try (InputStream inputStream = new FileInputStream(mCarAudioConfigurationPath)) {
446 CarAudioZonesHelper zonesHelper = new CarAudioZonesHelper(mContext, inputStream,
447 busToCarAudioDeviceInfo);
448 mCarAudioZones = zonesHelper.loadAudioZones();
449 } catch (IOException | XmlPullParserException e) {
450 throw new RuntimeException("Failed to parse audio zone configuration", e);
451 }
452 } else {
453 // In legacy mode, context -> bus mapping is done by querying IAudioControl HAL.
454 final IAudioControl audioControl = getAudioControl();
455 if (audioControl == null) {
456 throw new RuntimeException(
457 "Dynamic routing requested but audioControl HAL not available");
458 }
459 CarAudioZonesHelperLegacy legacyHelper = new CarAudioZonesHelperLegacy(mContext,
460 R.xml.car_volume_groups, busToCarAudioDeviceInfo, audioControl);
461 mCarAudioZones = legacyHelper.loadAudioZones();
462 }
463 for (CarAudioZone zone : mCarAudioZones) {
464 if (!zone.validateVolumeGroups()) {
465 throw new RuntimeException("Invalid volume groups configuration");
466 }
467 // Ensure HAL gets our initial value
468 zone.synchronizeCurrentGainIndex();
469 Log.v(CarLog.TAG_AUDIO, "Processed audio zone: " + zone);
470 }
471
472 // Setup dynamic routing rules by usage
473 final CarAudioDynamicRouting dynamicRouting = new CarAudioDynamicRouting(mCarAudioZones);
474 dynamicRouting.setupAudioDynamicRouting(builder);
475
476 // Attach the {@link AudioPolicyVolumeCallback}
477 builder.setAudioPolicyVolumeCallback(mAudioPolicyVolumeCallback);
478
479 if (sUseCarAudioFocus) {
480 // Configure our AudioPolicy to handle focus events.
481 // This gives us the ability to decide which audio focus requests to accept and bypasses
482 // the framework ducking logic.
483 mFocusHandler = new CarZonesAudioFocus(mAudioManager,
484 mContext.getPackageManager(),
485 mCarAudioZones);
486 builder.setAudioPolicyFocusListener(mFocusHandler);
487 builder.setIsAudioFocusPolicy(true);
488 }
489
490 mAudioPolicy = builder.build();
491 if (sUseCarAudioFocus) {
492 // Connect the AudioPolicy and the focus listener
493 mFocusHandler.setOwningPolicy(this, mAudioPolicy);
494 }
495
496 int r = mAudioManager.registerAudioPolicy(mAudioPolicy);
497 if (r != AudioManager.SUCCESS) {
498 throw new RuntimeException("registerAudioPolicy failed " + r);
499 }
500 }
通过getAudioConfigurationPath获取配置文件路径,然后解析配置文件。
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioZonesHelper.java
64 private static final Map<String, Integer> CONTEXT_NAME_MAP;
65
66 static {
67 CONTEXT_NAME_MAP = new HashMap<>();
68 CONTEXT_NAME_MAP.put("music", ContextNumber.MUSIC);
69 CONTEXT_NAME_MAP.put("navigation", ContextNumber.NAVIGATION);
70 CONTEXT_NAME_MAP.put("voice_command", ContextNumber.VOICE_COMMAND);
71 CONTEXT_NAME_MAP.put("call_ring", ContextNumber.CALL_RING);
72 CONTEXT_NAME_MAP.put("call", ContextNumber.CALL);
73 CONTEXT_NAME_MAP.put("alarm", ContextNumber.ALARM);
74 CONTEXT_NAME_MAP.put("notification", ContextNumber.NOTIFICATION);
75 CONTEXT_NAME_MAP.put("system_sound", ContextNumber.SYSTEM_SOUND);
76 }
......................................
232 private void parseVolumeGroupContexts(
233 XmlPullParser parser, CarVolumeGroup group, int busNumber)
234 throws XmlPullParserException, IOException {
235 while (parser.next() != XmlPullParser.END_TAG) {
236 if (parser.getEventType() != XmlPullParser.START_TAG) continue;
237 if (TAG_CONTEXT.equals(parser.getName())) {
238 group.bind(
239 parseContextNumber(parser.getAttributeValue(NAMESPACE, ATTR_CONTEXT_NAME)),
240 busNumber, mBusToCarAudioDeviceInfo.get(busNumber));
241 }
242 // Always skip to upper level since we're at the lowest.
243 skip(parser);
244 }
245 }
......................................
264 private int parseContextNumber(String context) {
265 return CONTEXT_NAME_MAP.getOrDefault(context.toLowerCase(), ContextNumber.INVALID);
266 }
xref: /packages/services/Car/service/src/com/android/car/audio/CarVolumeGroup.java
134 /**
135 * Binds the context number to physical bus number and audio device port information.
136 * Because this may change the groups min/max values, thus invalidating an index computed from
137 * a gain before this call, all calls to this function must happen at startup before any
138 * set/getGainIndex calls.
139 *
140 * @param contextNumber Context number as defined in audio control HAL
141 * @param busNumber Physical bus number for the audio device port
142 * @param info {@link CarAudioDeviceInfo} instance relates to the physical bus
143 */
144 void bind(int contextNumber, int busNumber, CarAudioDeviceInfo info) {
145 if (mBusToCarAudioDeviceInfo.size() == 0) {
146 mStepSize = info.getAudioGain().stepValue();
147 } else {
148 Preconditions.checkArgument(
149 info.getAudioGain().stepValue() == mStepSize,
150 "Gain controls within one group must have same step value");
151 }
152
153 mContextToBus.put(contextNumber, busNumber);
154 mBusToCarAudioDeviceInfo.put(busNumber, info);
155
156 if (info.getDefaultGain() > mDefaultGain) {
157 // We're arbitrarily selecting the highest bus default gain as the group's default.
158 mDefaultGain = info.getDefaultGain();
159 }
160 if (info.getMaxGain() > mMaxGain) {
161 mMaxGain = info.getMaxGain();
162 }
163 if (info.getMinGain() < mMinGain) {
164 mMinGain = info.getMinGain();
165 }
166 if (mStoredGainIndex < getMinGainIndex() || mStoredGainIndex > getMaxGainIndex()) {
167 // We expected to load a value from last boot, but if we didn't (perhaps this is the
168 // first boot ever?), then use the highest "default" we've seen to initialize
169 // ourselves.
170 mCurrentGainIndex = getIndexForGain(mDefaultGain);
171 } else {
172 // Just use the gain index we stored last time the gain was set (presumably during our
173 // last boot cycle).
174 mCurrentGainIndex = mStoredGainIndex;
175 }
176 }
mContextToBus.put(contextNumber, busNumber);将contextNumber与busNumber 相对应。 mBusToCarAudioDeviceInfo.put(busNumber, info);将busNumber与info相对应。这样每个contextNumber都对应着具体的输出设备。接下来看contextNumber是如何产生的。
car_audio_configuration.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <carAudioConfiguration version="1">
3 <zones>
4 <zone name="primary zone" isPrimary="true">
5 <volumeGroups>
6 <group>
7 <device address="bus0_media_out">
8 <context context="music"/>
9 </device>
10 <device address="bus3_call_ring_out">
11 <context context="call_ring"/>
12 </device>
13 </group>
14 <group>
15 <device address="bus1_navigation_out">
16 <context context="navigation"/>
17 </device>
18 </group>
19 </volumeGroups>
20 <displays>
21 <display port="1"/>
22 <display port="2"/>
23 </displays>
24 </zone>
25 <zone name="rear seat zone">
26 <volumeGroups>
27 <group>
28 <device address="bus100_rear_seat">
29 <context context="music"/>
30 <context context="navigation"/>
31 <context context="voice_command"/>
32 <context context="call_ring"/>
33 <context context="call"/>
34 <context context="alarm"/>
35 <context context="notification"/>
36 <context context="system_sound"/>
37 </device>
38 </group>
39 </volumeGroups>
40 </zone>
41 </zones>
42 </carAudioConfiguration>
audio_policy_configuration.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
2 <!-- Copyright (C) 2018 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 <audioPolicyConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
18 <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” -->
19
20 <!-- Global configuration Decalaration -->
21 <globalConfiguration speaker_drc_enabled="true"/>
22
23 <!-- Modules section:
24 There is one section per audio HW module present on the platform.
25 Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”.
26 The module names are the same as in current .conf file:
27 “primary”, “A2DP”, “remote_submix”, “USB”
28 Each module will contain the following sections:
29 “devicePorts”: a list of device descriptors for all input and output devices accessible via this
30 module.
31 This contains both permanently attached devices and removable devices.
32 "gain": constraints applied to the millibel values:
33 - maxValueMB >= minValueMB
34 - defaultValueMB >= minValueMB && defaultValueMB <= maxValueMB
35 - (maxValueMB - minValueMB) % stepValueMB == 0
36 - (defaultValueMB - minValueMB) % stepValueMB == 0
37 “mixPorts”: listing all output and input streams exposed by the audio HAL
38 “routes”: list of possible connections between input and output devices or between stream and
39 devices.
40 "route": is defined by an attribute:
41 -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix)
42 -"sink": the sink involved in this route
43 -"sources": all the sources than can be connected to the sink via vis route
44 “attachedDevices”: permanently attached devices.
45 The attachedDevices section is a list of devices names. The names correspond to device names
46 defined in <devicePorts> section.
47 “defaultOutputDevice”: device to be used by default when no policy rule applies
48 -->
49 <modules>
50 <!-- Primary Audio HAL -->
51 <module name="primary" halVersion="3.0">
52 <attachedDevices>
53 <!-- One bus per context -->
54 <item>bus0_media_out</item>
55 <item>bus1_navigation_out</item>
56 <item>bus2_voice_command_out</item>
57 <item>bus3_call_ring_out</item>
58 <item>bus4_call_out</item>
59 <item>bus5_alarm_out</item>
60 <item>bus6_notification_out</item>
61 <item>bus7_system_sound_out</item>
62 <item>bus100_rear_seat</item>
63 <item>Built-In Mic</item>
64 <item>Built-In Back Mic</item>
65 <item>Echo-Reference Mic</item>
66 <item>FM Tuner</item>
67 </attachedDevices>
68 <defaultOutputDevice>bus0_media_out</defaultOutputDevice>
69 <mixPorts>
70 <mixPort name="mixport_bus0_media_out" role="source"
71 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
72 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
73 samplingRates="48000"
74 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
75 </mixPort>
76 <mixPort name="mixport_bus1_navigation_out" role="source"
77 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
78 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
79 samplingRates="48000"
80 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
81 </mixPort>
82 <mixPort name="mixport_bus2_voice_command_out" role="source"
83 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
84 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
85 samplingRates="48000"
86 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
87 </mixPort>
88 <mixPort name="mixport_bus3_call_ring_out" role="source"
89 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
90 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
91 samplingRates="48000"
92 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
93 </mixPort>
94 <mixPort name="mixport_bus4_call_out" role="source"
95 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
96 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
97 samplingRates="48000"
98 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
99 </mixPort>
100 <mixPort name="mixport_bus5_alarm_out" role="source"
101 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
102 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
103 samplingRates="48000"
104 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
105 </mixPort>
106 <mixPort name="mixport_bus6_notification_out" role="source"
107 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
108 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
109 samplingRates="48000"
110 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
111 </mixPort>
112 <mixPort name="mixport_bus7_system_sound_out" role="source"
113 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
114 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
115 samplingRates="48000"
116 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
117 </mixPort>
118 <mixPort name="mixport_bus100_rear_seat" role="source"
119 flags="AUDIO_OUTPUT_FLAG_PRIMARY">
120 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
121 samplingRates="48000"
122 channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
123 </mixPort>
124 <mixPort name="primary input" role="sink">
125 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
126 samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
127 channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
128 </mixPort>
129 <mixPort name="mixport_tuner0" role="sink">
130 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
131 samplingRates="48000"
132 channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
133 </mixPort>
134 </mixPorts>
135 <devicePorts>
136 <devicePort tagName="bus0_media_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
137 address="bus0_media_out">
138 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
139 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
140 <gains>
141 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
142 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
143 </gains>
144 </devicePort>
145 <devicePort tagName="bus1_navigation_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
146 address="bus1_navigation_out">
147 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
148 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
149 <gains>
150 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
151 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
152 </gains>
153 </devicePort>
154 <devicePort tagName="bus2_voice_command_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
155 address="bus2_voice_command_out">
156 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
157 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
158 <gains>
159 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
160 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
161 </gains>
162 </devicePort>
163 <devicePort tagName="bus3_call_ring_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
164 address="bus3_call_ring_out">
165 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
166 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
167 <gains>
168 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
169 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
170 </gains>
171 </devicePort>
172 <devicePort tagName="bus4_call_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
173 address="bus4_call_out">
174 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
175 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
176 <gains>
177 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
178 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
179 </gains>
180 </devicePort>
181 <devicePort tagName="bus5_alarm_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
182 address="bus5_alarm_out">
183 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
184 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
185 <gains>
186 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
187 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
188 </gains>
189 </devicePort>
190 <devicePort tagName="bus6_notification_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
191 address="bus6_notification_out">
192 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
193 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
194 <gains>
195 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
196 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
197 </gains>
198 </devicePort>
199 <devicePort tagName="bus7_system_sound_out" role="sink" type="AUDIO_DEVICE_OUT_BUS"
200 address="bus7_system_sound_out">
201 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
202 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
203 <gains>
204 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
205 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
206 </gains>
207 </devicePort>
208 <devicePort tagName="bus100_rear_seat" role="sink" type="AUDIO_DEVICE_OUT_BUS"
209 address="bus100_rear_seat">
210 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
211 samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/>
212 <gains>
213 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
214 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
215 </gains>
216 </devicePort>
217 <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source">
218 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
219 samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
220 channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
221 </devicePort>
222 <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source">
223 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
224 samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
225 channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
226 </devicePort>
227 <devicePort tagName="Echo-Reference Mic" type="AUDIO_DEVICE_IN_ECHO_REFERENCE" role="source">
228 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
229 samplingRates="8000,11025,12000,16000,22050,24000,32000,44100,48000"
230 channelMasks="AUDIO_CHANNEL_IN_MONO,AUDIO_CHANNEL_IN_STEREO,AUDIO_CHANNEL_IN_FRONT_BACK"/>
231 </devicePort>
232 <devicePort tagName="FM Tuner" type="AUDIO_DEVICE_IN_FM_TUNER" role="source"
233 address="tuner0">
234 <profile name="" format="AUDIO_FORMAT_PCM_16_BIT"
235 samplingRates="48000" channelMasks="AUDIO_CHANNEL_IN_STEREO"/>
236 <gains>
237 <gain name="" mode="AUDIO_GAIN_MODE_JOINT"
238 minValueMB="-3200" maxValueMB="600" defaultValueMB="0" stepValueMB="100"/>
239 </gains>
240 </devicePort>
241 </devicePorts>
242 <!-- route declaration, i.e. list all available sources for a given sink -->
243 <routes>
244 <route type="mix" sink="bus0_media_out" sources="mixport_bus0_media_out"/>
245 <route type="mix" sink="bus1_navigation_out" sources="mixport_bus1_navigation_out"/>
246 <route type="mix" sink="bus2_voice_command_out" sources="mixport_bus2_voice_command_out"/>
247 <route type="mix" sink="bus3_call_ring_out" sources="mixport_bus3_call_ring_out"/>
248 <route type="mix" sink="bus4_call_out" sources="mixport_bus4_call_out"/>
249 <route type="mix" sink="bus5_alarm_out" sources="mixport_bus5_alarm_out"/>
250 <route type="mix" sink="bus6_notification_out" sources="mixport_bus6_notification_out"/>
251 <route type="mix" sink="bus7_system_sound_out" sources="mixport_bus7_system_sound_out"/>
252 <route type="mix" sink="bus100_rear_seat" sources="mixport_bus100_rear_seat"/>
253 <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,Echo-Reference Mic"/>
254 <route type="mix" sink="mixport_tuner0" sources="FM Tuner"/>
255 </routes>
256
257 </module>
258
259 <!-- A2dp Audio HAL -->
260 <xi:include href="a2dp_audio_policy_configuration.xml"/>
261
262 <!-- Usb Audio HAL -->
263 <xi:include href="usb_audio_policy_configuration.xml"/>
264
265 <!-- Remote Submix Audio HAL -->
266 <xi:include href="r_submix_audio_policy_configuration.xml"/>
267
268 </modules>
269 <!-- End of Modules section -->
270
271 <!-- Volume section -->
272
273 <xi:include href="audio_policy_volumes.xml"/>
274 <xi:include href="default_volume_tables.xml"/>
275
276 <!-- End of Volume section -->
277 <!-- End of Modules section -->
278
279 </audioPolicyConfiguration>
通过CONTEXT_NAME_MAP关系,根据context可以找到contextNumber。
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioService.java
472 // Setup dynamic routing rules by usage
473 final CarAudioDynamicRouting dynamicRouting = new CarAudioDynamicRouting(mCarAudioZones);
474 dynamicRouting.setupAudioDynamicRouting(builder);
通过usage设置动态路由策略
xref: /packages/services/Car/service/src/com/android/car/audio/CarAudioDynamicRouting.java
50 static final SparseIntArray USAGE_TO_CONTEXT = new SparseIntArray();
...............................................
67 static {
68 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_UNKNOWN, ContextNumber.MUSIC);
69 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_MEDIA, ContextNumber.MUSIC);
70 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VOICE_COMMUNICATION, ContextNumber.CALL);
71 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING,
72 ContextNumber.CALL);
73 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ALARM, ContextNumber.ALARM);
74 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION, ContextNumber.NOTIFICATION);
75 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_RINGTONE, ContextNumber.CALL_RING);
76 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST,
77 ContextNumber.NOTIFICATION);
78 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT,
79 ContextNumber.NOTIFICATION);
80 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED,
81 ContextNumber.NOTIFICATION);
82 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_NOTIFICATION_EVENT, ContextNumber.NOTIFICATION);
83 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY,
84 ContextNumber.VOICE_COMMAND);
85 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
86 ContextNumber.NAVIGATION);
87 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
88 ContextNumber.SYSTEM_SOUND);
89 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_GAME, ContextNumber.MUSIC);
90 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_VIRTUAL_SOURCE, ContextNumber.INVALID);
91 USAGE_TO_CONTEXT.put(AudioAttributes.USAGE_ASSISTANT, ContextNumber.VOICE_COMMAND);
92 }
.......................................
100 void setupAudioDynamicRouting(AudioPolicy.Builder builder) {
101 for (CarAudioZone zone : mCarAudioZones) {
102 for (CarVolumeGroup group : zone.getVolumeGroups()) {
103 setupAudioDynamicRoutingForGroup(group, builder);
104 }
105 }
106 }
107
108 /**
109 * Enumerates all physical buses in a given volume group and attach the mixing rules.
110 * @param group {@link CarVolumeGroup} instance to enumerate the buses with
111 * @param builder {@link AudioPolicy.Builder} to attach the mixing rules
112 */
113 private void setupAudioDynamicRoutingForGroup(CarVolumeGroup group,
114 AudioPolicy.Builder builder) {
115 // Note that one can not register audio mix for same bus more than once.
116 for (int busNumber : group.getBusNumbers()) {
117 boolean hasContext = false;
118 CarAudioDeviceInfo info = group.getCarAudioDeviceInfoForBus(busNumber);
119 AudioFormat mixFormat = new AudioFormat.Builder()
120 .setSampleRate(info.getSampleRate())
121 .setEncoding(info.getEncodingFormat())
122 .setChannelMask(info.getChannelCount())
123 .build();
124 AudioMixingRule.Builder mixingRuleBuilder = new AudioMixingRule.Builder();
125 for (int contextNumber : group.getContextsForBus(busNumber)) {
126 hasContext = true;
127 int[] usages = getUsagesForContext(contextNumber);
128 for (int usage : usages) {
129 mixingRuleBuilder.addRule(
130 new AudioAttributes.Builder().setUsage(usage).build(),
131 AudioMixingRule.RULE_MATCH_ATTRIBUTE_USAGE);
132 }
133 Log.d(CarLog.TAG_AUDIO, "Bus number: " + busNumber
134 + " contextNumber: " + contextNumber
135 + " sampleRate: " + info.getSampleRate()
136 + " channels: " + info.getChannelCount()
137 + " usages: " + Arrays.toString(usages));
138 }
139 if (hasContext) {
140 // It's a valid case that an audio output bus is defined in
141 // audio_policy_configuration and no context is assigned to it.
142 // In such case, do not build a policy mix with zero rules.
143 AudioMix audioMix = new AudioMix.Builder(mixingRuleBuilder.build())
144 .setFormat(mixFormat)
145 .setDevice(info.getAudioDeviceInfo())
146 .setRouteFlags(AudioMix.ROUTE_FLAG_RENDER)
147 .build();
148 builder.addMix(audioMix);
149 }
150 }
151 }
152
153 private int[] getUsagesForContext(int contextNumber) {
154 final List<Integer> usages = new ArrayList<>();
155 for (int i = 0; i < CarAudioDynamicRouting.USAGE_TO_CONTEXT.size(); i++) {
156 if (CarAudioDynamicRouting.USAGE_TO_CONTEXT.valueAt(i) == contextNumber) {
157 usages.add(CarAudioDynamicRouting.USAGE_TO_CONTEXT.keyAt(i));
158 }
159 }
160 return usages.stream().mapToInt(i -> i).toArray();
161 }
162 }
通过contextNumber获取到usages,遍历usages将usage添加到mixingRuleBuilder中,然后再将mixingRuleBuilder添加到AudioMix中,将AudioMix addMix 到AudioPolicy中, 这样usage和device就关联上了。