xref: /frameworks/base/core/res/res/values/config.xml
29
30 @string/status_bar_alarm_clock
31 @string/status_bar_rotate
32 @string/status_bar_headset
33 @string/status_bar_data_saver
34 @string/status_bar_ime
35 @string/status_bar_sync_failing
36 @string/status_bar_sync_active
37 @string/status_bar_nfc
38 @string/status_bar_tty
39 @string/status_bar_speakerphone
40 @string/status_bar_cdma_eri
41 @string/status_bar_data_connection
42 @string/status_bar_phone_evdo_signal
43 @string/status_bar_phone_signal
44 @string/status_bar_secure
45 @string/status_bar_managed_profile
46 @string/status_bar_cast
47 @string/status_bar_
48 @string/status_bar_bluetooth
49 @string/status_bar_camera
50 @string/status_bar_microphone
51 @string/status_bar_location
52 @string/status_bar_mute
53 @string/status_bar_volume
54 @string/status_bar_zen
55 @string/status_bar_ethernet
56 @string/status_bar_wifi
57 @string/status_bar_hotspot
58 @string/status_bar_mobile
59 @string/status_bar_airplane
60 @string/status_bar_battery
61 @string/status_bar_sensors_off
62
1. 确定耳机图标的位置
通过status_bar_headset在config.xml里面确定耳机图标的位置。 xref: /frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
597 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
598 @Override
599 public void onReceive(Context context, Intent intent) {
600 String action = intent.getAction();
601 switch (action) {
602 case AudioManager.RINGER_MODE_CHANGED_ACTION:
603 case AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION:
604 updateVolumeZen();
605 break;
606 case TelephonyIntents.ACTION_SIM_STATE_CHANGED:
607 // Avoid rebroadcast because SysUI is direct boot aware.
608 if (intent.getBooleanExtra(TelephonyIntents.EXTRA_REBROADCAST_ON_UNLOCK,
609 false)) {
610 break;
611 }
612 updateSimState(intent);
613 break;
614 case TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED:
615 updateTTY(intent.getIntExtra(TelecomManager.EXTRA_CURRENT_TTY_MODE,
616 TelecomManager.TTY_MODE_OFF));
617 break;
618 case Intent.ACTION_MANAGED_PROFILE_AVAILABLE:
619 case Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE:
620 case Intent.ACTION_MANAGED_PROFILE_REMOVED:
621 updateManagedProfile();
622 break;
623 case AudioManager.ACTION_HEADSET_PLUG:
624 updateHeadsetPlug(intent);
625 break;
626 }
627 }
628 };
563 private void updateHeadsetPlug(Intent intent) {
564 boolean connected = intent.getIntExtra("state", 0) != 0;
565 boolean hasMic = intent.getIntExtra("microphone", 0) != 0;
566 if (connected) {
567 String contentDescription = mContext.getString(hasMic
568 ? R.string.accessibility_status_bar_headset
569 : R.string.accessibility_status_bar_headphones);
570 mIconController.setIcon(mSlotHeadset, hasMic ? R.drawable.stat_sys_headset_mic
571 : R.drawable.stat_sys_headset, contentDescription);
572 mIconController.setIconVisibility(mSlotHeadset, true);
573 } else {
574 mIconController.setIconVisibility(mSlotHeadset, false);
575 }
576 }
2.监听耳机插拔事件
mIconController.setIconVisibility(mSlotHeadset, true);
通过AudioManager.ACTION_HEADSET_PLUG监听是否插入耳机,如果监听到耳机插入则显示耳机图标。
3.调用流程
false
config_useDevInputEventForAudioJack为false时使用uevent机制,为true时使用input子系统。
xref: /frameworks/native/services/inputflinger/InputReader.cpp
286 void InputReader::loopOnce() {
287 int32_t oldGeneration;
288 int32_t timeoutMillis;
289 bool inputDevicesChanged = false;
290 std::vector inputDevices;
291 { // acquire lock
292 AutoMutex _l(mLock);
293
294 oldGeneration = mGeneration;
295 timeoutMillis = -1;
296
297 uint32_t changes = mConfigurationChangesToRefresh;
298 if (changes) {
299 mConfigurationChangesToRefresh = 0;
300 timeoutMillis = 0;
301 refreshConfigurationLocked(changes);
302 } else if (mNextTimeout != LLONG_MAX) {
303 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
304 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
305 }
306 } // release lock
307
308 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
309
310 { // acquire lock
311 AutoMutex _l(mLock);
312 mReaderIsAliveCondition.broadcast();
313
314 if (count) {
315 processEventsLocked(mEventBuffer, count);
316 }
317
318 if (mNextTimeout != LLONG_MAX) {
319 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
320 if (now >= mNextTimeout) {
321 #if DEBUG_RAW_EVENTS
322 ALOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
323 #endif
324 mNextTimeout = LLONG_MAX;
325 timeoutExpiredLocked(now);
326 }
327 }
328
329 if (oldGeneration != mGeneration) {
330 inputDevicesChanged = true;
331 getInputDevicesLocked(inputDevices);
332 }
333 } // release lock
334
335 // Send out a message that the describes the changed input devices.
336 if (inputDevicesChanged) {
337 mPolicy->notifyInputDevicesChanged(inputDevices);
338 }
339
340 // Flush queued events out to the listener.
341 // This must happen outside of the lock because the listener could potentially call
342 // back into the InputReader's methods, such as getScanCodeState, or become blocked
343 // on another thread similarly waiting to acquire the InputReader lock thereby
344 // resulting in a deadlock. This situation is actually quite plausible because the
345 // listener is actually the input dispatcher, which calls into the window manager,
346 // which occasionally calls into the input reader.
347 mQueuedListener->flush();
348 }
如果有事件则调用processEventsLocked(mEventBuffer, count);进行处理,如果没有事件则休眠。
xref: /frameworks/native/services/inputflinger/InputReader.cpp
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {
351 for (const RawEvent* rawEvent = rawEvents; count;) {
352 int32_t type = rawEvent->type;
353 size_t batchSize = 1;
354 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
355 int32_t deviceId = rawEvent->deviceId;
356 while (batchSize < count) {
357 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
358 || rawEvent[batchSize].deviceId != deviceId) {
359 break;
360 }
361 batchSize += 1;
362 }
363 #if DEBUG_RAW_EVENTS
364 ALOGD("BatchSize: %zu Count: %zu", batchSize, count);
365 #endif
366 processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
367 } else {
368 switch (rawEvent->type) {
369 case EventHubInterface::DEVICE_ADDED:
370 addDeviceLocked(rawEvent->when, rawEvent->deviceId);
371 break;
372 case EventHubInterface::DEVICE_REMOVED:
373 removeDeviceLocked(rawEvent->when, rawEvent->deviceId);
374 break;
375 case EventHubInterface::FINISHED_DEVICE_SCAN:
376 handleConfigurationChangedLocked(rawEvent->when);
377 break;
378 default:
379 ALOG_ASSERT(false); // can't happen
380 break;
381 }
382 }
383 count -= batchSize;
384 rawEvent += batchSize;
385 }
386 }
xref: /frameworks/native/services/inputflinger/InputReader.cpp
522 void InputReader::processEventsForDeviceLocked(int32_t deviceId,
523 const RawEvent* rawEvents, size_t count) {
524 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
525 if (deviceIndex < 0) {
526 ALOGW("Discarding event for unknown deviceId %d.", deviceId);
527 return;
528 }
529
530 InputDevice* device = mDevices.valueAt(deviceIndex);
531 if (device->isIgnored()) {
532 //ALOGD("Discarding event for ignored deviceId %d.", deviceId);
533 return;
534 }
535
536 device->process(rawEvents, count);
537 }
538
539 void InputReader::timeoutExpiredLocked(nsecs_t when) {
540 for (size_t i = 0; i < mDevices.size(); i++) {
541 InputDevice* device = mDevices.valueAt(i);
542 if (!device->isIgnored()) {
543 device->timeoutExpired(when);
544 }
545 }
546 }
xref: /frameworks/native/services/inputflinger/InputReader.cpp
1132 void InputDevice::process(const RawEvent* rawEvents, size_t count) {
1133 // Process all of the events in order for each mapper.
1134 // We cannot simply ask each mapper to process them in bulk because mappers may
1135 // have side-effects that must be interleaved. For example, joystick movement events and
1136 // gamepad button presses are handled by different mappers but they should be dispatched
1137 // in the order received.
1138 for (const RawEvent* rawEvent = rawEvents; count != 0; rawEvent++) {
1139 #if DEBUG_RAW_EVENTS
1140 ALOGD("Input event: device=%d type=0x%04x code=0x%04x value=0x%08x when=%" PRId64,
1141 rawEvent->deviceId, rawEvent->type, rawEvent->code, rawEvent->value,
1142 rawEvent->when);
1143 #endif
1144
1145 if (mDropUntilNextSync) {
1146 if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
1147 mDropUntilNextSync = false;
1148 #if DEBUG_RAW_EVENTS
1149 ALOGD("Recovered from input event buffer overrun.");
1150 #endif
1151 } else {
1152 #if DEBUG_RAW_EVENTS
1153 ALOGD("Dropped input event while waiting for next input sync.");
1154 #endif
1155 }
1156 } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
1157 ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
1158 mDropUntilNextSync = true;
1159 reset(rawEvent->when);
1160 } else {
1161 for (InputMapper* mapper : mMappers) {
1162 mapper->process(rawEvent);
1163 }
1164 }
1165 --count;
1166 }
1167 }
mapper->process(rawEvent);最终调用到InputMapper的process函数。InputMapper是指SwitchInputMapper。
xref: /frameworks/native/services/inputflinger/InputReader.cpp
2029 void SwitchInputMapper::process(const RawEvent* rawEvent) {
2030 switch (rawEvent->type) {
2031 case EV_SW:
2032 processSwitch(rawEvent->code, rawEvent->value);
2033 break;
2034
2035 case EV_SYN:
2036 if (rawEvent->code == SYN_REPORT) {
2037 sync(rawEvent->when);
2038 }
2039 }
2040 }
2041
2042 void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {
2043 if (switchCode >= 0 && switchCode < 32) {
2044 if (switchValue) {
2045 mSwitchValues |= 1 << switchCode;
2046 } else {
2047 mSwitchValues &= ~(1 << switchCode);
2048 }
2049 mUpdatedSwitchMask |= 1 << switchCode;
2050 }
2051 }
异步事件处理
mSwitchValues |= 1 << switchCode;按下则记录switchCode值。
mSwitchValues &= ~(1 << switchCode);松开则清除switchCode值。
mUpdatedSwitchMask |= 1 << switchCode;将switchCode记录在mUpdatedSwitchMask里面。
xref: /frameworks/native/services/inputflinger/InputReader.cpp
2053 void SwitchInputMapper::sync(nsecs_t when) {
2054 if (mUpdatedSwitchMask) {
2055 uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;
2056 NotifySwitchArgs args(mContext->getNextSequenceNum(), when, 0, updatedSwitchValues,
2057 mUpdatedSwitchMask);
2058 getListener()->notifySwitch(&args);
2059
2060 mUpdatedSwitchMask = 0;
2061 }
2062 }
同步事件处理
getListener()->notifySwitch(&args);最终调用InputDispatcher::notifySwitch
xref: /frameworks/native/services/inputflinger/InputDispatcher.cpp
2809 void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {
2810 #if DEBUG_INBOUND_EVENT_DETAILS
2811 ALOGD("notifySwitch - eventTime=%" PRId64 ", policyFlags=0x%x, switchValues=0x%08x, "
2812 "switchMask=0x%08x",
2813 args->eventTime, args->policyFlags, args->switchValues, args->switchMask);
2814 #endif
2815
2816 uint32_t policyFlags = args->policyFlags;
2817 policyFlags |= POLICY_FLAG_TRUSTED;
2818 mPolicy->notifySwitch(args->eventTime,
2819 args->switchValues, args->switchMask, policyFlags);
2820 }
调用mPolicy->notifySwitch,最终调用NativeInputManager::notifySwitch
xref: /frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
692 void NativeInputManager::notifySwitch(nsecs_t when,
693 uint32_t switchValues, uint32_t switchMask, uint32_t /* policyFlags */) {
694 #if DEBUG_INPUT_DISPATCHER_POLICY
695 ALOGD("notifySwitch - when=%lld, switchValues=0x%08x, switchMask=0x%08x, policyFlags=0x%x",
696 when, switchValues, switchMask, policyFlags);
697 #endif
698 ATRACE_CALL();
699
700 JNIEnv* env = jniEnv();
701
702 env->CallVoidMethod(mServiceObj, gServiceClassInfo.notifySwitch,
703 when, switchValues, switchMask);
704 checkAndClearExceptionFromCallback(env, "notifySwitch");
705 }
env->CallVoidMethod调用java中的同名函数
xref: /frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
1753 private void notifySwitch(long whenNanos, int switchValues, int switchMask) {
1754 if (DEBUG) {
1755 Slog.d(TAG, "notifySwitch: values=" + Integer.toHexString(switchValues)
1756 + ", mask=" + Integer.toHexString(switchMask));
1757 }
1758
1759 if ((switchMask & SW_LID_BIT) != 0) {
1760 final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);
1761 mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);
1762 }
1763
1764 if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {
1765 final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);
1766 mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);
1767 }
1768
1769 if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {
1770 mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,
1771 switchMask);
1772 }
1773
1774 if ((switchMask & SW_TABLET_MODE_BIT) != 0) {
1775 SomeArgs args = SomeArgs.obtain();
1776 args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
1777 args.argi2 = (int) (whenNanos >> 32);
1778 args.arg1 = Boolean.valueOf((switchValues & SW_TABLET_MODE_BIT) != 0);
1779 mHandler.obtainMessage(MSG_DELIVER_TABLET_MODE_CHANGED,
1780 args).sendToTarget();
1781 }
1782 }
调用mWiredAccessoryCallbacks.notifyWiredAccessoryChanged。mUseDevInputEventForAudioJack来源于config.xml配置。
xref: /frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.java
137 @Override
138 public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {
139 if (LOG) {
140 Slog.v(TAG, "notifyWiredAccessoryChanged: when=" + whenNanos
141 + " bits=" + switchCodeToString(switchValues, switchMask)
142 + " mask=" + Integer.toHexString(switchMask));
143 }
144
145 synchronized (mLock) {
146 int headset;
147 mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;
148 switch (mSwitchValues &
149 (SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {
150 case 0:
151 headset = 0;
152 break;
153
154 case SW_HEADPHONE_INSERT_BIT:
155 headset = BIT_HEADSET_NO_MIC;
156 break;
157
158 case SW_LINEOUT_INSERT_BIT:
159 headset = BIT_LINEOUT;
160 break;
161
162 case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:
163 headset = BIT_HEADSET;
164 break;
165
166 case SW_MICROPHONE_INSERT_BIT:
167 headset = BIT_HEADSET;
168 break;
169
170 default:
171 headset = 0;
172 break;
173 }
174
175 updateLocked(NAME_H2W,
176 (mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);
177 }
178 }
最终调用到WiredAccessoryManager类里面的notifyWiredAccessoryChanged方法。根据驱动程序的上传mSwitchValues值来确定headset。
xref: /frameworks/base/services/core/java/com/android/server/WiredAccessoryManager.java
199 private void updateLocked(String newName, int newState) {
200 // Retain only relevant bits
201 int headsetState = newState & SUPPORTED_HEADSETS;
202 int usb_headset_anlg = headsetState & BIT_USB_HEADSET_ANLG;
203 int usb_headset_dgtl = headsetState & BIT_USB_HEADSET_DGTL;
204 int h2w_headset = headsetState & (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT);
205 boolean h2wStateChange = true;
206 boolean usbStateChange = true;
207 if (LOG) {
208 Slog.v(TAG, "newName=" + newName
209 + " newState=" + newState
210 + " headsetState=" + headsetState
211 + " prev headsetState=" + mHeadsetState);
212 }
213
214 if (mHeadsetState == headsetState) {
215 Log.e(TAG, "No state change.");
216 return;
217 }
218
219 // reject all suspect transitions: only accept state changes from:
220 // - a: 0 headset to 1 headset
221 // - b: 1 headset to 0 headset
222 if (h2w_headset == (BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) {
223 Log.e(TAG, "Invalid combination, unsetting h2w flag");
224 h2wStateChange = false;
225 }
226 // - c: 0 usb headset to 1 usb headset
227 // - d: 1 usb headset to 0 usb headset
228 if (usb_headset_anlg == BIT_USB_HEADSET_ANLG && usb_headset_dgtl == BIT_USB_HEADSET_DGTL) {
229 Log.e(TAG, "Invalid combination, unsetting usb flag");
230 usbStateChange = false;
231 }
232 if (!h2wStateChange && !usbStateChange) {
233 Log.e(TAG, "invalid transition, returning ...");
234 return;
235 }
236
237 mWakeLock.acquire();
238
239 Log.i(TAG, "MSG_NEW_DEVICE_STATE");
240 Message msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,
241 mHeadsetState, "");
242 mHandler.sendMessage(msg);
243
244 mHeadsetState = headsetState;
245 }
246
247 private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
248 @Override
249 public void handleMessage(Message msg) {
250 switch (msg.what) {
251 case MSG_NEW_DEVICE_STATE:
252 setDevicesState(msg.arg1, msg.arg2, (String) msg.obj);
253 mWakeLock.release();
254 break;
255 case MSG_SYSTEM_READY:
256 onSystemReady();
257 mWakeLock.release();
258 break;
259 }
260 }
261 };
262
263 private void setDevicesState(
264 int headsetState, int prevHeadsetState, String headsetName) {
265 synchronized (mLock) {
266 int allHeadsets = SUPPORTED_HEADSETS;
267 for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {
268 if ((curHeadset & allHeadsets) != 0) {
269 setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);
270 allHeadsets &= ~curHeadset;
271 }
272 }
273 }
274 }
275
276 private void setDeviceStateLocked(int headset,
277 int headsetState, int prevHeadsetState, String headsetName) {
278 if ((headsetState & headset) != (prevHeadsetState & headset)) {
279 int outDevice = 0;
280 int inDevice = 0;
281 int state;
282
283 if ((headsetState & headset) != 0) {
284 state = 1;
285 } else {
286 state = 0;
287 }
288
289 if (headset == BIT_HEADSET) {
290 outDevice = AudioManager.DEVICE_OUT_WIRED_HEADSET;
291 inDevice = AudioManager.DEVICE_IN_WIRED_HEADSET;
292 } else if (headset == BIT_HEADSET_NO_MIC) {
293 outDevice = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;
294 } else if (headset == BIT_LINEOUT) {
295 outDevice = AudioManager.DEVICE_OUT_LINE;
296 } else if (headset == BIT_USB_HEADSET_ANLG) {
297 outDevice = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;
298 } else if (headset == BIT_USB_HEADSET_DGTL) {
299 outDevice = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;
300 } else if (headset == BIT_HDMI_AUDIO) {
301 outDevice = AudioManager.DEVICE_OUT_HDMI;
302 } else {
303 Slog.e(TAG, "setDeviceState() invalid headset type: " + headset);
304 return;
305 }
306
307 if (LOG) {
308 Slog.v(TAG, "headsetName: " + headsetName +
309 (state == 1 ? " connected" : " disconnected"));
310 }
311
312 if (outDevice != 0) {
313 mAudioManager.setWiredDeviceConnectionState(outDevice, state, "", headsetName);
314 }
315 if (inDevice != 0) {
316 mAudioManager.setWiredDeviceConnectionState(inDevice, state, "", headsetName);
317 }
318 }
319 }
通过mAudioManager.setWiredDeviceConnectionState设置到mAudioManager
xref: /frameworks/base/media/java/android/media/AudioManager.java
4189 @UnsupportedAppUsage
4190 public void setWiredDeviceConnectionState(int type, int state, String address, String name) {
4191 final IAudioService service = getService();
4192 try {
4193 service.setWiredDeviceConnectionState(type, state, address, name,
4194 mApplicationContext.getOpPackageName());
4195 } catch (RemoteException e) {
4196 throw e.rethrowFromSystemServer();
4197 }
4198 }
xref: /frameworks/base/services/core/java/com/android/server/audio/AudioService.java
4368 public void setWiredDeviceConnectionState(int type,
4369 @ConnectionState int state, String address, String name,
4370 String caller) {
4371 if (state != CONNECTION_STATE_CONNECTED
4372 && state != CONNECTION_STATE_DISCONNECTED) {
4373 throw new IllegalArgumentException("Invalid state " + state);
4374 }
4375 mDeviceBroker.setWiredDeviceConnectionState(type, state, address, name, caller);
4376 }
xref: /frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
803 private void sendDeviceConnectionIntent(int device, int state, String address,
804 String deviceName) {
805 if (AudioService.DEBUG_DEVICES) {
806 Slog.i(TAG, "sendDeviceConnectionIntent(dev:0x" + Integer.toHexString(device)
807 + " state:0x" + Integer.toHexString(state) + " address:" + address
808 + " name:" + deviceName + ");");
809 }
810 Intent intent = new Intent();
811
812 switch(device) {
813 case AudioSystem.DEVICE_OUT_WIRED_HEADSET:
814 intent.setAction(Intent.ACTION_HEADSET_PLUG);
815 intent.putExtra("microphone", 1);
816 break;
817 case AudioSystem.DEVICE_OUT_WIRED_HEADPHONE:
818 case AudioSystem.DEVICE_OUT_LINE:
819 intent.setAction(Intent.ACTION_HEADSET_PLUG);
820 intent.putExtra("microphone", 0);
821 break;
822 case AudioSystem.DEVICE_OUT_USB_HEADSET:
823 intent.setAction(Intent.ACTION_HEADSET_PLUG);
824 intent.putExtra("microphone",
825 AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_IN_USB_HEADSET, "")
826 == AudioSystem.DEVICE_STATE_AVAILABLE ? 1 : 0);
827 break;
828 case AudioSystem.DEVICE_IN_USB_HEADSET:
829 if (AudioSystem.getDeviceConnectionState(AudioSystem.DEVICE_OUT_USB_HEADSET, "")
830 == AudioSystem.DEVICE_STATE_AVAILABLE) {
831 intent.setAction(Intent.ACTION_HEADSET_PLUG);
832 intent.putExtra("microphone", 1);
833 } else {
834 // do not send ACTION_HEADSET_PLUG when only the input side is seen as changing
835 return;
836 }
837 break;
838 case AudioSystem.DEVICE_OUT_HDMI:
839 case AudioSystem.DEVICE_OUT_HDMI_ARC:
840 configureHdmiPlugIntent(intent, state);
841 break;
842 }
843
844 if (intent.getAction() == null) {
845 return;
846 }
847
848 intent.putExtra(CONNECT_INTENT_KEY_STATE, state);
849 intent.putExtra(CONNECT_INTENT_KEY_ADDRESS, address);
850 intent.putExtra(CONNECT_INTENT_KEY_PORT_NAME, deviceName);
851
852 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
853
854 final long ident = Binder.clearCallingIdentity();
855 try {
856 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_CURRENT);
857 } finally {
858 Binder.restoreCallingIdentity(ident);
859 }
860 }
最终会调用到ActivityManager.broadcastStickyIntent把消息都广播发送出去。
4.声音通道的切换
xref: /frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
357 /*package*/ void onSetWiredDeviceConnectionState(
358 AudioDeviceInventory.WiredDeviceConnectionState wdcs) {
359 AudioService.sDeviceLogger.log(new AudioServiceEvents.WiredDevConnectEvent(wdcs));
360
361 synchronized (mConnectedDevices) {
362 if ((wdcs.mState == AudioService.CONNECTION_STATE_DISCONNECTED)
363 && ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0)) {
364 mDeviceBroker.setBluetoothA2dpOnInt(true,
365 "onSetWiredDeviceConnectionState state DISCONNECTED");
366 }
367
368 if (!handleDeviceConnection(wdcs.mState == AudioService.CONNECTION_STATE_CONNECTED,
369 wdcs.mType, wdcs.mAddress, wdcs.mName)) {
370 // change of connection state failed, bailout
371 return;
372 }
373 if (wdcs.mState != AudioService.CONNECTION_STATE_DISCONNECTED) {
374 if ((wdcs.mType & DEVICE_OVERRIDE_A2DP_ROUTE_ON_PLUG) != 0) {
375 mDeviceBroker.setBluetoothA2dpOnInt(false,
376 "onSetWiredDeviceConnectionState state not DISCONNECTED");
377 }
378 mDeviceBroker.checkMusicActive(wdcs.mType, wdcs.mCaller);
379 }
380 if (wdcs.mType == AudioSystem.DEVICE_OUT_HDMI) {
381 mDeviceBroker.checkVolumeCecOnHdmiConnection(wdcs.mState, wdcs.mCaller);
382 }
383 sendDeviceConnectionIntent(wdcs.mType, wdcs.mState, wdcs.mAddress, wdcs.mName);
384 updateAudioRoutes(wdcs.mType, wdcs.mState);
385 }
386 }
音频通道的处理在handleDeviceConnection方法里面,
xref: /frameworks/base/services/core/java/com/android/server/audio/AudioDeviceInventory.java
417 /*package*/ boolean handleDeviceConnection(boolean connect, int device, String address,
418 String deviceName) {
419 if (AudioService.DEBUG_DEVICES) {
420 Slog.i(TAG, "handleDeviceConnection(" + connect + " dev:"
421 + Integer.toHexString(device) + " address:" + address
422 + " name:" + deviceName + ")");
423 }
424 synchronized (mConnectedDevices) {
425 final String deviceKey = DeviceInfo.makeDeviceListKey(device, address);
426 if (AudioService.DEBUG_DEVICES) {
427 Slog.i(TAG, "deviceKey:" + deviceKey);
428 }
429 DeviceInfo di = mConnectedDevices.get(deviceKey);
430 boolean isConnected = di != null;
431 if (AudioService.DEBUG_DEVICES) {
432 Slog.i(TAG, "deviceInfo:" + di + " is(already)Connected:" + isConnected);
433 }
434 if (connect && !isConnected) {
435 final int res = AudioSystem.setDeviceConnectionState(device,
436 AudioSystem.DEVICE_STATE_AVAILABLE, address, deviceName,
437 AudioSystem.AUDIO_FORMAT_DEFAULT);
438 if (res != AudioSystem.AUDIO_STATUS_OK) {
439 Slog.e(TAG, "not connecting device 0x" + Integer.toHexString(device)
440 + " due to command error " + res);
441 return false;
442 }
443 mConnectedDevices.put(deviceKey, new DeviceInfo(
444 device, deviceName, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
445 mDeviceBroker.postAccessoryPlugMediaUnmute(device);
446 return true;
447 } else if (!connect && isConnected) {
448 AudioSystem.setDeviceConnectionState(device,
449 AudioSystem.DEVICE_STATE_UNAVAILABLE, address, deviceName,
450 AudioSystem.AUDIO_FORMAT_DEFAULT);
451 // always remove even if disconnection failed
452 mConnectedDevices.remove(deviceKey);
453 return true;
454 }
455 Log.w(TAG, "handleDeviceConnection() failed, deviceKey=" + deviceKey
456 + ", deviceSpec=" + di + ", connect=" + connect);
457 }
458 return false;
459 }
xref: /frameworks/av/media/libaudioclient/AudioSystem.cpp
786 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
787 audio_policy_dev_state_t state,
788 const char *device_address,
789 const char *device_name,
790 audio_format_t encodedFormat)
791 {
792 const sp& aps = AudioSystem::get_audio_policy_service();
793 const char *address = "";
794 const char *name = "";
795
796 if (aps == 0) return PERMISSION_DENIED;
797
798 if (device_address != NULL) {
799 address = device_address;
800 }
801 if (device_name != NULL) {
802 name = device_name;
803 }
804 return aps->setDeviceConnectionState(device, state, address, name, encodedFormat);
805 }
xref: /frameworks/base/core/jni/android_media_AudioSystem.cpp
492 static jint
493 android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address, jstring device_name,
494 jint codec)
495 {
496 const char *c_address = env->GetStringUTFChars(device_address, NULL);
497 const char *c_name = env->GetStringUTFChars(device_name, NULL);
498 int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast (device),
499 static_cast (state),
500 c_address, c_name,
501 static_cast (codec)));
502 env->ReleaseStringUTFChars(device_address, c_address);
503 env->ReleaseStringUTFChars(device_name, c_name);
504 return (jint) status;
505 }
xref: /frameworks/av/media/libaudioclient/AudioSystem.cpp
786 status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,
787 audio_policy_dev_state_t state,
788 const char *device_address,
789 const char *device_name,
790 audio_format_t encodedFormat)
791 {
792 const sp& aps = AudioSystem::get_audio_policy_service();
793 const char *address = "";
794 const char *name = "";
795
796 if (aps == 0) return PERMISSION_DENIED;
797
798 if (device_address != NULL) {
799 address = device_address;
800 }
801 if (device_name != NULL) {
802 name = device_name;
803 }
804 return aps->setDeviceConnectionState(device, state, address, name, encodedFormat);
805 }
xref: /frameworks/av/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
31 status_t AudioPolicyService::setDeviceConnectionState(audio_devices_t device,
32 audio_policy_dev_state_t state,
33 const char *device_address,
34 const char *device_name,
35 audio_format_t encodedFormat)
36 {
37 if (mAudioPolicyManager == NULL) {
38 return NO_INIT;
39 }
40 if (!settingsAllowed()) {
41 return PERMISSION_DENIED;
42 }
43 if (state != AUDIO_POLICY_DEVICE_STATE_AVAILABLE &&
44 state != AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
45 return BAD_VALUE;
46 }
47
48 ALOGV("setDeviceConnectionState()");
49 Mutex::Autolock _l(mLock);
50 AutoCallerClear acc;
51 return mAudioPolicyManager->setDeviceConnectionState(device, state,
52 device_address, device_name, encodedFormat);
53 }
xref: /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
83 status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,
84 audio_policy_dev_state_t state,
85 const char *device_address,
86 const char *device_name,
87 audio_format_t encodedFormat)
88 {
89 status_t status = setDeviceConnectionStateInt(device, state, device_address,
90 device_name, encodedFormat);
91 nextAudioPortGeneration();
92 return status;
93 }
105 status_t AudioPolicyManager::setDeviceConnectionStateInt(audio_devices_t deviceType,
106 audio_policy_dev_state_t state,
107 const char *device_address,
108 const char *device_name,
109 audio_format_t encodedFormat)
110 {
111 ALOGV("setDeviceConnectionStateInt() device: 0x%X, state %d, address %s name %s format 0x%X",
112 deviceType, state, device_address, device_name, encodedFormat);
113
114 // connect/disconnect only 1 device at a time
115 if (!audio_is_output_device(deviceType) && !audio_is_input_device(deviceType)) return BAD_VALUE;
116
117 sp device =
118 mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
119 state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
120 if (device == 0) {
121 return INVALID_OPERATION;
122 }
123
124 // handle output devices
125 if (audio_is_output_device(deviceType)) {
126 SortedVector outputs;
127
128 ssize_t index = mAvailableOutputDevices.indexOf(device);
129
130 // save a copy of the opened output descriptors before any output is opened or closed
131 // by checkOutputsForDevice(). This will be needed by checkOutputForAllStrategies()
132 mPreviousOutputs = mOutputs;
133 switch (state)
134 {
135 // handle output device connection
136 case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
137 if (index >= 0) {
138 ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
139 return INVALID_OPERATION;
140 }
141 ALOGV("%s() connecting device %s format %x",
142 __func__, device->toString().c_str(), encodedFormat);
143
144 // register new device as available
145 if (mAvailableOutputDevices.add(device) < 0) {
146 return NO_MEMORY;
147 }
148
149 // Before checking outputs, broadcast connect event to allow HAL to retrieve dynamic
150 // parameters on newly connected devices (instead of opening the outputs...)
151 broadcastDeviceConnectionState(device, state);
152
153 if (checkOutputsForDevice(device, state, outputs) != NO_ERROR) {
154 mAvailableOutputDevices.remove(device);
155
156 mHwModules.cleanUpForDevice(device);
157
158 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
159 return INVALID_OPERATION;
160 }
161
162 // outputs should never be empty here
163 ALOG_ASSERT(outputs.size() != 0, "setDeviceConnectionState():"
164 "checkOutputsForDevice() returned no outputs but status OK");
165 ALOGV("%s() checkOutputsForDevice() returned %zu outputs", __func__, outputs.size());
166
167 } break;
168 // handle output device disconnection
169 case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
170 if (index < 0) {
171 ALOGW("%s() device not connected: %s", __func__, device->toString().c_str());
172 return INVALID_OPERATION;
173 }
174
175 ALOGV("%s() disconnecting output device %s", __func__, device->toString().c_str());
176
177 // Send Disconnect to HALs
178 broadcastDeviceConnectionState(device, state);
179
180 // remove device from available output devices
181 mAvailableOutputDevices.remove(device);
182
183 mOutputs.clearSessionRoutesForDevice(device);
184
185 checkOutputsForDevice(device, state, outputs);
186
187 // Reset active device codec
188 device->setEncodedFormat(AUDIO_FORMAT_DEFAULT);
189
190 } break;
191
192 default:
193 ALOGE("%s() invalid state: %x", __func__, state);
194 return BAD_VALUE;
195 }
196
197 // Propagate device availability to Engine
198 setEngineDeviceConnectionState(device, state);
199
200 // No need to evaluate playback routing when connecting a remote submix
201 // output device used by a dynamic policy of type recorder as no
202 // playback use case is affected.
203 bool doCheckForDeviceAndOutputChanges = true;
204 if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
205 && strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
206 for (audio_io_handle_t output : outputs) {
207 sp desc = mOutputs.valueFor(output);
208 sp policyMix = desc->mPolicyMix.promote();
209 if (policyMix != nullptr
210 && policyMix->mMixType == MIX_TYPE_RECORDERS
211 && strncmp(device_address,
212 policyMix->mDeviceAddress.string(),
213 AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
214 doCheckForDeviceAndOutputChanges = false;
215 break;
216 }
217 }
218 }
219
220 auto checkCloseOutputs = [&]() {
221 // outputs must be closed after checkOutputForAllStrategies() is executed
222 if (!outputs.isEmpty()) {
223 for (audio_io_handle_t output : outputs) {
224 sp desc = mOutputs.valueFor(output);
225 // close unused outputs after device disconnection or direct outputs that have
226 // been opened by checkOutputsForDevice() to query dynamic parameters
227 if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) ||
228 (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
229 (desc->mDirectOpenCount == 0))) {
230 closeOutput(output);
231 }
232 }
233 // check A2DP again after closing A2DP output to reset mA2dpSuspended if needed
234 return true;
235 }
236 return false;
237 };
238
239 if (doCheckForDeviceAndOutputChanges) {
240 checkForDeviceAndOutputChanges(checkCloseOutputs);
241 } else {
242 checkCloseOutputs();
243 }
244
245 if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
246 DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
247 updateCallRouting(newDevices);
248 }
249 const DeviceVector msdOutDevices = getMsdAudioOutDevices();
250 for (size_t i = 0; i < mOutputs.size(); i++) {
251 sp desc = mOutputs.valueAt(i);
252 if ((mEngine->getPhoneState() != AUDIO_MODE_IN_CALL) || (desc != mPrimaryOutput)) {
253 DeviceVector newDevices = getNewOutputDevices(desc, true /*fromCache*/);
254 // do not force device change on duplicated output because if device is 0, it will
255 // also force a device 0 for the two outputs it is duplicated to which may override
256 // a valid device selection on those outputs.
257 bool force = (msdOutDevices.isEmpty() || msdOutDevices != desc->devices())
258 && !desc->isDuplicated()
259 && (!device_distinguishes_on_address(deviceType)
260 // always force when disconnecting (a non-duplicated device)
261 || (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
262 setOutputDevices(desc, newDevices, force, 0);
263 }
264 }
265
266 if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
267 cleanUpForDevice(device);
268 }
269
270 mpClientInterface->onAudioPortListUpdate();
271 return NO_ERROR;
272 } // end if is output device
273
274 // handle input devices
275 if (audio_is_input_device(deviceType)) {
276 ssize_t index = mAvailableInputDevices.indexOf(device);
277 switch (state)
278 {
279 // handle input device connection
280 case AUDIO_POLICY_DEVICE_STATE_AVAILABLE: {
281 if (index >= 0) {
282 ALOGW("%s() device already connected: %s", __func__, device->toString().c_str());
283 return INVALID_OPERATION;
284 }
285
286 if (mAvailableInputDevices.add(device) < 0) {
287 return NO_MEMORY;
288 }
289
290 // Before checking intputs, broadcast connect event to allow HAL to retrieve dynamic
291 // parameters on newly connected devices (instead of opening the inputs...)
292 broadcastDeviceConnectionState(device, state);
293
294 if (checkInputsForDevice(device, state) != NO_ERROR) {
295 mAvailableInputDevices.remove(device);
296
297 broadcastDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE);
298
299 mHwModules.cleanUpForDevice(device);
300
301 return INVALID_OPERATION;
302 }
303
304 } break;
305
306 // handle input device disconnection
307 case AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE: {
308 if (index < 0) {
309 ALOGW("%s() device not connected: %s", __func__, device->toString().c_str());
310 return INVALID_OPERATION;
311 }
312
313 ALOGV("%s() disconnecting input device %s", __func__, device->toString().c_str());
314
315 // Set Disconnect to HALs
316 broadcastDeviceConnectionState(device, state);
317
318 mAvailableInputDevices.remove(device);
319
320 checkInputsForDevice(device, state);
321 } break;
322
323 default:
324 ALOGE("%s() invalid state: %x", __func__, state);
325 return BAD_VALUE;
326 }
327
328 // Propagate device availability to Engine
329 setEngineDeviceConnectionState(device, state);
330
331 checkCloseInputs();
332 // As the input device list can impact the output device selection, update
333 // getDeviceForStrategy() cache
334 updateDevicesAndOutputs();
335
336 if (mEngine->getPhoneState() == AUDIO_MODE_IN_CALL && hasPrimaryOutput()) {
337 DeviceVector newDevices = getNewOutputDevices(mPrimaryOutput, false /*fromCache*/);
338 updateCallRouting(newDevices);
339 }
340
341 if (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE) {
342 cleanUpForDevice(device);
343 }
344
345 mpClientInterface->onAudioPortListUpdate();
346 return NO_ERROR;
347 } // end if is input device
348
349 ALOGW("%s() invalid device: %s", __func__, device->toString().c_str());
350 return BAD_VALUE;
351 }
经过一系列的调用最终走到AudioPolicyManager::setDeviceConnectionStateInt里面,checkOutputsForDevice(device, state, outputs);用于检测device是否有对应的outputs。
xref: /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
4547 status_t AudioPolicyManager::checkOutputsForDevice(const sp& device,
4548 audio_policy_dev_state_t state,
4549 SortedVector& outputs)
4550 {
4551 audio_devices_t deviceType = device->type();
4552 const String8 &address = device->address();
4553 sp desc;
4554
4555 if (audio_device_is_digital(deviceType)) {
4556 // erase all current sample rates, formats and channel masks
4557 device->clearAudioProfiles();
4558 }
4559
4560 if (state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE) {
4561 // first list already open outputs that can be routed to this device
4562 for (size_t i = 0; i < mOutputs.size(); i++) {
4563 desc = mOutputs.valueAt(i);
4564 if (!desc->isDuplicated() && desc->supportsDevice(device)
4565 && desc->deviceSupportsEncodedFormats(deviceType)) {
4566 ALOGV("checkOutputsForDevice(): adding opened output %d on device %s",
4567 mOutputs.keyAt(i), device->toString().c_str());
4568 outputs.add(mOutputs.keyAt(i));
4569 }
4570 }
4571 // then look for output profiles that can be routed to this device
4572 SortedVector< sp > profiles;
4573 for (const auto& hwModule : mHwModules) {
4574 for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
4575 sp profile = hwModule->getOutputProfiles()[j];
4576 if (profile->supportsDevice(device)) {
4577 profiles.add(profile);
4578 ALOGV("checkOutputsForDevice(): adding profile %zu from module %s",
4579 j, hwModule->getName());
4580 }
4581 }
4582 }
4583
4584 ALOGV(" found %zu profiles, %zu outputs", profiles.size(), outputs.size());
4585
4586 if (profiles.isEmpty() && outputs.isEmpty()) {
4587 ALOGW("checkOutputsForDevice(): No output available for device %04x", deviceType);
4588 return BAD_VALUE;
4589 }
4590
4591 // open outputs for matching profiles if needed. Direct outputs are also opened to
4592 // query for dynamic parameters and will be closed later by setDeviceConnectionState()
4593 for (ssize_t profile_index = 0; profile_index < (ssize_t)profiles.size(); profile_index++) {
4594 sp profile = profiles[profile_index];
4595
4596 // nothing to do if one output is already opened for this profile
4597 size_t j;
4598 for (j = 0; j < outputs.size(); j++) {
4599 desc = mOutputs.valueFor(outputs.itemAt(j));
4600 if (!desc->isDuplicated() && desc->mProfile == profile) {
4601 // matching profile: save the sample rates, format and channel masks supported
4602 // by the profile in our device descriptor
4603 if (audio_device_is_digital(deviceType)) {
4604 device->importAudioPort(profile);
4605 }
4606 break;
4607 }
4608 }
4609 if (j != outputs.size()) {
4610 continue;
4611 }
4612
4613 if (!profile->canOpenNewIo()) {
4614 ALOGW("Max Output number %u already opened for this profile %s",
4615 profile->maxOpenCount, profile->getTagName().c_str());
4616 continue;
4617 }
4618
4619 ALOGV("opening output for device %08x with params %s profile %p name %s",
4620 deviceType, address.string(), profile.get(), profile->getName().string());
4621 desc = new SwAudioOutputDescriptor(profile, mpClientInterface);
4622 audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
4623 status_t status = desc->open(nullptr, DeviceVector(device),
4624 AUDIO_STREAM_DEFAULT, AUDIO_OUTPUT_FLAG_NONE, &output);
4625
4626 if (status == NO_ERROR) {
4627 // Here is where the out_set_parameters() for card & device gets called
4628 if (!address.isEmpty()) {
4629 char *param = audio_device_address_to_parameter(deviceType, address);
4630 mpClientInterface->setParameters(output, String8(param));
4631 free(param);
4632 }
4633 updateAudioProfiles(device, output, profile->getAudioProfiles());
4634 if (!profile->hasValidAudioProfile()) {
4635 ALOGW("checkOutputsForDevice() missing param");
4636 desc->close();
4637 output = AUDIO_IO_HANDLE_NONE;
4638 } else if (profile->hasDynamicAudioProfile()) {
4639 desc->close();
4640 output = AUDIO_IO_HANDLE_NONE;
4641 audio_config_t config = AUDIO_CONFIG_INITIALIZER;
4642 profile->pickAudioProfile(
4643 config.sample_rate, config.channel_mask, config.format);
4644 config.offload_info.sample_rate = config.sample_rate;
4645 config.offload_info.channel_mask = config.channel_mask;
4646 config.offload_info.format = config.format;
4647
4648 status_t status = desc->open(&config, DeviceVector(device),
4649 AUDIO_STREAM_DEFAULT,
4650 AUDIO_OUTPUT_FLAG_NONE, &output);
4651 if (status != NO_ERROR) {
4652 output = AUDIO_IO_HANDLE_NONE;
4653 }
4654 }
4655
4656 if (output != AUDIO_IO_HANDLE_NONE) {
4657 addOutput(output, desc);
4658 if (device_distinguishes_on_address(deviceType) && address != "0") {
4659 sp policyMix;
4660 if (mPolicyMixes.getAudioPolicyMix(deviceType, address, policyMix)
4661 == NO_ERROR) {
4662 policyMix->setOutput(desc);
4663 desc->mPolicyMix = policyMix;
4664 } else {
4665 ALOGW("checkOutputsForDevice() cannot find policy for address %s",
4666 address.string());
4667 }
4668
4669 } else if (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0) &&
4670 hasPrimaryOutput()) {
4671 // no duplicated output for direct outputs and
4672 // outputs used by dynamic policy mixes
4673 audio_io_handle_t duplicatedOutput = AUDIO_IO_HANDLE_NONE;
4674
4675 //TODO: configure audio effect output stage here
4676
4677 // open a duplicating output thread for the new output and the primary output
4678 sp dupOutputDesc =
4679 new SwAudioOutputDescriptor(NULL, mpClientInterface);
4680 status_t status = dupOutputDesc->openDuplicating(mPrimaryOutput, desc,
4681 &duplicatedOutput);
4682 if (status == NO_ERROR) {
4683 // add duplicated output descriptor
4684 addOutput(duplicatedOutput, dupOutputDesc);
4685 } else {
4686 ALOGW("checkOutputsForDevice() could not open dup output for %d and %d",
4687 mPrimaryOutput->mIoHandle, output);
4688 desc->close();
4689 removeOutput(output);
4690 nextAudioPortGeneration();
4691 output = AUDIO_IO_HANDLE_NONE;
4692 }
4693 }
4694 }
4695 } else {
4696 output = AUDIO_IO_HANDLE_NONE;
4697 }
4698 if (output == AUDIO_IO_HANDLE_NONE) {
4699 ALOGW("checkOutputsForDevice() could not open output for device %x", deviceType);
4700 profiles.removeAt(profile_index);
4701 profile_index--;
4702 } else {
4703 outputs.add(output);
4704 // Load digital format info only for digital devices
4705 if (audio_device_is_digital(deviceType)) {
4706 device->importAudioPort(profile);
4707 }
4708
4709 if (device_distinguishes_on_address(deviceType)) {
4710 ALOGV("checkOutputsForDevice(): setOutputDevices %s",
4711 device->toString().c_str());
4712 setOutputDevices(desc, DeviceVector(device), true/*force*/, 0/*delay*/,
4713 NULL/*patch handle*/);
4714 }
4715 ALOGV("checkOutputsForDevice(): adding output %d", output);
4716 }
4717 }
4718
4719 if (profiles.isEmpty()) {
4720 ALOGW("checkOutputsForDevice(): No output available for device %04x", deviceType);
4721 return BAD_VALUE;
4722 }
4723 } else { // Disconnect
4724 // check if one opened output is not needed any more after disconnecting one device
4725 for (size_t i = 0; i < mOutputs.size(); i++) {
4726 desc = mOutputs.valueAt(i);
4727 if (!desc->isDuplicated()) {
4728 // exact match on device
4729 if (device_distinguishes_on_address(deviceType) && desc->supportsDevice(device)
4730 && desc->deviceSupportsEncodedFormats(deviceType)) {
4731 outputs.add(mOutputs.keyAt(i));
4732 } else if (!mAvailableOutputDevices.containsAtLeastOne(desc->supportedDevices())) {
4733 ALOGV("checkOutputsForDevice(): disconnecting adding output %d",
4734 mOutputs.keyAt(i));
4735 outputs.add(mOutputs.keyAt(i));
4736 }
4737 }
4738 }
4739 // Clear any profiles associated with the disconnected device.
4740 for (const auto& hwModule : mHwModules) {
4741 for (size_t j = 0; j < hwModule->getOutputProfiles().size(); j++) {
4742 sp profile = hwModule->getOutputProfiles()[j];
4743 if (profile->supportsDevice(device)) {
4744 ALOGV("checkOutputsForDevice(): "
4745 "clearing direct output profile %zu on module %s",
4746 j, hwModule->getName());
4747 profile->clearAudioProfiles();
4748 }
4749 }
4750 }
4751 }
4752 return NO_ERROR;
4753 }
desc->open打开新的output并创建播放线程playbackthread.
返回到AudioPolicyManager::setDeviceConnectionStateInt中,checkOutputsForDevice之后调用checkForDeviceAndOutputChanges方法,再调用AudioPolicyManager::checkOutputForAllStrategies,然后在调用checkOutputForAttributes方法。
xref: /frameworks/av/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
5030 void AudioPolicyManager::checkOutputForAttributes(const audio_attributes_t &attr)
5031 {
5032 auto psId = mEngine->getProductStrategyForAttributes(attr);
5033
5034 DeviceVector oldDevices = mEngine->getOutputDevicesForAttributes(attr, 0, true /*fromCache*/);
5035 DeviceVector newDevices = mEngine->getOutputDevicesForAttributes(attr, 0, false /*fromCache*/);
5036 SortedVector srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
5037 SortedVector dstOutputs = getOutputsForDevices(newDevices, mOutputs);
5038
5039 // also take into account external policy-related changes: add all outputs which are
5040 // associated with policies in the "before" and "after" output vectors
5041 ALOGVV("%s(): policy related outputs", __func__);
5042 for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
5043 const sp desc = mPreviousOutputs.valueAt(i);
5044 if (desc != 0 && desc->mPolicyMix != NULL) {
5045 srcOutputs.add(desc->mIoHandle);
5046 ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
5047 }
5048 }
5049 for (size_t i = 0 ; i < mOutputs.size() ; i++) {
5050 const sp desc = mOutputs.valueAt(i);
5051 if (desc != 0 && desc->mPolicyMix != NULL) {
5052 dstOutputs.add(desc->mIoHandle);
5053 ALOGVV(" new outputs: adding %d", desc->mIoHandle);
5054 }
5055 }
5056
5057 if (srcOutputs != dstOutputs) {
5058 // get maximum latency of all source outputs to determine the minimum mute time guaranteeing
5059 // audio from invalidated tracks will be rendered when unmuting
5060 uint32_t maxLatency = 0;
5061 for (audio_io_handle_t srcOut : srcOutputs) {
5062 sp desc = mPreviousOutputs.valueFor(srcOut);
5063 if (desc != 0 && maxLatency < desc->latency()) {
5064 maxLatency = desc->latency();
5065 }
5066 }
5067 ALOGV_IF(!(srcOutputs.isEmpty() || dstOutputs.isEmpty()),
5068 "%s: strategy %d, moving from output %s to output %s", __func__, psId,
5069 std::to_string(srcOutputs[0]).c_str(),
5070 std::to_string(dstOutputs[0]).c_str());
5071 // mute strategy while moving tracks from one output to another
5072 for (audio_io_handle_t srcOut : srcOutputs) {
5073 sp desc = mPreviousOutputs.valueFor(srcOut);
5074 if (desc != 0 && desc->isStrategyActive(psId)) {
5075 setStrategyMute(psId, true, desc);
5076 setStrategyMute(psId, false, desc, maxLatency * LATENCY_MUTE_FACTOR,
5077 newDevices.types());
5078 }
5079 sp source = getSourceForAttributesOnOutput(srcOut, attr);
5080 if (source != 0){
5081 connectAudioSource(source);
5082 }
5083 }
5084
5085 // Move effects associated to this stream from previous output to new output
5086 if (followsSameRouting(attr, attributes_initializer(AUDIO_USAGE_MEDIA))) {
5087 selectOutputForMusicEffects();
5088 }
5089 // Move tracks associated to this stream (and linked) from previous output to new output
5090 for (auto stream : mEngine->getStreamTypesForProductStrategy(psId)) {
5091 mpClientInterface->invalidateStream(stream);
5092 }
5093 }
5094 }
判断srcOutputs和dstOutputs是否相同,如果相同则不需要切换output,如果不相同则需要切换通道。mpClientInterface->invalidateStream使之前的output无效。
xref: /frameworks/av/media/libaudioclient/AudioTrack.cpp
2287 status_t AudioTrack::restoreTrack_l(const char *from)
2288 {
2289 ALOGW("%s(%d): dead IAudioTrack, %s, creating a new one from %s()",
2290 __func__, mPortId, isOffloadedOrDirect_l() ? "Offloaded or Direct" : "PCM", from);
2291 ++mSequence;
2292
2293 // refresh the audio configuration cache in this process to make sure we get new
2294 // output parameters and new IAudioFlinger in createTrack_l()
2295 AudioSystem::clearAudioConfigCache();
2296
2297 if (isOffloadedOrDirect_l() || mDoNotReconnect) {
2298 // FIXME re-creation of offloaded and direct tracks is not yet implemented;
2299 // reconsider enabling for linear PCM encodings when position can be preserved.
2300 return DEAD_OBJECT;
2301 }
2302
2303 // Save so we can return count since creation.
2304 mUnderrunCountOffset = getUnderrunCount_l();
2305
2306 // save the old static buffer position
2307 uint32_t staticPosition = 0;
2308 size_t bufferPosition = 0;
2309 int loopCount = 0;
2310 if (mStaticProxy != 0) {
2311 mStaticProxy->getBufferPositionAndLoopCount(&bufferPosition, &loopCount);
2312 staticPosition = mStaticProxy->getPosition().unsignedValue();
2313 }
2314
2315 // See b/74409267. Connecting to a BT A2DP device supporting multiple codecs
2316 // causes a lot of churn on the service side, and it can reject starting
2317 // playback of a previously created track. May also apply to other cases.
2318 const int INITIAL_RETRIES = 3;
2319 int retries = INITIAL_RETRIES;
2320 retry:
2321 if (retries < INITIAL_RETRIES) {
2322 // See the comment for clearAudioConfigCache at the start of the function.
2323 AudioSystem::clearAudioConfigCache();
2324 }
2325 mFlags = mOrigFlags;
2326
2327 // If a new IAudioTrack is successfully created, createTrack_l() will modify the
2328 // following member variables: mAudioTrack, mCblkMemory and mCblk.
2329 // It will also delete the strong references on previous IAudioTrack and IMemory.
2330 // If a new IAudioTrack cannot be created, the previous (dead) instance will be left intact.
2331 status_t result = createTrack_l();
2332
2333 if (result == NO_ERROR) {
2334 // take the frames that will be lost by track recreation into account in saved position
2335 // For streaming tracks, this is the amount we obtained from the user/client
2336 // (not the number actually consumed at the server - those are already lost).
2337 if (mStaticProxy == 0) {
2338 mPosition = mReleased;
2339 }
2340 // Continue playback from last known position and restore loop.
2341 if (mStaticProxy != 0) {
2342 if (loopCount != 0) {
2343 mStaticProxy->setBufferPositionAndLoop(bufferPosition,
2344 mLoopStart, mLoopEnd, loopCount);
2345 } else {
2346 mStaticProxy->setBufferPosition(bufferPosition);
2347 if (bufferPosition == mFrameCount) {
2348 ALOGD("%s(%d): restoring track at end of static buffer", __func__, mPortId);
2349 }
2350 }
2351 }
2352 // restore volume handler
2353 mVolumeHandler->forall([this](const VolumeShaper &shaper) -> VolumeShaper::Status {
2354 sp operationToEnd =
2355 new VolumeShaper::Operation(shaper.mOperation);
2356 // TODO: Ideally we would restore to the exact xOffset position
2357 // as returned by getVolumeShaperState(), but we don't have that
2358 // information when restoring at the client unless we periodically poll
2359 // the server or create shared memory state.
2360 //
2361 // For now, we simply advance to the end of the VolumeShaper effect
2362 // if it has been started.
2363 if (shaper.isStarted()) {
2364 operationToEnd->setNormalizedTime(1.f);
2365 }
2366 return mAudioTrack->applyVolumeShaper(shaper.mConfiguration, operationToEnd);
2367 });
2368
2369 if (mState == STATE_ACTIVE) {
2370 result = mAudioTrack->start();
2371 }
2372 // server resets to zero so we offset
2373 mFramesWrittenServerOffset =
2374 mStaticProxy.get() != nullptr ? staticPosition : mFramesWritten;
2375 mFramesWrittenAtRestore = mFramesWrittenServerOffset;
2376 }
2377 if (result != NO_ERROR) {
2378 ALOGW("%s(%d): failed status %d, retries %d", __func__, mPortId, result, retries);
2379 if (--retries > 0) {
2380 // leave time for an eventual race condition to clear before retrying
2381 usleep(500000);
2382 goto retry;
2383 }
2384 // if no retries left, set invalid bit to force restoring at next occasion
2385 // and avoid inconsistent active state on client and server sides
2386 if (mCblk != nullptr) {
2387 android_atomic_or(CBLK_INVALID, &mCblk->mFlags);
2388 }
2389 }
2390 return result;
2391 }
xref: /frameworks/av/media/libaudioclient/AudioTrack.cpp
1393 status_t AudioTrack::createTrack_l()
1394 {
1395 status_t status;
1396 bool callbackAdded = false;
1397
1398 const sp& audioFlinger = AudioSystem::get_audio_flinger();
1399 if (audioFlinger == 0) {
1400 ALOGE("%s(%d): Could not get audioflinger",
1401 __func__, mPortId);
1402 status = NO_INIT;
1403 goto exit;
1404 }
1405
1406 {
1407 // mFlags (not mOrigFlags) is modified depending on whether fast request is accepted.
1408 // After fast request is denied, we will request again if IAudioTrack is re-created.
1409 // Client can only express a preference for FAST. Server will perform additional tests.
1410 if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
1411 // either of these use cases:
1412 // use case 1: shared buffer
1413 bool sharedBuffer = mSharedBuffer != 0;
1414 bool transferAllowed =
1415 // use case 2: callback transfer mode
1416 (mTransfer == TRANSFER_CALLBACK) ||
1417 // use case 3: obtain/release mode
1418 (mTransfer == TRANSFER_OBTAIN) ||
1419 // use case 4: synchronous write
1420 ((mTransfer == TRANSFER_SYNC || mTransfer == TRANSFER_SYNC_NOTIF_CALLBACK)
1421 && mThreadCanCallJava);
1422
1423 bool fastAllowed = sharedBuffer || transferAllowed;
1424 if (!fastAllowed) {
1425 ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by client,"
1426 " not shared buffer and transfer = %s",
1427 __func__, mPortId,
1428 convertTransferToText(mTransfer));
1429 mFlags = (audio_output_flags_t) (mFlags & ~AUDIO_OUTPUT_FLAG_FAST);
1430 }
1431 }
1432
1433 IAudioFlinger::CreateTrackInput input;
1434 if (mStreamType != AUDIO_STREAM_DEFAULT) {
1435 input.attr = AudioSystem::streamTypeToAttributes(mStreamType);
1436 } else {
1437 input.attr = mAttributes;
1438 }
1439 input.config = AUDIO_CONFIG_INITIALIZER;
1440 input.config.sample_rate = mSampleRate;
1441 input.config.channel_mask = mChannelMask;
1442 input.config.format = mFormat;
1443 input.config.offload_info = mOffloadInfoCopy;
1444 input.clientInfo.clientUid = mClientUid;
1445 input.clientInfo.clientPid = mClientPid;
1446 input.clientInfo.clientTid = -1;
1447 if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
1448 // It is currently meaningless to request SCHED_FIFO for a Java thread. Even if the
1449 // application-level code follows all non-blocking design rules, the language runtime
1450 // doesn't also follow those rules, so the thread will not benefit overall.
1451 if (mAudioTrackThread != 0 && !mThreadCanCallJava) {
1452 input.clientInfo.clientTid = mAudioTrackThread->getTid();
1453 }
1454 }
1455 input.sharedBuffer = mSharedBuffer;
1456 input.notificationsPerBuffer = mNotificationsPerBufferReq;
1457 input.speed = 1.0;
1458 if (audio_has_proportional_frames(mFormat) && mSharedBuffer == 0 &&
1459 (mFlags & AUDIO_OUTPUT_FLAG_FAST) == 0) {
1460 input.speed = !isPurePcmData_l() || isOffloadedOrDirect_l() ? 1.0f :
1461 max(mMaxRequiredSpeed, mPlaybackRate.mSpeed);
1462 }
1463 input.flags = mFlags;
1464 input.frameCount = mReqFrameCount;
1465 input.notificationFrameCount = mNotificationFramesReq;
1466 input.selectedDeviceId = mSelectedDeviceId;
1467 input.sessionId = mSessionId;
1468
1469 IAudioFlinger::CreateTrackOutput output;
1470
1471 sp track = audioFlinger->createTrack(input,
1472 output,
1473 &status);
1474
1475 if (status != NO_ERROR || output.outputId == AUDIO_IO_HANDLE_NONE) {
1476 ALOGE("%s(%d): AudioFlinger could not create track, status: %d output %d",
1477 __func__, mPortId, status, output.outputId);
1478 if (status == NO_ERROR) {
1479 status = NO_INIT;
1480 }
1481 goto exit;
1482 }
1483 ALOG_ASSERT(track != 0);
1484
1485 mFrameCount = output.frameCount;
1486 mNotificationFramesAct = (uint32_t)output.notificationFrameCount;
1487 mRoutedDeviceId = output.selectedDeviceId;
1488 mSessionId = output.sessionId;
1489
1490 mSampleRate = output.sampleRate;
1491 if (mOriginalSampleRate == 0) {
1492 mOriginalSampleRate = mSampleRate;
1493 }
1494
1495 mAfFrameCount = output.afFrameCount;
1496 mAfSampleRate = output.afSampleRate;
1497 mAfLatency = output.afLatencyMs;
1498
1499 mLatency = mAfLatency + (1000LL * mFrameCount) / mSampleRate;
1500
1501 // AudioFlinger now owns the reference to the I/O handle,
1502 // so we are no longer responsible for releasing it.
1503
1504 // FIXME compare to AudioRecord
1505 sp iMem = track->getCblk();
1506 if (iMem == 0) {
1507 ALOGE("%s(%d): Could not get control block", __func__, mPortId);
1508 status = NO_INIT;
1509 goto exit;
1510 }
1511 void *iMemPointer = iMem->pointer();
1512 if (iMemPointer == NULL) {
1513 ALOGE("%s(%d): Could not get control block pointer", __func__, mPortId);
1514 status = NO_INIT;
1515 goto exit;
1516 }
1517 // invariant that mAudioTrack != 0 is true only after set() returns successfully
1518 if (mAudioTrack != 0) {
1519 IInterface::asBinder(mAudioTrack)->unlinkToDeath(mDeathNotifier, this);
1520 mDeathNotifier.clear();
1521 }
1522 mAudioTrack = track;
1523 mCblkMemory = iMem;
1524 IPCThreadState::self()->flushCommands();
1525
1526 audio_track_cblk_t* cblk = static_cast(iMemPointer);
1527 mCblk = cblk;
1528
1529 mAwaitBoost = false;
1530 if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
1531 if (output.flags & AUDIO_OUTPUT_FLAG_FAST) {
1532 ALOGI("%s(%d): AUDIO_OUTPUT_FLAG_FAST successful; frameCount %zu -> %zu",
1533 __func__, mPortId, mReqFrameCount, mFrameCount);
1534 if (!mThreadCanCallJava) {
1535 mAwaitBoost = true;
1536 }
1537 } else {
1538 ALOGW("%s(%d): AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %zu -> %zu",
1539 __func__, mPortId, mReqFrameCount, mFrameCount);
1540 }
1541 }
1542 mFlags = output.flags;
1543
1544 //mOutput != output includes the case where mOutput == AUDIO_IO_HANDLE_NONE for first creation
1545 if (mDeviceCallback != 0) {
1546 if (mOutput != AUDIO_IO_HANDLE_NONE) {
1547 AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
1548 }
1549 AudioSystem::addAudioDeviceCallback(this, output.outputId, output.portId);
1550 callbackAdded = true;
1551 }
1552
1553 mPortId = output.portId;
1554 // We retain a copy of the I/O handle, but don't own the reference
1555 mOutput = output.outputId;
1556 mRefreshRemaining = true;
1557
1558 // Starting address of buffers in shared memory. If there is a shared buffer, buffers
1559 // is the value of pointer() for the shared buffer, otherwise buffers points
1560 // immediately after the control block. This address is for the mapping within client
1561 // address space. AudioFlinger::TrackBase::mBuffer is for the server address space.
1562 void* buffers;
1563 if (mSharedBuffer == 0) {
1564 buffers = cblk + 1;
1565 } else {
1566 buffers = mSharedBuffer->pointer();
1567 if (buffers == NULL) {
1568 ALOGE("%s(%d): Could not get buffer pointer", __func__, mPortId);
1569 status = NO_INIT;
1570 goto exit;
1571 }
1572 }
1573
1574 mAudioTrack->attachAuxEffect(mAuxEffectId);
1575
1576 // If IAudioTrack is re-created, don't let the requested frameCount
1577 // decrease. This can confuse clients that cache frameCount().
1578 if (mFrameCount > mReqFrameCount) {
1579 mReqFrameCount = mFrameCount;
1580 }
1581
1582 // reset server position to 0 as we have new cblk.
1583 mServer = 0;
1584
1585 // update proxy
1586 if (mSharedBuffer == 0) {
1587 mStaticProxy.clear();
1588 mProxy = new AudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
1589 } else {
1590 mStaticProxy = new StaticAudioTrackClientProxy(cblk, buffers, mFrameCount, mFrameSize);
1591 mProxy = mStaticProxy;
1592 }
1593
1594 mProxy->setVolumeLR(gain_minifloat_pack(
1595 gain_from_float(mVolume[AUDIO_INTERLEAVE_LEFT]),
1596 gain_from_float(mVolume[AUDIO_INTERLEAVE_RIGHT])));
1597
1598 mProxy->setSendLevel(mSendLevel);
1599 const uint32_t effectiveSampleRate = adjustSampleRate(mSampleRate, mPlaybackRate.mPitch);
1600 const float effectiveSpeed = adjustSpeed(mPlaybackRate.mSpeed, mPlaybackRate.mPitch);
1601 const float effectivePitch = adjustPitch(mPlaybackRate.mPitch);
1602 mProxy->setSampleRate(effectiveSampleRate);
1603
1604 AudioPlaybackRate playbackRateTemp = mPlaybackRate;
1605 playbackRateTemp.mSpeed = effectiveSpeed;
1606 playbackRateTemp.mPitch = effectivePitch;
1607 mProxy->setPlaybackRate(playbackRateTemp);
1608 mProxy->setMinimum(mNotificationFramesAct);
1609
1610 mDeathNotifier = new DeathNotifier(this);
1611 IInterface::asBinder(mAudioTrack)->linkToDeath(mDeathNotifier, this);
1612
1613 }
1614
1615 exit:
1616 if (status != NO_ERROR && callbackAdded) {
1617 // note: mOutput is always valid is callbackAdded is true
1618 AudioSystem::removeAudioDeviceCallback(this, mOutput, mPortId);
1619 }
1620
1621 mStatus = status;
1622
1623 // sp track destructor will cause releaseOutput() to be called by AudioFlinger
1624 return status;
1625 }
最终会通过audioFlinger->createTrack在audioFlinger中创建一个新的track跟audioTrack相对应。后面数据会传给新的track,从而在新的设备上播放出来。