该系列文章总纲链接:专题分纲目录 Android Framework 音频子系统
本章关键点总结 & 说明:
本章节主要关注➕ 以上思维导图左上 耳麦插拔 部分 即可。本章节主要分析耳麦插拔流程,耳机发生插拔后,android是如何在framework层处理的。同时本章节 涉及输入子系统会写的相对简单一些,详细可参考输入子系统的专题链接:专题分纲目录 Android Framework 输入子系统
对于耳麦的插拔,Android有两种模式,可以使用input子系统,也可以使用state dev(uevent)上报拔插操作。说明如下:
- 输入子系统:可以上报按键事件也可以上报开关事件(EV_SW),事件类型包括headset、headPhone、lineOut。对于输入设备都需要指定能产生同步类事件EV_SYN. 对于按键事件,输入子系统还需要设置按键值的范围,但是对于开关类事件不需要设置。
- switch class子系统:通过uevent向用户空间发送数据,Android中有个线程专门监听这类事件。使用switch dev子系统时,名字必须要设置为"h2w",Android系统监听/sys/class/switch/h2w这个虚拟设备。
具体使用哪种操作 取决于config_useDevInputEventForAudioJack 这个配置值,定义在config.xml文件中,如下:
... <!-- When true use the linux /dev/input/event subsystem to detect the switch changeson the headphone/microphone jack. When false use the older uevent framework. --><bool name="config_useDevInputEventForAudioJack">false</bool>
...
该值为true时使用input子系统, 为false时使用uevent机制,该值在下述文件中定义, 后一个文件会覆盖前一个文件:
frameworks/base/core/res/res/values/config.xml
device/"平台厂商"/frameworks/base/core/res/res/values/config.xml
接下来我么对两种模式进行分析,两种模式前半段不一致,后半段处理是一致的。主要就是分析这样一个流程:底层的耳麦插拔是如何把事件一层层上报,最终通过ActivityManagerService将消息广播出去的过程。
1 前半段分析(两种模式到WiredAccessoryManager中updateLocked方法)
1.1 使用input子系统的流程(从input子系统到WiredAccessoryManager中updateLocked方法)
input子系统通过InputReader开始读取事件并处理。代码如下:
void InputReader::loopOnce() {//...//获取事件size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);{ // acquire lock//...//处理事件processEventsLocked(mEventBuffer, count);//...} // release lock// Send out a message that the describes the changed input devices.if (inputDevicesChanged) {mPolicy->notifyInputDevicesChanged(inputDevices);}mQueuedListener->flush();
}
InputReader线程 通过EventHub中的getEvent方法 从驱动中获取事件后使用processEventsLocked开始处理,processEventsLocked实现如下:
void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) {for (const RawEvent* rawEvent = rawEvents; count;) {int32_t type = rawEvent->type;size_t batchSize = 1;if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {//...processEventsForDeviceLocked(deviceId, rawEvent, batchSize);} else {//...}count -= batchSize;rawEvent += batchSize;}
}
这里继续分析processEventsForDeviceLocked的实现,代码如下:
void InputReader::processEventsForDeviceLocked(int32_t deviceId,const RawEvent* rawEvents, size_t count) {//...InputDevice* device = mDevices.valueAt(deviceIndex);//...device->process(rawEvents, count);
}
继续分析InputDevice的process方法,代码如下:
void InputDevice::process(const RawEvent* rawEvents, size_t count) {size_t numMappers = mMappers.size();for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {if (mDropUntilNextSync) {//...} else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {//...} else {for (size_t i = 0; i < numMappers; i++) {InputMapper* mapper = mMappers[i];mapper->process(rawEvent);}}}
}
对于swicth事件来说,这里的map是SwitchInputMapper,它的process函数实现如下:
void SwitchInputMapper::process(const RawEvent* rawEvent) {switch (rawEvent->type) {case EV_SW:processSwitch(rawEvent->code, rawEvent->value);break;case EV_SYN:if (rawEvent->code == SYN_REPORT) {sync(rawEvent->when);}}
}
继续分析processSwitch,代码如下:
void SwitchInputMapper::processSwitch(int32_t switchCode, int32_t switchValue) {if (switchCode >= 0 && switchCode < 32) {if (switchValue) {mSwitchValues |= 1 << switchCode;} else {mSwitchValues &= ~(1 << switchCode);}mUpdatedSwitchMask |= 1 << switchCode;}
}
这里主要是通过mSwitchValues的值进行状态存储,我们继续分析sync的实现,代码如下:
void SwitchInputMapper::sync(nsecs_t when) {if (mUpdatedSwitchMask) {uint32_t updatedSwitchValues = mSwitchValues & mUpdatedSwitchMask;NotifySwitchArgs args(when, 0, updatedSwitchValues, mUpdatedSwitchMask);getListener()->notifySwitch(&args);mUpdatedSwitchMask = 0;}
}
这里的getListener()->notifySwitch(&args)实际上就是InputDispatcher的notifySwitch方法,代码实现如下:
void InputDispatcher::notifySwitch(const NotifySwitchArgs* args) {uint32_t policyFlags = args->policyFlags;policyFlags |= POLICY_FLAG_TRUSTED;mPolicy->notifySwitch(args->eventTime,args->switchValues, args->switchMask, policyFlags);
}
这里的mPolicy->notifySwitch 经过JNI的回调最终会调用到Java层的InputManagerService中的notifySwitch方法,代码如下:
// Native callback.
private void notifySwitch(long whenNanos, int switchValues, int switchMask) {if ((switchMask & SW_LID_BIT) != 0) {final boolean lidOpen = ((switchValues & SW_LID_BIT) == 0);mWindowManagerCallbacks.notifyLidSwitchChanged(whenNanos, lidOpen);}if ((switchMask & SW_CAMERA_LENS_COVER_BIT) != 0) {final boolean lensCovered = ((switchValues & SW_CAMERA_LENS_COVER_BIT) != 0);mWindowManagerCallbacks.notifyCameraLensCoverSwitchChanged(whenNanos, lensCovered);}//mUseDevInputEventForAudioJack在这里被配置成true,会走该分支if (mUseDevInputEventForAudioJack && (switchMask & SW_JACK_BITS) != 0) {mWiredAccessoryCallbacks.notifyWiredAccessoryChanged(whenNanos, switchValues,switchMask);}
}
这里继续分析notifyWiredAccessoryChanged,代码实现如下:
@Override
public void notifyWiredAccessoryChanged(long whenNanos, int switchValues, int switchMask) {synchronized (mLock) {int headset;mSwitchValues = (mSwitchValues & ~switchMask) | switchValues;switch (mSwitchValues &(SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT)) {case 0:headset = 0;break;case SW_HEADPHONE_INSERT_BIT:headset = BIT_HEADSET_NO_MIC;break;case SW_LINEOUT_INSERT_BIT:headset = BIT_LINEOUT;break;case SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT:headset = BIT_HEADSET;break;case SW_MICROPHONE_INSERT_BIT:headset = BIT_HEADSET;break;default:headset = 0;break;}updateLocked(NAME_H2W,(mHeadsetState & ~(BIT_HEADSET | BIT_HEADSET_NO_MIC | BIT_LINEOUT)) | headset);}
}
这里调用到了updateLocked方法了。接下来的分析我们在后半段分析时继续。
1.2 使用uevent机制的流程(从uevent到WiredAccessoryManager中updateLocked方法)
在systemserver中的startOtherServices中关于WiredAccessoryManager的创建和使用如下:
private void startOtherServices() {final Context context = mSystemContext;//...if (!disableMedia) {try {//关键点1inputManager.setWiredAccessoryCallbacks(new WiredAccessoryManager(context, inputManager));} catch (Throwable e) {reportWtf("starting WiredAccessoryManager", e);}}//...final InputManagerService inputManagerF = inputManager;//...try {//关键点2if (inputManagerF != null) inputManagerF.systemRunning();} catch (Throwable e) {reportWtf("Notifying InputManagerService running", e);}//...
}
@1 WiredAccessoryManager创建
WiredAccessoryManager的构造器代码实现如下:
public WiredAccessoryManager(Context context, InputManagerService inputManager) {//这里涉及三个服务:电源子系统、输入输出子系统、音频子系统PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WiredAccessoryManager");mWakeLock.setReferenceCounted(false);mAudioManager = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);mInputManager = inputManager;mUseDevInputEventForAudioJack =context.getResources().getBoolean(R.bool.config_useDevInputEventForAudioJack);mObserver = new WiredAccessoryObserver();
}
这里的WiredAccessoryObserver是继承UEventObserver类的,UEventObserver实现为空,WiredAccessoryObserver的构造器代码如下:
public WiredAccessoryObserver() {mUEventInfo = makeObservedUEventList();
}
这里 makeObservedUEventList 的 代码实现如下:
private List<UEventInfo> makeObservedUEventList() {List<UEventInfo> retVal = new ArrayList<UEventInfo>();UEventInfo uei;//这里只监听这三个UEventInfo对应的事件,驱动程序通过uevent上报事件也只能上报这三个事件之一// Monitor h2wif (!mUseDevInputEventForAudioJack) {//用于监听名为"h2w"这个Switch class驱动中创建的虚拟文件 //./devices/virtual/switch/h2w//./class/switch/h2wuei = new UEventInfo(NAME_H2W, BIT_HEADSET, BIT_HEADSET_NO_MIC, BIT_LINEOUT);if (uei.checkSwitchExists()) {retVal.add(uei);}}// Monitor USBuei = new UEventInfo(NAME_USB_AUDIO, BIT_USB_HEADSET_ANLG, BIT_USB_HEADSET_DGTL, 0);if (uei.checkSwitchExists()) {retVal.add(uei);} uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0, 0);if (uei.checkSwitchExists()) {retVal.add(uei);} else {uei = new UEventInfo(NAME_HDMI, BIT_HDMI_AUDIO, 0, 0);if (uei.checkSwitchExists()) {retVal.add(uei);}}return retVal;
}
@2 inputManagerF的systemRunning()函数分析
inputManagerF.systemRunning()代码实现如下:
public void systemRunning() {//...if (mWiredAccessoryCallbacks != null) {mWiredAccessoryCallbacks.systemReady();}
}
这里systemReady代码实现如下:
@Override
public void systemReady() {synchronized (mLock) {mWakeLock.acquire();Message msg = mHandler.obtainMessage(MSG_SYSTEM_READY, 0, 0, null);mHandler.sendMessage(msg);}
}
处理MSG_SYSTEM_READY消息的handler代码如下:
private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_NEW_DEVICE_STATE:setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);mWakeLock.release();break;case MSG_SYSTEM_READY:onSystemReady();mWakeLock.release();break;}}
};
这里会调用到onSystemReady,代码实现如下:
private void onSystemReady() {if (mUseDevInputEventForAudioJack) {int switchValues = 0;if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_HEADPHONE_INSERT) == 1) {switchValues |= SW_HEADPHONE_INSERT_BIT;}if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_MICROPHONE_INSERT) == 1) {switchValues |= SW_MICROPHONE_INSERT_BIT;}if (mInputManager.getSwitchState(-1, InputDevice.SOURCE_ANY, SW_LINEOUT_INSERT) == 1) {switchValues |= SW_LINEOUT_INSERT_BIT;}notifyWiredAccessoryChanged(0, switchValues,SW_HEADPHONE_INSERT_BIT | SW_MICROPHONE_INSERT_BIT | SW_LINEOUT_INSERT_BIT);}mObserver.init();
}
继续分析mObserver的init()方法,代码实现如下:
void init() {//...for (int i = 0; i < mUEventInfo.size(); ++i) {UEventInfo uei = mUEventInfo.get(i);startObserving("DEVPATH="+uei.getDevPath());}
}
这里继续分析startObserving,代码实现如下:
public final void startObserving(String match) {final UEventThread t = getThread();t.addObserver(match, this);
}
继续看getThread的实现,代码如下:
private static UEventThread getThread() {synchronized (UEventObserver.class) {if (sThread == null) {sThread = new UEventThread();sThread.start();}return sThread;}
}
这里执行start时,会调用到UEventThread的run方法,代码实现如下:
public void run() {nativeSetup();while (true) {//...//等待事件,native层实现,从系统底层接收消息String message = nativeWaitForNextEvent();if (message != null) {//发送消息sendEvent(message);}}
}
发送消息实现如下:
private void sendEvent(String message) {//...if (!mTempObserversToSignal.isEmpty()) {final UEvent event = new UEvent(message);final int N = mTempObserversToSignal.size();for (int i = 0; i < N; i++) {final UEventObserver observer = mTempObserversToSignal.get(i);observer.onUEvent(event);}mTempObserversToSignal.clear();}
}
继续分析 observer的onUEvent(...)方法的实现,为空,这里会调用到子类WiredAccessoryObserver的实现,代码如下:
@Override
public void onUEvent(UEventObserver.UEvent event) {try {String devPath = event.get("DEVPATH");String name = event.get("SWITCH_NAME");int state = Integer.parseInt(event.get("SWITCH_STATE"));synchronized (mLock) {updateStateLocked(devPath, name, state);}} catch (NumberFormatException e) {Slog.e(TAG, "Could not parse switch state from event " + event);}
}
继续分析updateStateLocked,代码实现如下:
private void updateStateLocked(String devPath, String name, int state) {for (int i = 0; i < mUEventInfo.size(); ++i) {UEventInfo uei = mUEventInfo.get(i);if (devPath.equals(uei.getDevPath())) {updateLocked(name, uei.computeNewHeadsetState(mHeadsetState, state));return;}}
}
这里调用到了updateLocked方法了。接下来的分析我们在后半段分析时继续。
2 后半段分析( 从WiredAccessoryManager中updateLocked方法到上层ActivityManagerService发送广播)
WiredAccessoryManager的updateLocked代码实现如下:
private void updateLocked(String newName, int newState) {//...mWakeLock.acquire();//获得并发送messageMessage msg = mHandler.obtainMessage(MSG_NEW_DEVICE_STATE, headsetState,mHeadsetState, newName);mHandler.sendMessage(msg);mHeadsetState = headsetState;
}
这里的handler对于消息MSG_NEW_DEVICE_STATE的处理如下:
private final Handler mHandler = new Handler(Looper.myLooper(), null, true) {
@Override
public void handleMessage(Message msg) {switch (msg.what) {case MSG_NEW_DEVICE_STATE:setDevicesState(msg.arg1, msg.arg2, (String)msg.obj);mWakeLock.release();break;case MSG_SYSTEM_READY:onSystemReady();mWakeLock.release();break;}
}
这里关注setDevicesState的实现,代码如下:
private void setDevicesState(int headsetState, int prevHeadsetState, String headsetName) {synchronized (mLock) {int allHeadsets = SUPPORTED_HEADSETS;for (int curHeadset = 1; allHeadsets != 0; curHeadset <<= 1) {if ((curHeadset & allHeadsets) != 0) {setDeviceStateLocked(curHeadset, headsetState, prevHeadsetState, headsetName);allHeadsets &= ~curHeadset;}}}
}
这里关注setDeviceStateLocked的实现,代码如下:
private void setDeviceStateLocked(int headset,int headsetState, int prevHeadsetState, String headsetName) {if ((headsetState & headset) != (prevHeadsetState & headset)) {int outDevice = 0;int inDevice = 0;int state;if ((headsetState & headset) != 0) {state = 1;} else {state = 0;}if (headset == BIT_HEADSET) {outDevice = AudioManager.DEVICE_OUT_WIRED_HEADSET;inDevice = AudioManager.DEVICE_IN_WIRED_HEADSET;} else if (headset == BIT_HEADSET_NO_MIC){outDevice = AudioManager.DEVICE_OUT_WIRED_HEADPHONE;} else if (headset == BIT_LINEOUT){outDevice = AudioManager.DEVICE_OUT_LINE;} else if (headset == BIT_USB_HEADSET_ANLG) {outDevice = AudioManager.DEVICE_OUT_ANLG_DOCK_HEADSET;} else if (headset == BIT_USB_HEADSET_DGTL) {outDevice = AudioManager.DEVICE_OUT_DGTL_DOCK_HEADSET;} else if (headset == BIT_HDMI_AUDIO) {outDevice = AudioManager.DEVICE_OUT_HDMI;} else {Slog.e(TAG, "setDeviceState() invalid headset type: "+headset);return;}if (outDevice != 0) {//进入了Audio系统,设置有线设备的连接状态mAudioManager.setWiredDeviceConnectionState(outDevice, state, headsetName);}if (inDevice != 0) {mAudioManager.setWiredDeviceConnectionState(inDevice, state, headsetName);}}
}
这里关注mAudioManager的setWiredDeviceConnectionState方法实现,代码如下:
public void setWiredDeviceConnectionState(int device, int state, String name) {IAudioService service = getService();try {service.setWiredDeviceConnectionState(device, state, name);} catch (RemoteException e) {Log.e(TAG, "Dead object in setWiredDeviceConnectionState "+e);}
}
继续分析 setWiredDeviceConnectionState,代码实现如下:
public void setWiredDeviceConnectionState(int device, int state, String name) {synchronized (mConnectedDevices) {int delay = checkSendBecomingNoisyIntent(device, state);queueMsgUnderWakeLock(mAudioHandler,MSG_SET_WIRED_DEVICE_CONNECTION_STATE,device,state,name,delay);}
}
这里的queueMsgUnderWakeLock代码实现如下:
private void queueMsgUnderWakeLock(Handler handler, int msg,int arg1, int arg2, Object obj, int delay) {final long ident = Binder.clearCallingIdentity();mAudioEventWakeLock.acquire();Binder.restoreCallingIdentity(ident);sendMsg(handler, msg, SENDMSG_QUEUE, arg1, arg2, obj, delay);
}
handler对于MSG_SET_WIRED_DEVICE_CONNECTION_STATE消息进行处理,代码如下:
@Override
public void handleMessage(Message msg) {switch (msg.what) {case MSG_SET_DEVICE_VOLUME:setDeviceVolume((VolumeStreamState) msg.obj, msg.arg1);break;//...case MSG_SET_WIRED_DEVICE_CONNECTION_STATE:onSetWiredDeviceConnectionState(msg.arg1, msg.arg2, (String)msg.obj);mAudioEventWakeLock.release();break;//...}
}
onSetWiredDeviceConnectionState的代码实现如下:
private void onSetWiredDeviceConnectionState(int device, int state, String name)
{synchronized (mConnectedDevices) {//...//关键点1:声道切换入口handleDeviceConnection((state == 1), device, (isUsb ? name : ""));if (state != 0) {//...if ((device & mSafeMediaVolumeDevices) != 0) {sendMsg(mAudioHandler,MSG_CHECK_MUSIC_ACTIVE,SENDMSG_REPLACE,0,0,null,MUSIC_ACTIVE_POLL_PERIOD_MS);}//...} else {//...}if (!isUsb && (device != AudioSystem.DEVICE_IN_WIRED_HEADSET)) {//关键点2:通过AMS上报intentsendDeviceConnectionIntent(device, state, name);}}
}
从这里开始我们有两个关键点需要关注,声道切换入口handleDeviceConnection 和 给AMS上报intent的sendDeviceConnectionIntent。
@1 继续分析handleDeviceConnection,代码实现如下:
private boolean handleDeviceConnection(boolean connected, int device, String params) {synchronized (mConnectedDevices) {boolean isConnected = (mConnectedDevices.containsKey(device) &&(params.isEmpty() || mConnectedDevices.get(device).equals(params)));if (isConnected && !connected) {AudioSystem.setDeviceConnectionState(device,AudioSystem.DEVICE_STATE_UNAVAILABLE,mConnectedDevices.get(device));mConnectedDevices.remove(device);return true;} else if (!isConnected && connected) {AudioSystem.setDeviceConnectionState(device,AudioSystem.DEVICE_STATE_AVAILABLE,params);mConnectedDevices.put(new Integer(device), params);return true;}}return false;
}
这里会调用AudioSystem的setDeviceConnectionState方法,它的JNI映射关系为:
{"setDeviceConnectionState", "(IILjava/lang/String;)I", (void *)android_media_AudioSystem_setDeviceConnectionState}
继续分析android_media_AudioSystem_setDeviceConnectionState的实现,代码如下:
static jint
android_media_AudioSystem_setDeviceConnectionState(JNIEnv *env, jobject thiz, jint device, jint state, jstring device_address)
{const char *c_address = env->GetStringUTFChars(device_address, NULL);int status = check_AudioSystem_Command(AudioSystem::setDeviceConnectionState(static_cast <audio_devices_t>(device),static_cast <audio_policy_dev_state_t>(state),c_address));env->ReleaseStringUTFChars(device_address, c_address);return (jint) status;
}
这里专注分析Native层AudioSystem的setDeviceConnectionState,代码实现如下:
status_t AudioSystem::setDeviceConnectionState(audio_devices_t device,audio_policy_dev_state_t state,const char *device_address)
{const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();const char *address = "";//...if (device_address != NULL) {address = device_address;}return aps->setDeviceConnectionState(device, state, address);
}
这里返回的是AudioPolicyManager的setDeviceConnectionState方法,代码实现如下:
status_t AudioPolicyManager::setDeviceConnectionState(audio_devices_t device,audio_policy_dev_state_t state,const char *device_address)
{return setDeviceConnectionStateInt(device, state, device_address);
}
在这里我们只需要知道从Java层AudioService的handleDeviceConnection方法最终可以直接调用到Native层AudioPolicyManager的setDeviceConnectionStateInt,后面我们会专门对setDeviceConnectionStateInt部分代码进行详细的解读。
@2 继续分析sendDeviceConnectionIntent,代码实现如下:
private void sendDeviceConnectionIntent(int device, int state, String name)
{//构建一个Intent结构,然后向应用程序广播它,注册对这个Intent感兴趣的App就会收到它Intent intent = new Intent();intent.putExtra("state", state);intent.putExtra("name", name);intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);//...//intent其他处理//...try {ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);} finally {//...}
}
到这里,通过构建一个Intent结构,然后向应用程序广播它,接下来注册对这个Intent感兴趣的App就会收到它,控制权交给APP。后面会以案例形式接收并处理该intent。