在android手机插入或者拔出耳机的瞬间,kernel层会监听到耳机的变化,以下是插入耳机的瞬间打印的log,可以看到产生event事件然后逐级上报。
01-02 05:26:25.479 405 465 D ENGPC : parse_event: event { 'change', '/devices/virtual/switch/h2w', 'switch', '' }
然后wiredAccessoryManager检查到耳机链接,
01-02 05:26:25.480 750 1564 V WiredAccessoryManager: newName=h2w newState=1 headsetState=1 prev headsetState=0
01-02 05:26:25.481 750 1564 D PowerManagerService: acquireWakeLockInternal: lock=253941888, flags=0x1, tag="WiredAccessoryManager", ws=null, uid=1000, pid=750 packageName=android
01-02 05:26:25.481 750 1564 I WiredAccessoryManager: MSG_NEW_DEVICE_STATE
01-02 05:26:25.482 750 750 V WiredAccessoryManager: headsetName: connected
通过发消息的方式把耳机连接事件传递给audioservice,数字1表示插入,其余两个参数为null.
01-02 05:26:25.482 750 750 I AudioService: setWiredDeviceConnectionState(1 nm: addr:)
public void setWiredDeviceConnectionState(int type, int state, String address, String name,
String caller) {
synchronized (mConnectedDevices) {
if (DEBUG_DEVICES) {
Slog.i(TAG, "setWiredDeviceConnectionState(" + state + " nm: " + name + " addr:"
+ address + ")");
}
int delay = checkSendBecomingNoisyIntent(type, state);
queueMsgUnderWakeLock(mAudioHandler,
MSG_SET_WIRED_DEVICE_CONNECTION_STATE,
0,
0,
new WiredDeviceConnectionState(type, state, address, name, caller),
delay);
}
}
第一个状态表示类型是耳机或者蓝牙耳机表示设备,第二个参数便是连接的状态,1表示连接,0表示断开。地址和名字为空,最后一个根据名字是caller。
AudioService外设状态管理主要有三个作用:
1. 管理发送ACTION_AUDIO_BECOMING_NOISY广播。
2. 发送设备状态变化的广播,通知应用。
3. 将其变化通知到AudioPolicyManager底层。
主要有两个广播ACTION_AUDIO_BECOMING_NOISY 和 ACTION_HEADSET_PLUG
/**
* Broadcast intent, a hint for applications that audio is about to become
* 'noisy' due to a change in audio outputs. For example, this intent may
* be sent when a wired headset is unplugged, or when an A2DP audio
* sink is disconnected, and the audio system is about to automatically
* switch audio route to the speaker. Applications that are controlling
* audio streams may consider pausing, reducing volume or some other action
* on receipt of this intent so as not to surprise the user with audio
* from the speaker.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_AUDIO_BECOMING_NOISY = "android.media.AUDIO_BECOMING_NOISY";
这个广播英语解释已经很清楚了,说明最后的安静设备被拔出时发送,最简单的例子是如果耳机被拔出此时只有外放的话,会发送这个广播通知应用应用及时停止播放。
/**
* Broadcast Action: Wired Headset plugged in or unplugged.
*
* You <em>cannot</em> receive this through components declared
* in manifests, only by explicitly registering for it with
* {@link Context#registerReceiver(BroadcastReceiver, IntentFilter)
* Context.registerReceiver()}.
*
* <p>The intent will have the following extra values:
* <ul>
* <li><em>state</em> - 0 for unplugged, 1 for plugged. </li>
* <li><em>name